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 and cancel items from open and packed detail pages and revamped the detail page UI(#472) #477

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
322a365
Implemented: support to fetch additional info for order and display t…
ymaheshwari1 Dec 31, 2024
fe566e9
Added: payment details card and moved the customer info card(#472)
ymaheshwari1 Dec 31, 2024
d55ff82
Improved: styling for the card and timeline components(#472)
ymaheshwari1 Dec 31, 2024
2f7465f
Implemented: support to reject order item from the details page(#472)
ymaheshwari1 Jan 2, 2025
8957dec
Fixed: print picklist button in header to call correct method(#472)
ymaheshwari1 Jan 2, 2025
05016fb
Implemented: order item cancel flow for packed orders(#472)
ymaheshwari1 Jan 3, 2025
9db8546
Implemented: supoprt to display order status once order is shipping/h…
ymaheshwari1 Jan 3, 2025
056e960
Improved: code to handle the case to not display reject/cancel button…
ymaheshwari1 Jan 3, 2025
c26f66c
Implemented: support to fetch job and shopify config details and disp…
ymaheshwari1 Jan 3, 2025
68b6865
Improved: timeline to show picker info as soon as picklist is created…
ymaheshwari1 Jan 6, 2025
e4cec4d
Implemented: support to display order status beside the timeline(#472)
ymaheshwari1 Jan 6, 2025
e1535e9
Improved: styling for the order line item on detail page(#472)
ymaheshwari1 Jan 7, 2025
f3f8cf5
Improved: code to handle the showKitComponents logic on item level, p…
ymaheshwari1 Jan 8, 2025
fcf3c8a
Improved: date formatting inside the cancel confirm modal(#472)
ymaheshwari1 Jan 8, 2025
b0f4944
Improved: code to pass reason map when cancelling order item(#472)
ymaheshwari1 Jan 8, 2025
920a3f1
Implemented: function to prepare the order timeline and fixed issue i…
ymaheshwari1 Jan 9, 2025
6be8f81
Imporved: logic to display correct picklist date and added support to…
ymaheshwari1 Jan 9, 2025
9915d29
Improved: code to sort the timeline once prepared()
ymaheshwari1 Jan 10, 2025
c70c1ee
Removed: unwanted variables, imports and methods those are not used a…
ymaheshwari1 Jan 10, 2025
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
198 changes: 198 additions & 0 deletions src/components/ConfirmCancelModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
<template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="closeModal">
<ion-icon slot="icon-only" :icon="closeOutline" />
</ion-button>
</ion-buttons>
<ion-title>{{ translate("Cancel items") }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-list-header>{{ translate("Summary") }}</ion-list-header>
<ion-item v-for="(item, index) in cancelledItems" :key="index">
<ion-thumbnail slot="start">
<DxpShopifyImg :src="getProduct(item.productId).mainImageUrl" size="small" />
</ion-thumbnail>
<ion-label class="ion-text-wrap">
<h2>{{ getProductIdentificationValue(productIdentificationPref.primaryId, getProduct(item.productId)) ? getProductIdentificationValue(productIdentificationPref.primaryId, getProduct(item.productId)) : getProduct(item.productId).productName }}</h2>
<p class="ion-text-wrap">{{ getProductIdentificationValue(productIdentificationPref.secondaryId, getProduct(item.productId)) }}</p>
<p class="ion-text-wrap">{{ getCancelReasonDescription(item.cancelReason) }}</p>
<ion-badge color="dark" v-if="isKit(item)">{{ translate("Kit") }}</ion-badge>
</ion-label>
<ion-note slot="end">{{ getProduct(item.productId).LIST_PRICE_PURCHASE_USD_STORE_GROUP_price ? getProduct(item.productId).LIST_PRICE_PURCHASE_USD_STORE_GROUP_price : "" }}</ion-note>
</ion-item>

<ion-item lines="full">
<ion-label>{{ translate("Total") }}</ion-label>
<ion-note slot="end">{{ orderTotal }}</ion-note>
</ion-item>

<ion-item lines="full" v-if="isCancelationSyncJobEnabled && isProcessRefundEnabled">
<ion-label>
{{ translate("Estimated time to refund customer on Shopify") }}
<p>{{ translate("Showing the next estimated time to sync cancelation to Shopify") }}</p>
</ion-label>
<ion-note slot="end">{{ runTimeDiff }}</ion-note>
</ion-item>
<ion-item lines="full" v-else-if="isCancelationSyncJobEnabled">
<ion-label>
{{ translate("Estimated time to cancelation on Shopify") }}
<p>{{ translate("Showing the next estimated time to sync cancelation to Shopify") }}</p>
<p>{{ translate("Cancelation sync to Shopify is enabled. Refund processing is disabled.") }}</p>
</ion-label>
<ion-note slot="end">{{ runTimeDiff }}</ion-note>
</ion-item>
<ion-item lines="full" v-else>
<ion-label>
{{ translate("Cancelation not syncing to Shopify") }}
<p>{{ translate("Cancelation and refund sync to Shopify is not enabled.") }}</p>
</ion-label>
</ion-item>
</ion-list>

<ion-button class="ion-margin" color="danger" @click="cancelOrder">
{{ translate("Confirm Cancelation") }}
</ion-button>
</ion-content>
</template>

<script lang="ts">
import {
IonBadge,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonListHeader,
IonNote,
IonTitle,
IonThumbnail,
IonToolbar,
modalController,
} from "@ionic/vue";
import { computed, defineComponent } from "vue";
import { closeOutline, saveOutline } from "ionicons/icons";
import { mapGetters, useStore } from "vuex"
import { OrderService } from "@/services/OrderService";
import { getProductIdentificationValue, translate, useProductIdentificationStore, useUserStore } from "@hotwax/dxp-components";

Check warning on line 84 in src/components/ConfirmCancelModal.vue

View workflow job for this annotation

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

'useUserStore' is defined but never used

Check warning on line 84 in src/components/ConfirmCancelModal.vue

View workflow job for this annotation

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

'useUserStore' is defined but never used
import { isKit } from "@/utils/order"
import { showToast } from "@/utils";

Check warning on line 86 in src/components/ConfirmCancelModal.vue

View workflow job for this annotation

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

'showToast' is defined but never used

Check warning on line 86 in src/components/ConfirmCancelModal.vue

View workflow job for this annotation

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

'showToast' is defined but never used
import { hasError } from "@hotwax/oms-api";
import { DateTime } from "luxon";

export default defineComponent({
name: "ConfirmCancelModal",
components: {
IonBadge,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonListHeader,
IonNote,
IonTitle,
IonThumbnail,
IonToolbar
},
props: ["order", "isCancelationSyncJobEnabled", "isProcessRefundEnabled", "cancelJobNextRunTime", "orderType"],
data() {
return {
cancelledItems: [] as Array<any>,
orderTotal: 0,
currentOrder: {} as any,
runTimeDiff: ""
}
},
computed: {
...mapGetters({
getProduct: "product/getProduct",
cancelReasons: "util/getCancelReasons",
currency: "user/getCurrency"
})
},
mounted() {
this.currentOrder = JSON.parse(JSON.stringify(this.order))
this.cancelledItems = this.currentOrder.part.items.filter((item: any) => item.cancelReason)
this.orderTotal = this.cancelledItems.reduce((total: any, item: any) => this.getProduct(item.productId).LIST_PRICE_PURCHASE_USD_STORE_GROUP_price + total, 0)
const timeDiff = DateTime.fromMillis(this.cancelJobNextRunTime).diff(DateTime.local());
this.runTimeDiff = DateTime.local().plus(timeDiff).toRelative();
},
methods: {
closeModal() {
modalController.dismiss({ dismissed: true });
},
getCancelReasonDescription(cancelReasonId: string) {
const reason = this.cancelReasons?.find((reason: any) => reason.enumId === cancelReasonId)
return reason?.description ? reason.description : reason?.enumDescription ? reason.enumDescription : reason?.enumId;
},
async cancelOrder() {
let isCancelled = true
for (const item of this.cancelledItems) {
const params = {
orderId: this.currentOrder.orderId,
orderItemSeqId: item.orderItemSeqId,
shipGroupSeqId: item.shipGroupSeqId,
cancelQuantity: item.quantity ? parseInt(item.quantity) : 1,
[`irm_${item.orderItemSeqId}`]: item.cancelReason
}

try {
const resp = await OrderService.cancelItem(params);

if(hasError(resp)) {
throw resp.data
} else {
this.currentOrder["part"] = {
...this.currentOrder.part,
items: this.currentOrder.part.items.filter((orderItem: any) => !(orderItem.orderItemSeqId === item.orderItemSeqId && orderItem.productId === item.productId))
}
}
} catch(err) {
isCancelled = false
}
}

// If all the items are cancelled then marking the whole order as cancelled
if(!this.currentOrder.part.items.length) {
this.currentOrder.cancelled = true;
} else {
// If we have only cancelled some order items and the cancelation is completd then changing the shipment status to packed
// This is done because when cancelling some of the order items the shipment is marked as approved, resulting in removing the order from packed tab
// but we need the order to be displayed in packed tab as it still has some items as reserved status
if(isCancelled) {
await this.store.dispatch("order/packDeliveryItems", this.currentOrder.shipmentId)
}
}

await this.store.dispatch("order/updateCurrent", { order: this.currentOrder });
this.closeModal();
}
},
setup() {
const store = useStore();
const productIdentificationStore = useProductIdentificationStore();
let productIdentificationPref = computed(() => productIdentificationStore.getProductIdentificationPref)

return {
closeOutline,
isKit,
getProductIdentificationValue,
productIdentificationPref,
saveOutline,
store,
translate
};
}
});
</script>
60 changes: 60 additions & 0 deletions src/components/ReportAnIssuePopover.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<template>
<ion-content>
<ion-list v-if="reasonType === 'reject'">
<ion-item v-for="reason in rejectReasons" :key="reason.enumId" @click="updateIssue(reason.enumId)" button>
{{ reason.description ? translate(reason.description) : reason.enumDescription ? translate(reason.enumDescription) : reason.enumId }}
</ion-item>
</ion-list>
<ion-list v-else>
<ion-item v-for="reason in cancelReasons" :key="reason.enumId" @click="updateIssue(reason.enumId)" button>
{{ reason.description ? translate(reason.description) : reason.enumDescription ? translate(reason.enumDescription) : reason.enumId }}
</ion-item>
</ion-list>
</ion-content>
</template>

<script lang="ts">
import {
IonContent,
IonItem,
IonList,
popoverController,
} from "@ionic/vue";
import { defineComponent } from "vue";
import { mapGetters } from 'vuex';
import { translate } from '@hotwax/dxp-components';

export default defineComponent({
name: "ReportIssuePopover",
components: {
IonContent,
IonItem,
IonList
},
props: {
reasonType: {
type: String,
default: "reject"
}
},
computed: {
...mapGetters({
rejectReasons: 'util/getRejectReasons',
cancelReasons: 'util/getCancelReasons',
})
},
methods: {
closePopover() {
popoverController.dismiss();
},
updateIssue(enumId: string) {
popoverController.dismiss(enumId);
},
},
setup() {
return {
translate
}
}
});
</script>
3 changes: 2 additions & 1 deletion src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { RouteRecordRaw } from 'vue-router';
import store from '@/store'
import Tabs from '@/views/Tabs.vue'
import OrderDetail from '@/views/OrderDetail.vue'

Check warning on line 5 in src/router/index.ts

View workflow job for this annotation

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

'OrderDetail' is defined but never used

Check warning on line 5 in src/router/index.ts

View workflow job for this annotation

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

'OrderDetail' is defined but never used
import ProductDetail from '@/views/ProductDetail.vue'
import ShipToStoreOrders from '@/views/ShipToStoreOrders.vue'
import Notifications from '@/views/Notifications.vue'
Expand All @@ -15,6 +15,7 @@
import 'vue-router'
import { DxpLogin, useAuthStore } from '@hotwax/dxp-components';
import { loader } from '@/utils/user';
import OrderDetailUpdated from '@/views/OrderDetailUpdated.vue';

// Defining types for the meta values
declare module 'vue-router' {
Expand Down Expand Up @@ -89,7 +90,7 @@
{
path: "/orderdetail/:orderType/:orderId/:orderPartSeqId",
name: "OrderDetail",
component: OrderDetail,
component: OrderDetailUpdated,
beforeEnter: authGuard,
props: true,
meta: {
Expand Down
18 changes: 18 additions & 0 deletions src/services/OrderService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { api, client, hasError } from '@/adapter';

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

View workflow job for this annotation

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

'client' is defined but never used

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

View workflow job for this annotation

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

'client' is defined but never used
import emitter from '@/event-bus';
import { translate } from '@hotwax/dxp-components';
import store from '@/store';
Expand Down Expand Up @@ -347,7 +347,24 @@
})
}

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

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

export const OrderService = {
cancelItem,
fetchOrderItems,
fetchOrderPaymentPreferences,
fetchTrackingCodes,
Expand All @@ -368,6 +385,7 @@
getCustomerContactDetails,
getShippingPhoneNumber,
packOrder,
performFind,
printPicklist,
printShippingLabelAndPackingSlip
}
18 changes: 18 additions & 0 deletions src/services/UtilService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,32 @@ const isEnumExists = async (enumId: string): Promise<any> => {
}
}

const fetchJobInformation = async (payload: any): Promise <any> => {
return api({
url: "/findJobs",
method: "get",
params: payload
});
}

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

export const UtilService = {
createEnumeration,
createProductStoreSetting,
fetchFacilityTypeInformation,
fetchJobInformation,
fetchPartyInformation,
fetchPaymentMethodTypeDesc,
fetchRejectReasons,
fetchStatusDesc,
getProcessRefundStatus,
getProductStoreSettings,
isEnumExists,
resetPicker,
Expand Down
Loading
Loading