Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented: support to display good identification options dynamically(dxp/345) #488

Merged
merged 6 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ VUE_APP_CACHE_MAX_AGE=3600
VUE_APP_VIEW_SIZE=10
VUE_APP_PERMISSION_ID="INVCOUNT_APP_VIEW"
VUE_APP_DEFAULT_LOG_LEVEL="error"
VUE_APP_PRDT_IDENT=["productId", "groupId", "groupName", "internalName", "parentProductName", "sku", "title", "SHOPIFY_PROD_SKU", "ERP_ID", "UPCA"]
VUE_APP_PRDT_IDENT=["productId", "groupId", "groupName", "internalName", "parentProductName", "primaryProductCategoryName", "title"]
VUE_APP_MAPPING_TYPES={"INVCOUNT": "INVCNT_MAPPING_PREF"}
VUE_APP_MAPPING_INVCOUNT={"countImportName": { "label": "Count name", "required": true}, "productSku": { "label": "Product SKU", "required": true, "description": "Products will not be deduplicated. Make sure products are only added to a count once."}, "facility": { "label": "Facility", "required": false, "description": "If a file includes multiple facilities, a count is created for every facility. All items with no facility location will be added to the same count." }, "statusId": { "label": "Status", "required": false, "description": "Defaults to 'Draft'" }, "dueDate": { "label": "Due date", "description": "Format: yyyy-mm-dd", "required": false }}
VUE_APP_LOGIN_URL="http://launchpad.hotwax.io/login"
2 changes: 1 addition & 1 deletion src/authorization/Rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ export default {
"APP_STORE_PERMISSIONS_VIEW": "COMMON_ADMIN",
"APP_SETTINGS_VIEW": "",
"APP_COUNT_VIEW": "FULFILL_INVCUNT_ADMIN OR INV_COUNT_ADMIN",
"APP_PRODUCT_IDENTIFIER_UPDATE": "",
"APP_PRODUCT_IDENTIFIER_UPDATE": "COMMON_ADMIN",
"INVCOUNT_APP_VIEW": "INVCOUNT_APP_VIEW"
} as any
3 changes: 2 additions & 1 deletion src/components/AddProductModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<Image :src="product.mainImageUrl" />
</ion-thumbnail>
<ion-label>
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, product) }}</h2>
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, product) || getProduct(product.productId).productName }}</h2>
<p>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].secondaryId, product) }}</p>
</ion-label>
<ion-icon v-if="isProductAvailableInCycleCount(product.productId)" color="success" :icon="checkmarkCircle" />
Expand Down Expand Up @@ -73,6 +73,7 @@ const props = defineProps(["cycleCount"])
const products = computed(() => store.getters["product/getProducts"])
const isScrollable = computed(() => store.getters["product/isScrollable"])
const productStoreSettings = computed(() => store.getters["user/getProductStoreSettings"])
const getProduct = computed(() => (id: any) => store.getters["product/getProduct"](id))

let queryString = ref('')
const isSearching = ref(false);
Expand Down
2 changes: 1 addition & 1 deletion src/components/AssignedCountPopover.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<ion-content>
<ion-list>
<ion-list-header>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) || item.productId }}</ion-list-header>
<ion-list-header>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) || getProduct(item.productId).productName }}</ion-list-header>
<ion-item :lines="item.quantity ? 'none' : 'full'">
<ion-label>{{ translate("Last counted")}}</ion-label>
<ion-note slot="end">{{ timeFromNow(item.lastCountedDate) }}</ion-note>
Expand Down
10 changes: 5 additions & 5 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"Before": "Before",
"Browser TimeZone": "Browser TimeZone",
"Browser time zone": "Browser time zone",
"Built: ": "Built: {builtDateTime}",
"Built:": "Built: {builtDateTime}",
"Bulk Upload Cycle Counts": "Bulk Upload Cycle Counts",
"Camera permission denied.": "Camera permission denied.",
"Cancel": "Cancel",
Expand Down Expand Up @@ -159,6 +159,7 @@
"NOT COUNTED": "NOT COUNTED",
"not counted": "not counted",
"No facility": "No facility",
"None": "None",
"Fetching time zones": "Fetching time zones",
"Ok": "Ok",
"OMS": "OMS",
Expand All @@ -176,9 +177,8 @@
"Please select the column that corresponds to the product identifier": "Please select the column that corresponds to the product identifier",
"Preparing file to downlaod...": "Preparing file to downlaod...",
"Primary": "Primary",
"Primary identifier": "Primary identifier",
"Primary product ID": "Primary product ID",
"Primary Product Identifier": "Primary Product Identifier",
"primary identifier": "primary identifier",
"processed": "processed",
"processing": "processing",
"Product Identifier": "Product Identifier",
Expand Down Expand Up @@ -218,7 +218,6 @@
"Saving recount will replace the existing count for item.": "Saving recount will replace the existing count for item.",
"Scan": "Scan",
"Scan or search products": "Scan or search products",
"Secondary Product Identifier": "Secondary Product Identifier",
"selected": "selected",
"Select": "Select",
"Select fields": "Select fields",
Expand All @@ -230,6 +229,7 @@
"Search time zones": "Search time zones",
"Searching on SKU": "Searching on SKU",
"Secondary": "Secondary",
"secondary identifier": "secondary identifier",
"Select all the required fields to continue": "Select all the required fields to continue",
"Select date": "Select date",
"Select the column containing products": "Select the column containing products",
Expand Down Expand Up @@ -284,7 +284,7 @@
"variance": "variance",
"Variance reason": "Variance reason",
"Variance updated successfully": "Variance updated successfully",
"Version: ": "Version: {appVersion}",
"Version:": "Version: {appVersion}",
"View": "View",
"You do not have permission to access the app.": "You do not have permission to access the app.",
"You do not have permission to access this page": "You do not have permission to access this page",
Expand Down
17 changes: 17 additions & 0 deletions src/services/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,29 @@ const getFieldMappings = async (payload: any): Promise <any> => {
});
}

