diff --git a/src/components/Menu.vue b/src/components/Menu.vue index 2b3bfa86..0bbd41b9 100644 --- a/src/components/Menu.vue +++ b/src/components/Menu.vue @@ -68,7 +68,7 @@ export default defineComponent({ url: "/draft", iosIcon: createOutline, mdIcon: createOutline, - childRoutes: ["/draft/", "/bulkUpload", "/hard-count"], + childRoutes: ["/draft/", "/bulkUpload", "/hard-count", "/hard-count-detail"], meta: { permissionId: "APP_DRAFT_VIEW" } diff --git a/src/locales/en.json b/src/locales/en.json index 49521f42..f83207d1 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -12,6 +12,7 @@ "Any edits made in the counted quantity on this page will be lost.": "Any edits made in the counted quantity on this page will be lost.", "Add product": "Add product", "Add to count": "Add to count", + "Add to existing count": "Add to existing count", "Added product to count": "Added product to count", "App": "App", "Assigned count": "Assigned count", @@ -163,6 +164,7 @@ "Map all required fields": "Map all required fields", "Mapping name": "Mapping name", "Match product": "Match product", + "matching...": "matching...", "Name - A to Z": "Name - A to Z", "Name - Z to A": "Name - Z to A", "New Count": "New Count", @@ -173,6 +175,7 @@ "No items found": "No items found", "No new file upload. Please try again.": "No new file upload. Please try again.", "No products found.": "No products found.", + "no match found": "no match found", "No new file upload. Please try again": "No new file upload. Please try again", "No rejection history": "No rejection history", "No results found": "No results found", @@ -228,6 +231,7 @@ "Re-assign": "Re-assign", "Re-submitted": "Re-submitted", "Remove from count": "Remove from count", + "Replace existing count": "Replace existing count", "Review count": "Review count", "rejected counts": "rejected counts", "Require barcode scanning": "Require barcode scanning", @@ -299,11 +303,13 @@ "The inventory will be immediately updated and cannot be undone. Are you sure you want to update the inventory variance?": "The inventory will be immediately updated and cannot be undone. Are you sure you want to update the inventory variance?", "The products in the upload list will be removed.": "The products in the upload list will be removed.", "The timezone you select is used to ensure automations you schedule are always accurate to the time you select.": "The timezone you select is used to ensure automations you schedule are always accurate to the time you select.", + "There are some unmatched or unsaved changes in this count. Any edits made in the counted quantity on this page will be lost.": "There are some unmatched or unsaved changes in this count. Any edits made in the counted quantity on this page will be lost.", "This is the name of the OMS you are connected to right now. Make sure that you are connected to the right instance before proceeding.": "This is the name of the OMS you are connected to right now. Make sure that you are connected to the right instance before proceeding.", "Timezone": "Timezone", "Time zone updated successfully": "Time zone updated successfully", "Total variance": "Total variance", "total variance": "total variance", + "UNMATCHED": "UNMATCHED", "Update": "Update", "Update count": "Update count", "Upload count": "Upload count", diff --git a/src/views/HardCountDetail.vue b/src/views/HardCountDetail.vue index 80a1f849..5d9b0e09 100644 --- a/src/views/HardCountDetail.vue +++ b/src/views/HardCountDetail.vue @@ -76,7 +76,7 @@ - + @@ -100,24 +100,26 @@ - - {{ translate("New count") }} - - - - - - - {{ translate("Add to existing count") }} - - - - - - {{ translate("Replace existing count") }} - - - + {{ translate((currentProduct.isMatchNotFound || currentProduct.isMatching) ? "Match product" : "Save count") }} @@ -258,7 +260,7 @@ onBeforeRouteLeave(async (to) => { const alert = await alertController.create({ header: translate("Leave page"), - message: translate("Any edits made in the counted quantity on this page will be lost."), + 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"), @@ -406,17 +408,19 @@ async function addProductToItemsList() { async function findProductFromIdentifier(scannedValue: string ) { const product = await store.dispatch("product/fetchProductByIdentification", { scannedValue }) - let importItemSeqId = ""; - if(product?.productId) importItemSeqId = await addProductToCount(product.productId) + let newItem = {} as any; + if(product?.productId) newItem = await addProductToCount(product.productId) setTimeout(() => { - updateCurrentItemInList(importItemSeqId, product, scannedValue); + updateCurrentItemInList(newItem, scannedValue); }, 1000) } async function addProductToCount(productId: any) { + let resp = {} as any, newProduct = {} as any; + try { - const resp = await CountService.addProductToCount({ + resp = await CountService.addProductToCount({ inventoryCountImportId: cycleCount.value.inventoryCountImportId, itemList: [{ idValue: productId, @@ -425,72 +429,56 @@ async function addProductToCount(productId: any) { }) if(!hasError(resp) && resp.data?.itemList?.length) { - return resp.data.itemList[0].importItemSeqId + const importItemSeqId = resp.data.itemList[0].importItemSeqId + + resp = await CountService.fetchCycleCountItems({ inventoryCountImportId: cycleCount.value.inventoryCountImportId, importItemSeqId, pageSize: 1 }) + if(!hasError(resp)) { + newProduct = resp.data[0]; + } else { + throw resp; + } + } else { + throw resp; } } catch(err) { logger.error("Failed to add product to count", err) } - return 0; + return newProduct; } -async function updateCurrentItemInList(importItemSeqId: any, product: any, scannedValue: string, isMatchedUpdate = false) { +async function updateCurrentItemInList(newItem: any, scannedValue: string) { const items = JSON.parse(JSON.stringify(cycleCountItems.value.itemList)); const updatedProduct = JSON.parse(JSON.stringify(currentProduct.value)) - let prevItem = {} as any, hasErrorSavingCount = false; - if(updatedProduct.scannedId === scannedValue && !isMatchedUpdate) { - if(importItemSeqId) { - updatedProduct["importItemSeqId"] = importItemSeqId - updatedProduct["productId"] = product.productId - updatedProduct["isMatchNotFound"] = false - } else { - updatedProduct["isMatchNotFound"] = true - } - updatedProduct["isMatching"] = false; - store.dispatch("product/currentProduct", updatedProduct); - } else if(importItemSeqId && isMatchedUpdate) { - prevItem = items.find((item: any) => item.scannedId === scannedValue); - - if(prevItem && prevItem?.scannedCount >= 0) { - try { - const resp = await CountService.updateCount({ - inventoryCountImportId: cycleCount.value.inventoryCountImportId, - importItemSeqId, - productId: product.productId, - quantity: prevItem.scannedCount, - countedByUserLoginId: userProfile.value.username - }) - - if(hasError(resp)) { - hasErrorSavingCount = true; - updatedProduct["isMatching"] = false; - updatedProduct["isMatchNotFound"] = false - updatedProduct["importItemSeqId"] = importItemSeqId - updatedProduct["productId"] = product.productId - updatedProduct["productId"] = updatedProduct.scannedCount - } - } catch(error) { - logger.error(error) + let updatedItem = items.find((item: any) => item.scannedId === scannedValue); + updatedItem = { ...updatedItem, ...newItem, isMatching: false } + updatedItem["isMatchNotFound"] = newItem?.importItemSeqId ? false : true + + if(updatedItem && updatedItem.scannedId !== updatedProduct.scannedId && updatedItem?.scannedCount) { + try { + const resp = await CountService.updateCount({ + inventoryCountImportId: cycleCount.value.inventoryCountImportId, + importItemSeqId: updatedItem?.importItemSeqId, + productId: updatedItem.productId, + quantity: updatedItem.scannedCount, + countedByUserLoginId: userProfile.value.username + }) + + if(hasError(resp)) { + updatedItem["quantity"] = updatedItem.scannedCount + delete updatedItem["scannedCount"]; } + } catch(error) { + logger.error(error) } } - items.map((item: any) => { - if(item.scannedId === scannedValue) { - if(importItemSeqId) { - item["importItemSeqId"] = importItemSeqId - item["productId"] = product.productId - item["isMatchNotFound"] = false - } else { - item["isMatchNotFound"] = true - } - item["isMatching"] = false; - if(prevItem && Object.keys(prevItem)?.length && !hasErrorSavingCount) { - item["quantity"] = item.scannedCount - delete item["scannedCount"] - } - } - }) + if(updatedProduct.scannedId === updatedItem.scannedId) { + store.dispatch("product/currentProduct", updatedItem); + } + + const currentItemIndex = items.findIndex((item: any) => item.scannedId === updatedItem.scannedId); + items[currentItemIndex] = updatedItem store.dispatch('count/updateCycleCountItems', items); } @@ -589,13 +577,13 @@ async function saveCount(currentProduct: any, isScrollEvent = false) { inventoryCountImportId: currentProduct.inventoryCountImportId, importItemSeqId: currentProduct.importItemSeqId, productId: currentProduct.productId, - quantity: selectedCountUpdateType.value === "all" ? inputCount.value : inputCount.value + (currentProduct.quantity || 0), + quantity: selectedCountUpdateType.value === "replace" ? inputCount.value : Number(inputCount.value) + Number(currentProduct.quantity || 0), countedByUserLoginId: userProfile.value.username }; const resp = await CountService.updateCount(payload); if (!hasError(resp)) { - currentProduct.quantity = inputCount.value + currentProduct.quantity = selectedCountUpdateType.value === "replace" ? inputCount.value : Number(inputCount.value) + Number(currentProduct.quantity || 0) currentProduct.countedByGroupName = userProfile.value.userFullName currentProduct.countedByUserLoginId = userProfile.value.username currentProduct.isRecounting = false; @@ -603,7 +591,7 @@ async function saveCount(currentProduct: any, isScrollEvent = false) { const items = JSON.parse(JSON.stringify(cycleCountItems.value.itemList)) items.map((item: any) => { if(item.importItemSeqId === currentProduct.importItemSeqId) { - item.quantity = currentProduct.quantity + item.quantity = selectedCountUpdateType.value === "replace" ? inputCount.value : Number(inputCount.value) + Number(currentProduct.quantity || 0) item.countedByGroupName = userProfile.value.userFullName item.countedByUserLoginId = userProfile.value.username } @@ -630,8 +618,8 @@ async function matchProduct(currentProduct: any) { addProductModal.onDidDismiss().then(async (result) => { if(result.data.selectedProduct) { const product = result.data.selectedProduct - const importItemSeqId = await addProductToCount(product.productId) - updateCurrentItemInList(importItemSeqId, product, currentProduct.scannedId, true); + const newItem = await addProductToCount(product.productId) + updateCurrentItemInList(newItem, currentProduct.scannedId); } }) @@ -650,7 +638,7 @@ function getVariance(item: any , isRecounting: boolean) { } function hasUnsavedChanges() { - return (inputCount.value && inputCount.value >= 0) || cycleCountItems.value.itemList.find((item: any) => item.scannedCount && !item.isMatchNotFound); + return (inputCount.value && inputCount.value >= 0) || cycleCountItems.value.itemList.some((item: any) => item.scannedCount); } function isItemAlreadyAdded(product: any) { diff --git a/src/views/ProductItemList.vue b/src/views/ProductItemList.vue index 5c669055..77d32c1a 100644 --- a/src/views/ProductItemList.vue +++ b/src/views/ProductItemList.vue @@ -10,6 +10,7 @@

{{ item.scannedId }}

+

{{ translate(item.isMatching ? "matching..." : "no match found") }}

{{ (!item.quantity && item.quantity !== 0) ? translate("not counted") : translate("units", { count: item.quantity }) }}