Skip to content

Commit

Permalink
Merge pull request #582 from amansinghbais/#559-persist
Browse files Browse the repository at this point in the history
Improved: persisting the unmatched product in the cycle count as long as count is not submitted (#559)
  • Loading branch information
ymaheshwari1 authored Jan 8, 2025
2 parents fa24c85 + 929f674 commit 684490f
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 40 deletions.
2 changes: 1 addition & 1 deletion src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { setPermissions } from "@/authorization"
const state: any = {}

const persistState = createPersistedState({
paths: ["user", "product.cached"],
paths: ["user", "product.cached", "count.cachedUnmatchProducts"],
fetchBeforeUse: true
})

Expand Down
1 change: 1 addition & 0 deletions src/store/modules/count/CountState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export default interface CountState {
cycleCountItems: any;
cycleCountImportSystemMessages: Array<any>;
defaultRecountUpdateBehaviour: String;
cachedUnmatchProducts: any;
}
20 changes: 18 additions & 2 deletions src/store/modules/count/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,16 @@ const actions: ActionTree<CountState, RootState> = {
commit(types.COUNT_LIST_UPDATED, { counts, total , isScrollable })
},

async fetchCycleCountStats({ commit }, inventoryCountImportIds) {
async fetchCycleCountStats({ commit, state }, inventoryCountImportIds) {
const cachedProducts = JSON.parse(JSON.stringify(state.cachedUnmatchProducts))
try {
const resp = await CountService.fetchCycleCountStats({ inventoryCountImportIds });

if(!hasError(resp) && resp.data?.importStats?.length > 0) {

// Sorting the statusHistory based on statusDate, as in response we are getting this information sorted on statusId
resp.data.importStats.map((stats: any) => {
stats["totalItems"] = stats["totalItems"] + (cachedProducts[stats.inventoryCountImportId]?.length || 0)
stats.statusHistory.sort((a: any, b: any) => {
if(a["statusDate"] === b["statusDate"]) return 0;

Expand Down Expand Up @@ -177,7 +179,8 @@ const actions: ActionTree<CountState, RootState> = {
commit(types.COUNT_UPDATED, {})
},

async fetchCycleCountItems({commit} ,payload) {
async fetchCycleCountItems({commit, state} ,payload) {
const cachedProducts = state.cachedUnmatchProducts[payload.inventoryCountImportId]?.length ? JSON.parse(JSON.stringify(state.cachedUnmatchProducts[payload.inventoryCountImportId])) : [];
let items = [] as any, resp, pageIndex = 0;

try {
Expand All @@ -194,6 +197,7 @@ const actions: ActionTree<CountState, RootState> = {
logger.error(err)
}
this.dispatch("product/fetchProducts", { productIds: [...new Set(items.map((item: any) => item.productId))] })
if(cachedProducts?.length) items = items.concat(cachedProducts)
commit(types.COUNT_ITEMS_UPDATED, { itemList: items })
},

Expand Down Expand Up @@ -225,6 +229,18 @@ const actions: ActionTree<CountState, RootState> = {
}
commit(types.COUNT_IMPORT_SYSTEM_MESSAGES_UPDATED, systemMessages)
},

async updateCachedUnmatchProducts({commit, state}, payload) {
const cachedUnmatchProducts = JSON.parse(JSON.stringify(state.cachedUnmatchProducts));
cachedUnmatchProducts[payload.id] = payload.unmatchedProducts;
commit(types.COUNT_CACHED_UNMATCH_PRODUCTS_UPDATED, cachedUnmatchProducts)
},

async clearCurrentCountFromCachedUnmatchProducts({commit, state}, id) {
const cachedUnmatchProducts = JSON.parse(JSON.stringify(state.cachedUnmatchProducts));
delete cachedUnmatchProducts[id]
commit(types.COUNT_CACHED_UNMATCH_PRODUCTS_UPDATED, cachedUnmatchProducts)
},
}

export default actions;
3 changes: 3 additions & 0 deletions src/store/modules/count/getters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const getters: GetterTree<CountState, RootState> = {
},
getDefaultRecountUpdateBehaviour(state) {
return state.defaultRecountUpdateBehaviour
},
getCachedUnmatchProducts: (state) => (id: string) => {
return state.cachedUnmatchProducts[id]
}
};

Expand Down
3 changes: 2 additions & 1 deletion src/store/modules/count/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const countModule: Module<CountState, RootState> = {
isScrollable: true
},
cycleCountItems: {},
defaultRecountUpdateBehaviour: "add"
defaultRecountUpdateBehaviour: "add",
cachedUnmatchProducts: {}
},
getters,
actions,
Expand Down
3 changes: 2 additions & 1 deletion src/store/modules/count/mutation-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export const COUNT_QUERY_CLEARED = SN_COUNT + "/QUERY_CLEARED"
export const COUNT_STATS_UPDATED = SN_COUNT + "/STATS_UPDATED"
export const COUNT_UPDATED = SN_COUNT + '/UPDATED'
export const COUNT_ITEMS_UPDATED = SN_COUNT + '/ITEMS_UPDATED'
export const COUNT_IMPORT_SYSTEM_MESSAGES_UPDATED = SN_COUNT + 'IMPORT_SYSTEM_MESSAGES_UPDATED'
export const COUNT_IMPORT_SYSTEM_MESSAGES_UPDATED = SN_COUNT + 'IMPORT_SYSTEM_MESSAGES_UPDATED'
export const COUNT_CACHED_UNMATCH_PRODUCTS_UPDATED = SN_COUNT + 'CACHED_UNMATCHED_PRODUCTS_UPDATED'
3 changes: 3 additions & 0 deletions src/store/modules/count/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ const mutations: MutationTree <CountState> = {
},
[types.COUNT_IMPORT_SYSTEM_MESSAGES_UPDATED] (state, payload) {
state.cycleCountImportSystemMessages = payload
},
[types.COUNT_CACHED_UNMATCH_PRODUCTS_UPDATED] (state, payload) {
state.cachedUnmatchProducts = payload
}

}
Expand Down
63 changes: 28 additions & 35 deletions src/views/HardCountDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ import { CountService } from "@/services/CountService";
import Image from "@/components/Image.vue";
import router from "@/router";
import MatchProductModal from "@/components/MatchProductModal.vue";
import { onBeforeRouteLeave } from 'vue-router';
const store = useStore();
Expand Down Expand Up @@ -259,46 +258,43 @@ onIonViewDidEnter(async() => {
await store.dispatch("product/currentProduct", itemsList.value?.length ? itemsList.value[0] : {})
barcodeInputRef.value?.$el?.setFocus();
selectedCountUpdateType.value = defaultRecountUpdateBehaviour.value
window.addEventListener('beforeunload', handleBeforeUnload);
})
onIonViewDidLeave(async() => {
window.removeEventListener('beforeunload', handleBeforeUnload);
await handleBeforeUnload();
await store.dispatch('count/updateCycleCountItems', []);
store.dispatch("product/currentProduct", {});
})
onBeforeRouteLeave(async (to) => {
if(to.path === "/login") return;
if(!hasUnsavedChanges()) return true;
let leavePage = false;
async function handleBeforeUnload() {
if(inputCount.value && isItemAlreadyAdded(currentProduct.value)) {
await saveCount(currentProduct.value);
inputCount.value = "";
}
const alert = await alertController.create({
header: translate("Leave page"),
message: translate("There are some unmatched or unsaved changes in this count. Any edits made in the counted quantity on this page will be lost."),
buttons: [
{
text: translate("STAY"),
handler: () => {
leavePage = false
const unmatchedProducts = [] as any;
cycleCountItems.value.itemList.map((item: any) => {
let unmatchedItem = {} as any;
if(item.isMatchNotFound || item.isMatching) {
unmatchedItem = { ...item, isMatching: false, isMatchNotFound: true }
if(unmatchedItem.scannedId === currentProduct.value.scannedId) {
if(unmatchedItem?.scannedCount) {
unmatchedItem = { ...unmatchedItem, scannedCount: selectedCountUpdateType.value === "replace" ? inputCount.value : (Number(inputCount.value) + Number(unmatchedItem.scannedCount)) }
} else {
unmatchedItem = { ...unmatchedItem, scannedCount: inputCount.value }
}
},
{
text: translate("LEAVE"),
handler: () => {
leavePage = true
},
},
],
});
inputCount.value = ""
}
}
alert.present();
const data = await alert.onDidDismiss()
// If clicking backdrop just close the modal and do not redirect the user to previous page
if(data?.role === "backdrop") {
return false;
}
if(Object.keys(unmatchedItem)?.length) unmatchedProducts.push(unmatchedItem)
})
return leavePage
})
store.dispatch("count/updateCachedUnmatchProducts", { id: cycleCount.value.inventoryCountImportId, unmatchedProducts });
}
async function fetchCycleCount() {
emitter.emit("presentLoader");
Expand Down Expand Up @@ -473,7 +469,7 @@ async function addProductToCount(productId: any) {
return newProduct;
}
async function updateCurrentItemInList(newItem: any, scannedValue: string) {
async function updateCurrentItemInList(newItem: any, scannedValue: string) {
const items = JSON.parse(JSON.stringify(cycleCountItems.value.itemList));
const updatedProduct = JSON.parse(JSON.stringify(currentProduct.value))
Expand Down Expand Up @@ -535,6 +531,7 @@ async function readyForReview() {
statusId: "INV_COUNT_REVIEW"
})
router.push("/tabs/count")
store.dispatch('count/clearCurrentCountFromCachedUnmatchProducts', props.id);
showToast(translate("Count has been submitted for review"))
} catch(err) {
showToast(translate("Failed to submit cycle count for review"))
Expand Down Expand Up @@ -673,10 +670,6 @@ function getVariance(item: any , isRecounting: boolean) {
return item.itemStatusId === "INV_COUNT_REJECTED" ? 0 : parseInt(isRecounting ? inputCount.value : qty) - parseInt(item.qoh)
}
function hasUnsavedChanges() {
return (inputCount.value && inputCount.value >= 0) || cycleCountItems.value.itemList.some((item: any) => item.scannedCount);
}
function isItemAlreadyAdded(product: any) {
return product.productId && product.importItemSeqId;
}
Expand Down

0 comments on commit 684490f

Please sign in to comment.