const fetchGoodIdentificationTypes = async (payload: any): Promise <any> => {
const omsRedirectionInfo = store.getters["user/getOmsRedirectionInfo"]
const baseURL = omsRedirectionInfo.url.startsWith('http') ? omsRedirectionInfo.url.includes('/api') ? omsRedirectionInfo.url : `${omsRedirectionInfo.url}/api/` : `https://${omsRedirectionInfo.url}.hotwax.io/api/`;

return await client({
url: "performFind",
method: "post",
baseURL,
data: payload,
headers: {
"Authorization": 'Bearer ' + omsRedirectionInfo.token,
'Content-Type': 'application/json'
}
});
}

export const UserService = {
createFieldMapping,
createProductStoreSetting,
deleteFieldMapping,
fetchAssociatedFacilities,
fetchFacilities,
fetchGoodIdentificationTypes,
fetchProductStores,
fetchProductStoreSettings,
getAvailableTimeZones,
Expand Down
3 changes: 2 additions & 1 deletion src/store/modules/user/UserState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ export default interface UserState {
primaryId: string,
secondaryId: string
}
}
},
goodIdentificationTypes: Array<string>;
}
26 changes: 26 additions & 0 deletions src/store/modules/user/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ const actions: ActionTree<UserState, RootState> = {
primaryId: 'productId',
secondaryId: ''
}})
commit(types.USER_GOOD_IDENTIFICATION_TYPES_UPDATED, [])
this.dispatch('count/clearCycleCounts')
this.dispatch('count/clearCycleCountItems')

Expand Down Expand Up @@ -545,6 +546,31 @@ const actions: ActionTree<UserState, RootState> = {
name: '',
value: {}
})
},

