diff --git a/src/components/AddAddressModal.vue b/src/components/AddAddressModal.vue deleted file mode 100644 index dd25a63a..00000000 --- a/src/components/AddAddressModal.vue +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - {{ translate("Address") }} - - - - - - {{ translate("Address line 1") }} - - - - {{ translate("Address line 2") }} - - - - {{ translate("City") }} - - - - {{ translate("Country") }} - - - - {{ translate("State") }} - - - - {{ translate("Zipcode") }} - - - - - - - - - - - - \ No newline at end of file diff --git a/src/components/AddGeoPointModal.vue b/src/components/AddGeoPointModal.vue deleted file mode 100644 index 02d57d96..00000000 --- a/src/components/AddGeoPointModal.vue +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - {{ translate("Latitude & Longitude") }} - - - - - - {{ "" }} - - {{ translate("Generate") }} - - - - - {{ translate("Latitude") }} - - - - {{ translate("Longitude") }} - - - - - - - - - - - - \ No newline at end of file diff --git a/src/components/AddLocationModal.vue b/src/components/AddLocationModal.vue index 14a3f952..4ef6917e 100644 --- a/src/components/AddLocationModal.vue +++ b/src/components/AddLocationModal.vue @@ -15,30 +15,30 @@ - {{ translate("Type") }} + {{ translate("Type") }} {{ description }} - {{ translate("Area") }} * - + {{ translate("Area") }} * + - {{ translate("Aisle") }} * - + {{ translate("Aisle") }} * + - {{ translate("Section") }} * - + {{ translate("Section") }} * + - {{ translate("Level") }} * - + {{ translate("Level") }} * + - {{ translate("Sequence") }} - + {{ translate("Sequence") }} + @@ -103,7 +103,7 @@ export default defineComponent({ locationInfo: {} as any } }, - mounted() { + beforeMount() { this.locationInfo = this.location ? JSON.parse(JSON.stringify(this.location)) : {} }, computed: { diff --git a/src/components/FacilityAddressModal.vue b/src/components/FacilityAddressModal.vue new file mode 100644 index 00000000..87443ba7 --- /dev/null +++ b/src/components/FacilityAddressModal.vue @@ -0,0 +1,171 @@ + + + + + + + + + {{ translate("Address") }} + + + + + + + {{ translate("Address line 1") }} * + + + + {{ translate("Address line 2") }} + + + + {{ translate("City") }} * + + + + {{ translate("Country") }} + + {{ country.geoName }} + + + + {{ translate("State") }} + + {{ state.geoName }} + + + + {{ translate("Zipcode") }} + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/FacilityGeoPointModal.vue b/src/components/FacilityGeoPointModal.vue new file mode 100644 index 00000000..5734a632 --- /dev/null +++ b/src/components/FacilityGeoPointModal.vue @@ -0,0 +1,160 @@ + + + + + + + + + {{ translate("Latitude & Longitude") }} + + + + + + + + + {{ translate("Generate") }} + + + + + {{ translate("Latitude") }} + + + + {{ translate("Longitude") }} + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/Filters.vue b/src/components/Filters.vue index fe4a0e74..54620715 100644 --- a/src/components/Filters.vue +++ b/src/components/Filters.vue @@ -21,7 +21,9 @@ {{ translate("Type") }} {{ translate("All") }} - {{ description }} + + {{ type.description }} + diff --git a/src/components/OpenStorePopover.vue b/src/components/OpenStorePopover.vue deleted file mode 100644 index bc88616e..00000000 --- a/src/components/OpenStorePopover.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - - {{ "NotNaked" }} - - {{ translate("Make primary") }} - - - - {{ translate("Unlink") }} - - - - - - - diff --git a/src/components/ProductStorePopover.vue b/src/components/ProductStorePopover.vue new file mode 100644 index 00000000..d4f60f11 --- /dev/null +++ b/src/components/ProductStorePopover.vue @@ -0,0 +1,199 @@ + + + + {{ getProductStore(currentProductStore.productStoreId).storeName }} + + {{ translate("Primary") }} + + + + {{ translate("Unlink") }} + + + + + + + \ No newline at end of file diff --git a/src/components/SelectProductStoreModal.vue b/src/components/SelectProductStoreModal.vue index 1b4edb16..9dd78e96 100644 --- a/src/components/SelectProductStoreModal.vue +++ b/src/components/SelectProductStoreModal.vue @@ -12,17 +12,16 @@ - + - {{ "Demo Store" }} - {{ "STORE_ID" }} + {{ productStore.storeName }} + {{ productStore.productStoreId }} - + - - + @@ -49,6 +48,7 @@ import { import { defineComponent } from "vue"; import { closeOutline, saveOutline } from "ionicons/icons"; import { translate } from '@hotwax/dxp-components' +import { mapGetters, useStore } from "vuex"; export default defineComponent({ name: "SelectProductStoreModal", @@ -67,15 +67,59 @@ export default defineComponent({ IonTitle, IonToolbar }, + computed: { + ...mapGetters({ + productStores: 'util/getProductStores', + facilityProductStores: 'facility/getFacilityProductStores', + }) + }, + props: ["facilityId", "selectedProductStores"], + data() { + return { + selectedProductStoreValues: JSON.parse(JSON.stringify(this.selectedProductStores)), + } + }, methods: { closeModal() { modalController.dismiss({ dismissed: true}); + }, + async saveProductStores() { + const productStoresToCreate = this.selectedProductStoreValues.filter((selectedFacility: any) => !this.selectedProductStores.some((facility: any) => facility.facilityId === selectedFacility.facilityId)) + const productStoresToRemove = this.selectedProductStores.filter((facility: any) => !this.selectedProductStoreValues.some((selectedFacility: any) => facility.facilityId === selectedFacility.facilityId)) + + modalController.dismiss({ + dismissed: true, + value: { + selectedProductStores: this.selectedProductStoreValues, + productStoresToCreate, + productStoresToRemove + } + }); + + modalController.dismiss() + }, + toggleProductStoreSelection(updatedStore: any) { + let selectedStore = this.selectedProductStoreValues.some((store: any) => store.productStoreId === updatedStore.productStoreId); + if(selectedStore) { + this.selectedProductStoreValues = this.selectedProductStoreValues.filter((store: any) => store.productStoreId !== updatedStore.productStoreId); + } else { + this.selectedProductStoreValues.push(updatedStore); + } + }, + isSelected(productStoreId: string) { + return this.selectedProductStoreValues.some((productStore: any) => productStore.productStoreId === productStoreId); + }, + isProductStoreUpdated() { + return this.selectedProductStoreValues.some((selectedStore: any) => this.selectedProductStores.some((store: any) => store.productStoreId === selectedStore.productStoreId)); } }, setup() { + const store = useStore() + return { closeOutline, saveOutline, + store, translate }; }, diff --git a/src/components/TimezoneModal.vue b/src/components/TimezoneModal.vue index 7363e67f..89156320 100644 --- a/src/components/TimezoneModal.vue +++ b/src/components/TimezoneModal.vue @@ -6,10 +6,10 @@ - {{ $t("Select time zone") }} + {{ translate("Select time zone") }} - + @@ -17,12 +17,12 @@ - {{ $t("Fetching TimeZones")}} + {{ translate("Fetching TimeZones")}} - {{ $t("No time zone found")}} + {{ translate("No time zone found")}} @@ -74,6 +74,7 @@ import { UserService } from "@/services/UserService"; import { hasError } from '@/adapter' import { DateTime } from 'luxon'; import logger from "@/logger"; +import { translate } from "@hotwax/dxp-components"; export default defineComponent({ name: "TimeZoneModal", @@ -153,6 +154,7 @@ export default defineComponent({ return { closeOutline, saveOutline, + translate, store }; } diff --git a/src/locales/en.json b/src/locales/en.json index 18c9c7e7..dcae1d03 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1,7 +1,11 @@ { "Add": "Add", + "Add address later": "Add address later", "Add locations to facility": "Add locations to facility", "Add staff member to facility": "Add staff member to facility", + "Add Store": "Add Store", + "Add Store Address": "Add Store Address", + "Add Store Configuration": "Add Store Configuration", "Add timings": "Add timings", "Address": "Address", "Address line 1": "Address line 1", @@ -27,8 +31,11 @@ "City": "City", "Click the backdrop to dismiss.": "Click the backdrop to dismiss.", "Closing Time": "Closing Time", + "Configure settings later": "Configure settings later", "Configure the order fulfillment capacity of your facility.": "Configure the order fulfillment capacity of your facility.", "Consumed Order Limit": "Consumed Order Limit", + "Create login credentials": "Create login credentials", + "Create store": "Create store", "Custom": "Custom", "Custom fulfillment capacity": "Custom fulfillment capacity", "Custom mapping": "Custom mapping", @@ -44,32 +51,52 @@ "Edit": "Edit", "Edit location": "Edit location", "End Time": "End Time", + "External ID": "External ID", "External mapping created successfully": "External mapping created successfully", "External mapping updated successfully": "External mapping updated successfully", "External mappings": "External mappings", "Facilities": "Facilities", + "Facility address created successfully.": "Facility address created successfully.", + "Facility created successfully.": "Facility created successfully.", + "Facility configurations created successfully.": "Facility configurations created successfully.", + "Facility": "Facility", + "Facility address updated successfully.": "Facility address updated successfully.", "Facility details": "Facility details", + "Facility latitude & longitude updated successfully.": "Facility latitude & longitude updated successfully.", "Facility ID": "Facility ID", "Facility location created successfully": "Facility location created successfully", "Facility location removed successfully": "Facility location removed successfully", "Facility location updated successfully": "Facility location updated successfully", "Facility name": "Facility name", + "Facility name is required.": "Facility name is required.", "Facility Management": "Facility Management", + "Failed to add some product stores to the facility.": "Failed to add some product stores to the facility.", "Failed to create external mapping": "Failed to create external mapping", + "Failed to create facility.": "Failed to create facility.", + "Failed to create facility address.": "Failed to create facility address.", "Failed to create facility location": "Failed to create facility location", "Failed to create shopify mapping": "Failed to create shopify mapping", "Failed to fetch facility information": "Failed to fetch facility information", "Failed to find the facility locations": "Failed to find the facility locations", + "Failed to generate latitude and longitude.": "Failed to generate latitude and longitude.", + "Failed to make product store as primary.": "Failed to make product store as primary.", + "Failed to create facility login credentials.": "Failed to create facility login credentials.", + "Failed to generate latitude & Longitude.": "Failed to generate latitude & Longitude.", + "Failed to make product store primary.": "Failed to make product store primary.", "Failed to remove facility location": "Failed to remove facility location", "Failed to remove facility mapping": "Failed to remove facility mapping", "Failed to remove party from facility.": "Failed to remove party from facility.", "Failed to remove shopify mapping": "Failed to remove shopify mapping", "Failed to update default days to ship": "Failed to update default days to ship", "Failed to update external mapping": "Failed to update external mapping", + "Failed to update facility address.": "Failed to update facility address.", + "Failed to update facility latitude & longitude.": "Failed to update facility latitude & longitude.", "Failed to update facility location": "Failed to update facility location", "Failed to update fulfillment capacity for ": "Failed to update fulfillment capacity for {facilityName}", "Failed to update fulfillment setting": "Failed to update fulfillment setting", "Failed to update shopify mapping": "Failed to update shopify mapping", + "Failed to update some fulfillment settings.": "Failed to update some fulfillment settings.", + "Failed to update some product stores": "Failed to update some product stores", "Failed to update some role(s).": "Failed to update some role(s).", "Fetching TimeZones": "Fetching TimeZones", "Find Facilities": "Find Facilities", @@ -84,6 +111,7 @@ "Go to OMS": "Go to OMS", "Groups": "Groups", "Identification": "Identification", + "Internal ID": "Internal ID", "Instance Url": "Instance Url", "Language": "Language", "Latitude": "Latitude", @@ -101,7 +129,6 @@ "Login failed": "Login failed", "Logout": "Logout", "Longitude": "Longitude", - "Make primary": "Make primary", "Mapping ID": "Mapping ID", "Mapping Name": "Mapping Name", "Map facility to an external system": "Map facility to an external system", @@ -114,6 +141,7 @@ "No facilities found": "No facilities found", "No fulfillment capacity": "No fulfillment capacity", "No party found": "No party found", + "No product stores added.": "No product stores added.", "No records found": "No records found", "No time zone found": "No time zone found", "OMS": "OMS", @@ -134,9 +162,12 @@ "Please contact the administrator.": "Please contact the administrator.", "Please enter a valid value": "Please enter a valid value", "Please fill all the required fields": "Please fill all the required fields", + "Please provide a password.": "Please provide a password.", + "Primary": "Primary", "primary store": "primary store", "Product Store": "Product Store", "Product Stores": "Product Stores", + "Product stores updated successfully.": "Product stores updated successfully.", "Reason:": "Reason:", "Remove": "Remove", "Remove location": "Remove location", @@ -149,10 +180,14 @@ "Role(s) updated successfully.": "Role(s) updated successfully.", "Saturday": "Saturday", "Save": "Save", + "Save address": "Save address", + "Save configurations": "Save configurations", "Section": "Section", "section": "section", "Select": "Select", "Select a saved calendar of store hours or create a new calendar": "Select a saved calendar of store hours or create a new calendar", + "Select country": "Select country", + "Select state": "Select state", "Search facilities": "Search facilities", "Search time zones": "Search time zones", "Select time zone": "Select time zone", @@ -164,6 +199,7 @@ "sequence": "sequence", "Settings": "Settings", "Setting fulfillment capacity to 0 disables new order from being allocated to this facility. Leave this empty if this facility's fulfillment capacity is unrestricted.": "Setting fulfillment capacity to 0 disables new order from being allocated to this facility. Leave this empty if this facility's fulfillment capacity is unrestricted.", + "Setup Store": "Setup Store", "Shopify": "Shopify", "Shopify facility": "Shopify facility", "Shopify location": "Shopify location", @@ -176,7 +212,10 @@ "Staff": "Staff", "Start Time": "Start Time", "State": "State", + "Store": "Store", "store name": "store name", + "Store unlink failed.": "Store unlink failed.", + "Store unlinked successfully.": "Store unlinked successfully.", "Successfully associated calendar to the facility.": "Successfully associated calendar to the facility.", "Sunday": "Sunday", "The timezone you select is used to ensure automations you schedule are always accurate to the time you select.": "The timezone you select is used to ensure automations you schedule are always accurate to the time you select.", @@ -193,7 +232,7 @@ "Unlimited capacity removes the fulfillment capacity limit entirely. To add a fulfillment capacity to this facility, use the custom option.": "Unlimited capacity removes the fulfillment capacity limit entirely. To add a fulfillment capacity to this facility, use the custom option.", "Unlimited fulfillment capacity": "Unlimited fulfillment capacity", "Unlimited orders": "Unlimited orders", - "Unlink":"Unlink", + "Unlink": "Unlink", "Update days to ship": "Update days to ship", "Username": "Username", "Uses native fulfillment app": "Uses native fulfillment app", @@ -203,4 +242,4 @@ "Wednesday": "Wednesday", "Would you like to update your time zone to . Your profile is currently set to . This setting can always be changed from the settings menu.": "Would you like to update your time zone to {localTimeZone}. Your profile is currently set to {profileTimeZone}. This setting can always be changed from the settings menu.", "Zipcode": "Zipcode" -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/router/index.ts b/src/router/index.ts index 273b9495..c2ad66d1 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -10,6 +10,9 @@ import { loader } from '@/utils/user'; import FacilityManagement from '@/views/FacilityManagement.vue' import Settings from '@/views/Settings.vue'; import FindFacilities from '@/views/FindFacilities.vue'; +import CreateFacility from '@/views/CreateFacility.vue'; +import AddFacilityAddress from '@/views/AddFacilityAddress.vue'; +import AddFacilityConfig from '@/views/AddFacilityConfig.vue'; // Defining types for the meta values declare module 'vue-router' { @@ -68,6 +71,26 @@ const routes: Array = [ props: true, beforeEnter: authGuard }, + { + path: "/create-facility", + name: "Create Facility", + component: CreateFacility, + beforeEnter: authGuard + }, + { + path: "/add-facility-address/:facilityId", + name: "Add Facility Address", + component: AddFacilityAddress, + props: true, + beforeEnter: authGuard + }, + { + path: "/add-facility-config/:facilityId", + name: "Add Facility Config", + component: AddFacilityConfig, + props: true, + beforeEnter: authGuard + }, { path: '/settings', name: 'Settings', diff --git a/src/services/FacilityService.ts b/src/services/FacilityService.ts index b2711dd9..4a644950 100644 --- a/src/services/FacilityService.ts +++ b/src/services/FacilityService.ts @@ -2,6 +2,14 @@ import { api, hasError } from '@/adapter'; import logger from '@/logger'; import { DateTime } from 'luxon'; +const createFacilityPostalAddress = async (payload: any): Promise => { + return api({ + url: "service/createFacilityPostalAddress", + method: "post", + data: payload + }) +} + const fetchFacilities = async(query: any): Promise => { return api({ url: "performFind", @@ -18,7 +26,7 @@ const fetchFacilityGroupInformation = async(facilityIds: Array): Promise facilityId: facilityIds, facilityId_op: "in" }, - fieldList: ['facilityId', 'facilityGroupId', 'facilityGroupTypeId', "fromDate"], + fieldList: ['facilityGroupId', 'facilityId', 'facilityGroupTypeId', "fromDate"], entityName: "FacilityGroupAndMember", distinct: 'Y', filterByDate: 'Y', @@ -142,6 +150,32 @@ const fetchFacilityOrderCounts = async(facilityId: string): Promise => { return facilityOrderCounts; } +const fetchFacilityGroup = async (payload: any): Promise => { + return api({ + url: "performFind", + method: "post", + data: payload + }); +} + +const fetchFacilityContactDetails = async(payload: any): Promise => { + return api({ + url: "performFind", + method: "post", + data: payload + }); +} + +const getFacilityProductStores = async (payload: any): Promise => { + return api({ + url: "performFind", + method: "POST", + data: payload + }) +} + + + const addPartyToFacility = async (payload: any): Promise => { return api({ url: "service/addPartyToFacility", @@ -150,6 +184,8 @@ const addPartyToFacility = async (payload: any): Promise => { }); } + + const removePartyFromFacility = async (payload: any): Promise => { return api({ url: "service/removePartyFromFacility", @@ -158,22 +194,24 @@ const removePartyFromFacility = async (payload: any): Promise => { }); } -const updateFacility = async (payload: any): Promise => { + +const updateProductStoreFacility = async (payload: any): Promise => { return api({ - url: "service/updateFacility", + url: "service/updateProductStoreFacility", method: "post", data: payload - }) + }); } const fetchFacilityLocations = async(payload: any): Promise => { return api({ url: "performFind", - method: "post", + method: "POST", data: payload }) } + const addFacilityToGroup = async (payload: any): Promise => { return api({ url: "service/addFacilityToGroup", @@ -190,6 +228,14 @@ const associateCalendarToFacility = async (payload: any): Promise => { }) } +const createFacilityGroup = async(payload: any): Promise => { + return api({ + url: "service/createFacilityGroup", + method: "post", + data: payload + }) +} + const createFacilityLocation = async(payload: any): Promise => { return api({ url: "service/createFacilityLocation", @@ -198,6 +244,30 @@ const createFacilityLocation = async(payload: any): Promise => { }) } +const createProductStoreFacility = async (payload: any): Promise => { + return api({ + url: "service/createProductStoreFacility", + method: "post", + data: payload + }); +} + +const fetchFacilityPrimaryMember = async (payload: any): Promise => { + return api({ + url: "performFind", + method: "post", + data: payload + }); +} + +const updateFacility = async (payload: any): Promise => { + return api({ + url: "service/updateFacility", + method: "post", + data: payload + }) +} + const updateFacilityLocation = async(payload: any): Promise => { return api({ url: "service/updateFacilityLocation", @@ -222,6 +292,23 @@ const updateFacilityToGroup = async (payload: any): Promise => { }) } +const createFacility = async (payload: any): Promise => { + return api({ + url: "service/createFacility", + method: "post", + data: payload + }) +} + +const updateFacilityPostalAddress = async (payload: any): Promise => { + return api({ + url: "service/updateFacilityPostalAddress", + method: "post", + data: payload + }) +} + + const fetchFacilityMappings = async (payload: any): Promise => { return api({ url: "performFind", @@ -312,22 +399,30 @@ const removeFacilityCalendar = async (payload: any): Promise => { export const FacilityService = { addFacilityToGroup, + createFacilityGroup, + createFacility, + createFacilityLocation, addPartyToFacility, associateCalendarToFacility, createEnumeration, createFacilityCalendar, createFacilityIdentification, - createFacilityLocation, - createShopifyShopLocation, + createFacilityPostalAddress, + createProductStoreFacility, deleteFacilityLocation, + fetchFacilityGroup, + fetchFacilityLocations, + fetchFacilityContactDetails, + createShopifyShopLocation, deleteShopifyShopLocation, fetchFacilities, fetchFacilitiesOrderCount, fetchFacilityCalendars, fetchFacilityGroupInformation, - fetchFacilityLocations, fetchFacilityMappings, fetchFacilityOrderCounts, + fetchFacilityPrimaryMember, + getFacilityProductStores, fetchShopifyFacilityMappings, getFacilityParties, getPartyRoleAndPartyDetails, @@ -336,6 +431,8 @@ export const FacilityService = { updateFacility, updateFacilityIdentification, updateFacilityLocation, + updateFacilityPostalAddress, updateFacilityToGroup, + updateProductStoreFacility, updateShopifyShopLocation } \ No newline at end of file diff --git a/src/services/UserService.ts b/src/services/UserService.ts index be353c14..c4415b5c 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -136,8 +136,26 @@ const getUserProfile = async (token: any): Promise => { } } +const createFacilityUser = async (payload: any): Promise => { + return api({ + url: "service/createRelationship", + method: "post", + data: payload + }); +} + +const addPartyToFacility = async (payload: any): Promise => { + return api({ + url: "service/addPartyToFacility", + method: "post", + data: payload + }); +} + export const UserService = { + addPartyToFacility, login, + createFacilityUser, getAvailableTimeZones, getUserProfile, setUserTimeZone, diff --git a/src/services/UtilService.ts b/src/services/UtilService.ts index 64e37f14..c819fa42 100644 --- a/src/services/UtilService.ts +++ b/src/services/UtilService.ts @@ -18,6 +18,15 @@ const fetchProductStores = async (payload: any): Promise => { }) } +const generateLatLong = async (payload: any): Promise => { + return api({ + url: "postcodeLookup", + method: "POST", + data: payload, + cache: true + }) +} + const fetchPartyRoles = async (payload: any): Promise => { return api({ url: 'performFind', @@ -26,6 +35,7 @@ const fetchPartyRoles = async (payload: any): Promise => { cache: true }) } + const fetchLocationTypes = async (payload: any): Promise => { return api({ url: "performFind", @@ -35,6 +45,24 @@ const fetchLocationTypes = async (payload: any): Promise => { }) } +const fetchCountries = async (payload: any): Promise => { + return api({ + url: "performFind", + method: "POST", + data: payload, + cache: true + }) +} + +const fetchStates = async (payload: any): Promise => { + return api({ + url: "performFind", + method: "POST", + data: payload, + cache: true + }) +} + const fetchExternalMappingTypes = async (payload: any): Promise => { return api({ url: "performFind", @@ -63,10 +91,13 @@ const fetchCalendarWeek = async (payload: any): Promise => { export const UtilService = { fetchCalendars, fetchCalendarWeek, + fetchCountries, fetchExternalMappingTypes, fetchFacilityTypes, fetchLocationTypes, + fetchProductStores, + fetchStates, + generateLatLong, fetchPartyRoles, - fetchProductStores } diff --git a/src/store/modules/facility/actions.ts b/src/store/modules/facility/actions.ts index b2d5e676..b0022279 100644 --- a/src/store/modules/facility/actions.ts +++ b/src/store/modules/facility/actions.ts @@ -10,7 +10,50 @@ import { showToast } from '@/utils' import { translate } from '@hotwax/dxp-components' const actions: ActionTree = { - async fetchFacilities({ commit, state }, payload) { + async fetchFacilitiesAdditionalInformation({ commit, state }, payload = { viewIndex: 0 }) { + + // getting all the facilties from state + const cachedFacilities = JSON.parse(JSON.stringify(state.facilities.list)); // maintaining cachedFacilities as to prepare the facilities payload to fetch additional information + let stateFacilities = JSON.parse(JSON.stringify(state.facilities.list)); // maintaining stateFacilities as to update the facility information once information in fetched + const total = state.facilities.total + + const facilityIds: Array = []; + + // splitting the facilities in batches to fetch the additional facilities information + const facilities = cachedFacilities.splice(payload.viewIndex * (process.env.VUE_APP_VIEW_SIZE as any), process.env.VUE_APP_VIEW_SIZE) + facilities.map((facility: any) => facilityIds.push(facility.facilityId)) + + stateFacilities = stateFacilities.filter((facility: any) => !facilityIds.includes(facility.facilityId)) + + const [facilitiesGroupInformation, facilitiesOrderCount] = await Promise.all([FacilityService.fetchFacilityGroupInformation(facilityIds), FacilityService.fetchFacilitiesOrderCount(facilityIds)]) + + facilities.map((facility: any) => { + const fulfillmentOrderLimit = facility.maximumOrderLimit + if (fulfillmentOrderLimit === 0) { + facility.orderLimitType = 'no-capacity' + } else if (fulfillmentOrderLimit) { + facility.orderLimitType = 'custom' + } else { + facility.orderLimitType = 'unlimited' + } + + facility.orderCount = facilitiesOrderCount[facility.facilityId] ? facilitiesOrderCount[facility.facilityId] : 0; + + const facilityGroupInformation = facilitiesGroupInformation[facility.facilityId] + + if(facilityGroupInformation?.length) { + facility.groupInformation = facilityGroupInformation + facility.sellOnline = (facilityGroupInformation.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'FAC_GRP')) + facility.useOMSFulfillment = (facilityGroupInformation.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'OMS_FULFILLMENT')) + facility.generateShippingLabel = (facilityGroupInformation.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'AUTO_SHIPPING_LABEL')) + facility.allowPickup = (facilityGroupInformation.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'PICKUP')) + } + }) + + commit(types.FACILITY_LIST_UPDATED, { facilities: stateFacilities.concat(facilities), total }) + }, + + async fetchFacilities({ commit, dispatch, state }, payload) { if (payload.viewIndex === 0) emitter.emit("presentLoader"); const filters = { 'parentFacilityTypeId': 'VIRTUAL_FACILITY', @@ -49,7 +92,7 @@ const actions: ActionTree = { ...payload } - let facilities = [], total = 0; + let facilities = [], total = 0, facilityList = []; try { const resp = await FacilityService.fetchFacilities(params) @@ -58,32 +101,7 @@ const actions: ActionTree = { facilities = resp.data.docs total = resp.data.count - const [facilitiesGroupInformation, facilitiesOrderCount] = await Promise.all([FacilityService.fetchFacilityGroupInformation(facilities.map((facility: any) => facility.facilityId)), FacilityService.fetchFacilitiesOrderCount(facilities.map((facility: any) => facility.facilityId))]) - - facilities.map((facility: any) => { - const fulfillmentOrderLimit = facility.maximumOrderLimit - if (fulfillmentOrderLimit === 0) { - facility.orderLimitType = 'no-capacity' - } else if (fulfillmentOrderLimit) { - facility.orderLimitType = 'custom' - } else { - facility.orderLimitType = 'unlimited' - } - - facility.orderCount = facilitiesOrderCount[facility.facilityId] ? facilitiesOrderCount[facility.facilityId] : 0; - - const facilityGroupInformation = facilitiesGroupInformation[facility.facilityId] - - if(facilityGroupInformation.length) { - facility.groupInformation = facilityGroupInformation - facility.sellOnline = (facilityGroupInformation.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'FAC_GRP')) - facility.useOMSFulfillment = (facilityGroupInformation.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'OMS_FULFILLMENT')) - facility.generateShippingLabel = (facilityGroupInformation.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'AUTO_SHIPPING_LABEL')) - facility.allowPickup = (facilityGroupInformation.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'PICKUP')) - } - }) - - if(payload.viewIndex && payload.viewIndex > 0) facilities = JSON.parse(JSON.stringify(state.facilities.list)).concat(facilities) + if(payload.viewIndex && payload.viewIndex > 0) facilityList = JSON.parse(JSON.stringify(state.facilities.list)).concat(facilities) } else { throw resp.data } @@ -92,14 +110,47 @@ const actions: ActionTree = { } emitter.emit("dismissLoader"); - commit(types.FACILITY_LIST_UPDATED , { facilities, total }); + commit(types.FACILITY_LIST_UPDATED , { facilities: facilityList.length ? facilityList : facilities, total }); + + if(facilities.length) { + await dispatch('fetchFacilitiesAdditionalInformation', payload) + } + }, + + async fetchFacilityAdditionalInformation({ commit, state }) { + const facility = JSON.parse(JSON.stringify(state.current)) + + const [facilityGroupInformation, facilityOrderCount] = await Promise.all([FacilityService.fetchFacilityGroupInformation([facility.facilityId]), FacilityService.fetchFacilitiesOrderCount([facility.facilityId])]) + + const fulfillmentOrderLimit = facility.maximumOrderLimit + if (fulfillmentOrderLimit === 0) { + facility.orderLimitType = 'no-capacity' + } else if (fulfillmentOrderLimit) { + facility.orderLimitType = 'custom' + } else { + facility.orderLimitType = 'unlimited' + } + + facility.orderCount = facilityOrderCount[facility.facilityId] ? facilityOrderCount[facility.facilityId] : 0; + + const facilityGroupInfo = facilityGroupInformation[facility.facilityId] + + if(facilityGroupInfo.length) { + facility.groupInformation = facilityGroupInfo + facility.sellOnline = (facilityGroupInfo.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'FAC_GRP')) + facility.useOMSFulfillment = (facilityGroupInfo.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'OMS_FULFILLMENT')) + facility.generateShippingLabel = (facilityGroupInfo.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'AUTO_SHIPPING_LABEL')) + facility.allowPickup = (facilityGroupInfo.some((facilityGroup: any) => facilityGroup.facilityGroupId === 'PICKUP')) + } + + commit(types.FACILITY_CURRENT_UPDATED, facility) }, async fetchCurrentFacility({ commit, state }, payload) { // checking that if the list contains basic information for facility then not fetching the same information again const cachedFacilities = JSON.parse(JSON.stringify(state.facilities.list)) const current = cachedFacilities.find((facility: any) => facility.facilityId === payload.facilityId) - if(current?.facilityId) { + if(current?.facilityId && !payload.skipState) { commit(types.FACILITY_CURRENT_UPDATED, current); return; } @@ -158,6 +209,44 @@ const actions: ActionTree = { commit(types.FACILITY_CURRENT_UPDATED, facility); }, + updateCurrentFacility({ commit }, facility) { + commit(types.FACILITY_CURRENT_UPDATED, facility); + }, + + async fetchFacilityContactDetails({ commit }, payload) { + let postalAddress = {} as any + const params = { + inputFields: { + contactMechPurposeTypeId: 'PRIMARY_LOCATION', + contactMechTypeId: 'POSTAL_ADDRESS', + facilityId: payload.facilityId + }, + entityName: "FacilityContactDetailByPurpose", + orderBy: 'fromDate DESC', + filterByDate: 'Y', + fieldList: ['address1', 'address2', 'city', 'contactMechId', 'countryGeoId', 'countryGeoName', 'latitude', 'longitude', 'postalCode', 'stateGeoId', 'stateGeoName'], + viewSize: 1 + } + + try { + const resp = await FacilityService.fetchFacilityContactDetails(params) + if(!hasError(resp)) { + postalAddress = resp.data.docs[0] + postalAddress = { + ...postalAddress, + stateProvinceGeoId: postalAddress.stateGeoId + } + delete postalAddress.stateGeoId + } else { + throw resp.data + } + } catch(err) { + logger.error('Failed to fetch the postal address for the facility', err) + } + + commit(types.FACILITY_POSTAL_ADDRESS_UPDATED , postalAddress); + }, + updateQuery({ commit }, query) { commit(types.FACILITY_QUERY_UPDATED, query) }, @@ -222,6 +311,33 @@ const actions: ActionTree = { commit(types.FACILITY_CALENDAR_UPDATED, facilityCalendar) }, + async getFacilityProductStores({ commit }, params) { + let productStores = [] + const payload = { + inputFields: { + facilityId: params.facilityId + }, + viewSize: 100, + entityName: 'ProductStoreFacility', + filterByDate: 'Y', + fieldList: ['fromDate', 'productStoreId'] + } + + try { + const resp = await FacilityService.getFacilityProductStores(payload) + + if(!hasError(resp) && resp.data.count) { + productStores = resp.data.docs + } else { + throw resp.data + } + } catch(error) { + logger.error(error) + } + + commit(types.FACILITY_PRODUCT_STORES_UPDATED , productStores); + }, + async fetchFacilityMappings({ commit }, payload) { let mappings = [] try { diff --git a/src/store/modules/facility/getters.ts b/src/store/modules/facility/getters.ts index d83f2970..6e2ad64f 100644 --- a/src/store/modules/facility/getters.ts +++ b/src/store/modules/facility/getters.ts @@ -6,6 +6,9 @@ const getters: GetterTree = { getFacilities(state) { return JSON.parse(JSON.stringify(state.facilities.list)) }, + getFacilityProductStores(state) { + return state.current.productStores + }, getQuery(state) { return JSON.parse(JSON.stringify(state.query)) }, @@ -23,5 +26,8 @@ const getters: GetterTree = { getFacilityParties(state) { return state.current.parties }, + getPostalAddress(state) { + return state.current?.postalAddress ? JSON.parse(JSON.stringify(state.current.postalAddress)) : {} + } } export default getters; \ No newline at end of file diff --git a/src/store/modules/facility/mutation-types.ts b/src/store/modules/facility/mutation-types.ts index 40ceb51e..864d31bf 100644 --- a/src/store/modules/facility/mutation-types.ts +++ b/src/store/modules/facility/mutation-types.ts @@ -2,9 +2,11 @@ export const SN_FACILITY = 'facility' export const FACILITY_LIST_UPDATED = SN_FACILITY + '/LIST_UPDATED' export const FACILITY_QUERY_UPDATED = SN_FACILITY + '/QUERY_UPDATED' export const FACILITY_CURRENT_UPDATED = SN_FACILITY + '/CURRENT_UPDATED' +export const FACILITY_CURRENT_LOCATION_UPDATED = SN_FACILITY + '/CURRENT_LOCATION_UPDATED' export const FACILITY_LOCATIONS_UPDATED = SN_FACILITY + '/LOCATIONS_UPDATED' +export const FACILITY_POSTAL_ADDRESS_UPDATED = SN_FACILITY + '/POSTAL_ADDRESS_UPDATED' export const FACILITY_MAPPINGS_UPDATED = SN_FACILITY + '/MAPPINGS_UPDATED' export const FACILITY_SHOPIFY_MAPPINGS_UPDATED = SN_FACILITY + '/SHOPIFY_MAPPINGS_UPDATED' export const FACILITY_CALENDAR_UPDATED = SN_FACILITY + '/CALENDAR_UPDATED' -export const FACILITY_CURRENT_LOCATION_UPDATED = SN_FACILITY + '/CURRENT_LOCATION_UPDATED' export const FACILITY_PARTIES_UPDATED = SN_FACILITY + '/PARTIES_UPDATED' +export const FACILITY_PRODUCT_STORES_UPDATED = SN_FACILITY + '/PRODUCT_STORES_UPDATED' diff --git a/src/store/modules/facility/mutations.ts b/src/store/modules/facility/mutations.ts index a2ce1f0d..12a86eef 100644 --- a/src/store/modules/facility/mutations.ts +++ b/src/store/modules/facility/mutations.ts @@ -16,17 +16,32 @@ const mutations: MutationTree = { [types.FACILITY_CURRENT_UPDATED](state, payload) { state.current = payload }, + [types.FACILITY_CURRENT_LOCATION_UPDATED](state, payload) { + state.current.locations = payload + }, + [types.FACILITY_POSTAL_ADDRESS_UPDATED](state, payload) { + state.current.postalAddress = payload + }, + [types.FACILITY_PRODUCT_STORES_UPDATED](state, payload) { + state.current.productStores = payload + }, [types.FACILITY_LOCATIONS_UPDATED](state, payload) { state.current.locations = payload }, [types.FACILITY_MAPPINGS_UPDATED](state, payload) { state.current.facilityMappings = payload }, + [types.FACILITY_POSTAL_ADDRESS_UPDATED](state, payload) { + state.current.postalAddress = payload + }, [types.FACILITY_SHOPIFY_MAPPINGS_UPDATED](state, payload) { state.current.shopifyFacilityMappings = payload }, [types.FACILITY_PARTIES_UPDATED](state, payload) { state.current.parties = payload - } + }, + [types.FACILITY_PRODUCT_STORES_UPDATED](state, payload) { + state.current.productStores = payload + }, } export default mutations; \ No newline at end of file diff --git a/src/store/modules/util/UtilState.ts b/src/store/modules/util/UtilState.ts index 119957e9..e122e802 100644 --- a/src/store/modules/util/UtilState.ts +++ b/src/store/modules/util/UtilState.ts @@ -2,7 +2,11 @@ export default interface UtilState { calendars: any[]; facilityTypes: object; locationTypes: object; + countries: any[]; + states: any; externalMappingTypes: object; productStores: any[]; partyRoles: any[]; + countries: any[]; + states: any; } \ No newline at end of file diff --git a/src/store/modules/util/actions.ts b/src/store/modules/util/actions.ts index 3a033c6b..b45136de 100644 --- a/src/store/modules/util/actions.ts +++ b/src/store/modules/util/actions.ts @@ -47,14 +47,14 @@ const actions: ActionTree = { viewSize: 100, noConditionFind: 'Y', entityName: 'FacilityType', - fieldList: ['facilityTypeId', 'description'] + fieldList: ['facilityTypeId', 'description', 'parentTypeId'] } as any try { const resp = await UtilService.fetchFacilityTypes(params) if (!hasError(resp)) { facilityTypes = resp.data.docs.reduce((facilityType: any, type: any) => { - facilityType[type.facilityTypeId] = type.description + facilityType[type.facilityTypeId] = { description: type.description, parentTypeId: type.parentTypeId } return facilityType }, {}) @@ -228,12 +228,75 @@ const actions: ActionTree = { commit(types.UTIL_CALENDARS_UPDATED, calendars) }, + async fetchCountries({ commit, dispatch }, payload) { + let countries = [] as any + + const params = { + inputFields: { + geoIdTo: "DBIC" + }, + entityName: 'GeoAssocAndGeoFrom', + fieldList: ['geoName', 'geoId'], + noConditionFind: 'Y', + } as any + + try { + const resp = await UtilService.fetchCountries(params) + + if(!hasError(resp)) { + countries = resp.data.docs + dispatch('fetchStates', { geoId: payload.countryGeoId ? payload.countryGeoId : 'USA'}) + } else { + throw resp.data + } + } catch(err) { + logger.error(err) + } + + commit(types.UTIL_COUNTRIES_UPDATED, countries) + }, + + async fetchStates({ commit, state }, payload) { + if(payload.geoId in state.states){ + commit(types.UTIL_STATES_UPDATED, { countryGeoId: payload.geoId, states: state.states[payload.geoId] }) + return; + } + let states = [] as any + + const params = { + inputFields: { + geoIdFrom: payload.geoId + }, + entityName: 'GeoAssocAndGeoTo', + fieldList: ['geoName', 'geoId'], + noConditionFind: 'Y', + viewSize: 100 + } as any + + try { + const resp = await UtilService.fetchStates(params) + + if(!hasError(resp)) { + states = resp.data.docs + + } else { + throw resp.data + } + } catch(err) { + logger.error(err) + } + + commit(types.UTIL_STATES_UPDATED, { countryGeoId: payload.geoId, states }) + }, + clearUtilState({ commit }) { commit(types.UTIL_PRODUCT_STORES_UPDATED, []) - commit(types.UTIL_FACILITY_TYPES_UPDATED, {}) + commit(types.UTIL_FACILITY_TYPES_UPDATED, []) + commit(types.UTIL_COUNTRIES_UPDATED, []) + commit(types.UTIL_STATES_UPDATED, {}) commit(types.UTIL_LOCATION_TYPES_UPDATED, {}) commit(types.UTIL_EXTERNAL_MAPPING_TYPES_UPDATED, {}) - } + }, } export default actions; \ No newline at end of file diff --git a/src/store/modules/util/getters.ts b/src/store/modules/util/getters.ts index ebb89758..e1ceb958 100644 --- a/src/store/modules/util/getters.ts +++ b/src/store/modules/util/getters.ts @@ -20,6 +20,15 @@ const getters: GetterTree = { }, getExternalMappingTypes(state) { return state.externalMappingTypes + }, + getProductStore: (state) => (productStoreId: string) => { + return state.productStores.find((store: any) => store.productStoreId === productStoreId) + }, + getCountries(state) { + return state.countries + }, + getStates(state) { + return state.states } } export default getters; \ No newline at end of file diff --git a/src/store/modules/util/index.ts b/src/store/modules/util/index.ts index 47c4761e..7a93a224 100644 --- a/src/store/modules/util/index.ts +++ b/src/store/modules/util/index.ts @@ -13,7 +13,9 @@ const utilModule: Module = { productStores: [], facilityTypes: {}, locationTypes: {}, - externalMappingTypes: {} + externalMappingTypes: {}, + countries: [], + states: {} }, getters, actions, diff --git a/src/store/modules/util/mutation-types.ts b/src/store/modules/util/mutation-types.ts index 9d174179..25daa052 100644 --- a/src/store/modules/util/mutation-types.ts +++ b/src/store/modules/util/mutation-types.ts @@ -3,5 +3,7 @@ export const UTIL_CALENDARS_UPDATED = SN_UTIL + '/CALENDARS_UPDATED' export const UTIL_PRODUCT_STORES_UPDATED = SN_UTIL + '/PRODUCT_STORES_UPDATED' export const UTIL_FACILITY_TYPES_UPDATED = SN_UTIL + '/FACILITY_TYPES_UPDATED' export const UTIL_LOCATION_TYPES_UPDATED = SN_UTIL + '/LOCATION_TYPES_UPDATED' +export const UTIL_COUNTRIES_UPDATED = SN_UTIL + '/COUNTRIES_UPDATED' export const UTIL_EXTERNAL_MAPPING_TYPES_UPDATED = SN_UTIL + '/EXTERNAL_MAPPING_TYPES_UPDATED' export const UTIL_PARTY_ROLES_UPDATED = SN_UTIL + '/PARTY_ROLES_UPDATED' +export const UTIL_STATES_UPDATED = SN_UTIL + '/STATES_UPDATED' diff --git a/src/store/modules/util/mutations.ts b/src/store/modules/util/mutations.ts index ac177d83..f2374282 100644 --- a/src/store/modules/util/mutations.ts +++ b/src/store/modules/util/mutations.ts @@ -15,11 +15,23 @@ const mutations: MutationTree = { [types.UTIL_LOCATION_TYPES_UPDATED](state, payload) { state.locationTypes = payload }, + [types.UTIL_COUNTRIES_UPDATED](state, payload) { + state.countries = payload + }, + [types.UTIL_STATES_UPDATED](state, payload) { + state.states[payload.countryGeoId] = payload.states + }, [types.UTIL_EXTERNAL_MAPPING_TYPES_UPDATED](state, payload) { state.externalMappingTypes = payload }, [types.UTIL_PARTY_ROLES_UPDATED](state, payload) { state.partyRoles = payload + }, + [types.UTIL_COUNTRIES_UPDATED](state, payload) { + state.countries = payload + }, + [types.UTIL_STATES_UPDATED](state, payload) { + state.states[payload.countryGeoId] = payload.states } } export default mutations; \ No newline at end of file diff --git a/src/utils/index.ts b/src/utils/index.ts index 2ebc61d5..b0da7257 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -40,4 +40,10 @@ const copyToClipboard = async (value: string, text?: string) => { }); } -export { copyToClipboard, showToast } +const isValidPassword = (password : string) => { + // Regular expression pattern for a valid password + const passwordPattern = /^.*(?=.{5,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#$%^&*]).*$/; + return passwordPattern.test(password); +} + +export { copyToClipboard, isValidPassword, showToast } diff --git a/src/views/AddFacilityAddress.vue b/src/views/AddFacilityAddress.vue new file mode 100644 index 00000000..997f267a --- /dev/null +++ b/src/views/AddFacilityAddress.vue @@ -0,0 +1,255 @@ + + + + + + {{ translate("Add Store Address") }} + + + + + + + {{ translate('Address') }} + + + + + {{ translate('Address line 1') }} * + + + + + + {{ translate('Address line 2') }} + + + + + + {{ translate('City') }} * + + + + + + {{ translate('Zipcode') }} + + + + + + {{ translate('Country') }} + + + + {{ country.geoName }} + + + + + + {{ translate('State') }} + + + + {{ state.geoName }} + + + + + + + + + {{ translate('Latitude & Longitude') }} + + + + + + + {{ translate('Generate') }} + + + + + {{ translate('Latitude') }} + + + + + + {{ translate('Longitude') }} + + + + + + + + + {{ translate("Save address") }} + + + {{ translate("Add address later") }} + + + + + + + + + + \ No newline at end of file diff --git a/src/views/AddFacilityConfig.vue b/src/views/AddFacilityConfig.vue new file mode 100644 index 00000000..153c0e09 --- /dev/null +++ b/src/views/AddFacilityConfig.vue @@ -0,0 +1,444 @@ + + + + + + {{ translate("Add Store Configuration") }} + + + + + + + + {{ translate("Product Stores") }} + + + + {{ translate("Add") }} + + + + + + + {{ getProductStore(store.productStoreId)?.storeName }} + + + {{ translate("primary store") }} + + + + + + + + + + {{ getProductStore(store.productStoreId).storeName }} + + {{ translate("Primary") }} + + + + {{ translate("Unlink") }} + + + + + + + + + + {{ translate("No product stores added.") }} + + + + + + + {{ translate("Fulfillment Settings") }} + + + + + {{ translate("Sell Inventory Online") }} + + + + {{ translate("Uses native fulfillment app") }} + + + + {{ translate("Allow pickup") }} + + + + {{ translate("Create login credentials") }} + + + + + {{ translate('Password') }} * + + + + {{ translate('Password should be at least 5 characters long, it contains at least one number, one alphabet and one special character.') }} + + + + + + + + + {{ translate("Save configurations") }} + + + {{ translate("Configure settings later") }} + + + + + + + + + + \ No newline at end of file diff --git a/src/views/CreateFacility.vue b/src/views/CreateFacility.vue new file mode 100644 index 00000000..a107527c --- /dev/null +++ b/src/views/CreateFacility.vue @@ -0,0 +1,208 @@ + + + + + + {{ translate("Add Store") }} + + + + + + + {{ translate('Setup Store') }} + + + + {{ translate("Type") }} + + + {{ type.description }} + + + + + + {{ translate('Name') }} * + + + + + + {{ translate('Internal ID') }} + + + + + + {{ translate('External ID') }} + + + + + + + + + + {{ translate("Create store") }} + + + + + + + + + + \ No newline at end of file diff --git a/src/views/FacilityDetails.vue b/src/views/FacilityDetails.vue index a17737e1..b47244f3 100644 --- a/src/views/FacilityDetails.vue +++ b/src/views/FacilityDetails.vue @@ -23,16 +23,18 @@ {{ translate("Address") }} - - - {{ "Address line 1" }} - {{ "Address line 2" }} - {{ "City," }} {{ "Zipcode" }} - {{ "State," }} {{ "Country" }} - - - {{ translate("Edit") }} - + + + + {{ postalAddress.address1 }} + {{ postalAddress.address2 }} + {{ postalAddress.postalCode ? `${postalAddress.city}, ${postalAddress.postalCode}` : postalAddress.city }} + {{ postalAddress.countryGeoName ? `${postalAddress.stateGeoName}, ${postalAddress.countryGeoName}` : postalAddress.stateGeoName }} + + + {{ translate("Edit") }} + + {{ translate("Add") }} @@ -47,16 +49,18 @@ {{ translate("These values are used to help customers lookup how close they are to your stores when they are finding nearby stores.") }} - - {{ translate("Latitude") }} - {{ "" }} - - - {{ translate("Longitude") }} - {{ "" }} - - {{ translate("Edit") }} - + + + {{ translate("Latitude") }} + {{ postalAddress.latitude }} + + + {{ translate("Longitude") }} + {{ postalAddress.longitude }} + + {{ translate("Edit") }} + + {{ translate("Add") }} @@ -158,27 +162,17 @@ {{ translate("Product Stores") }} - + {{ translate("Add") }} - - - - {{ "NotNaked" }} - - {{ translate("primary store") }} - - - - - - + - {{ "Wasatch Ski company" }} + {{ getProductStore(store.productStoreId)?.storeName }} - + {{ translate("primary store") }} + @@ -447,9 +441,9 @@ import { import { translate } from '@hotwax/dxp-components'; import FacilityMappingPopover from '@/components/FacilityMappingPopover.vue' import LocationDetailsPopover from '@/components/LocationDetailsPopover.vue'; -import OpenStorePopover from '@/components/OpenStorePopover.vue'; -import AddAddressModal from '@/components/AddAddressModal.vue' -import AddGeoPointModal from '@/components/AddGeoPointModal.vue'; +import FacilityAddressModal from '@/components/FacilityAddressModal.vue' +import FacilityGeoPointModal from '@/components/FacilityGeoPointModal.vue'; +import ProductStorePopover from '@/components/ProductStorePopover.vue'; import SelectProductStoreModal from '@/components/SelectProductStoreModal.vue' import AddOperatingHoursModal from '@/components/AddOperatingHoursModal.vue' import AddLocationModal from '@/components/AddLocationModal.vue'; @@ -502,31 +496,34 @@ export default defineComponent({ isLoading: true, // shows whether the facility information fetching is completed or not segment: 'external-mappings', defaultDaysToShip: '', // not assinging 0 by default as it will convey the user that the facility can ship same day(as the value is 0), but actually defaultDays are not setup on the facility + primaryMember: {} as any, isCalendarFound: true, selectedCalendarId: 'DEFAULT' } }, computed: { ...mapGetters({ - current: 'facility/getCurrent', calendars: 'util/getCalendars', - locationTypes: 'util/getLocationTypes', + current: 'facility/getCurrent', externalMappingTypes: 'util/getExternalMappingTypes', facilityCalendar: 'facility/getFacilityCalendar', facilityParties: 'facility/getFacilityParties', + facilityProductStores: 'facility/getFacilityProductStores', + getProductStore: 'util/getProductStore', + locationTypes: 'util/getLocationTypes', partyRoles: 'util/getPartyRoles', - userProfile: 'user/getUserProfile' + productStores: 'util/getProductStores', + postalAddress: 'facility/getPostalAddress', + userProfile: 'user/getUserProfile', }) }, props: ["facilityId"], async ionViewWillEnter() { await Promise.all([this.store.dispatch('facility/fetchCurrentFacility', { facilityId: this.facilityId }), this.store.dispatch('util/fetchExternalMappingTypes'), this.store.dispatch('util/fetchLocationTypes'), this.store.dispatch('util/fetchPartyRoles')]) - await Promise.all([this.store.dispatch('facility/fetchFacilityLocations', { facilityId: this.facilityId }), this.store.dispatch('facility/getFacilityParties', { facilityId: this.facilityId }), this.store.dispatch('facility/fetchFacilityMappings', { facilityId: this.facilityId, facilityIdenTypeIds: Object.keys(this.externalMappingTypes)}), this.store.dispatch('facility/fetchShopifyFacilityMappings', { facilityId: this.facilityId })]) - await this.store.dispatch('util/fetchUtilCalendars', { facilityId: this.facilityId }) - await this.store.dispatch('facility/fetchFacilityCalendar', { facilityId: this.facilityId }) + await Promise.all([this.store.dispatch('facility/fetchFacilityLocations', { facilityId: this.facilityId }), this.store.dispatch('facility/getFacilityParties', { facilityId: this.facilityId }), this.store.dispatch('facility/fetchFacilityMappings', { facilityId: this.facilityId, facilityIdenTypeIds: Object.keys(this.externalMappingTypes)}), this.store.dispatch('facility/fetchShopifyFacilityMappings', { facilityId: this.facilityId }), this.store.dispatch('facility/getFacilityProductStores', { facilityId: this.facilityId }), this.store.dispatch('util/fetchProductStores'), this.store.dispatch('facility/fetchFacilityContactDetails', { facilityId: this.facilityId }), this.store.dispatch('util/fetchUtilCalendars', { facilityId: this.facilityId }), this.store.dispatch('facility/fetchFacilityCalendar', { facilityId: this.facilityId })]) this.defaultDaysToShip = this.current.defaultDaysToShip this.isLoading = false - + this.fetchFacilityPrimaryMember() }, methods: { goToLink(link: string) { @@ -534,12 +531,22 @@ export default defineComponent({ // opening link in new tab without passing any reference window.open(url, '_blank', 'noopener, noreferrer') }, - async openStorePopover(ev: Event) { + async productStorePopover(ev: Event, store: any) { const popover = await popoverController.create({ - component: OpenStorePopover, + component: ProductStorePopover, + componentProps: { + currentProductStore: store, + facilityId: this.facilityId, + primaryMember: this.primaryMember + }, event: ev, showBackdrop: false }); + + popover.onDidDismiss().then(async() => { + await this.fetchFacilityPrimaryMember() + }) + return popover.present() }, async associateCalendarToFacility() { @@ -564,12 +571,13 @@ export default defineComponent({ logger.error(err) } }, - async addAddress() { - const addAddressModal = await modalController.create({ - component: AddAddressModal + async openAddressModal() { + const addressModal = await modalController.create({ + component: FacilityAddressModal, + componentProps: { facilityId: this.facilityId } }) - addAddressModal.present() + addressModal.present() }, async addCustomSchedule() { const customScheduleModal = await modalController.create({ @@ -579,19 +587,61 @@ export default defineComponent({ customScheduleModal.present() }, - async addGeoPoint() { - const addGeoPointModal = await modalController.create({ - component: AddGeoPointModal + async openGeoPointModal() { + const geoPointModal = await modalController.create({ + component: FacilityGeoPointModal, + componentProps: { facilityId: this.facilityId } }) - addGeoPointModal.present() + geoPointModal.present() }, - async addProductStore() { - const addProductStoreModal = await modalController.create({ - component: SelectProductStoreModal + async selectProductStores() { + const selectProductStoreModal = await modalController.create({ + component: SelectProductStoreModal, + componentProps: { facilityId: this.facilityId, selectedProductStores: this.facilityProductStores } }) - addProductStoreModal.present() + selectProductStoreModal.onDidDismiss().then(async(result: any) => { + if (result.data && result.data.value) { + const productStoresToCreate = result.data.value.productStoresToCreate + const productStoresToRemove = result.data.value.productStoresToRemove + + const updateResponses = await Promise.allSettled(productStoresToRemove + .map(async (payload: any) => await FacilityService.updateProductStoreFacility({ + facilityId: this.facilityId, + fromDate: this.facilityProductStores.find((store: any) => payload.productStoreId === store.productStoreId).fromDate, + productStoreId: payload.productStoreId, + thruDate: DateTime.now().toMillis() + })) + ) + + const createResponses = await Promise.allSettled(productStoresToCreate + .map(async (payload: any) => await FacilityService.createProductStoreFacility({ + productStoreId: payload.productStoreId, + facilityId: this.facilityId, + fromDate: DateTime.now().toMillis(), + })) + ) + + const hasFailedResponse = [...updateResponses, ...createResponses].some((response: any) => response.status === 'rejected') + if(hasFailedResponse) { + showToast(translate("Failed to update some product stores")) + } else { + productStoresToRemove.map((store: any) => { + if(store.productStoreId === this.primaryMember.facilityGroupId) { + this.revokePrimaryStatusFromStore() + } + }) + showToast(translate("Product stores updated successfully.")) + } + + // refetching product stores with updated roles and primary Member + await this.store.dispatch('facility/getFacilityProductStores', { facilityId: this.facilityId }) + await this.fetchFacilityPrimaryMember() + } + }) + + selectProductStoreModal.present() }, async addLocationModal() { const addLocationModal = await modalController.create({ @@ -721,6 +771,7 @@ export default defineComponent({ if(!hasError(resp)) { showToast(translate('Fulfillment setting updated successfully')) + this.store.dispatch('facility/fetchFacilityAdditionalInformation') } else { throw resp.data } @@ -729,6 +780,19 @@ export default defineComponent({ logger.error('Failed to update fulfillment setting', err) } }, + async revokePrimaryStatusFromStore() { + let resp; + try { + resp = await FacilityService.updateFacilityToGroup({ + "facilityId": this.facilityId, + "facilityGroupId": this.primaryMember.facilityGroupId, + "fromDate": this.primaryMember.fromDate, + "thruDate": DateTime.now().toMillis() + }) + } catch (err) { + logger.error(err) + } + }, async updateFulfillmentSetting(event: any, facilityGroupId: string) { event.stopImmediatePropagation(); @@ -756,6 +820,7 @@ export default defineComponent({ if (!hasError(resp)) { showToast(translate('Fulfillment setting updated successfully')) + this.store.dispatch('facility/fetchFacilityAdditionalInformation') } else { throw resp.data } @@ -783,6 +848,31 @@ export default defineComponent({ showToast(translate('Failed to update default days to ship')) } }, + async fetchFacilityPrimaryMember() { + let primaryMember = {} + const payload = { + inputFields: { + facilityId: this.facilityId, + facilityGroupTypeId: 'FEATURING' + }, + entityName: 'FacilityGroupAndMember', + filterByDate: 'Y', + viewSize: 1, + } + + try { + const resp = await FacilityService.fetchFacilityPrimaryMember(payload) + + if(!hasError(resp)) { + primaryMember = resp.data.docs[0] + } else { + throw resp.data + } + } catch(err) { + logger.error(err) + } + this.primaryMember = primaryMember + }, async removeFacilityMapping(mapping: any) { try { const payload = { diff --git a/src/views/FindFacilities.vue b/src/views/FindFacilities.vue index 0c53f80a..fb8f836b 100644 --- a/src/views/FindFacilities.vue +++ b/src/views/FindFacilities.vue @@ -35,7 +35,9 @@ {{ translate("Type") }} {{ translate("All") }} - {{ description }} + + {{ type.description }} + @@ -46,7 +48,7 @@ - {{ facility.facilityTypeId ? facilityTypes[facility.facilityTypeId] ? facilityTypes[facility.facilityTypeId] : facilityTypes.facilityTypeId : '' }} + {{ facility.facilityTypeId ? facilityTypes[facility.facilityTypeId] ? facilityTypes[facility.facilityTypeId].description : facilityTypes.facilityTypeId : '' }} {{ facility.facilityName }} {{ facility.facilityId }} @@ -82,6 +84,20 @@ + + + + + + + + + + + + + +
{{ "STORE_ID" }}
{{ productStore.productStoreId }}
{{ $t("Fetching TimeZones")}}
{{ translate("Fetching TimeZones")}}
{{ $t("No time zone found")}}
{{ translate("No time zone found")}}
{{ translate("No product stores added.") }}
{{ "City," }} {{ "Zipcode" }}
{{ "State," }} {{ "Country" }}
{{ postalAddress.postalCode ? `${postalAddress.city}, ${postalAddress.postalCode}` : postalAddress.city }}
{{ postalAddress.countryGeoName ? `${postalAddress.stateGeoName}, ${postalAddress.countryGeoName}` : postalAddress.stateGeoName }}
{{ "" }}
{{ postalAddress.latitude }}
{{ postalAddress.longitude }}
{{ facility.facilityTypeId ? facilityTypes[facility.facilityTypeId] ? facilityTypes[facility.facilityTypeId] : facilityTypes.facilityTypeId : '' }}
{{ facility.facilityTypeId ? facilityTypes[facility.facilityTypeId] ? facilityTypes[facility.facilityTypeId].description : facilityTypes.facilityTypeId : '' }}
{{ facility.facilityId }}