diff --git a/src/components/OrderItemRejHistoryModal.vue b/src/components/OrderItemRejHistoryModal.vue new file mode 100644 index 000000000..efe1da17b --- /dev/null +++ b/src/components/OrderItemRejHistoryModal.vue @@ -0,0 +1,111 @@ + + + \ No newline at end of file diff --git a/src/components/ProductListItem.vue b/src/components/ProductListItem.vue index f3b6f12b3..efb069b8c 100644 --- a/src/components/ProductListItem.vue +++ b/src/components/ProductListItem.vue @@ -13,7 +13,7 @@
- + {{ getProductStock(item.productId).quantityOnHandTotal }} {{ $t('pieces in stock') }} @@ -26,7 +26,7 @@ \ No newline at end of file diff --git a/src/components/ReportAnIssueModal.vue b/src/components/ReportAnIssueModal.vue new file mode 100644 index 000000000..e4c58c620 --- /dev/null +++ b/src/components/ReportAnIssueModal.vue @@ -0,0 +1,134 @@ + + + \ No newline at end of file diff --git a/src/locales/en.json b/src/locales/en.json index 76991c243..818f06bb6 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1,6 +1,6 @@ { "App": "App", - "All items were canceled from the order": "All items were canceled from the order", + "All items were rejected from the order": "All items were rejected from the order", "Allow partial rejection": "Allow partial rejection", "An email notification will be sent to that their order is ready for pickup. This order will also be moved to the packed orders tab.": "An email notification will be sent to { customerName } that their order is ready for pickup.{ space } This order will also be moved to the packed orders tab.", "An email notification will be sent to that their order is ready for pickup.": "An email notification will be sent to { customerName } that their order is ready for pickup.", @@ -49,6 +49,7 @@ "Instance Url": "Instance Url", "In store": "In store", "Inventory": "Inventory", + "Item has been rejected successfully.": "Item has been rejected successfully.", "Language": "Language", "Last name": "Last name", "Learn more about unfillable items": "Learn more about unfillable items", @@ -68,6 +69,7 @@ "No notifications to show": "No notifications to show", "No picker assigned.": "No picker assigned.", "No picker found": "No picker found", + "No records found.": "No records found.", "No time zone found": "No time zone found", "Notifications": "Notifications", "Notification Preference": "Notification Preference", @@ -77,11 +79,15 @@ "Open": "Open", "OMS": "OMS", "OMS instance": "OMS instance", + "On rejecting this item, will be sent an email with alternate fulfillment options and this order item will be removed from your dashboard.": "On rejecting this item, { customerName } will be sent an email with alternate fulfillment options and this order item will be removed from your dashboard.", + "On rejecting this order, will be sent an email with alternate fulfilment options and this order will be removed from your dashboard.": "On rejecting this order, { customerName } will be sent an email with alternate fulfilment options and this order will be removed from your dashboard.", "Other stores inventory": "Other stores inventory", "Order": "Order", "Order delivered to": "Order delivered to { customerName }", "Order details": "Order details", "Order edit permissions": "Order edit permissions", + "Order is now ready to handover.": "Order is now ready to handover.", + "Order has been rejected.": "Order has been rejected.", "Order marked as ready for pickup, an email notification has been sent to the customer": "Order marked as ready for pickup, an email notification has been sent to the customer", "Order marked as ready for pickup but something went wrong while sending the email notification": "Order marked as ready for pickup but something went wrong while sending the email notification", "Order not found": "Order not found", @@ -90,6 +96,7 @@ "Order will be marked as completed. This action is irreversible.": "Order will be marked as completed. This action is irreversible.", "Orders": "Orders", "Orders Not Found": "Orders Not Found", + "Order item rejection history": "Order item rejection history", "Other stores": "Other stores", "Packed": "Packed", "Packing Slip": "Packing Slip", @@ -99,6 +106,7 @@ "pending approval": "pending approval", "Picked by": "Picked by { pickers }", "Pick up location": "Pick up location", + "pieces in stock": "pieces in stock", "Product details": "Product details", "Product not found": "Product not found", "Products not found": "Products not found", @@ -106,13 +114,17 @@ "Ready for pickup": "Ready for pickup", "Ready to create an app?": "Ready to create an app?", "Ready to ship": "Ready to ship", + "Reject": "Reject", "Reject Order": "Reject Order", + "Reject Order Item": "Reject Order Item", "Reason": "Reason", + "Report an issue": "Report an issue", "Resend ready for pickup email": "Resend ready for pickup email", "Search": "Search", "Search Orders": "Search Orders", "Search time zones": "Search time zones", "Select facility": "Select facility", + "Select reason": "Select reason", "Select time zone": "Select time zone", "Select the notifications you want to receive.": "Select the notifications you want to receive.", "Select your preferred language.": "Select your preferred language.", @@ -137,6 +149,7 @@ "Sorry, your username or password is incorrect. Please try again.": "Sorry, your username or password is incorrect. Please try again.", "Specify whether you reject a BOPIS order partially when any order item inventory is insufficient at the store.": "Specify whether you reject a BOPIS order partially when any order item inventory is insufficient at the store.", "Specify which facility you want to operate from. Order, inventory and other configuration data will be specific to the facility you select.": "Specify which facility you want to operate from. Order, inventory and other configuration data will be specific to the facility you select.", + "Specify whether you reject partial BOPIS order when any order item’s inventory is insufficient at the store.": "Specify whether you reject partial BOPIS order when any order item’s inventory is insufficient at the store.", "State": "State", "Staff": "Staff", "Street": "Street", @@ -151,10 +164,10 @@ "Track Pickers": "Track Pickers", "Track who picked orders by entering picker IDs when packing an order.": "Track who picked orders by entering picker IDs when packing an order.", "Unfillable Items": "Unfillable Items", - "Update Order": "Update Order", "Update time zone": "Update time zone", "Username": "Username", "Warehouse": "Warehouse", + "will be removed from your dashboard. This action cannot be undone.": "{ productName } will be removed from your dashboard.{ space } This action cannot be undone.", "Worn Display": "Worn Display", "This order will be removed from your dashboard. This action cannot be undone.": "This order will be removed from your dashboard.{ space } This action cannot be undone.", "Update notification preferences": "Update notification preferences", diff --git a/src/locales/es.json b/src/locales/es.json index 37745ac9a..cfaebdb7e 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -1,6 +1,6 @@ { "App": "Aplicación", - "All items were canceled from the order": "Todos los artículos se cancelaron del pedido", + "All items were rejected from the order": "All items were rejected from the order", "Allow partial rejection": "Allow partial rejection", "An email notification will be sent to that their order is ready for pickup. This order will also be moved to the packed orders tab.": "Se enviará una notificación por correo electrónico a {customerName} de que su pedido está listo para recoger.{ space } Este pedido también se moverá a la pestaña de pedidos empacados.", "An email notification will be sent to that their order is ready for pickup.": "Se enviará una notificación por correo electrónico a {customerName} de que su pedido está listo para recoger.", @@ -49,6 +49,7 @@ "Instance Url": "URL de la instancia", "In store": "En tienda", "Inventory": "Inventario", + "Item has been rejected successfully.": "Item has been rejected successfully.", "Language": "Idioma", "Last name": "Apellido", "Learn more about unfillable items": "Obtenga más información sobre artículos que no se pueden cumplir", @@ -67,6 +68,7 @@ "No notifications to show": "No notifications to show", "No picker assigned.": "No picker assigned.", "No picker found": "No se encontró recolector", + "No records found.": "No records found.", "No time zone found": "No se encontró zona horaria", "Notifications": "Notifications", "Notification Preference": "Notification Preference", @@ -76,11 +78,15 @@ "Open": "Abierto", "OMS": "OMS", "OMS instance": "Instancia de OMS", + "On rejecting this item, will be sent an email with alternate fulfillment options and this order item will be removed from your dashboard.": "On rejecting this item, { customerName } will be sent an email with alternate fulfillment options and this order item will be removed from your dashboard.", + "On rejecting this order, will be sent an email with alternate fulfilment options and this order will be removed from your dashboard.": "On rejecting this order, { customerName } will be sent an email with alternate fulfilment options and this order will be removed from your dashboard.", "Other stores inventory": "Inventario de otras tiendas", "Order": "Orden", "Order delivered to": "Orden entregada a {customerName}", "Order details": "Detalles de la orden", "Order edit permissions": "Permisos de edición de la orden", + "Order is now ready to handover.": "Order is now ready to handover.", + "Order has been rejected.": "Order has been rejected.", "Order marked as ready for pickup, an email notification has been sent to the customer": "Pedido marcado como listo para recoger, se ha enviado una notificación por correo electrónico al cliente", "Order marked as ready for pickup but something went wrong while sending the email notification": "Pedido marcado como listo para recoger pero algo salió mal al enviar la notificación por correo electrónico", "Order not found": "Orden no encontrada", @@ -89,6 +95,7 @@ "Order will be marked as completed. This action is irreversible.": "El pedido se marcará como completado. Esta acción es irreversible.", "Orders": "Órdenes", "Orders Not Found": "Órdenes no encontradas", + "Order item rejection history": "Order item rejection history", "Other stores": "Otras tiendas", "Packed": "Empacado", "Packing Slip": "Remisión de embalaje", @@ -98,6 +105,7 @@ "pending approval": "pendiente de aprobación", "Picked by": "Picked by { pickers }", "Pick up location": "Ubicación de recogida", + "pieces in stock": "pieces in stock", "Product details": "Detalles del producto", "Product not found": "Producto no encontrado", "Products not found": "Productos no encontrados", @@ -105,13 +113,17 @@ "Ready for pickup": "Listo para recoger", "Ready to create an app?": "¿Listo para crear una aplicación?", "Ready to ship": "Listo para enviar", + "Reject": "Reject", "Reject Order": "Rechazar pedido", + "Reject Order Item": "Reject Order Item", "Reason": "Razón", + "Report an issue": "Report an issue", "Resend ready for pickup email": "Reenviar correo electrónico de listo para recoger", "Search": "Buscar", "Search Orders": "Buscar pedidos", "Search time zones": "Buscar zonas horarias", "Select facility": "Seleccionar instalación", + "Select reason": "Select reason", "Select time zone": "Seleccionar zona horaria", "Select the notifications you want to receive.": "Select the notifications you want to receive.", "Select your preferred language.": "Selecciona tu idioma preferido.", @@ -136,6 +148,7 @@ "Sorry, your username or password is incorrect. Please try again.": "Lo siento, tu nombre de usuario o contraseña es incorrecto. Por favor, inténtalo de nuevo.", "Specify whether you reject a BOPIS order partially when any order item inventory is insufficient at the store.": "Specify whether you reject a BOPIS order partially when any order item inventory is insufficient at the store.", "Specify which facility you want to operate from. Order, inventory, and other configuration data will be specific to the facility you select.": "Especifique desde qué instalación desea operar. El pedido, el inventario y otros datos de configuración serán específicos de la instalación que seleccione.", + "Specify whether you reject partial BOPIS order when any order item’s inventory is insufficient at the store.": "Specify whether you reject partial BOPIS order when any order item’s inventory is insufficient at the store.", "State": "Estado", "Staff": "Personal", "Street": "Calle", @@ -150,10 +163,10 @@ "Track Pickers": "Seguimiento de recolectores", "Track who picked orders by entering picker IDs when packing an order.": "Realiza un seguimiento de quién recogió los pedidos ingresando los ID de los recolectores al empacar un pedido.", "Unfillable Items": "Artículos no disponibles", - "Update Order": "Actualizar pedido", "Update time zone": "Actualizar zona horaria", "Username": "Nombre de usuario", "Warehouse": "Almacén", + "will be removed from your dashboard. This action cannot be undone.": "{ productName } will be removed from your dashboard.{ space } This action cannot be undone.", "Worn Display": "Pantalla desgastada", "This order will be removed from your dashboard. This action cannot be undone.": "Este pedido será eliminado de tu panel de control.{ space } Esta acción no se puede deshacer.", "Update notification preferences": "Update notification preferences", diff --git a/src/locales/ja.json b/src/locales/ja.json index 06358ccce..5cc87691a 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1,6 +1,6 @@ { "App": "App", - "All items were canceled from the order": "全ての商品が注文からキャンセルされました", + "All items were rejected from the order": "All items were rejected from the order", "Allow partial rejection": "Allow partial rejection", "An email notification will be sent to that their order is ready for pickup. This order will also be moved to the packed orders tab.": "{ customerName }様宛に注文の受け取り準備が完了したことをお知らするメールが送信されます。{ space } この注文は「梱包済み注文」タブに移動されます.", "An email notification will be sent to that their order is ready for pickup.": "{ customerName }様宛に注文の受け取り準備が完了したことをお知らするメールが送信されます。", @@ -49,6 +49,7 @@ "Instance Url": "インスタンスURL", "In store": "店頭", "Inventory": "在庫", + "Item has been rejected successfully.": "Item has been rejected successfully.", "Language": "言語", "Last name": "姓", "Learn more about unfillable items": "記入できない項目の詳細", @@ -67,6 +68,7 @@ "No notifications to show": "No notifications to show", "No picker assigned.": "No picker assigned.", "No picker found": "受取人が見つかりません", + "No records found.": "No records found.", "No time zone found": "タイムゾーンが見つかりません", "Notifications": "Notifications", "Notification Preference": "Notification Preference", @@ -76,11 +78,15 @@ "Open": "オープン", "OMS": "OMS", "OMS instance": "OMSインスタンス", + "On rejecting this item, will be sent an email with alternate fulfillment options and this order item will be removed from your dashboard.": "On rejecting this item, { customerName } will be sent an email with alternate fulfillment options and this order item will be removed from your dashboard.", + "On rejecting this order, will be sent an email with alternate fulfilment options and this order will be removed from your dashboard.": "On rejecting this order, { customerName } will be sent an email with alternate fulfilment options and this order will be removed from your dashboard.", "Other stores inventory": "その他店舗在庫", "Order": "注文", "Order delivered to": "注文は { customerName }様 に配達されました", "Order details": "注文詳細", "Order edit permissions": "注文の編集権限", + "Order is now ready to handover.": "Order is now ready to handover.", + "Order has been rejected.": "Order has been rejected.", "Order marked as ready for pickup, an email notification has been sent to the customer": "注文された商品の受取準備完了とマークされ、Eメールによる通知がお客様に送信されました。", "Order marked as ready for pickup but something went wrong while sending the email notification": "注文された商品の受取準備完了とマークされましたが、Eメールによる通知の送信中に何かしらの問題が発生しました。", "Order not found": "注文が見つかりません", @@ -89,6 +95,7 @@ "Order will be marked as completed. This action is irreversible.": "注文の完了がマークされます。この操作は元に戻せません。", "Orders": "注文", "Orders Not Found": "注文が見つかりません", + "Order item rejection history": "Order item rejection history", "Other stores": "Other stores", "Packed": "梱包済み", "Packing slip": "納品書", @@ -98,6 +105,7 @@ "pending approval": "承認待ち", "Picked by": "Picked by { pickers }", "Pick up location": "受取場所", + "pieces in stock": "pieces in stock", "Product details": "商品詳細", "Product not found": "商品が見つかりません", "Products not found": "商品が見つかりません", @@ -105,13 +113,17 @@ "Ready for pickup": "ピックアップの準備ができました", "Ready to create an app?": "アプリを作成する準備はできましたか?", "Ready to ship": "出荷する準備ができました", + "Reject": "Reject", "Reject Order": "注文を拒否", + "Reject Order Item": "Reject Order Item", "Reason": "理由", + "Report an issue": "Report an issue", "Resend ready for pickup email": "受取準備完了メールの再送", "Search": "検索", "Search Orders": "注文の検索", "Search time zones": "タイムゾーンの検索", "Select facility": "拠点の検索", + "Select reason": "Select reason", "Select time zone": "タイムゾーンを選択", "Select the notifications you want to receive.": "Select the notifications you want to receive.", "Select your preferred language.": "お好みの言語の選択", @@ -136,6 +148,7 @@ "Sorry, your username or password is incorrect. Please try again.": "ユーザー名またはパスワードが正しくありません。もう一度お試しください。", "Specify whether you reject a BOPIS order partially when any order item inventory is insufficient at the store.": "Specify whether you reject a BOPIS order partially when any order item inventory is insufficient at the store.", "Specify which facility you want to operate from. Order, inventory and other configuration data will be specific to the facility you select.": "どの拠点からオペレーションを行うかを指定します。注文、在庫、その他の設定データは、選択した拠点に固有のものとなります。", + "Specify whether you reject partial BOPIS order when any order item’s inventory is insufficient at the store.": "Specify whether you reject partial BOPIS order when any order item’s inventory is insufficient at the store.", "State": "都道府県", "Staff": "スタッフ", "Street": "市区町村", @@ -150,10 +163,10 @@ "Track Pickers": "受取人の追跡", "Track who picked orders by entering picker IDs when packing an order.": "注文を梱包する際に受取人IDを入力することで、誰が注文を受け取ったかを追跡できます。", "Unfillable Items": "記入不可の項目", - "Update Order": "注文を更新する", "Update time zone": "タイムゾーンを更新する", "Username": "ユーザーネーム", "Warehouse": "倉庫", + "will be removed from your dashboard. This action cannot be undone.": "{ productName } will be removed from your dashboard.{ space } This action cannot be undone.", "Worn Display": "すり切れたディスプレイ", "This order will be removed from your dashboard. This action cannot be undone.": "この注文はダッシュボードから削除されます。{ space } この操作は元に戻せません。", "Update notification preferences": "Update notification preferences", diff --git a/src/services/OrderService.ts b/src/services/OrderService.ts index 30bcb6cd0..140d8214a 100644 --- a/src/services/OrderService.ts +++ b/src/services/OrderService.ts @@ -1,5 +1,8 @@ import { api, client, hasError } from '@/adapter'; +import emitter from '@/event-bus'; +import { translate } from '@/i18n'; import store from '@/store'; +import { showToast } from '@/utils'; const getOpenOrders = async (payload: any): Promise => { return api({ @@ -57,6 +60,38 @@ const quickShipEntireShipGroup = async (payload: any): Promise => { }); } +const rejectItem = async (payload: any): Promise => { + try { + emitter.emit("presentLoader"); + const params = { + 'orderId': payload.orderId, + 'rejectReason': payload.item.reason, + 'facilityId': payload.item.facilityId, + 'orderItemSeqId': payload.item.orderItemSeqId, + 'shipmentMethodTypeId': payload.shipmentMethodEnumId, + 'quantity': parseInt(payload.item.quantity), + ...(payload.shipmentMethodEnumId === "STOREPICKUP" && ({ "naFacilityId": "PICKUP_REJECTED" })), + } + + const resp = await api({ + url: "rejectOrderItem", + method: "post", + data: { 'payload': params } + }); + + if (!hasError(resp)) { + showToast(translate('Item has been rejected successfully.')); + } else { + showToast(translate('Something went wrong')); + } + return resp; + } catch (error) { + console.error(error); + } finally { + emitter.emit("dismissLoader"); + } +} + const rejectOrderItem = async (payload: any): Promise => { return api({ url: "rejectOrderItem", @@ -128,12 +163,22 @@ const getShipmentItems = async (shipmentIds: any): Promise => { }, []) } +const getOrderItemRejHistory = async (payload: any): Promise => { + return api({ + url: 'performFind', + method: 'POST', + data: payload + }) +} + export const OrderService = { getOpenOrders, getOrderDetails, getCompletedOrders, getPackedOrders, + getOrderItemRejHistory, quickShipEntireShipGroup, + rejectItem, rejectOrderItem, updateShipment, createPicklist, diff --git a/src/services/UtilService.ts b/src/services/UtilService.ts new file mode 100644 index 000000000..1e5878e1e --- /dev/null +++ b/src/services/UtilService.ts @@ -0,0 +1,14 @@ +import { api } from '@/adapter'; + +const fetchRejectReasons = async (query: any): Promise => { + return api({ + url: "performFind", + method: "get", + params: query, + cache: true + }) +} + +export const UtilService = { + fetchRejectReasons +} \ No newline at end of file diff --git a/src/store/index.ts b/src/store/index.ts index 6cd710b94..2ce954f6d 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -5,6 +5,7 @@ import actions from './actions' import RootState from './RootState' import createPersistedState from "vuex-persistedstate"; import userModule from './modules/user'; +import utilModule from "./modules/util" import orderModule from './modules/order'; import stockModule from "./modules/stock" import productModule from "./modules/product" @@ -20,7 +21,7 @@ const state: any = { } const persistState = createPersistedState({ - paths: ['user'], + paths: ['user', 'order.current'], fetchBeforeUse: true }) @@ -35,7 +36,8 @@ const store = createStore({ 'user': userModule, 'order': orderModule, 'stock': stockModule, - 'product': productModule + 'product': productModule, + 'util': utilModule }, }) diff --git a/src/store/modules/order/OrderState.ts b/src/store/modules/order/OrderState.ts index b371f21af..2c6e2b312 100644 --- a/src/store/modules/order/OrderState.ts +++ b/src/store/modules/order/OrderState.ts @@ -1,5 +1,6 @@ export default interface OrderState { open: any; + orderItemRejectionHistory: []; current: any; packed: any; completed: any; diff --git a/src/store/modules/order/actions.ts b/src/store/modules/order/actions.ts index 8db8d6b27..cb050ad86 100644 --- a/src/store/modules/order/actions.ts +++ b/src/store/modules/order/actions.ts @@ -100,9 +100,10 @@ const actions: ActionTree ={ async getOrderDetail( { dispatch, state }, payload ) { const current = state.current as any const orders = JSON.parse(JSON.stringify(state.open.list)) as any - - if(current.orderId === payload.orderId) { return current } - + if(current.orderId === payload.orderId) { + this.dispatch('product/getProductInformation', { orders: [ current ] }) + return current + } if(orders.length) { const order = orders.find((order: any) => { return order.orderId === payload.orderId; @@ -112,7 +113,6 @@ const actions: ActionTree ={ return order; } } - const orderQueryPayload = prepareOrderQuery({ ...payload, shipmentMethodTypeId: !store.state.user.preference.showShippingOrders ? 'STOREPICKUP' : '', @@ -450,6 +450,9 @@ const actions: ActionTree ={ } }) } + // Added ready to handover because we need to show the user that the order has moved to the packed tab (ready to handover) + dispatch('updateCurrent', { order : { ...payload.order, readyToHandover: true } }) + showToast(translate("Order packed and ready for delivery")) } else { showToast(translate("Something went wrong")) @@ -470,7 +473,7 @@ const actions: ActionTree ={ return await dispatch("rejectOrderItems", payload).then((resp) => { const refreshPickupOrders = resp.find((response: any) => !(response.data._ERROR_MESSAGE_ || response.data._ERROR_MESSAGE_LIST_)) if (refreshPickupOrders) { - showToast(translate('All items were canceled from the order') + ' ' + payload.orderId); + showToast(translate('All items were rejected from the order') + ' ' + payload.orderId); } else { showToast(translate('Something went wrong')); } @@ -764,6 +767,41 @@ const actions: ActionTree ={ return resp; }, + async getOrderItemRejHistory({ commit }, payload) { + emitter.emit("presentLoader"); + let rejectionHistory = [] as any; + + try { + const params = { + inputFields: { + orderId: payload.orderId, + changeReasonEnumId: payload.rejectReasonEnumIds, + changeReasonEnumId_op: "in", + }, + fieldList: ['changeDatetime', 'changeUserLogin', 'productId', 'changeReasonEnumId'], + entityName: 'OrderFacilityChangeAndOrderItem', + orderBy: 'changeDatetime DESC', + viewSize: 20, + } + const resp = await OrderService.getOrderItemRejHistory(params); + + if (!hasError(resp) && resp.data.count > 0) { + rejectionHistory = resp.data.docs; + const productIds = [ ...(resp.data.docs.reduce((productIds: any, history: any) => productIds.add(history.productId), new Set())) ]; + + // Get products that exist in order item rejection history + await this.dispatch('product/fetchProducts', { productIds }) + } else { + throw resp.data + } + } catch (err) { + console.error('Failed to fetch order item rejection history', err) + } + + commit(types.ORDER_ITEM_REJECTION_HISTORY_UPDATED, rejectionHistory) + emitter.emit("dismissLoader"); + }, + // clearning the orders state when logout, or user store is changed clearOrders ({ commit }) { commit(types.ORDER_OPEN_UPDATED, {orders: {} , total: 0}) diff --git a/src/store/modules/order/getters.ts b/src/store/modules/order/getters.ts index 82d173ef6..290265522 100644 --- a/src/store/modules/order/getters.ts +++ b/src/store/modules/order/getters.ts @@ -41,7 +41,10 @@ const getters: GetterTree = { }, isShipToStoreCmpltdOrdrsScrlbl: (state) => { return state.shipToStore.completed.list.length > 0 && state.shipToStore.completed.list.length < state.shipToStore.completed.total - } + }, + getOrderItemRejectionHistory: (state) => { + return state.orderItemRejectionHistory + }, } export default getters; \ No newline at end of file diff --git a/src/store/modules/order/index.ts b/src/store/modules/order/index.ts index 805e87a3a..44d9a6e6e 100644 --- a/src/store/modules/order/index.ts +++ b/src/store/modules/order/index.ts @@ -10,6 +10,7 @@ const orderModule: Module = { namespaced: true, state: { current: {}, + orderItemRejectionHistory: [], open: { list: {}, total: 0 diff --git a/src/store/modules/order/mutation-types.ts b/src/store/modules/order/mutation-types.ts index e3a3ebc68..862b8047e 100644 --- a/src/store/modules/order/mutation-types.ts +++ b/src/store/modules/order/mutation-types.ts @@ -6,3 +6,4 @@ export const ORDER_COMPLETED_UPDATED = SN_ORDER + '/COMPLETED_UPDATED' export const ORDER_SHIP_TO_STORE_INCOMING_UPDATED = SN_ORDER + '/SHIP_TO_STORE_INCOMING_UPDATED' export const ORDER_SHIP_TO_STORE_RDYFORPCKUP_UPDATED = SN_ORDER + '/SHIP_TO_STORE_RDYFORPCKUP_UPDATED' export const ORDER_SHIP_TO_STORE_COMPLETED_UPDATED = SN_ORDER + '/SHIP_TO_STORE_COMPLETED_UPDATED' +export const ORDER_ITEM_REJECTION_HISTORY_UPDATED = SN_ORDER + '/ITEM_REJECTION_HISTORY_UPDATED' diff --git a/src/store/modules/order/mutations.ts b/src/store/modules/order/mutations.ts index dd807363d..6d0780814 100644 --- a/src/store/modules/order/mutations.ts +++ b/src/store/modules/order/mutations.ts @@ -29,6 +29,9 @@ const mutations: MutationTree = { [types.ORDER_SHIP_TO_STORE_COMPLETED_UPDATED] (state, payload) { state.shipToStore.completed.list = payload.orders state.shipToStore.completed.total = payload.total + }, + [types.ORDER_ITEM_REJECTION_HISTORY_UPDATED] (state, payload) { + state.orderItemRejectionHistory = payload } } diff --git a/src/store/modules/user/getters.ts b/src/store/modules/user/getters.ts index ab2daeffd..4fb4fc6dd 100644 --- a/src/store/modules/user/getters.ts +++ b/src/store/modules/user/getters.ts @@ -27,6 +27,9 @@ const getters: GetterTree = { const baseUrl = process.env.VUE_APP_BASE_URL; return baseUrl ? baseUrl : state.instanceUrl; }, + partialOrderRejection (state) { + return state.preference.partialOrderRejection; + }, showShippingOrders (state) { return state.preference.showShippingOrders; }, diff --git a/src/store/modules/user/index.ts b/src/store/modules/user/index.ts index f1816bf33..469e479e5 100644 --- a/src/store/modules/user/index.ts +++ b/src/store/modules/user/index.ts @@ -16,6 +16,7 @@ const userModule: Module = { showShippingOrders: true, showPackingSlip: false, configurePicker: false, + partialOrderRejection: false }, locale: 'en', currentEComStore: {}, diff --git a/src/store/modules/util/UtilState.ts b/src/store/modules/util/UtilState.ts new file mode 100644 index 000000000..40c0fb62b --- /dev/null +++ b/src/store/modules/util/UtilState.ts @@ -0,0 +1,3 @@ +export default interface UtilState { + rejectReasons: []; +} \ No newline at end of file diff --git a/src/store/modules/util/actions.ts b/src/store/modules/util/actions.ts new file mode 100644 index 000000000..4cb226fe2 --- /dev/null +++ b/src/store/modules/util/actions.ts @@ -0,0 +1,38 @@ +import { ActionTree } from 'vuex' +import RootState from '@/store/RootState' +import UtilState from './UtilState' +import * as types from './mutation-types' +import { UtilService } from '@/services/UtilService' +import { hasError } from '@/adapter' + +const actions: ActionTree = { + async fetchRejectReasons({ commit }) { + let rejectReasons = []; + try { + const payload = { + "inputFields": { + "parentEnumTypeId": ["REPORT_AN_ISSUE", "RPRT_NO_VAR_LOG"], + "parentEnumTypeId_op": "in" + }, + "fieldList": ["enumId", "description"], + "distinct": "Y", + "entityName": "EnumTypeChildAndEnum", + "viewSize": 20 // keeping view size 20 as considering that we will have max 20 reasons + } + + const resp = await UtilService.fetchRejectReasons(payload) + + if(!hasError(resp) && resp.data.count > 0) { + rejectReasons = resp.data.docs + } else { + throw resp.data + } + } catch (err) { + console.error('Failed to fetch reject reasons', err) + } + + commit(types.UTIL_REJECT_REASONS_UPDATED, rejectReasons) + } +} + +export default actions; \ No newline at end of file diff --git a/src/store/modules/util/getters.ts b/src/store/modules/util/getters.ts new file mode 100644 index 000000000..ea30c97ba --- /dev/null +++ b/src/store/modules/util/getters.ts @@ -0,0 +1,10 @@ +import { GetterTree } from 'vuex' +import UtilState from './UtilState' +import RootState from '@/store/RootState' + +const getters: GetterTree = { + getRejectReasons(state) { + return state.rejectReasons ? state.rejectReasons : [] + } +} +export default getters; \ No newline at end of file diff --git a/src/store/modules/util/index.ts b/src/store/modules/util/index.ts new file mode 100644 index 000000000..c3d84ab42 --- /dev/null +++ b/src/store/modules/util/index.ts @@ -0,0 +1,17 @@ +import actions from './actions' +import getters from './getters' +import mutations from './mutations' +import { Module } from 'vuex' +import RootState from '@/store/RootState' +import UtilState from './UtilState' + +const utilModule: Module = { + namespaced: true, + state: { + rejectReasons: [] + }, + getters, + actions, + mutations, +} +export default utilModule; \ No newline at end of file diff --git a/src/store/modules/util/mutation-types.ts b/src/store/modules/util/mutation-types.ts new file mode 100644 index 000000000..0a0a289f7 --- /dev/null +++ b/src/store/modules/util/mutation-types.ts @@ -0,0 +1,2 @@ +export const SN_UTIL = 'util' +export const UTIL_REJECT_REASONS_UPDATED = SN_UTIL + '/REJECT_REASONS_UPDATED' \ No newline at end of file diff --git a/src/store/modules/util/mutations.ts b/src/store/modules/util/mutations.ts new file mode 100644 index 000000000..5ffa976f9 --- /dev/null +++ b/src/store/modules/util/mutations.ts @@ -0,0 +1,10 @@ +import { MutationTree } from 'vuex' +import UtilState from './UtilState' +import * as types from './mutation-types' + +const mutations: MutationTree = { + [types.UTIL_REJECT_REASONS_UPDATED] (state, payload) { + state.rejectReasons = payload + } +} +export default mutations; \ No newline at end of file diff --git a/src/theme/variables.css b/src/theme/variables.css index 6a77ae08d..cab8a3bcd 100644 --- a/src/theme/variables.css +++ b/src/theme/variables.css @@ -237,4 +237,21 @@ http://ionicframework.com/docs/theming/ */ ion-select { max-width: 100%; +} + +.empty-state { + max-width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 10px; +} + +.empty-state>img { + object-fit: contain; +} + +.empty-state>p { + text-align: center; } \ No newline at end of file diff --git a/src/views/OrderDetail.vue b/src/views/OrderDetail.vue index 4dbd530be..beff5616e 100644 --- a/src/views/OrderDetail.vue +++ b/src/views/OrderDetail.vue @@ -4,123 +4,144 @@ {{ $t("Order details") }} + + + + + + + + +
- - + +
+ + +
+ + {{ $t("Report an issue") }} + +
+
+
+
- - - - - {{ $t("Reject Order") }} - - + + + + +
- + +@media (min-width: 768px) { + main { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--spacer-base); + } + + aside { + grid-column: 2; + grid-row: 1; + } +} + \ No newline at end of file diff --git a/src/views/Settings.vue b/src/views/Settings.vue index 7e0ae62fd..8c69d1ef7 100644 --- a/src/views/Settings.vue +++ b/src/views/Settings.vue @@ -194,6 +194,21 @@ + + + + {{ $t("Partial Order rejection") }} + + + + {{ $t('Specify whether you reject partial BOPIS order when any order item’s inventory is insufficient at the store.') }} + + + {{ $t("Allow partial rejection") }} + + + + @@ -230,6 +245,7 @@ import { IonIcon, IonItem, IonLabel, + IonList, IonPage, IonSelect, IonSelectOption, @@ -275,6 +291,7 @@ export default defineComponent({ IonIcon, IonItem, IonLabel, + IonList, IonPage, IonSelect, IonSelectOption, @@ -307,6 +324,7 @@ export default defineComponent({ currentFacility: 'user/getCurrentFacility', currentEComStore: 'user/getCurrentEComStore', configurePicker: "user/configurePicker", + partialOrderRejection: 'user/partialOrderRejection', showShippingOrders: 'user/showShippingOrders', showPackingSlip: 'user/showPackingSlip', partialOrderRejectionConfig: 'user/getPartialOrderRejectionConfig', @@ -366,6 +384,9 @@ export default defineComponent({ goToLaunchpad() { window.location.href = `${process.env.VUE_APP_LOGIN_URL}` }, + setPartialOrderRejectionPreference (ev: any) { + this.store.dispatch('user/setUserPreference', { partialOrderRejection: ev.detail.checked }) + }, setShowShippingOrdersPreference (ev: any) { this.store.dispatch('user/setUserPreference', { showShippingOrders: ev.detail.checked }) },