async fetchGoodIdentificationTypes({ commit }, parentTypeId = "HC_GOOD_ID_TYPE") {
let identificationTypes = process.env.VUE_APP_PRDT_IDENT ? JSON.parse(process.env.VUE_APP_PRDT_IDENT) : []
const payload = {
"inputFields": {
parentTypeId
},
"fieldList": ["goodIdentificationTypeId", "description"],
"viewSize": 50,
"entityName": "GoodIdentificationType",
}
try {
const resp = await UserService.fetchGoodIdentificationTypes(payload)
if (!hasError(resp) && resp.data?.docs?.length) {
const identificationOptions = resp.data.docs?.map((fetchedGoodIdentificationType: any) => fetchedGoodIdentificationType.goodIdentificationTypeId) || [];
// Merge the arrays and remove duplicates
identificationTypes = Array.from(new Set([...identificationOptions, ...identificationTypes])).sort();
} else {
throw resp.data;
}
} catch (err) {
console.error('Failed to fetch the good identification types, setting default types')
}
commit(types.USER_GOOD_IDENTIFICATION_TYPES_UPDATED, identificationTypes)
}
}
export default actions;
3 changes: 3 additions & 0 deletions src/store/modules/user/getters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ const getters: GetterTree <UserState, RootState> = {
return fieldMapping ? fieldMapping : {}
}
return state.fieldMappings;
},
getGoodIdentificationTypes(state) {
return state.goodIdentificationTypes;
}
}
export default getters;
3 changes: 2 additions & 1 deletion src/store/modules/user/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ const userModule: Module<UserState, RootState> = {
primaryId: 'productId',
secondaryId: ''
},
}
},
goodIdentificationTypes: []
},
getters,
actions,
Expand Down
3 changes: 2 additions & 1 deletion src/store/modules/user/mutation-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export const USER_CURRENT_PRODUCT_STORE_UPDATED = SN_USER + '/CURRENT_PRODUCT_ST
export const USER_PRODUCT_STORE_SETTING_UPDATED = SN_USER + '/PRODUCT_STORE_SETTING_UPDATED'
export const USER_FIELD_MAPPINGS_UPDATED = SN_USER + '/FIELD_MAPPINGS_UPDATED'
export const USER_FIELD_MAPPING_CREATED = SN_USER + '/FIELD_MAPPING_CREATED'
export const USER_CURRENT_FIELD_MAPPING_UPDATED = SN_USER + '/_CURRENT_FIELD_MAPPING_UPDATED'
export const USER_CURRENT_FIELD_MAPPING_UPDATED = SN_USER + '/_CURRENT_FIELD_MAPPING_UPDATED'
export const USER_GOOD_IDENTIFICATION_TYPES_UPDATED = SN_USER + '/PRODUCT_IDENTIFICATION_OPTIONS_UPDATED'
3 changes: 3 additions & 0 deletions src/store/modules/user/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ const mutations: MutationTree <UserState> = {
name: payload.name,
value: payload.value
};
},
[types.USER_GOOD_IDENTIFICATION_TYPES_UPDATED](state, payload = []) {
state.goodIdentificationTypes = payload.length ? payload : process.env.VUE_APP_PRDT_IDENT ? JSON.parse(process.env.VUE_APP_PRDT_IDENT) : []
}
}
export default mutations;
4 changes: 2 additions & 2 deletions src/views/AssignedDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
<Image :src="getProduct(item.productId).mainImageUrl"/>
</ion-thumbnail>
<ion-label>
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) }}</h2>
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) || getProduct(item.productId).productName }}</h2>
<p>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].secondaryId, getProduct(item.productId)) }}</p>
</ion-label>
</ion-item>
Expand Down Expand Up @@ -138,7 +138,7 @@
import { computed, defineProps, nextTick, ref } from "vue";
import { translate } from '@/i18n'
import { addOutline, calendarClearOutline, businessOutline, personCircleOutline, ellipsisVerticalOutline, lockClosedOutline } from "ionicons/icons";
import { IonBackButton, IonButton, IonButtons, IonChip, IonContent, IonDatetime, IonModal, IonFab, IonFabButton, IonHeader, IonIcon, IonInput, IonItem, IonLabel, IonList, IonPage, IonSpinner, IonThumbnail, IonTitle, IonToolbar, modalController, onIonViewWillEnter, popoverController, onIonViewWillLeave } from "@ionic/vue";
import { IonBackButton, IonButton, IonButtons, IonChip, IonContent, IonDatetime, IonModal, IonFab, IonFabButton, IonHeader, IonIcon, IonInput, IonItem, IonLabel, IonList, IonPage, IonThumbnail, IonTitle, IonToolbar, modalController, onIonViewWillEnter, popoverController, onIonViewWillLeave } from "@ionic/vue";
import AssignedCountPopover from "@/components/AssignedCountPopover.vue"
import store from "@/store"
import logger from "@/logger"
Expand Down
2 changes: 1 addition & 1 deletion src/views/CountDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
<div class="detail" v-if="Object.keys(product)?.length">
<ion-item lines="none">
<ion-label class="ion-text-wrap">
<h1>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(product.productId)) }}</h1>
<h1>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(product.productId)) || getProduct(product.productId).productName }}</h1>
<p>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].secondaryId, getProduct(product.productId)) }}</p>
</ion-label>

