From 260e87279323712a1833233bd6ad7d73d364976f Mon Sep 17 00:00:00 2001 From: amansinghbais Date: Wed, 14 Aug 2024 13:01:50 +0530 Subject: [PATCH 1/2] Implemented: logic for job execution timezone management (#719) --- src/components/ExecutionTimeZoneSwitcher.vue | 97 ++++++++++++ src/components/TimeZoneModal.vue | 146 +++++++++++++++++++ src/services/UtilService.ts | 65 ++++++++- src/store/modules/user/actions.ts | 2 + src/store/modules/util/UtilState.ts | 1 + src/store/modules/util/actions.ts | 129 +++++++++++++++- src/store/modules/util/getters.ts | 3 + src/store/modules/util/index.ts | 3 +- src/store/modules/util/mutation-types.ts | 3 +- src/store/modules/util/mutations.ts | 3 + src/views/Settings.vue | 6 +- 11 files changed, 453 insertions(+), 5 deletions(-) create mode 100644 src/components/ExecutionTimeZoneSwitcher.vue create mode 100644 src/components/TimeZoneModal.vue diff --git a/src/components/ExecutionTimeZoneSwitcher.vue b/src/components/ExecutionTimeZoneSwitcher.vue new file mode 100644 index 00000000..9504a718 --- /dev/null +++ b/src/components/ExecutionTimeZoneSwitcher.vue @@ -0,0 +1,97 @@ + + + + \ No newline at end of file diff --git a/src/components/TimeZoneModal.vue b/src/components/TimeZoneModal.vue new file mode 100644 index 00000000..5f2265e7 --- /dev/null +++ b/src/components/TimeZoneModal.vue @@ -0,0 +1,146 @@ + + + \ No newline at end of file diff --git a/src/services/UtilService.ts b/src/services/UtilService.ts index eb917320..1ec14497 100644 --- a/src/services/UtilService.ts +++ b/src/services/UtilService.ts @@ -1,4 +1,5 @@ import { api } from '@/adapter'; +import { hasError } from '@hotwax/oms-api'; const getServiceStatusDesc = async (payload: any): Promise => { return api({ @@ -9,6 +10,68 @@ const getServiceStatusDesc = async (payload: any): Promise => { }); } +const getProductStoreSetting = async (payload: any): Promise => { + return api({ + url: "performFind", + method: "post", + data: payload + }); +} + +const isEnumExists = async (enumId: string): Promise => { + try { + const resp = await api({ + url: 'performFind', + method: 'POST', + data: { + entityName: "Enumeration", + inputFields: { + enumId + }, + viewSize: 1, + fieldList: ["enumId"], + noConditionFind: 'Y' + } + }) as any + + if (!hasError(resp) && resp.data.docs.length) { + return true + } + return false + } catch (err) { + return false + } +} + +const createEnumeration = async (payload: any): Promise => { + return api({ + url: "/service/createEnumeration", + method: "post", + data: payload + }) +} + +const createProductStoreSetting = async (payload: any): Promise => { + return api({ + url: "service/createProductStoreSetting", + method: "post", + data: payload + }); +} + +const updateProductStoreSetting = async (payload: any): Promise => { + return api({ + url: "service/updateProductStoreSetting", + method: "post", + data: payload + }); +} + export const UtilService = { - getServiceStatusDesc + createEnumeration, + createProductStoreSetting, + getProductStoreSetting, + getServiceStatusDesc, + isEnumExists, + updateProductStoreSetting } \ No newline at end of file diff --git a/src/store/modules/user/actions.ts b/src/store/modules/user/actions.ts index 60051585..fa3625ff 100644 --- a/src/store/modules/user/actions.ts +++ b/src/store/modules/user/actions.ts @@ -95,6 +95,7 @@ const actions: ActionTree = { // Getting service status description // TODO check if we could move it to logic for fetching jobs this.dispatch('util/getServiceStatusDesc') + this.dispatch('util/getJobRecurrenceTimeZone', preferredStore.productStoreId); } catch (err: any) { // If any of the API call in try block has status code other than 2xx it will be handled in common catch block. // TODO Check if handling of specific status codes is required. @@ -162,6 +163,7 @@ const actions: ActionTree = { } commit(types.USER_CURRENT_ECOM_STORE_UPDATED, productStore); await dispatch('getShopifyConfig', productStore.productStoreId); + this.dispatch('util/getForceScanSetting', productStore.productStoreId) }, /** * Update user timeZone diff --git a/src/store/modules/util/UtilState.ts b/src/store/modules/util/UtilState.ts index a43d5b06..762cebcd 100644 --- a/src/store/modules/util/UtilState.ts +++ b/src/store/modules/util/UtilState.ts @@ -1,3 +1,4 @@ export default interface UtilState { statusDesc: any; + jobRecurrenceTimeZone: any; } \ No newline at end of file diff --git a/src/store/modules/util/actions.ts b/src/store/modules/util/actions.ts index def99658..4467e286 100644 --- a/src/store/modules/util/actions.ts +++ b/src/store/modules/util/actions.ts @@ -3,8 +3,10 @@ import { ActionTree } from 'vuex' import RootState from '@/store/RootState' import UtilState from './UtilState' import * as types from './mutation-types' -import { hasError } from '@/utils' +import { hasError, showToast } from '@/utils' import logger from "@/logger"; +import store from '@/store' +import { translate } from '@hotwax/dxp-components' const actions: ActionTree = { /** @@ -29,6 +31,131 @@ const actions: ActionTree = { logger.error(err) } }, + + async getJobRecurrenceTimeZone({ commit, dispatch }, eComStoreId) { + const payload = { + "inputFields": { + "productStoreId": eComStoreId, + "settingTypeEnumId": "JOB_RECUR_TIMEZONE" + }, + "filterByDate": 'Y', + "entityName": "ProductStoreSetting", + "fieldList": ["settingValue", "fromDate"], + "viewSize": 1 + } + + try { + const resp = await UtilService.getProductStoreSetting(payload) as any + if(!hasError(resp)) { + const respValue = resp.data.docs[0].settingValue + commit(types.UITL_JOB_RECURRENCE_TIME_ZONE_UPDATED, respValue) + } else { + dispatch('createJobRecurrenceTimeZone'); + } + } catch(err) { + console.error(err) + commit(types.UITL_JOB_RECURRENCE_TIME_ZONE_UPDATED, "") + } + }, + + async createJobRecurrenceTimeZone({ commit }) { + const ecomStore = store.getters['user/getCurrentEComStore']; + const fromDate = Date.now() + + try { + if(!await UtilService.isEnumExists("JOB_RECUR_TIMEZONE")) { + const resp = await UtilService.createEnumeration({ + "enumId": "JOB_RECUR_TIMEZONE", + "enumTypeId": "PROD_STR_STNG", + "description": "Timezone for the job recurrence.", + "enumName": "Job Recurrence Timezone", + "enumCode": "JOB_RECUR_TIMEZONE" + }) + + if(hasError(resp)) { + throw resp.data; + } + } + + const params = { + fromDate, + "productStoreId": ecomStore.productStoreId, + "settingTypeEnumId": "JOB_RECUR_TIMEZONE", + "settingValue": "" + } + + await UtilService.createProductStoreSetting(params) as any + } catch(err) { + console.error(err) + } + + // not checking for resp success and fail case as every time we need to update the state with the + // default value when creating a scan setting + commit(types.UITL_JOB_RECURRENCE_TIME_ZONE_UPDATED, "") + return fromDate; + }, + + async setJobRecurrenceTimeZone({ commit, dispatch, state }, value) { + let prefValue = state.jobRecurrenceTimeZone + const eComStoreId = store.getters['user/getCurrentEComStore'].productStoreId; + + // when selecting none as ecom store, not updating the pref as it's not possible to save pref with empty productStoreId + if(!eComStoreId) { + showToast(translate("Unable to update job execution time zone.")) + commit(types.UITL_JOB_RECURRENCE_TIME_ZONE_UPDATED, prefValue) + return; + } + + let fromDate; + + try { + const resp = await UtilService.getProductStoreSetting({ + "inputFields": { + "productStoreId": eComStoreId, + "settingTypeEnumId": "JOB_RECUR_TIMEZONE" + }, + "filterByDate": 'Y', + "entityName": "ProductStoreSetting", + "fieldList": ["fromDate"], + "viewSize": 1 + }) as any + if(!hasError(resp)) { + fromDate = resp.data.docs[0]?.fromDate + } + } catch(err) { + console.error(err) + } + + if(!fromDate) { + fromDate = await dispatch("createJobRecurrenceTimeZone"); + } + + const params = { + "fromDate": fromDate, + "productStoreId": eComStoreId, + "settingTypeEnumId": "JOB_RECUR_TIMEZONE", + "settingValue": value + } + + try { + const resp = await UtilService.updateProductStoreSetting(params) as any + + if((!hasError(resp))) { + showToast(translate("Job execution timezone updated successfully.")) + prefValue = value + } else { + throw resp.data; + } + } catch(err) { + showToast(translate("Failed to update job execution timezone.")) + console.error(err) + } + commit(types.UITL_JOB_RECURRENCE_TIME_ZONE_UPDATED, prefValue) + }, + + async updateForceScanStatus({ commit }, payload) { + commit(types.UITL_JOB_RECURRENCE_TIME_ZONE_UPDATED, payload) + } } 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 7918e532..e651f21b 100644 --- a/src/store/modules/util/getters.ts +++ b/src/store/modules/util/getters.ts @@ -5,6 +5,9 @@ import RootState from '@/store/RootState' const getters: GetterTree = { getStatusDesc: (state) => (statusId: any) => { return state.statusDesc[statusId] ? state.statusDesc[statusId] : "-"; + }, + getJobRecurrenceTimeZone: (state) => { + return state.jobRecurrenceTimeZone; } } 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 48861ca1..eefdee34 100644 --- a/src/store/modules/util/index.ts +++ b/src/store/modules/util/index.ts @@ -8,7 +8,8 @@ import RootState from '@/store/RootState' const utilModule: Module = { namespaced: true, state: { - statusDesc: {} + statusDesc: {}, + jobRecurrenceTimeZone: "" }, getters, actions, diff --git a/src/store/modules/util/mutation-types.ts b/src/store/modules/util/mutation-types.ts index 88fb7638..1c13b896 100644 --- a/src/store/modules/util/mutation-types.ts +++ b/src/store/modules/util/mutation-types.ts @@ -1,2 +1,3 @@ export const SN_UTIL = 'util' -export const UTIL_SERVICE_STATUS_DESC_UPDATED = SN_UTIL + '/SERVICE_STATUS_DESC_UPDATED' \ No newline at end of file +export const UTIL_SERVICE_STATUS_DESC_UPDATED = SN_UTIL + '/SERVICE_STATUS_DESC_UPDATED' +export const UITL_JOB_RECURRENCE_TIME_ZONE_UPDATED = SN_UTIL + '/JOB_RECURRENCE_TIME_ZONE_UPDATED' \ No newline at end of file diff --git a/src/store/modules/util/mutations.ts b/src/store/modules/util/mutations.ts index e3530da4..17cc0d1b 100644 --- a/src/store/modules/util/mutations.ts +++ b/src/store/modules/util/mutations.ts @@ -7,6 +7,9 @@ const mutations: MutationTree = { payload.map((status: any) => { state.statusDesc[status.statusId] = status.description; }) + }, + [types.UITL_JOB_RECURRENCE_TIME_ZONE_UPDATED] (state, payload) { + state.jobRecurrenceTimeZone = payload } } export default mutations; \ No newline at end of file diff --git a/src/views/Settings.vue b/src/views/Settings.vue index 46cac240..fe06e4f5 100644 --- a/src/views/Settings.vue +++ b/src/views/Settings.vue @@ -80,6 +80,8 @@
+ +
@@ -93,6 +95,7 @@ import { mapGetters, useStore } from 'vuex'; import { useRouter } from 'vue-router'; import Image from '@/components/Image.vue' import { translate } from '@hotwax/dxp-components'; +import ExecutionTimeZoneSwitcher from "@/components/ExecutionTimeZoneSwitcher.vue" export default defineComponent({ name: 'Settings', @@ -114,7 +117,8 @@ export default defineComponent({ IonSelectOption, IonTitle, IonToolbar, - Image + Image, + ExecutionTimeZoneSwitcher }, data() { return { From 61f2f2dde8b61de8c22308201d6ca5ddd3faf975 Mon Sep 17 00:00:00 2001 From: amansinghbais Date: Tue, 20 Aug 2024 11:08:55 +0530 Subject: [PATCH 2/2] Improved: logic to use the user selected recurrence timezone while job scheduling actions (#719) --- src/store/modules/job/actions.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/store/modules/job/actions.ts b/src/store/modules/job/actions.ts index c63bc496..5291c483 100644 --- a/src/store/modules/job/actions.ts +++ b/src/store/modules/job/actions.ts @@ -511,7 +511,7 @@ const actions: ActionTree = { const payload = { 'jobId': job.jobId, 'systemJobEnumId': job.systemJobEnumId, - 'recurrenceTimeZone': this.state.user.current.userTimeZone, + 'recurrenceTimeZone': this.state.util.jobRecurrenceTimeZone ? this.state.util.jobRecurrenceTimeZone : this.state.user.current.userTimeZone, 'tempExprId': job.jobStatus, 'statusId': "SERVICE_PENDING", 'runTimeEpoch': '', // when updating a job clearning the epoch time, as job honors epoch time as runTime and the new job created also uses epoch time as runTime @@ -567,7 +567,7 @@ const actions: ActionTree = { '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, + 'recurrenceTimeZone': this.state.util.jobRecurrenceTimeZone ? this.state.util.jobRecurrenceTimeZone : this.state.user.current.userTimeZone, 'createdByUserLogin': this.state.user.current.userLoginId, 'lastModifiedByUserLogin': this.state.user.current.userLoginId, }, @@ -653,7 +653,7 @@ const actions: ActionTree = { 'jobId': job.jobId, 'runTime': updatedRunTime, 'systemJobEnumId': job.systemJobEnumId, - 'recurrenceTimeZone': this.state.user.current.userTimeZone, + 'recurrenceTimeZone': this.state.util.jobRecurrenceTimeZone ? this.state.util.jobRecurrenceTimeZone : this.state.user.current.userTimeZone, 'statusId': "SERVICE_PENDING", 'runTimeEpoch': '' } as any @@ -696,7 +696,7 @@ const actions: ActionTree = { '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 'parentJobId': job.parentJobId, - 'recurrenceTimeZone': this.state.user.current.userTimeZone, + 'recurrenceTimeZone': this.state.util.jobRecurrenceTimeZone ? this.state.util.jobRecurrenceTimeZone : this.state.user.current.userTimeZone, 'createdByUserLogin': this.state.user.current.userLoginId, 'lastModifiedByUserLogin': this.state.user.current.userLoginId }, @@ -897,7 +897,7 @@ const actions: ActionTree = { '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, + 'recurrenceTimeZone': this.state.util.jobRecurrenceTimeZone ? this.state.util.jobRecurrenceTimeZone : this.state.user.current.userTimeZone, 'createdByUserLogin': this.state.user.current.userLoginId, 'lastModifiedByUserLogin': this.state.user.current.userLoginId },