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

Improved: persisting the unmatched product in the cycle count as long as count is not submitted (#559) #582

Merged
merged 8 commits into from
Jan 8, 2025
2 changes: 1 addition & 1 deletion src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createStore, useStore as useVuexStore, Store } from "vuex";

Check warning on line 1 in src/store/index.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

'Store' is defined but never used

Check warning on line 1 in src/store/index.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

'Store' is defined but never used
import createPersistedState from "vuex-persistedstate";
import RootState from "./RootState"; // Ensure this is correctly imported
import mutations from "./mutations";
Expand All @@ -18,7 +18,7 @@
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 @@
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 @@
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 @@
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 All @@ -205,7 +209,7 @@
commit(types.COUNT_ITEMS_UPDATED, [])
},

async fetchCycleCountImportSystemMessages({commit} ,payload) {

Check warning on line 212 in src/store/modules/count/actions.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

'payload' is defined but never used

Check warning on line 212 in src/store/modules/count/actions.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

'payload' is defined but never used
let systemMessages;
try {
const twentyFourHoursEarlier = DateTime.now().minus({ hours: 24 });
Expand All @@ -225,6 +229,18 @@
}
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;
ymaheshwari1 marked this conversation as resolved.
Show resolved Hide resolved
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
Loading