Skip to content

Commit

Permalink
Implemented: Scheduled Restock Functionality(hotwax#285)
Browse files Browse the repository at this point in the history
  • Loading branch information
R-Sourabh committed May 29, 2024
1 parent 39ae070 commit faf1697
Show file tree
Hide file tree
Showing 14 changed files with 728 additions and 115 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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"
11 changes: 11 additions & 0 deletions src/components/CreateMappingModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
3 changes: 0 additions & 3 deletions src/components/ScheduledRestockPopover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
<ion-item button>
Cancel
</ion-item>
<ion-item button lines="none">
View Details
</ion-item>
</ion-list>
</ion-content>
</template>
Expand Down
22 changes: 22 additions & 0 deletions src/services/StockService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { api } from '@/adapter';

const scheduleJob = async (payload: any): Promise <any> => {
return api({
url: "scheduleService",
method: "post",
data: payload
});
}

const fetchJobInformation = async (payload: any): Promise <any> => {
return api({
url: "/findJobs",
method: "get",
params: payload
});
}

export const StockService = {
scheduleJob,
fetchJobInformation
}
11 changes: 10 additions & 1 deletion src/services/UtilService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,17 @@ const fetchGoodIdentificationTypes = async (payload: any): Promise<any> => {
})
}

const fetchShopifyShop = async (payload: any): Promise<any> => {
return api({
url: "/performFind",
method: "POST",
data: payload
})
}

export const UtilService = {
fetchGoodIdentificationTypes,
fetchShopifyShop,
getFacilities,
getFacilityLocations
getFacilityLocations,
}
10 changes: 9 additions & 1 deletion src/store/modules/stock/StockState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
147 changes: 146 additions & 1 deletion src/store/modules/stock/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<StockState, RootState> = {
async processUpdateStockItems ({ commit, rootGetters }, items) {
Expand Down Expand Up @@ -53,7 +58,6 @@ const actions: ActionTree<StockState, RootState> = {
}).filter((item: any) => item);

const original = JSON.parse(JSON.stringify(items));

commit(types.STOCK_ITEMS_UPDATED, { parsed, original, initial });
this.dispatch('util/updateFileProcessingStatus', false);
},
Expand All @@ -63,6 +67,146 @@ const actions: ActionTree<StockState, RootState> = {
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) => {
Expand All @@ -78,4 +222,5 @@ const actions: ActionTree<StockState, RootState> = {
this.dispatch('stock/updateStockItems', state.items);
}
}

export default actions;
14 changes: 14 additions & 0 deletions src/store/modules/stock/getters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,19 @@ const getters: GetterTree<OrderState, RootState> = {
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;
10 changes: 9 additions & 1 deletion src/store/modules/stock/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ const orderModule: Module<StockState, RootState> = {
unidentifiedItems: [],
initial: []
},
fileName: ""
fileName: "",
restockItems: [],
schedule: {
scheduledTime: "",
shopId: "",
restockName: ""
},
shopifyShops: [],
jobs: {}
},
actions,
getters,
Expand Down
6 changes: 5 additions & 1 deletion src/store/modules/stock/mutation-types.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export const SN_STOCK = 'stock'
export const STOCK_ITEMS_UPDATED = SN_STOCK + '/ITEMS_UPDATED'
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'
14 changes: 14 additions & 0 deletions src/store/modules/stock/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ const mutations: MutationTree <StockState> = {
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;
6 changes: 6 additions & 0 deletions src/theme/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -281,4 +281,10 @@ http://ionicframework.com/docs/theming/ */
.mobile-only {
display: none;
}
}

.date-time-modal {
--width: 320px;
--height: 385px;
--border-radius: 8px;
}
Loading

0 comments on commit faf1697

Please sign in to comment.