Expand Down
2 changes: 1 addition & 1 deletion src/views/DraftDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
<Image :src="getProduct(item.productId).mainImageUrl"/>
</ion-thumbnail>
<ion-label class="ion-text-wrap">
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) }}</h2>
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) || getProduct(item.productId).productName }}</h2>
<p>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].secondaryId, getProduct(item.productId)) }}</p>
</ion-label>
</ion-item>
Expand Down
2 changes: 1 addition & 1 deletion src/views/PendingReviewDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
<Image :src="getProduct(item.productId).mainImageUrl"/>
</ion-thumbnail>
<ion-label class="ion-text-wrap">
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) }}</h2>
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) || getProduct(item.productId).productName }}</h2>
<p>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].secondaryId, getProduct(item.productId)) }}</p>
</ion-label>
</ion-item>
Expand Down
2 changes: 1 addition & 1 deletion src/views/ProductItemList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</ion-thumbnail>
<ion-label class="ion-text-wrap">
<p class="overline">{{ item.itemStatusId === 'INV_COUNT_REJECTED' ? "rejected" : "" }}</p>
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) }}</h2>
<h2>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].primaryId, getProduct(item.productId)) || getProduct(item.productId).productName }}</h2>
<p>{{ getProductIdentificationValue(productStoreSettings["productIdentificationPref"].secondaryId, getProduct(item.productId)) }}</p>
</ion-label>
<ion-badge slot="end" color="danger" v-if="item.itemStatusId === 'INV_COUNT_REJECTED'">
Expand Down
10 changes: 5 additions & 5 deletions src/views/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,12 @@
</ion-card-content>

<ion-item>
<ion-select :label="translate('Primary Product Identifier')" :disabled="!hasPermission(Actions.APP_PRODUCT_IDENTIFIER_UPDATE) || !(currentFacility?.productStore?.productStoreId || currentProductStore.productStoreId)" interface="popover" :placeholder="translate('primary identifier')" :value="productStoreSettings['productIdentificationPref'].primaryId" @ionChange="setProductIdentificationPref($event.detail.value, 'primaryId')">
<ion-select :label="translate('Primary')" :disabled="!hasPermission(Actions.APP_PRODUCT_IDENTIFIER_UPDATE) || !(currentFacility?.productStore?.productStoreId || currentProductStore.productStoreId)" interface="popover" :placeholder="translate('primary identifier')" :value="productStoreSettings['productIdentificationPref'].primaryId" @ionChange="setProductIdentificationPref($event.detail.value, 'primaryId')">
<ion-select-option v-for="identification in productIdentifications" :key="identification" :value="identification" >{{ identification }}</ion-select-option>
</ion-select>
</ion-item>
<ion-item>
<ion-select :label="translate('Secondary Product Identifier')" :disabled="!hasPermission(Actions.APP_PRODUCT_IDENTIFIER_UPDATE) || !(currentFacility?.productStore?.productStoreId || currentProductStore.productStoreId)" interface="popover" :placeholder="translate('secondary identifier')" :value="productStoreSettings['productIdentificationPref'].secondaryId" @ionChange="setProductIdentificationPref($event.detail.value, 'secondaryId')">
<ion-select :label="translate('Secondary')" :disabled="!hasPermission(Actions.APP_PRODUCT_IDENTIFIER_UPDATE) || !(currentFacility?.productStore?.productStoreId || currentProductStore.productStoreId)" interface="popover" :placeholder="translate('secondary identifier')" :value="productStoreSettings['productIdentificationPref'].secondaryId" @ionChange="setProductIdentificationPref($event.detail.value, 'secondaryId')">
<ion-select-option v-for="identification in productIdentifications" :key="identification" :value="identification" >{{ identification }}</ion-select-option>
<ion-select-option value="">{{ translate("None") }}</ion-select-option>
</ion-select>
Expand All @@ -153,8 +153,6 @@ const store = useStore()
const appVersion = ref("")
const appInfo = (process.env.VUE_APP_VERSION_INFO ? JSON.parse(process.env.VUE_APP_VERSION_INFO) : {}) as any

const productIdentifications = process.env.VUE_APP_PRDT_IDENT ? JSON.parse(process.env.VUE_APP_PRDT_IDENT) : []

const userProfile = computed(() => store.getters["user/getUserProfile"])
const oms = computed(() => store.getters["user/getInstanceUrl"])
const omsRedirectionInfo = computed(() => store.getters["user/getOmsRedirectionInfo"])
Expand All @@ -163,9 +161,11 @@ const currentFacility = computed(() => store.getters["user/getCurrentFacility"])
const currentProductStore = computed(() => store.getters["user/getCurrentProductStore"])
const productStores = computed(() => store.getters["user/getProductStores"])
const productStoreSettings = computed(() => store.getters["user/getProductStoreSettings"])
const productIdentifications = computed(() => store.getters["user/getGoodIdentificationTypes"])

onMounted(() => {
onMounted(async () => {
appVersion.value = appInfo.branch ? (appInfo.branch + "-" + appInfo.revision) : appInfo.tag;
await store.dispatch("user/fetchGoodIdentificationTypes")
})

function logout() {
Expand Down
Loading