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

Implemented: support to reject transfer order items(#903) #935

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/components/ReportIssuePopover.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<template>
<ion-content>
<ion-list>
<ion-item v-for="reason in rejectReasonOptions" :key="reason.enumId" @click="updateIssue(reason.enumId)" button>
<!-- If getting reject reasons in props, then use the same otherwise get the reasons from the util state -->
<ion-item v-for="reason in (rejectReasons?.length ? rejectReasons : rejectReasonOptions)" :key="reason.enumId" @click="updateIssue(reason.enumId)" button>
{{ reason.description ? translate(reason.description) : reason.enumDescription ? translate(reason.enumDescription) : reason.enumId }}
</ion-item>
</ion-list>
Expand Down Expand Up @@ -31,7 +32,7 @@ export default defineComponent({
rejectReasonOptions: 'util/getRejectReasonOptions'
})
},
props: ["shipmentPackages"],
props: ["rejectReasons"],
methods: {
closePopover() {
popoverController.dismiss();
Expand Down
66 changes: 61 additions & 5 deletions src/components/TransferOrderItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,23 @@
<ion-progress-bar :color="getProgressBarColor(item)" :value="getPickedToOrderedFraction(item)" />
</div>

<div class="to-item-history">
<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>
<ion-chip outline @click="shippedHistory(item.productId)">
<ion-icon :icon="checkmarkDone"/>
<ion-label> {{ getShippedQuantity(item) }} {{ translate("shipped") }} </ion-label>
Expand All @@ -60,16 +76,18 @@ import {
IonProgressBar,
IonThumbnail,
modalController,
popoverController,
} from '@ionic/vue';
import { computed, defineComponent } from 'vue';
import { add, checkmarkDone, barcodeOutline } from 'ionicons/icons';
import { add, caretDownOutline, checkmarkDone, closeCircleOutline, barcodeOutline } from 'ionicons/icons';
import { mapGetters, useStore } from "vuex";
import { getProductIdentificationValue, DxpShopifyImg, translate, useProductIdentificationStore } from '@hotwax/dxp-components';

import { useRouter } from 'vue-router';
import { Actions } from '@/authorization'
import { getFeature } from '@/utils';
import ShippedHistoryModal from '@/components/ShippedHistoryModal.vue'
import ReportIssuePopover from './ReportIssuePopover.vue';


export default defineComponent({
Expand All @@ -86,19 +104,29 @@ export default defineComponent({
IonThumbnail,
DxpShopifyImg,
},
props: ["itemDetail"],
// As we are using the same component on detail and review page, thus defined prop isRejectionSupported
// for handing the case to enable rejection functionality
props: ["itemDetail", "isRejectionSupported"],
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: {
...mapGetters({
currentOrder: 'transferorder/getCurrent',
getProduct: 'product/getProduct',
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 Expand Up @@ -159,7 +187,33 @@ export default defineComponent({
},
getErrorText(item: any) {
return translate('The picked quantity cannot exceed the ordered quantity.') + " " + (this.getShippedQuantity(item) > 0 ? translate("already shipped.", {shippedQuantity: this.getShippedQuantity(item)}): '')
}
},
async openRejectReasonPopover(ev: Event, item: any) {
const reportIssuePopover = await popoverController.create({
component: ReportIssuePopover,
componentProps: { rejectReasons: this.rejectReasons },
event: ev,
translucent: true,
showBackdrop: false,
});

reportIssuePopover.present();

const result = await reportIssuePopover.onDidDismiss();

if(result.data) {
item.rejectReasonId = result.data
await this.store.dispatch('transferorder/updateCurrentTransferOrder', this.currentOrder)
}
},
async removeRejectionReason(item: any) {
delete item["rejectReasonId"];
await this.store.dispatch('transferorder/updateCurrentTransferOrder', this.currentOrder)
},
getRejectionReasonDescription(rejectionReasonId: string) {
const reason = this.rejectReasons?.find((reason: any) => reason.enumId === rejectionReasonId)
return reason?.description ? reason.description : reason?.enumDescription ? reason.enumDescription : reason?.enumId;
},
},
setup() {
const store = useStore();
Expand All @@ -172,7 +226,9 @@ export default defineComponent({
Actions,
add,
barcodeOutline,
caretDownOutline,
checkmarkDone,
closeCircleOutline,
getFeature,
getProductIdentificationValue,
productIdentificationPref,
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +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": "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 Expand Up @@ -372,6 +373,7 @@
"Order Identifications": "Order Identifications",
"Order Invoicing Status": "Order Invoicing Status",
"Order item sequence ID": "Order item sequence ID",
"Order items are rejected": "Order items are rejected",
"Order Lookup": "Order Lookup",
"Order level charges like shipping fees and taxes are being credited on this label becuase it is the first shipment of this order.": "Order level charges like shipping fees and taxes are being credited on this label becuase it is the first shipment of this order.",
"Order level charges like shipping fees and taxes were already charged to the customer on the first label generated for this order.Label was generated by facility with tracking code": "Order level charges like shipping fees and taxes were already charged to the customer on the first label generated for this order.{space}Label was generated by facility {facilityName} with tracking code {trackingCode}",
Expand Down Expand Up @@ -454,8 +456,10 @@
"Reject all open orders": "Reject all open orders",
"Reject to avoid order split (no variance)": "Reject to avoid order split (no variance)",
"Reject in progress orders.": "Reject { ordersCount } in progress orders.",
"Reject Items": "Reject Items",
"Reject open orders.": "Reject { ordersCount } open orders.",
"Reject order": "Reject order",
"Rejected": "Rejected",
"Rejected at": "Rejected at",
"Rejected by": "Rejected by",
"Rejected from": "Rejected from",
Expand Down
3 changes: 3 additions & 0 deletions src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +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": "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 Expand Up @@ -369,6 +370,7 @@
"Order ID": "ID del Pedido",
"Order Invoicing Status": "Estado de facturación de la orden ",
"Order item sequence ID": "Order item sequence ID",
"Order items are rejected": "Order items are rejected",
"Order Lookup": "Búsqueda de pedidos",
"Order level charges like shipping fees and taxes are being credited on this label becuase it is the first shipment of this order.": "Order level charges like shipping fees and taxes are being credited on this label becuase it is the first shipment of this order.",
"Order level charges like shipping fees and taxes were already charged to the customer on the first label generated for this order.Label was generated by facility with tracking code": "Order level charges like shipping fees and taxes were already charged to the customer on the first label generated for this order.{space}Label was generated by facility {facilityName} with tracking code {trackingCode}",
Expand Down Expand Up @@ -450,6 +452,7 @@
"Reject all in progress orders": "Rechazar todos los pedidos en curso",
"Reject all open orders": "Rechazar todos los pedidos abiertos",
"Reject in progress orders.": "Rechazar { ordersCount } pedidos en curso.",
"Reject Items": "Reject Items",
"Reject open orders.": "Rechazar { ordersCount } pedidos abiertos.",
"Reject order": "Rechazar pedido",
"Reject to avoid order split (no variance)": "Reject to avoid order split (no variance)",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +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": "Failed to reject order",
"Failed to reject outstanding orders": "未処理の注文の拒否に失敗しました",
"Failed to remove rejection reason.": "拒否理由の削除に失敗しました。",
"Failed to update carrier and shipment method association.": "キャリアと出荷方法の関連付けの更新に失敗しました。",
Expand Down Expand Up @@ -370,6 +371,7 @@
"Order Identifications": "注文識別",
"Order Invoicing Status": "Order Invoicing Status",
"Order item sequence ID": "Order item sequence ID",
"Order items are rejected": "Order items are rejected",
"Order Lookup": "注文検索",
"Order level charges like shipping fees and taxes are being credited on this label becuase it is the first shipment of this order.": "Order level charges like shipping fees and taxes are being credited on this label becuase it is the first shipment of this order.",
"Order level charges like shipping fees and taxes were already charged to the customer on the first label generated for this order.Label was generated by facility with tracking code": "Order level charges like shipping fees and taxes were already charged to the customer on the first label generated for this order.{space}Label was generated by facility {facilityName} with tracking code {trackingCode}",
Expand Down Expand Up @@ -451,9 +453,11 @@
"Reject all in progress orders": "進行中のすべての注文を拒否",
"Reject all open orders": "オープン注文をすべて拒否",
"Reject in progress orders.": "進行中の{ordersCount}件の注文を拒否。",
"Reject Items": "Reject Items",
"Reject open orders.": "オープンの{ordersCount}件の注文を拒否。",
"Reject order": "注文を拒否",
"Reject to avoid order split (no variance)": "Reject to avoid order split (no variance)",
"Rejected": "Rejected",
"Rejected at": "Rejected at",
"Rejected by": "Rejected by",
"Rejected from": "Rejected from",
Expand Down
20 changes: 20 additions & 0 deletions src/services/OrderService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { showToast, formatPhoneNumber } from '@/utils';
import store from '@/store';
import { cogOutline } from 'ionicons/icons';
import { prepareSolrQuery } from '@/utils/solrHelper';

Check warning on line 7 in src/services/OrderService.ts

View workflow job for this annotation

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

'prepareSolrQuery' is defined but never used

Check warning on line 7 in src/services/OrderService.ts

View workflow job for this annotation

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

'prepareSolrQuery' is defined but never used

const fetchOrderHeader = async (params: any): Promise<any> => {
return await api({
Expand Down Expand Up @@ -887,6 +888,23 @@
return phoneNumber
}

const fetchRejectReasons = async(query: any): Promise<any> => {
return api({
url: "performFind",
method: "get", // TODO: cache this api request
params: query,
cache: true
})
}

const rejectOrderItems = async (payload: any): Promise <any> => {
return api({
url: "rejectOrderItems",
method: "post",
data: payload
});
}

export const OrderService = {
addShipmentBox,
addTrackingCode,
Expand All @@ -896,6 +914,7 @@
fetchOrderAttribute,
fetchOrderHeader,
fetchOrderItems,
fetchRejectReasons,
fetchShipmentCarrierDetail,
fetchShipmentItems,
fetchShipments,
Expand All @@ -919,6 +938,7 @@
printTransferOrder,
rejectFulfillmentReadyOrderItem,
rejectOrderItem,
rejectOrderItems,
retryShippingLabel,
shipOrder,
unpackOrder,
Expand Down
3 changes: 2 additions & 1 deletion src/store/modules/transferorder/TransferOrderState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export default interface TransferOrderState {
shipment: {
current: any,
list: any
}
},
rejectReasons: Array<any>;
}
59 changes: 59 additions & 0 deletions src/store/modules/transferorder/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,65 @@ const actions: ActionTree<TransferOrderState, RootState> = {
},
async clearCurrentTransferShipment({ commit }) {
commit(types.ORDER_CURRENT_SHIPMENT_CLEARED)
},
async fetchRejectReasons({ commit }) {
let rejectReasons = [];

const permissions = store.getters["user/getUserPermissions"];
const isAdminUser = permissions.some((permission: any) => permission.action === "APP_STOREFULFILLMENT_ADMIN")

if(isAdminUser) {
try {
const payload = {
inputFields: {
parentEnumTypeId: ["REPORT_AN_ISSUE", "RPRT_NO_VAR_LOG"],
parentEnumTypeId_op: "in"
},
fieldList: ["description", "enumId", "enumName", "enumTypeId", "sequenceNum"],
distinct: "Y",
entityName: "EnumTypeChildAndEnum",
viewSize: 20, // keeping view size 20 as considering that we will have max 20 reasons
orderBy: "sequenceNum"
}

const resp = await OrderService.fetchRejectReasons(payload)

if(!hasError(resp) && resp.data.count > 0) {
rejectReasons = resp.data.docs
} else {
throw resp.data
}
} catch (err) {
logger.error("Failed to fetch reject reasons", err)
}
} else {
try {
const payload = {
inputFields: {
enumerationGroupId: "TO_REJ_RSN_GRP"
},
// We shouldn't fetch description here, as description contains EnumGroup description which we don't wanna show on UI.
fieldList: ["enumerationGroupId", "enumId", "fromDate", "sequenceNum", "enumDescription", "enumName"],
distinct: "Y",
entityName: "EnumerationGroupAndMember",
viewSize: 200,
filterByDate: "Y",
orderBy: "sequenceNum"
}

const resp = await OrderService.fetchRejectReasons(payload)

if(!hasError(resp) && resp?.data.docs.length > 0) {
rejectReasons = resp.data.docs
} else {
throw resp.data
}
} catch (err) {
logger.error("Failed to fetch fulfillment reject reasons", err)
}
}

commit(types.ORDER_REJECT_REASONS_UPDATED, rejectReasons)
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/store/modules/transferorder/getters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const getters: GetterTree<TransferOrderState, RootState> = {
},
getCurrentShipment (state) {
return state.shipment.current
},
getRejectReasons(state) {
return state.rejectReasons;
}
};
export default getters;
3 changes: 2 additions & 1 deletion src/store/modules/transferorder/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ const orderModule: Module<TransferOrderState, RootState> = {
shipment:{
current: {},
list: []
}
},
rejectReasons: []
},
getters,
actions,
Expand Down
1 change: 1 addition & 0 deletions src/store/modules/transferorder/mutation-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export const ORDER_TRANSFER_QUERY_CLEARED = SN_ORDER + '/TRANSFER_QUERY_CLEARED'
export const ORDER_CURRENT_SHIPMENT_UPDATED = SN_ORDER + '/CURRENT_SHIPMENT_UPDATED'
export const ORDER_CURRENT_SHIPMENT_CLEARED = SN_ORDER + '/CURRENT_SHIPMENT_CLEARED'
export const ORDER_CURRENT_CLEARED = SN_ORDER + '/CURRENT_ORDER_CLEARED'
export const ORDER_REJECT_REASONS_UPDATED = SN_ORDER + '/REJECT_REASONS_UPDATED'
3 changes: 3 additions & 0 deletions src/store/modules/transferorder/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ const mutations: MutationTree <TransferOrderState> = {
},
[types.ORDER_CURRENT_CLEARED](state) {
state.current = {}
},
[types.ORDER_REJECT_REASONS_UPDATED](state, payload) {
state.rejectReasons = payload
}
}
export default mutations;
Loading
Loading