From 449c250eaf160b6b090335ca903f9086a55021c6 Mon Sep 17 00:00:00 2001
From: R-Sourabh
Date: Fri, 24 May 2024 20:59:50 +0530
Subject: [PATCH 01/21] Implemented: New component 'Scheduled Restock' and
created basic UI with routing(#285)
---
src/components/Menu.vue | 4 +
src/router/index.ts | 7 ++
src/views/ScheduledRestock.vue | 153 +++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+)
create mode 100644 src/views/ScheduledRestock.vue
diff --git a/src/components/Menu.vue b/src/components/Menu.vue
index e4c25814..8041a148 100644
--- a/src/components/Menu.vue
+++ b/src/components/Menu.vue
@@ -91,6 +91,10 @@ export default defineComponent({
iosIcon: albumsOutline,
mdIcon: albumsOutline
},
+ {
+ title: "Scheduled restock",
+ url: "/scheduled-restock",
+ },
{
title: "Purchase order",
url: "/purchase-order",
diff --git a/src/router/index.ts b/src/router/index.ts
index ad4bc2ad..52ab4664 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -6,6 +6,7 @@ import InventoryReview from '@/views/InventoryReview.vue'
import PurchaseOrderReview from '@/views/PurchaseOrderReview.vue';
import SavedMappings from '@/views/SavedMappings.vue'
import Settings from "@/views/Settings.vue"
+import ScheduledRestock from "@/views/ScheduledRestock.vue";
import store from '@/store'
import MappingDetail from '@/views/MappingDetail.vue'
import { DxpLogin, translate, useAuthStore } from '@hotwax/dxp-components';
@@ -66,6 +67,12 @@ const routes: Array = [
permissionId: "APP_INVENTORY_VIEW"
}
},
+ {
+ path: '/scheduled-restock',
+ name: 'ScheduledRestock',
+ component: ScheduledRestock,
+ // beforeEnter: authGuard
+ },
{
path: '/inventory-review',
name: 'InventoryDetail',
diff --git a/src/views/ScheduledRestock.vue b/src/views/ScheduledRestock.vue
new file mode 100644
index 00000000..46ee2f1a
--- /dev/null
+++ b/src/views/ScheduledRestock.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+ {{ translate("Scheduled Restock") }}
+
+
+
+
+
+
+ Restock
+ {{ }}
+
+
+
+
+
+ {{ translate("Saved mappings") }}
+
+
+
+ {{ translate("New mapping") }}
+
+
+ Netsuite
+
+
+ Fishbowl
+
+
+
+
+
+ {{ translate("Select the column index for the following information in the uploaded CSV.") }}
+
+ Required
+
+
+
+ {{ }}
+
+
+
+
+ {{ }}
+
+
+
+
+ {{ }}
+
+
+
+
+ Optional, or select during review
+
+
+ Schedule
+ 10:00AM 17TH MARCH 2024
+
+
+
+ {{ }}
+
+
+
+
+
+
+
+
+ {{ translate("Review") }}
+
+
+
+
+ Scheduled Restock
+
+
+ job id
+ jobname
+ inbound
+
+ 10:00AM 17TH MARCH 2024
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 39ae0708db6981a762273044cba845cf79465d75 Mon Sep 17 00:00:00 2001
From: R-Sourabh
Date: Mon, 27 May 2024 15:28:18 +0530
Subject: [PATCH 02/21] Implemented: Scheduled restock page and Restock review
page UI(#285)
---
src/components/Menu.vue | 8 +-
src/components/ScheduledRestockPopover.vue | 44 ++++++
src/router/index.ts | 15 ++-
src/views/ScheduledRestock.vue | 81 +++++++-----
src/views/ScheduledRestockReview.vue | 147 +++++++++++++++++++++
5 files changed, 255 insertions(+), 40 deletions(-)
create mode 100644 src/components/ScheduledRestockPopover.vue
create mode 100644 src/views/ScheduledRestockReview.vue
diff --git a/src/components/Menu.vue b/src/components/Menu.vue
index 8041a148..24697b3f 100644
--- a/src/components/Menu.vue
+++ b/src/components/Menu.vue
@@ -52,7 +52,7 @@ import {
} from "@ionic/vue";
import { computed, defineComponent } from "vue";
import { mapGetters } from "vuex";
-import { albumsOutline, bookmarkOutline, settings, calendar } from "ionicons/icons";
+import { albumsOutline, bookmarkOutline, settings, calendar, timerOutline } from "ionicons/icons";
import { useStore } from "@/store";
import { useRouter } from "vue-router";
import { translate } from '@hotwax/dxp-components'
@@ -94,6 +94,9 @@ export default defineComponent({
{
title: "Scheduled restock",
url: "/scheduled-restock",
+ childRoutes: ["/scheduled-restock-review"],
+ iosIcon: timerOutline,
+ mdIcon: timerOutline
},
{
title: "Purchase order",
@@ -129,7 +132,8 @@ export default defineComponent({
calendar,
settings,
store,
- translate
+ translate,
+ timerOutline
};
}
});
diff --git a/src/components/ScheduledRestockPopover.vue b/src/components/ScheduledRestockPopover.vue
new file mode 100644
index 00000000..fbc2d51b
--- /dev/null
+++ b/src/components/ScheduledRestockPopover.vue
@@ -0,0 +1,44 @@
+
+
+
+
+ jobname
+
+
+ Reschedule
+
+
+ Cancel
+
+
+ View Details
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/router/index.ts b/src/router/index.ts
index 52ab4664..a681987d 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -7,6 +7,7 @@ import PurchaseOrderReview from '@/views/PurchaseOrderReview.vue';
import SavedMappings from '@/views/SavedMappings.vue'
import Settings from "@/views/Settings.vue"
import ScheduledRestock from "@/views/ScheduledRestock.vue";
+import ScheduledRestockReview from "@/views/ScheduledRestockReview.vue"
import store from '@/store'
import MappingDetail from '@/views/MappingDetail.vue'
import { DxpLogin, translate, useAuthStore } from '@hotwax/dxp-components';
@@ -67,6 +68,12 @@ const routes: Array = [
permissionId: "APP_INVENTORY_VIEW"
}
},
+ {
+ path: '/inventory-review',
+ name: 'InventoryDetail',
+ component: InventoryReview,
+ beforeEnter: authGuard
+ },
{
path: '/scheduled-restock',
name: 'ScheduledRestock',
@@ -74,10 +81,10 @@ const routes: Array = [
// beforeEnter: authGuard
},
{
- path: '/inventory-review',
- name: 'InventoryDetail',
- component: InventoryReview,
- beforeEnter: authGuard
+ path: '/scheduled-restock-review',
+ name: 'ScheduledRestockDetail',
+ component: ScheduledRestockReview,
+ // beforeEnter: authGuard
},
{
path: '/login',
diff --git a/src/views/ScheduledRestock.vue b/src/views/ScheduledRestock.vue
index 46ee2f1a..207e0581 100644
--- a/src/views/ScheduledRestock.vue
+++ b/src/views/ScheduledRestock.vue
@@ -3,7 +3,7 @@
- {{ translate("Scheduled Restock") }}
+ Scheduled Restock
@@ -11,8 +11,8 @@
Restock
- {{ }}
-
+
+
@@ -65,12 +65,12 @@
{{ }}
-
+
-
+
{{ translate("Review") }}
@@ -81,12 +81,12 @@
job id
jobname
- inbound
+ inbound
10:00AM 17TH MARCH 2024
-
-
-
+
+
+
@@ -95,43 +95,56 @@
-
+
+
From faf16977e2ffe8f71656eb31233a20a954cda621 Mon Sep 17 00:00:00 2001
From: R-Sourabh
Date: Wed, 29 May 2024 16:46:59 +0530
Subject: [PATCH 03/21] Implemented: Scheduled Restock Functionality(#285)
---
.env.example | 3 +-
src/components/CreateMappingModal.vue | 11 +
src/components/ScheduledRestockPopover.vue | 3 -
src/services/StockService.ts | 22 ++
src/services/UtilService.ts | 11 +-
src/store/modules/stock/StockState.ts | 10 +-
src/store/modules/stock/actions.ts | 147 ++++++++-
src/store/modules/stock/getters.ts | 14 +
src/store/modules/stock/index.ts | 10 +-
src/store/modules/stock/mutation-types.ts | 6 +-
src/store/modules/stock/mutations.ts | 14 +
src/theme/variables.css | 6 +
src/views/ScheduledRestock.vue | 231 +++++++++++---
src/views/ScheduledRestockReview.vue | 355 +++++++++++++++++----
14 files changed, 728 insertions(+), 115 deletions(-)
create mode 100644 src/services/StockService.ts
diff --git a/.env.example b/.env.example
index 312d326c..79dc8526 100644
--- a/.env.example
+++ b/.env.example
@@ -5,8 +5,9 @@ VUE_APP_VIEW_SIZE=10
VUE_APP_DATE_FORMAT=MM/dd/yyyy
VUE_APP_PERMISSION_ID="IMPORT_APP_VIEW"
VUE_APP_ALIAS={}
-VUE_APP_MAPPING_TYPES={"PO": "PO_MAPPING_PREF","RSTINV": "INV_MAPPING_PREF"}
+VUE_APP_MAPPING_TYPES={"PO": "PO_MAPPING_PREF","RSTINV": "INV_MAPPING_PREF","RSTSTK": "STK_MAPPING_PREF"}
VUE_APP_MAPPING_PO={"orderId": { "label": "Order ID", "required": true }, "productSku": { "label": "Shopify product SKU", "required": true },"orderDate": { "label": "Arrival date", "required": true }, "quantity": { "label": "Ordered quantity", "required": true }, "facility": { "label": "Facility ID", "required": true }}
VUE_APP_MAPPING_RSTINV={"productIdentification": { "label": "Product Identification", "required": true }, "quantity": { "label": "Quantity", "required": true }, "facility": { "label": "Facility ID", "required": true }}
+VUE_APP_MAPPING_RSTSTK={"product": { "label": "Product", "required": true }, "facility": { "label": "Facility", "required": true }, "restockQuantity": { "label": "Restock quantity", "required": true }, "schedule": { "label": "Schedule", "required": false }, "shopifyStore": { "label": "Shopify store", "required": false }, "restockName": { "label": "Restock name", "required": false }}
VUE_APP_DEFAULT_LOG_LEVEL="error"
VUE_APP_LOGIN_URL="http://launchpad.hotwax.io/login"
\ No newline at end of file
diff --git a/src/components/CreateMappingModal.vue b/src/components/CreateMappingModal.vue
index ce5ac899..e449375d 100644
--- a/src/components/CreateMappingModal.vue
+++ b/src/components/CreateMappingModal.vue
@@ -107,6 +107,17 @@ export default defineComponent({
methods: {
getFields() {
const fields = process.env["VUE_APP_MAPPING_" + this.mappingType];
+ if (this.mappingType == 'RSTSTK') {
+ const parsedFields = fields ? JSON.parse(fields) : {};
+ const requiredFields: any = {};
+ for (const [key, value] of Object.entries(parsedFields)) {
+ if ((value as any).required == true) {
+ requiredFields[key] = value;
+ }
+ }
+ return requiredFields;
+ }
+
return fields ? JSON.parse(fields) : {};
},
closeModal() {
diff --git a/src/components/ScheduledRestockPopover.vue b/src/components/ScheduledRestockPopover.vue
index fbc2d51b..4effb876 100644
--- a/src/components/ScheduledRestockPopover.vue
+++ b/src/components/ScheduledRestockPopover.vue
@@ -10,9 +10,6 @@
Cancel
-
- View Details
-
diff --git a/src/services/StockService.ts b/src/services/StockService.ts
new file mode 100644
index 00000000..129f7db1
--- /dev/null
+++ b/src/services/StockService.ts
@@ -0,0 +1,22 @@
+import { api } from '@/adapter';
+
+const scheduleJob = async (payload: any): Promise => {
+ return api({
+ url: "scheduleService",
+ method: "post",
+ data: payload
+ });
+}
+
+const fetchJobInformation = async (payload: any): Promise => {
+ return api({
+ url: "/findJobs",
+ method: "get",
+ params: payload
+ });
+}
+
+export const StockService = {
+ scheduleJob,
+ fetchJobInformation
+}
\ No newline at end of file
diff --git a/src/services/UtilService.ts b/src/services/UtilService.ts
index 5c65c4df..24aa1b19 100644
--- a/src/services/UtilService.ts
+++ b/src/services/UtilService.ts
@@ -25,8 +25,17 @@ const fetchGoodIdentificationTypes = async (payload: any): Promise => {
})
}
+const fetchShopifyShop = async (payload: any): Promise => {
+ return api({
+ url: "/performFind",
+ method: "POST",
+ data: payload
+ })
+}
+
export const UtilService = {
fetchGoodIdentificationTypes,
+ fetchShopifyShop,
getFacilities,
- getFacilityLocations
+ getFacilityLocations,
}
\ No newline at end of file
diff --git a/src/store/modules/stock/StockState.ts b/src/store/modules/stock/StockState.ts
index fee226ff..726840d6 100644
--- a/src/store/modules/stock/StockState.ts
+++ b/src/store/modules/stock/StockState.ts
@@ -5,5 +5,13 @@ export default interface StockState {
unidentifiedItems: any,
initial: any,
},
- fileName: string
+ fileName: string,
+ restockItems: [],
+ schedule: {
+ scheduledTime: string,
+ shopId: string,
+ restockName: string
+ }
+ shopifyShops: any,
+ jobs: any
}
diff --git a/src/store/modules/stock/actions.ts b/src/store/modules/stock/actions.ts
index 324ba61f..9c64d9b6 100644
--- a/src/store/modules/stock/actions.ts
+++ b/src/store/modules/stock/actions.ts
@@ -3,6 +3,11 @@ import store from '@/store'
import RootState from '@/store/RootState'
import StockState from './StockState'
import * as types from './mutation-types'
+import { showToast } from '@/utils';
+import { hasError } from "@/adapter";
+import { StockService } from "@/services/StockService";
+import { translate } from "@hotwax/dxp-components";
+import logger from "@/logger";
const actions: ActionTree = {
async processUpdateStockItems ({ commit, rootGetters }, items) {
@@ -53,7 +58,6 @@ const actions: ActionTree = {
}).filter((item: any) => item);
const original = JSON.parse(JSON.stringify(items));
-
commit(types.STOCK_ITEMS_UPDATED, { parsed, original, initial });
this.dispatch('util/updateFileProcessingStatus', false);
},
@@ -63,6 +67,146 @@ const actions: ActionTree = {
clearStockItems({ commit }){
commit(types.STOCK_ITEMS_UPDATED, { parsed: [], original: []});
},
+ async processUpdateRestockItems({ commit }, items) {
+
+ const productIds = items.filter((item: any) => item.product).map((item: any) => item.product);
+
+ const payload = {
+ productIds,
+ identificationTypeId: items[0]?.identificationTypeId
+ };
+
+ const externalFacilityIds = [...new Set(items.map((item: any) => item.externalFacilityId))];
+ const facilities = await store.dispatch('util/fetchFacilities');
+ const facilityMapping = facilities.reduce((facilityMapping: any, facility: any) => {
+ if (facility.externalId) facilityMapping[facility.externalId] = facility.facilityId;
+ return facilityMapping;
+ }, {});
+ const facilityIds = externalFacilityIds.map((externalFacilityId: any) => facilityMapping[externalFacilityId]).filter((facilityId: any) => facilityId);
+ const cachedProducts = await store.dispatch("product/fetchProducts", payload);
+
+ const initial = items.map((item: any) => {
+ const product = cachedProducts[item.product];
+
+ if (product) {
+ item.parentProductId = product?.parent?.id;
+ item.pseudoId = product.pseudoId;
+ item.parentProductName = product?.parent?.productName;
+ item.productId = product.productId
+ item.imageUrl = product.images?.mainImageUrl;
+ item.isSelected = true;
+ return item;
+ }
+ return;
+ }).filter((item: any) => item);
+
+ commit(types.STOCK_SCHEDULE_ITEMS_UPDATED, initial );
+ },
+ clearRetockItems({ commit }) {
+ commit(types.STOCK_SCHEDULE_ITEMS_UPDATED, []);
+ },
+ async scheduledStock({ commit }, payload) {
+ commit(types.STOCK_SCHEDULED_INFORMATION, payload)
+ },
+
+ async shopifyShop({ commit }, payload) {
+ commit(types.STOCK_SHOPIFY_SHOPS_UPDATED, payload)
+ },
+
+ async scheduleService({ commit }, params) {
+ let resp;
+
+ const job = params.job
+
+ const payload = {
+ 'JOB_NAME': job.jobName,
+ 'SERVICE_NAME': job.serviceName,
+ 'SERVICE_COUNT': '0',
+ 'SERVICE_TEMP_EXPR': job.jobStatus,
+ 'SERVICE_RUN_AS_SYSTEM':'Y',
+ 'jobFields': {
+ 'systemJobEnumId': job.systemJobEnumId,
+ 'tempExprId': job.jobStatus, // Need to remove this as we are passing frequency in SERVICE_TEMP_EXPR, currently kept it for backward compatibility
+ 'maxRecurrenceCount': '-1',
+ 'parentJobId': job.parentJobId,
+ 'runAsUser': 'system', //default system, but empty in run now. TODO Need to remove this as we are using SERVICE_RUN_AS_SYSTEM, currently kept it for backward compatibility
+ 'recurrenceTimeZone': this.state.user.current.userTimeZone,
+ 'createdByUserLogin': this.state.user.current.userLoginId,
+ 'lastModifiedByUserLogin': this.state.user.current.userLoginId,
+ },
+ 'statusId': "SERVICE_PENDING",
+ 'systemJobEnumId': job.systemJobEnumId,
+ ...params.jobCustomParameters
+ }
+
+
+ const jobRunTimeDataKeys = job?.runtimeData ? Object.keys(job?.runtimeData) : [];
+ if (jobRunTimeDataKeys.includes('shopifyConfigId') || jobRunTimeDataKeys.includes('shopId')) {
+ const shopifyConfig = this.state.user.currentShopifyConfig
+ if (Object.keys(shopifyConfig).length == 0) {
+ showToast(translate('Shopify configuration not found. Scheduling failed.'))
+ return;
+ }
+
+ jobRunTimeDataKeys.includes('shopifyConfigId') && (payload['shopifyConfigId'] = shopifyConfig?.shopifyConfigId);
+ jobRunTimeDataKeys.includes('shopId') && (payload['shopId'] = shopifyConfig?.shopId);
+ payload['jobFields']['shopId'] = shopifyConfig?.shopId;
+ }
+
+ job?.priority && (payload['SERVICE_PRIORITY'] = job.priority.toString())
+ job?.runTime && (payload['SERVICE_TIME'] = job.runTime.toString())
+ job?.sinceId && (payload['sinceId'] = job.sinceId)
+
+ try {
+ resp = await StockService.scheduleJob({ ...payload });
+ if (resp.status == 200 && !hasError(resp)) {
+ showToast(translate('Service has been scheduled'));
+ await store.dispatch('fetchJobs', {
+ inputFields: {
+ 'systemJobEnumId': payload.systemJobEnumId,
+ 'systemJobEnumId_op': 'equals',
+ },
+ orderBy: "runTime ASC"
+ })
+ } else {
+ showToast(translate('Something went wrong'))
+ }
+ } catch (err) {
+ showToast(translate('Something went wrong'))
+ logger.error(err)
+ }
+ return {};
+ },
+
+ async fetchJobs ({ commit }) {
+ let resp;
+
+ try{
+ const params = {
+ "inputFields": {
+ "statusId": "SERVICE_PENDING",
+ 'systemJobEnumId': "JOB_BKR_ORD",
+ 'systemJobEnumId_op': 'equals',
+ 'orderBy': 'runTime ASC',
+ 'tempExprId_op': 'not-empty'
+ },
+ "noConditionFind": "Y",
+ "viewSize": 50
+ } as any
+
+ resp = await StockService.fetchJobInformation(params)
+
+ if(!hasError(resp) && resp.data.count > 0) {
+ const jobs = resp.data.docs
+ commit(types.STOCK_JOBS_UPDATED, jobs);
+ } else {
+ commit(types.STOCK_JOBS_UPDATED, []);
+ }
+ } catch(error) {
+ logger.error(error);
+ }
+ return resp
+ },
async updateMissingFacilities({ state }, facilityMapping){
const facilityLocations = await this.dispatch('util/fetchFacilityLocations', Object.values(facilityMapping));
Object.keys(facilityMapping).map((facilityId: any) => {
@@ -78,4 +222,5 @@ const actions: ActionTree = {
this.dispatch('stock/updateStockItems', state.items);
}
}
+
export default actions;
diff --git a/src/store/modules/stock/getters.ts b/src/store/modules/stock/getters.ts
index 81c0c5b7..d0bfee0d 100644
--- a/src/store/modules/stock/getters.ts
+++ b/src/store/modules/stock/getters.ts
@@ -6,5 +6,19 @@ const getters: GetterTree = {
getStockItems(state) {
return JSON.parse(JSON.stringify(state.items));
},
+ getRestockItems(state) {
+ return JSON.parse(JSON.stringify(state.restockItems))
+ },
+ getScheduledInformation(state) {
+ return state.schedule
+ },
+ getShopifyShops(state) {
+ return state.shopifyShops
+ },
+ getScheduledJobs(state) {
+ return state.jobs
+ }
+
+
};
export default getters;
\ No newline at end of file
diff --git a/src/store/modules/stock/index.ts b/src/store/modules/stock/index.ts
index 60be7fe3..57c997bf 100644
--- a/src/store/modules/stock/index.ts
+++ b/src/store/modules/stock/index.ts
@@ -14,7 +14,15 @@ const orderModule: Module = {
unidentifiedItems: [],
initial: []
},
- fileName: ""
+ fileName: "",
+ restockItems: [],
+ schedule: {
+ scheduledTime: "",
+ shopId: "",
+ restockName: ""
+ },
+ shopifyShops: [],
+ jobs: {}
},
actions,
getters,
diff --git a/src/store/modules/stock/mutation-types.ts b/src/store/modules/stock/mutation-types.ts
index 91e0c1a6..2ec43ce2 100644
--- a/src/store/modules/stock/mutation-types.ts
+++ b/src/store/modules/stock/mutation-types.ts
@@ -1,2 +1,6 @@
export const SN_STOCK = 'stock'
-export const STOCK_ITEMS_UPDATED = SN_STOCK + '/ITEMS_UPDATED'
\ No newline at end of file
+export const STOCK_ITEMS_UPDATED = SN_STOCK + '/ITEMS_UPDATED'
+export const STOCK_SCHEDULE_ITEMS_UPDATED = SN_STOCK + '/SCHEDULE_ITEMS_UPDATED'
+export const STOCK_SCHEDULED_INFORMATION = SN_STOCK + '/SCHEDULED_INFORMATION'
+export const STOCK_SHOPIFY_SHOPS_UPDATED = SN_STOCK + '/SHOPIFY_SHOPS_UPDATED'
+export const STOCK_JOBS_UPDATED = SN_STOCK + '/JOBS_UPDATED'
diff --git a/src/store/modules/stock/mutations.ts b/src/store/modules/stock/mutations.ts
index 7cf5fd83..35a46c11 100644
--- a/src/store/modules/stock/mutations.ts
+++ b/src/store/modules/stock/mutations.ts
@@ -8,6 +8,20 @@ const mutations: MutationTree = {
state.items.original = payload.original;
state.items.unidentifiedItems = payload.unidentifiedItems;
state.items.initial = payload.initial;
+ },
+ [types.STOCK_SCHEDULE_ITEMS_UPDATED] (state, payload) {
+ state.restockItems = payload;
+ },
+ [types.STOCK_SCHEDULED_INFORMATION] (state, payload) {
+ state.schedule.scheduledTime = payload.scheduledTime;
+ state.schedule.shopId = payload.shopId;
+ state.schedule.restockName = payload.restockName;
+ },
+ [types.STOCK_SHOPIFY_SHOPS_UPDATED] (state, payload) {
+ state.shopifyShops = payload
+ },
+ [types.STOCK_JOBS_UPDATED] (state, payload) {
+ state.jobs = payload
}
}
export default mutations;
\ No newline at end of file
diff --git a/src/theme/variables.css b/src/theme/variables.css
index bc8f0ef9..2bf57ac1 100644
--- a/src/theme/variables.css
+++ b/src/theme/variables.css
@@ -281,4 +281,10 @@ http://ionicframework.com/docs/theming/ */
.mobile-only {
display: none;
}
+}
+
+.date-time-modal {
+ --width: 320px;
+ --height: 385px;
+ --border-radius: 8px;
}
\ No newline at end of file
diff --git a/src/views/ScheduledRestock.vue b/src/views/ScheduledRestock.vue
index 207e0581..42244d59 100644
--- a/src/views/ScheduledRestock.vue
+++ b/src/views/ScheduledRestock.vue
@@ -11,23 +11,20 @@
Restock
-
-
+ {{ file.name }}
+
{{ translate("Saved mappings") }}
-
+
{{ translate("New mapping") }}
-
- Netsuite
-
-
- Fishbowl
+
+ {{ mapping.name }}
@@ -37,53 +34,60 @@
Required
-
-
- {{ }}
-
-
-
-
- {{ }}
-
-
-
-
- {{ }}
-
-
+
+
+
+
+ {{ prop }}
+
+
+
Optional, or select during review
Schedule
- 10:00AM 17TH MARCH 2024
+ {{ schedule ? getTime(schedule) : getTime(DateTime.now().toMillis()) }}
+ isDateTimeModalOpen = false">
+
+
+
+
-
- {{ }}
+
+
+ {{ shop.name ? shop.name : shop.shopId }}
+
-
+
-
+
{{ translate("Review") }}
Scheduled Restock
-
+
- job id
- jobname
+ {{ job.jobId }}
+ {{ job.jobName }}
inbound
- 10:00AM 17TH MARCH 2024
+ {{ getTime(job.runTime) }}
@@ -95,14 +99,20 @@
-
+
\ No newline at end of file
From ef70d891df2a6c028538a018de7ebdeba284f33d Mon Sep 17 00:00:00 2001
From: R-Sourabh
Date: Thu, 30 May 2024 14:19:12 +0530
Subject: [PATCH 07/21] Implemented: Scheduled restock upload to support
product identifiers & add support to only add selected items from review
page(#285)
---
.env.example | 2 +-
src/store/modules/stock/actions.ts | 7 ++-----
src/views/ScheduledRestock.vue | 30 ++++++++++++++++++----------
src/views/ScheduledRestockReview.vue | 2 +-
4 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/.env.example b/.env.example
index 7669ab14..1ce2c661 100644
--- a/.env.example
+++ b/.env.example
@@ -8,6 +8,6 @@ VUE_APP_ALIAS={}
VUE_APP_MAPPING_TYPES={"PO": "PO_MAPPING_PREF","RSTINV": "INV_MAPPING_PREF","RSTSTK": "STK_MAPPING_PREF"}
VUE_APP_MAPPING_PO={"orderId": { "label": "Order ID", "required": true }, "productSku": { "label": "Shopify product SKU", "required": true },"orderDate": { "label": "Arrival date", "required": true }, "quantity": { "label": "Ordered quantity", "required": true }, "facility": { "label": "Facility ID", "required": true }}
VUE_APP_MAPPING_RSTINV={"productIdentification": { "label": "Product Identification", "required": true }, "quantity": { "label": "Quantity", "required": true }, "facility": { "label": "Facility ID", "required": true }}
-VUE_APP_MAPPING_RSTSTK={"product": { "label": "Product", "required": true }, "facility": { "label": "Facility", "required": true }, "restockQuantity": { "label": "Restock quantity", "required": true }}
+VUE_APP_MAPPING_RSTSTK={"productIdentification": { "label": "Product Identification", "required": true }, "facility": { "label": "Facility", "required": true }, "restockQuantity": { "label": "Restock quantity", "required": true }}
VUE_APP_DEFAULT_LOG_LEVEL="error"
VUE_APP_LOGIN_URL="http://launchpad.hotwax.io/login"
\ No newline at end of file
diff --git a/src/store/modules/stock/actions.ts b/src/store/modules/stock/actions.ts
index 6145a795..4e25333a 100644
--- a/src/store/modules/stock/actions.ts
+++ b/src/store/modules/stock/actions.ts
@@ -70,7 +70,7 @@ const actions: ActionTree = {
},
async processUpdateRestockItems({ commit }, items) {
- const productIds = items.filter((item: any) => item.product).map((item: any) => item.product);
+ const productIds = items.map((item: any) => item.identification);
const payload = {
productIds,
@@ -87,7 +87,7 @@ const actions: ActionTree = {
const cachedProducts = await store.dispatch("product/fetchProducts", payload);
const initial = items.map((item: any) => {
- const product = cachedProducts[item.product];
+ const product = cachedProducts[item.identification];
if (product) {
item.parentProductId = product?.parent?.id;
@@ -103,9 +103,6 @@ const actions: ActionTree = {
commit(types.STOCK_SCHEDULE_ITEMS_UPDATED, initial );
},
- clearRetockItems({ commit }) {
- commit(types.STOCK_SCHEDULE_ITEMS_UPDATED, []);
- },
async scheduledStock({ commit }, payload) {
commit(types.STOCK_SCHEDULED_INFORMATION, payload)
},
diff --git a/src/views/ScheduledRestock.vue b/src/views/ScheduledRestock.vue
index 3b237fde..f746e6a4 100644
--- a/src/views/ScheduledRestock.vue
+++ b/src/views/ScheduledRestock.vue
@@ -34,14 +34,21 @@
Required
-
-
-
-
+
+
+
+ {{ goodIdentificationType.description }}
+
+
{{ prop }}
-
-
+
+
+
+ {{ prop }}
+
+
+
Optional, or select during review
@@ -164,6 +171,7 @@ export default defineComponent({
fileColumns: [],
fieldMapping: {},
fields: process.env["VUE_APP_MAPPING_RSTSTK"] ? JSON.parse(process.env["VUE_APP_MAPPING_RSTSTK"]) : {},
+ identificationTypeId: "SHOPIFY_PROD_SKU",
schedule: '',
isDateTimeModalOpen: false,
shopifyShops: [],
@@ -172,12 +180,13 @@ export default defineComponent({
selectedShopifyShopId: '',
isUpdateDateTimeModalOpen: false,
shopId: '',
- currentJob: {}
+ currentJob: {},
}
},
computed: {
...mapGetters({
fieldMappings: 'user/getFieldMappings',
+ goodIdentificationTypes: 'util/getGoodIdentificationTypes',
jobs: 'stock/getScheduledJobs',
productStores: 'util/getProductStores',
userProfile: 'user/getUserProfile'
@@ -196,6 +205,7 @@ export default defineComponent({
this.$refs.file.value = null;
await this.store.dispatch('stock/fetchJobs')
await this.store.dispatch('util/fetchProductStores')
+ await this.store.dispatch('util/fetchGoodIdentificationTypes');
},
methods: {
@@ -338,8 +348,8 @@ export default defineComponent({
return {
quantity: item[this.fieldMapping.restockQuantity],
facilityId: '',
- product: item[this.fieldMapping.product],
- identificationTypeId: "SHOPIFY_PROD_SKU",
+ identification: item[this.fieldMapping.productIdentification],
+ identificationTypeId: this.identificationTypeId,
externalFacilityId: item[this.fieldMapping.facility]
}
})
@@ -393,7 +403,7 @@ main {
margin: var(--spacer-sm) auto 0;
}
-.review{
+.review {
margin: var(--spacer-base) var(--spacer-sm);
}
diff --git a/src/views/ScheduledRestockReview.vue b/src/views/ScheduledRestockReview.vue
index 43ed9786..94f96763 100644
--- a/src/views/ScheduledRestockReview.vue
+++ b/src/views/ScheduledRestockReview.vue
@@ -253,7 +253,7 @@ export default defineComponent({
return;
}
const groupedItems = Object.keys(this.parsedItems).reduce((result, key) => {
- const items = this.parsedItems[key];
+ const items = this.parsedItems[key].filter(item => item.isSelected);
items.forEach(item => {
if (!result[item.externalFacilityId]) {
result[item.externalFacilityId] = [];
From 77d1b2f164cca5c15d6c8396a80f57b7722655bc Mon Sep 17 00:00:00 2001
From: R-Sourabh
Date: Thu, 30 May 2024 15:58:04 +0530
Subject: [PATCH 08/21] Updated: datetime button styling, edited the
systemJobEnumId(285)
---
src/store/modules/stock/actions.ts | 16 +++++++++-----
src/theme/variables.css | 24 +++++++++++++++-----
src/views/ScheduledRestock.vue | 6 ++---
src/views/ScheduledRestockReview.vue | 33 ++++++++++++++--------------
4 files changed, 49 insertions(+), 30 deletions(-)
diff --git a/src/store/modules/stock/actions.ts b/src/store/modules/stock/actions.ts
index 4e25333a..c2437133 100644
--- a/src/store/modules/stock/actions.ts
+++ b/src/store/modules/stock/actions.ts
@@ -85,9 +85,15 @@ const actions: ActionTree = {
}, {});
const facilityIds = externalFacilityIds.map((externalFacilityId: any) => facilityMapping[externalFacilityId]).filter((facilityId: any) => facilityId);
const cachedProducts = await store.dispatch("product/fetchProducts", payload);
+ // creating products object based on identification selected
+ const products: any = Object.values(cachedProducts).reduce((updatedProducts: any, product: any) => {
+ const identification = product.identifications.find((identification: any) => payload.identificationTypeId.toLowerCase() === identification.productIdTypeEnumId.toLowerCase())
+ updatedProducts[identification.idValue] = product
+ return updatedProducts;
+ }, {})
const initial = items.map((item: any) => {
- const product = cachedProducts[item.identification];
+ const product = products[item.identification];
if (product) {
item.parentProductId = product?.parent?.id;
@@ -116,13 +122,13 @@ const actions: ActionTree = {
const job = await dispatch("fetchDraftJob")
- if(!job.jobId) {
+ if(!job.jobId || !job.serviceName || job.serviceName == '_NA_') {
showToast(translate("Configuration missing"))
return;
}
const payload = {
- 'JOB_NAME': restockName || state.schedule.restockName || `Created ${DateTime.now().toLocaleString(DateTime.DATETIME_MED)}`,
+ 'JOB_NAME': restockName || state.schedule.restockName || `Created ${DateTime.fromMillis(+state.schedule.scheduledTime).toLocaleString(DateTime.DATETIME_MED)}`,
'SERVICE_NAME': job.serviceName,
'SERVICE_COUNT': '0',
'SERVICE_TEMP_EXPR': job.jobStatus,
@@ -167,7 +173,7 @@ const actions: ActionTree = {
"inputFields": {
"statusId": "SERVICE_DRAFT",
"statusId_op": "equals",
- "systemJobEnumId": "JOB_RST_STK",
+ "systemJobEnumId": "JOB_SCHEDULED_RSTK",
"systemJobEnumId_op": "equals"
},
"fieldList": [ "systemJobEnumId", "runTime", "tempExprId", "parentJobId", "serviceName", "jobId", "jobName", "currentRetryCount", "statusId", "runtimeDataId", "productStoreId", "priority"],
@@ -207,7 +213,7 @@ const actions: ActionTree = {
const params = {
"inputFields": {
"statusId": "SERVICE_PENDING",
- 'systemJobEnumId': "JOB_RST_STK",
+ 'systemJobEnumId': "JOB_SCHEDULED_RSTK",
'systemJobEnumId_op': 'equals',
'orderBy': 'runTime ASC'
},
diff --git a/src/theme/variables.css b/src/theme/variables.css
index 44358dc2..eaff9696 100644
--- a/src/theme/variables.css
+++ b/src/theme/variables.css
@@ -273,6 +273,24 @@ http://ionicframework.com/docs/theming/ */
text-align: center;
}
+.date-time-button::part(native) {
+ box-shadow: none;
+ border-radius: 8px;
+ padding-inline: 12px;
+ padding-top: 6px;
+ padding-bottom: 6px;
+ background: var(--ion-color-step-300, #edeef0);
+ color: var(--ion-text-color, #000);
+ font-family: inherit;
+ font-size: 1rem;
+}
+
+.date-time-modal {
+ --width: 320px;
+ --height: 445px;
+ --border-radius: 8px;
+}
+
@media (min-width: 991px) {
.desktop-only {
display: unset;
@@ -282,9 +300,3 @@ http://ionicframework.com/docs/theming/ */
display: none;
}
}
-
-.date-time-modal {
- --width: 320px;
- --height: 445px;
- --border-radius: 8px;
-}
\ No newline at end of file
diff --git a/src/views/ScheduledRestock.vue b/src/views/ScheduledRestock.vue
index f746e6a4..c63490d9 100644
--- a/src/views/ScheduledRestock.vue
+++ b/src/views/ScheduledRestock.vue
@@ -55,7 +55,7 @@
Schedule
- {{ schedule ? getTime(schedule) : getTime(DateTime.now().toMillis()) }}
+ {{ schedule ? getTime(schedule) : getTime(DateTime.now().toMillis()) }}
isDateTimeModalOpen = false">
-
+
{{ shop.name ? shop.name : shop.shopId }}
@@ -101,7 +101,7 @@
{{ job.jobName }}
inbound
- {{ getTime(job.runTime) }}
+ {{ getTime(job.runTime) }}
diff --git a/src/views/ScheduledRestockReview.vue b/src/views/ScheduledRestockReview.vue
index 94f96763..614794c5 100644
--- a/src/views/ScheduledRestockReview.vue
+++ b/src/views/ScheduledRestockReview.vue
@@ -26,24 +26,24 @@
Schedule
- {{ schedule.scheduledTime ? getTime(schedule.scheduledTime) : getTime(DateTime.now().toMillis())}}
+ {{ schedule.scheduledTime ? getTime(schedule.scheduledTime) : getTime(DateTime.now().toMillis())}}
isDateTimeModalOpen = false">
-
-
-
-
+
+
+
+
-
- {{ getFacilityName(facilityId) }}
+
+ {{ getFacilityName(facilityId) }}
@@ -57,7 +57,7 @@
-
+
{{ shop.name ? shop.name : shop.shopId }}
@@ -82,7 +82,8 @@
- {{ item.parentProductName }}
+ {{ item.parentProductName }}
+ {{ item.identification }}
From b909719a6308a5649d4ca58fd3dae8e3893e7a6d Mon Sep 17 00:00:00 2001
From: R-Sourabh
Date: Thu, 30 May 2024 16:15:12 +0530
Subject: [PATCH 09/21] Updated: added check for facility Id, scheduled time
and current datetime(#285)
---
src/views/ScheduledRestock.vue | 4 ++--
src/views/ScheduledRestockReview.vue | 11 ++++++++++-
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/views/ScheduledRestock.vue b/src/views/ScheduledRestock.vue
index c63490d9..4763c646 100644
--- a/src/views/ScheduledRestock.vue
+++ b/src/views/ScheduledRestock.vue
@@ -55,7 +55,7 @@
Schedule
- {{ schedule ? getTime(schedule) : getTime(DateTime.now().toMillis()) }}
+ {{ schedule ? getTime(schedule) : 'Select time' }}
isDateTimeModalOpen = false">
inbound
- {{ getTime(job.runTime) }}
+ {{ getTime(job.runTime) ? getTime(job.runTime) : 'Select time' }}
diff --git a/src/views/ScheduledRestockReview.vue b/src/views/ScheduledRestockReview.vue
index 614794c5..47016efb 100644
--- a/src/views/ScheduledRestockReview.vue
+++ b/src/views/ScheduledRestockReview.vue
@@ -26,7 +26,7 @@
Schedule
- {{ schedule.scheduledTime ? getTime(schedule.scheduledTime) : getTime(DateTime.now().toMillis())}}
+ {{ schedule.scheduledTime ? getTime(schedule.scheduledTime) : 'Select time' }}
isDateTimeModalOpen = false">
{
const items = this.parsedItems[key].filter(item => item.isSelected);
items.forEach(item => {
@@ -270,6 +275,10 @@ export default defineComponent({
}, {});
const destinationFacilityId = Object.keys(groupedItems)[0];
+ if(!destinationFacilityId) {
+ showToast(translate("Facility not found"));
+ return;
+ }
const items = groupedItems[destinationFacilityId];
const uploadData = {
From dc903c40296066b9aa8c2f62a4a3060715e73c81 Mon Sep 17 00:00:00 2001
From: R-Sourabh
Date: Thu, 30 May 2024 16:47:17 +0530
Subject: [PATCH 10/21] Updated: added schedule restock mapping on
savedmappings page(#285)
---
src/theme/variables.css | 1 -
src/views/SavedMappings.vue | 6 ++++++
src/views/ScheduledRestockReview.vue | 3 +--
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/theme/variables.css b/src/theme/variables.css
index eaff9696..6df17b20 100644
--- a/src/theme/variables.css
+++ b/src/theme/variables.css
@@ -282,7 +282,6 @@ http://ionicframework.com/docs/theming/ */
background: var(--ion-color-step-300, #edeef0);
color: var(--ion-text-color, #000);
font-family: inherit;
- font-size: 1rem;
}
.date-time-modal {
diff --git a/src/views/SavedMappings.vue b/src/views/SavedMappings.vue
index 71bf19e0..c322c6f0 100644
--- a/src/views/SavedMappings.vue
+++ b/src/views/SavedMappings.vue
@@ -25,6 +25,12 @@
{{ mapping.name }}
+
+ {{ translate("Scheduled restock") }}
+
+ {{ mapping.name }}
+
+