diff --git a/src/locales/en.json b/src/locales/en.json index 8d36c657..967f66d7 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -79,6 +79,7 @@ "Purchase Order": "Purchase Order", "Purchase Order Details": "Purchase Order Details", "Purchase Orders": "Purchase Orders", + "Purchase order received successfully" : "Purchase order received successfully {orderId}", "Qty": "Qty", "Receive": "Receive", "Receive All": "Receive All", diff --git a/src/services/OrderService.ts b/src/services/OrderService.ts index a10e0bc1..988e9495 100644 --- a/src/services/OrderService.ts +++ b/src/services/OrderService.ts @@ -24,6 +24,14 @@ const createPurchaseShipment = async (payload: any): Promise => { }) } +const createIncomingShipment = async (payload: any): Promise => { + return api({ + url: "/service/createIncomingShipment", + method: "POST", + data: payload + }) +} + const fetchPOHistory = async (payload: any): Promise => { return api({ url: "/performFind", @@ -43,6 +51,7 @@ const updatePOItemStatus = async (payload: any): Promise => { export const OrderService = { fetchPurchaseOrders, fetchPODetail, + createIncomingShipment, createPurchaseShipment, fetchPOHistory, updatePOItemStatus diff --git a/src/services/UploadService.ts b/src/services/UploadService.ts new file mode 100644 index 00000000..923450dc --- /dev/null +++ b/src/services/UploadService.ts @@ -0,0 +1,42 @@ +import { api } from '@/adapter'; +import { UploadRequest } from '@/types' + +const uploadJsonFile = async (payload: any): Promise => { + return api({ + url: "uploadAndImportFile", + method: "post", + ...payload + }); +} + +const prepareUploadJsonPayload = (request: UploadRequest) => { + const blob = new Blob([JSON.stringify(request.uploadData)], { type: 'application/json'}); + const formData = new FormData(); + const fileName = request.fileName ? request.fileName : Date.now() + ".json" ; + formData.append("uploadedFile", blob, fileName); + if (request.params) { + for (const key in request.params) { + formData.append(key, request.params[key]); + } + } + return { + data: formData, + headers: { + 'Content-Type': 'multipart/form-data;' + } + } +} + +const fetchDataManagerLog = async (payload: any): Promise => { + return api({ + url: "/performFind", + method: "POST", + data: payload + }) +} + +export const UploadService = { + fetchDataManagerLog, + prepareUploadJsonPayload, + uploadJsonFile +} \ No newline at end of file diff --git a/src/store/modules/order/actions.ts b/src/store/modules/order/actions.ts index 9d56b736..55258b2e 100644 --- a/src/store/modules/order/actions.ts +++ b/src/store/modules/order/actions.ts @@ -164,6 +164,50 @@ const actions: ActionTree = { return resp; }, + async createAndReceiveIncomingShipment({ commit }, payload) { + let resp; + try { + payload.items.map((item: any, index: number) => { + item.itemSeqId = `1000${index+1}` + item.quantity = item.quantityAccepted + }) + + const params = { + orderId: payload.orderId, + destinationFacilityId: this.state.user.currentFacility.facilityId, + "type": "PURCHASE_SHIPMENT", + "status": "PURCH_SHIP_CREATED", + "items": payload.items + } + resp = await OrderService.createIncomingShipment({"payload": params}) + + if (resp.status === 200 && !hasError(resp) && resp.data.shipmentId) { + const facilityLocations = await this.dispatch('user/getFacilityLocations', this.state.user.currentFacility.facilityId); + if (facilityLocations.length){ + const locationSeqId = facilityLocations[0].locationSeqId + payload.items.map((item: any) => { + item.locationSeqId = locationSeqId + item.quantityReceived = item.quantityAccepted ? Number(item.quantityAccepted) : 0 + }) + } else { + showToast(translate("Facility locations were not found corresponding to destination facility of PO. Please add facility locations to avoid receive PO failure.")) + } + const poShipment = { + shipmentId : resp.data.shipmentId, + items: payload.items, + isMultiReceivingEnabled: true + } + return await this.dispatch('shipment/receiveShipmentJson', poShipment).catch((err) => console.error(err)) + } else { + showToast(translate("Something went wrong")); + } + } catch(error){ + console.error(error) + showToast(translate("Something went wrong")); + } + return false; + }, + async getPOHistory({ commit, state }, payload) { let resp; const current = state.current as any; @@ -175,7 +219,8 @@ const actions: ActionTree = { }, "entityName": "ShipmentReceiptAndItem", "fieldList": ["datetimeReceived", "productId", "quantityAccepted", "quantityRejected", "receivedByUserLoginId", "shipmentId", 'locationSeqId'], - "orderBy": 'datetimeReceived DESC' + "orderBy": 'datetimeReceived DESC', + "viewSize": "250" } const facilityLocations = await this.dispatch('user/getFacilityLocations', this.state.user.currentFacility.facilityId); const locationSeqId = facilityLocations.length > 0 ? facilityLocations[0].locationSeqId : ""; diff --git a/src/store/modules/return/actions.ts b/src/store/modules/return/actions.ts index 4bd19b35..7deb5c05 100644 --- a/src/store/modules/return/actions.ts +++ b/src/store/modules/return/actions.ts @@ -90,6 +90,7 @@ const actions: ActionTree = { const locationSeqId = facilityLocations[0].locationSeqId resp.data.items.map((item: any) => { item.locationSeqId = locationSeqId; + item.quantityReceived = item.quantityAccepted ? Number(item.quantityAccepted) : 0 }); } else { showToast(translate("Facility locations were not found corresponding to destination facility of return shipment. Please add facility locations to avoid receive return shipment failure.")) diff --git a/src/store/modules/shipment/actions.ts b/src/store/modules/shipment/actions.ts index 7eb7f5ed..ac9fe0e5 100644 --- a/src/store/modules/shipment/actions.ts +++ b/src/store/modules/shipment/actions.ts @@ -7,6 +7,9 @@ import { hasError, showToast } from '@/utils' import { getProductIdentificationValue, translate } from '@hotwax/dxp-components' import emitter from '@/event-bus' import store from "@/store"; +import { DateTime } from 'luxon'; +import { UploadService } from "@/services/UploadService"; +import { toHandlerKey } from "vue"; const actions: ActionTree = { async findShipment ({ commit, state }, payload) { @@ -138,6 +141,75 @@ const actions: ActionTree = { return areAllSuccess; }, + async receiveShipmentJson ({ dispatch }, payload) { + emitter.emit("presentLoader"); + const fileName = `ReceiveShipment_${payload.shipmentId}_${DateTime.now().toLocaleString(DateTime.DATETIME_MED_WITH_SECONDS)}.json`; + const params = { + "configId": "RECEIVE_SHIP_ITEMS" + } + if(!payload.isMultiReceivingEnabled) { + payload.items = payload.items.filter((item: any) => item.quantityReceived === 0) + } + const uploadData = payload.items.map((item: any) => { + return { + shipmentId: payload.shipmentId, + facilityId: this.state.user.currentFacility.facilityId, + shipmentItemSeqId: item.itemSeqId, + productId: item.productId, + quantityAccepted: item.quantityAccepted, + orderId: item.orderId, + orderItemSeqId: item.orderItemSeqId, + unitCost: 0.00, + locationSeqId: item.locationSeqId + }; + }) + + try { + const uploadPayload = UploadService.prepareUploadJsonPayload({ + uploadData, + fileName, + params + }); + let resp = await UploadService.uploadJsonFile(uploadPayload); + if (resp.status == 200 && !hasError(resp)) { + const uploadFileContentId = resp.data.uploadFileContentId; + if (uploadFileContentId) { + resp = await UploadService.fetchDataManagerLog({ + "inputFields": { + "configId": "RECEIVE_SHIP_ITEMS", + "uploadFileContentId": uploadFileContentId, + "errorRecordContentId_op": "empty", + "statusI": "SERVICE_FINISHED", + }, + "fieldList": ["logId", "configId", "uploadFileContentId", "errorRecordContentId", "statusId"], + "entityName": "DataManagerLog", + "viewSize": 1 + }); + if (!hasError(resp) && resp.data.docs.length) { + //If there is no error and file is processed then mark the shipment as received + resp = await ShipmentService.receiveShipment({ + "shipmentId": payload.shipmentId, + "statusId": "PURCH_SHIP_RECEIVED" + }) + if (resp.status == 200 && !hasError(resp)) { + return true; + } else { + throw resp.data; + } + } else { + throw resp.data; + } + } + } else { + throw resp.data; + } + } catch (err) { + showToast(translate("Something went wrong, please try again")); + } + emitter.emit("dismissLoader"); + return false; + }, + async receiveShipment ({ dispatch }, payload) { emitter.emit("presentLoader", {message: 'Receiving in-progress.', backdropDismiss: false}); const areAllSuccess = await dispatch("receiveShipmentItem", payload); diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 00000000..980465b0 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,5 @@ +export interface UploadRequest { + params?: any; + fileName?: string; + uploadData: any; +} \ No newline at end of file diff --git a/src/views/PurchaseOrderDetail.vue b/src/views/PurchaseOrderDetail.vue index c55fc3cf..ec989379 100644 --- a/src/views/PurchaseOrderDetail.vue +++ b/src/views/PurchaseOrderDetail.vue @@ -361,9 +361,14 @@ export default defineComponent({ }, async createShipment() { const eligibleItems = this.order.items.filter((item: any) => item.quantityAccepted > 0) - const resp = await this.store.dispatch('order/createPurchaseShipment', { items: eligibleItems, orderId: this.order.orderId }) - if (resp.status === 200 && !hasError(resp)) { + const isShipmentReceived = await this.store.dispatch('order/createAndReceiveIncomingShipment', { items: eligibleItems, orderId: this.order.orderId }) + if (isShipmentReceived) { + showToast(translate("Purchase order received successfully", { orderId: this.order.orderId })) this.router.push('/purchase-orders') + } else { + this.store.dispatch("order/getOrderDetail", { orderId: this.$route.params.slug }).then(() => { + this.store.dispatch('order/getPOHistory', { orderId: this.order.orderId }) + }) } }, isEligibileForCreatingShipment() { diff --git a/src/views/ReturnDetails.vue b/src/views/ReturnDetails.vue index 4b77b2f2..b5ac1fd7 100644 --- a/src/views/ReturnDetails.vue +++ b/src/views/ReturnDetails.vue @@ -55,17 +55,17 @@
- + - + {{ item.quantityAccepted }} {{ translate("received") }}
- + {{ translate("Receive All") }} @@ -228,9 +228,13 @@ export default defineComponent({ async receiveReturn() { const eligibleItems = this.current.items.filter((item: any) => item.quantityAccepted > 0) const shipmentId = this.current.shipment ? this.current.shipment.shipmentId : this.current.shipmentId - let resp = await this.store.dispatch('return/receiveReturn', { items: eligibleItems, shipmentId }); - if(resp.status === 200 && !hasError(resp)) { + let isReturnReceived = await this.store.dispatch('shipment/receiveShipmentJson', { items: eligibleItems, shipmentId }); + if (isReturnReceived) { + showToast(translate("Return received successfully", { shipmentId: shipmentId })) this.router.push('/returns'); + } else { + showToast(translate('Something went wrong')); + await this.store.dispatch('return/setCurrent', { shipmentId: this.$route.params.id }) } }, isEligibleForReceivingReturns() { diff --git a/src/views/ShipmentDetails.vue b/src/views/ShipmentDetails.vue index 50ff3e44..4a71f370 100644 --- a/src/views/ShipmentDetails.vue +++ b/src/views/ShipmentDetails.vue @@ -225,8 +225,9 @@ export default defineComponent({ async receiveShipment() { const eligibleItems = this.current.items.filter((item: any) => item.quantityAccepted > 0) const shipmentId = this.current.shipment ? this.current.shipment.shipmentId : this.current.shipmentId - const isShipmentReceived = await this.store.dispatch('shipment/receiveShipment', { items: eligibleItems, shipmentId }) - if(isShipmentReceived) { + const isShipmentReceived = await this.store.dispatch('shipment/receiveShipmentJson', { items: eligibleItems, shipmentId }) + if (isShipmentReceived) { + showToast(translate("Shipment received successfully", { shipmentId: shipmentId })) this.router.push('/shipments'); } else { showToast(translate("Failed to receive shipment"))