Skip to content

Commit

Permalink
Improved: logic to reject entire order(#903)
Browse files Browse the repository at this point in the history
Removed logic to display rejected items and the corresponding actions and services
Implemented support to reject entire order at once, only if any of the order items are not shipped
  • Loading branch information
ymaheshwari1 committed Feb 7, 2025
1 parent 62737d0 commit a52932b
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 182 deletions.
25 changes: 18 additions & 7 deletions src/components/TransferOrderItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,20 @@
<ion-progress-bar :color="getProgressBarColor(item)" :value="getPickedToOrderedFraction(item)" />
</div>

<div class="to-item-history" v-if="isRejectionSupported && !getShippedQuantity(item)">
<ion-chip outline v-if="!item.rejectReasonId" @click="openRejectReasonPopover($event, item)">
<ion-label>{{ translate("Report an issue") }}</ion-label>
<ion-icon :icon="caretDownOutline"/>
</ion-chip>
<ion-chip outline color="danger" v-else @click="openRejectReasonPopover($event, item)">
<div class="to-item-history" v-if="isRejectionSupported && !isAnyItemShipped">
<ion-chip outline color="danger" v-if="item.rejectReasonId" @click="openRejectReasonPopover($event, item)">
<ion-icon :icon="closeCircleOutline" @click.stop="removeRejectionReason(item)"/>
<ion-label>{{ getRejectionReasonDescription(item.rejectReasonId) }}</ion-label>
<ion-icon :icon="caretDownOutline"/>
</ion-chip>
<ion-chip outline v-else-if="isAnyItemSelectedForRejection" @click="openRejectReasonPopover($event, item)">
<ion-label>{{ getRejectionReasonDescription(defaultRejectReasonId) }}</ion-label>
<ion-icon :icon="caretDownOutline"/>
</ion-chip>
<ion-chip outline v-else @click="openRejectReasonPopover($event, item)">
<ion-label>{{ translate("Report an issue") }}</ion-label>
<ion-icon :icon="caretDownOutline"/>
</ion-chip>
</div>

<div class="to-item-history" v-else>
Expand Down Expand Up @@ -106,7 +110,8 @@ export default defineComponent({
data() {
return {
pickedQuantity: this.itemDetail.pickedQuantity,
item: this.itemDetail
item: this.itemDetail,
defaultRejectReasonId: "NO_VARIANCE_LOG" // default variance reason, to be used when any other item is selected for rejection
}
},
computed: {
Expand All @@ -116,6 +121,12 @@ export default defineComponent({
isForceScanEnabled: 'util/isForceScanEnabled',
rejectReasons: "transferorder/getRejectReasons"
}),
isAnyItemSelectedForRejection() {
return this.currentOrder.items.some((item: any) => item.rejectReasonId)
},
isAnyItemShipped() {
return !!Object.keys(this.currentOrder?.shippedQuantityInfo)?.length
}
},
methods: {
getProgressBarColor(item: any) {
Expand Down
2 changes: 1 addition & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
"Failed to send to Retail Pro Server due to the following error, please contact support:.": "Failed to send to Retail Pro Server due to the following error, please contact support: {message}.",
"Failed to ship order": "Failed to ship order",
"Failed to reject in progress orders": "Failed to reject in progress orders",
"Failed to reject order items": "Failed to reject order items",
"Failed to reject order": "Failed to reject order",
"Failed to reject outstanding orders": "Failed to reject outstanding orders",
"Failed to remove rejection reason.": "Failed to remove rejection reason.",
"Failed to update carrier and shipment method association.": "Failed to update carrier and shipment method association.",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@
"Failed to send to Retail Pro Server due to the following error, please contact support:.": "Erro al enviar al servidor de Ratail Pro debido al siguiente error, por favor contactar a soporte: {message}.",
"Failed to ship order": "Error al enviar el pedido",
"Failed to reject in progress orders": "Error al rechazar pedidos en curso",
"Failed to reject order items": "Failed to reject order items",
"Failed to reject order": "Failed to reject order",
"Failed to reject outstanding orders": "Error al rechazar pedidos pendientes",
"Failed to remove rejection reason.": "Error al eliminar la razon de rechazo.",
"Failed to update carrier and shipment method association.": "Error al actualizar transportadora y asociación de metodo de envio.",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
"Failed to send to Retail Pro Server due to the following error, please contact support:.": "Failed to send to Retail Pro Server due to the following error, please contact support: {message}.",
"Failed to ship order": "注文の出荷に失敗しました",
"Failed to reject in progress orders": "進行中の注文の拒否に失敗しました",
"Failed to reject order items": "Failed to reject order items",
"Failed to reject order": "Failed to reject order",
"Failed to reject outstanding orders": "未処理の注文の拒否に失敗しました",
"Failed to remove rejection reason.": "拒否理由の削除に失敗しました。",
"Failed to update carrier and shipment method association.": "キャリアと出荷方法の関連付けの更新に失敗しました。",
Expand Down
94 changes: 0 additions & 94 deletions src/services/OrderService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,98 +58,6 @@ const fetchOrderItems = async (orderId: string): Promise<any> => {
return orderItems
}

const fetchRejectedOrderItems = async (orderId: string): Promise<any> => {
let viewIndex = 0;
let orderItems = [] as any, resp;

try {
do {
resp = await api({
url: "performFind",
method: "get",
params : {
"entityName": "OrderItemAndShipGroup",
"inputFields": {
"orderId": orderId,
"facilityId": "REJECTED_ITM_PARKING" // When rejecting order items they will be moved to mentioned parking
},
"fieldList": ["orderId", "orderItemSeqId", "productId", "shipGroupSeqId", "facilityId"],
"viewIndex": viewIndex,
"viewSize": 250, // maximum records we could have
"distinct": "Y",
"noConditionFind": "Y"
}
}) as any;

if (!hasError(resp) && resp.data.count) {
orderItems = orderItems.concat(resp.data.docs)
viewIndex++;
} else {
throw resp.data;
}
}
while (resp.data.docs.length >= 250);
} catch (error) {
logger.error(error);
}
return orderItems
}

const fetchOrderItemRejectionInfo = async(orderItems: Array<any>, orderId: string): Promise<any> => {
let rejectedItemsInfo = [] as Array<any>;
const rejectedItemIds = orderItems.map((item: any) => item.productId);

const filters = {
productId_s: { value: rejectedItemIds },
orderId_s: { value: orderId }
}

const query = prepareSolrQuery({
coreName: "logInsights",
docType: "FULFILLMENT_REJECTION",
viewIndex: 0,
viewSize: rejectedItemIds.length,
sort: 'rejectedAt_dt desc',
filters
})

try {
const resp = await api({
url: "solr-query",
method: "post",
data: query
}) as any;

if(!hasError(resp) && resp?.data?.response?.docs?.length > 0) {
const rejectionReasons = store.getters["transferorder/getRejectReasons"]

const items = orderItems.reduce((items: any, item: any) => {
items[item.productId] = item
return items;
}, {})
rejectedItemsInfo = resp?.data?.response?.docs.map((item: any) => ({
...items[item.productId_s],
orderId: item.orderId_s,
orderItemSeqId: item.orderItemSeqId_s,
itemDescription: item.itemDescription_txt_en,
rejectedBy: item.rejectedBy_txt_en,
rejectedAt: item.rejectedAt_dt,
rejectionReasonId: item.rejectionReasonId_txt_en,
rejectionReasonDesc: rejectionReasons?.find((reason: any) => reason.enumId === item.rejectionReasonId_txt_en)?.description || item.rejectionReasonId_txt_en,
brokeredAt: item.brokeredAt_dt,
brokeredBy: item.brokeredBy_txt_en
}))
} else {
throw resp.data;
}
} catch(err) {
logger.error("Rejection information not found for items")
return orderItems;
}

return rejectedItemsInfo;
}

const fetchShippedQuantity = async (orderId: string): Promise<any> => {
let docCount = 0;
let shippedItemQuantitySum = [] as any
Expand Down Expand Up @@ -1005,9 +913,7 @@ export const OrderService = {
fetchAdditionalShipGroupForOrder,
fetchOrderAttribute,
fetchOrderHeader,
fetchOrderItemRejectionInfo,
fetchOrderItems,
fetchRejectedOrderItems,
fetchRejectReasons,
fetchShipmentCarrierDetail,
fetchShipmentItems,
Expand Down
17 changes: 2 additions & 15 deletions src/store/modules/transferorder/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,7 @@ const actions: ActionTree<TransferOrderState, RootState> = {
orderDetail = resp.data.docs?.[0];

//fetch order items
const orderItems = await OrderService.fetchOrderItems(payload.orderId);
const rejectedItems = await OrderService.fetchRejectedOrderItems(payload.orderId);

const rejectedItemsSeqId = rejectedItems?.map((item: any) => item.orderItemSeqId)
orderDetail.rejectedItems = orderItems?.filter((item: any) => rejectedItemsSeqId.includes(item.orderItemSeqId))
orderDetail.items = orderItems?.filter((item: any) => !rejectedItemsSeqId.includes(item.orderItemSeqId))

orderDetail.items = await OrderService.fetchOrderItems(payload.orderId);
if (orderDetail?.items?.length > 0) {
orderDetail.items.forEach((item: any) => {
item.pickedQuantity = 0;
Expand All @@ -121,15 +115,9 @@ const actions: ActionTree<TransferOrderState, RootState> = {
shippedQuantityInfo[doc.orderItemSeqId] = doc.shippedQuantity;
});
orderDetail.shippedQuantityInfo = shippedQuantityInfo;
}

if(orderDetail?.rejectedItems?.length) {
orderDetail.rejectedItems = await OrderService.fetchOrderItemRejectionInfo(orderDetail.rejectedItems, orderDetail.orderId)
}

if(orderItems?.length) {
//fetch product details
const productIds = [...new Set(orderItems.map((item:any) => item.productId))];
const productIds = [...new Set(orderDetail.items.map((item:any) => item.productId))];

const batchSize = 250;
const productIdBatches = [];
Expand All @@ -138,7 +126,6 @@ const actions: ActionTree<TransferOrderState, RootState> = {
}
await Promise.all([productIdBatches.map((productIds) => this.dispatch('product/fetchProducts', { productIds })), this.dispatch('util/fetchStatusDesc', [orderDetail.statusId])])
}

commit(types.ORDER_CURRENT_UPDATED, orderDetail)
} else {
throw resp.data;
Expand Down
74 changes: 11 additions & 63 deletions src/views/TransferOrderDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@
<ion-segment-button value="completed">
<ion-label>{{ translate("Completed") }}</ion-label>
</ion-segment-button>
<ion-segment-button value="rejected">
<ion-label>{{ translate("Rejected") }}</ion-label>
</ion-segment-button>
</ion-segment>
<div class="segments" v-if="currentOrder">
<template v-if="selectedSegment === 'open'">
Expand All @@ -51,7 +48,7 @@
</div>
</template>
</template>
<template v-else-if="selectedSegment === 'completed'">
<template v-else>
<template v-if="getShipments('shipped')?.length > 0">
<ion-card class="order" v-for="(shipment, index) in getShipments('shipped')" :key="index">
<div class="order-header">
Expand Down Expand Up @@ -114,47 +111,6 @@
</div>
</template>
</template>
<template v-else>
<template v-if="currentOrder.rejectedItems?.length > 0">
<ion-card v-for="item in currentOrder.rejectedItems" :key="item.orderItemSeqId">
<div class="list-item">
<div class="product-info">
<ion-item lines="none">
<ion-thumbnail slot="start">
<DxpShopifyImg :src="getProduct(item.productId).mainImageUrl" size="small"/>
</ion-thumbnail>
<ion-label class="ion-text-wrap">
<p class="overline">{{ getProductIdentificationValue(productIdentificationPref.secondaryId, getProduct(item.productId)) }}</p>
{{ getProductIdentificationValue(productIdentificationPref.primaryId, getProduct(item.productId)) ? getProductIdentificationValue(productIdentificationPref.primaryId, getProduct(item.productId)) : item.productName }}
<p>{{ getFeature(getProduct(item.productId).featureHierarchy, '1/COLOR/')}} {{ getFeature(getProduct(item.productId).featureHierarchy, '1/SIZE/')}}</p>
</ion-label>
</ion-item>
</div>
<ion-label>
{{ formatUtcDate(item.rejectedAt, "dd MMMM yyyy hh:mm a ZZZZ")}}
<p>{{ translate("rejected time") }}</p>
</ion-label>
<ion-label>
{{ item.quantity }}
<p>{{ translate("ordered") }}</p>
</ion-label>
<ion-label>
{{ item.rejectionReasonDesc }}
<p>{{ translate("rejection reason") }}</p>
</ion-label>
<ion-chip outline>
<ion-icon :icon="personCircleOutline" />
<ion-label>{{ item.rejectedBy }}</ion-label>
</ion-chip>
</div>
</ion-card>
</template>
<template v-else>
<div class="empty-state">
<p>{{ translate('No data available') }}</p>
</div>
</template>
</template>
</div>
</main>
</ion-content>
Expand Down Expand Up @@ -213,7 +169,7 @@
import Scanner from "@/components/Scanner.vue";
import { Actions, hasPermission } from '@/authorization'
import { DateTime } from 'luxon';
import { formatUtcDate, getFeature, showToast } from '@/utils';
import { getFeature, showToast } from '@/utils';
import { hasError } from '@/adapter';
import { OrderService } from '@/services/OrderService'
import TransferOrderItem from '@/components/TransferOrderItem.vue'
Expand Down Expand Up @@ -253,7 +209,8 @@
queryString: '',
selectedSegment: 'open',
isCreatingShipment: false,
lastScannedId: ''
lastScannedId: '',
defaultRejectReasonId: "NO_VARIANCE_LOG" // default variance reason, to be used when any other item is selected for rejection
}
},
async ionViewWillEnter() {
Expand Down Expand Up @@ -445,11 +402,9 @@
items: []
} as any
const itemsToReject = this.currentOrder.items.filter((item: any) => item.rejectReasonId)
itemsToReject.map((item: any) => {
this.currentOrder.items.map((item: any) => {
payload.items.push({
rejectReason: item.rejectReasonId,
rejectReason: item.rejectReasonId || this.defaultRejectReasonId,
facilityId: this.currentOrder.facilityId,
orderItemSeqId: item.orderItemSeqId,
shipmentMethodTypeId: this.currentOrder.shipmentMethodTypeId,
Expand All @@ -462,14 +417,16 @@
const resp = await OrderService.rejectOrderItems({ payload });
if(!hasError(resp) && resp.data?.rejectedItemsList.length) {
await this.store.dispatch("transferorder/fetchTransferOrderDetail", { orderId: this.$route.params.orderId })
showToast(translate("Order items are rejected"))
showToast(translate("All order items are rejected"))
this.$router.replace("/transfer-orders")
} else {
throw resp;
}
} catch(err) {
logger.error(err);
showToast(translate("Failed to reject order items"))
showToast(translate("Failed to reject order"))
// If there is any error in rejecting the order, fetch the updated order information
await this.store.dispatch("transferorder/fetchTransferOrderDetail", { orderId: this.$route.params.orderId })
}
emitter.emit("dismissLoader")
Expand All @@ -493,7 +450,6 @@
add,
barcodeOutline,
checkmarkDone,
formatUtcDate,
getFeature,
getProductIdentificationValue,
hasPermission,
Expand Down Expand Up @@ -524,13 +480,5 @@
*/
outline: 2px solid var( --ion-color-medium-tint);
}
ion-thumbnail {
cursor: pointer;
}
.list-item {
--columns-desktop: 5;
}
</style>

0 comments on commit a52932b

Please sign in to comment.