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

Improved: Returns page & returns-detail page(#2v7gpv1) #132

Merged
merged 8 commits into from
Sep 26, 2022
21 changes: 16 additions & 5 deletions src/components/ReturnListItem.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
<template>
<ion-item button @click="viewReturn()">
<ion-label>
<h2>{{ returnShipment.shipmentId }}</h2>
<p>{{ returnShipment.shipmentItemCount }} {{ (returnShipment.shipmentItemCount > 1 ? 'Items' : 'Item') }}</p>
<h2>{{ returnShipment.trackingCode ? returnShipment.trackingCode : returnShipment.externalId ? returnShipment.externalId : returnShipment.shipmentId }}</h2>
<p>{{ returnShipment.shopifyOrderName ? returnShipment.shopifyOrderName : returnShipment.hcOrderId }}</p>
</ion-label>
<ion-note slot="end">{{ returnShipment.estimatedArrivalDate ? ($filters.formatDate(returnShipment.estimatedArrivalDate)) : returnShipment.statusDesc }}</ion-note>
<ion-badge :color="statusColorMapping[returnShipment.statusDesc] ? statusColorMapping[returnShipment.statusDesc] : 'medium'" slot="end">{{ returnShipment.statusDesc }}</ion-badge>
</ion-item>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import {
IonBadge,
IonItem,
IonLabel,
IonNote
} from '@ionic/vue'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex';

export default defineComponent({
name: "ReturnListItem",
data() {
return {
statusColorMapping: {
'Received': 'success',
'Approved': 'tertiary',
'Cancelled': 'danger',
'Shipped': 'medium',
'Created': 'medium'
} as any
}
},
components: {
IonBadge,
IonItem,
IonLabel,
IonNote,
},
props: ["returnShipment"],
methods: {
Expand Down
4 changes: 2 additions & 2 deletions src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ const i18n = createI18n({

// TODO Check if this is needed in updated versions
// Currently this method is added to be used in ts files
const translate = (key: string) => {
const translate = (key: string, named?: any) => {
if (!key) {
return '';
}
return i18n.global.t(key);
return i18n.global.t(key, named);
};

export { i18n as default, translate }
3 changes: 2 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"Returns": "Returns",
"Returns not found": "Returns not found",
"rejected": "rejected",
"returned": "returned",
"Scan": "Scan",
"Scan ASN to start receiving": "Scan ASN to start receiving",
"Scan barcodes to receive them": "Scan barcodes to receive them",
Expand All @@ -56,8 +57,8 @@
"Shipped": "Shipped",
"Something went wrong": "Something went wrong",
"Sorry, your username or password is incorrect. Please try again.": "Sorry, your username or password is incorrect. Please try again.",
"eCom Store": "eCom Store",
"store name": "store name",
"This return has been and cannot be edited.": "This return has been {status} and cannot be edited.",
"Time zone updated successfully": "Time zone updated successfully",
"Username": "Username",
"ZeroQuantity": "ZeroQuantity"
Expand Down
70 changes: 32 additions & 38 deletions src/store/modules/return/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,42 @@ const actions: ActionTree<ReturnState, RootState> = {
});
commit(types.RETURN_CURRENT_UPDATED, state);
},
async setCurrent ({ commit }, payload) {
async setCurrent ({ commit, state }, payload) {
let resp;
try {
// Check if already exist in the returns list
let returnShipment = state.returns.list.find((returnShipment: any) => returnShipment.shipmentId === payload.shipmentId);

if (!returnShipment) {
// Fetch shipment records if miss in return list
const getReturnShipmentPayload = {
"entityName": "SalesReturnShipmentView",
"inputFields": {
"shipmentId": payload.shipmentId
},
"fieldList" : [ "shipmentId","externalId","statusId","shopifyOrderName","hcOrderId","trackingCode" ],
"noConditionFind": "Y",
"viewSize": 1,
"viewIndex": 0,
} as any
resp = await ReturnService.findReturns(getReturnShipmentPayload)
if (resp.status === 200 && !hasError(resp) && resp.data.docs?.length > 0) {
returnShipment = resp.data.docs[0];
const statuses = await this.dispatch('util/fetchStatus', [ returnShipment.statusId ]);
returnShipment.statusDesc = statuses[returnShipment.statusId]
} else {
showToast(translate('Something went wrong'));
console.error("error", resp.data._ERROR_MESSAGE_);
return;
}
}

// Get shipment items of return shipment
resp = await ReturnService.getReturnDetail(payload);

if (resp.status === 200 && !hasError(resp) && resp.data.items) {
commit(types.RETURN_CURRENT_UPDATED, { current: resp.data })
// Current should have data of return shipment as well as items
commit(types.RETURN_CURRENT_UPDATED, { current: { ...resp.data, ...returnShipment} })
const productIds = [ ...new Set(resp.data.items.map((item: any) => item.productId)) ]

if(productIds.length) {
Expand Down Expand Up @@ -108,42 +138,6 @@ const actions: ActionTree<ReturnState, RootState> = {
console.error(err);
}
},
async addReturnItem ({ state, commit, dispatch }, payload) {
const item = payload.shipmentId ? { ...(payload.item) } : { ...payload }
const product = {
...item,
quantityAccepted: 0,
quantityOrdered: 0
}
const params = {
orderId: payload.orderId,
productId: product.productId,
quantity: 0,
shipmentId: payload.shipmentId ? payload.shipmentId : state.current.shipmentId,
returnItemSeqId: payload.shipmentItemSeqId
}
const resp = await ReturnService.addReturnItem(params);
if (resp.status == 200 && !hasError(resp)){
dispatch('updateProductCount', { shipmentId: resp.data.shipmentId })
if (!payload.shipmentId) commit(types.RETURN_CURRENT_PRODUCT_ADDED, product)
return resp;
} else {
showToast(translate('Something went wrong'));
console.error("error", resp._ERROR_MESSAGE_);
return Promise.reject(new Error(resp.data._ERROR_MESSAGE_));
}
},
// TODO: Fix this later
async updateProductCount({ commit, state }, payload ) {
const returns = state.returns.list;
returns.map((returnShipment: any) => {
if(returnShipment.shipmentId === payload.shipmentId) {
returnShipment.shipmentItemCount = parseInt(returnShipment.shipmentItemCount) + 1;
return;
}
})
commit(types.RETURN_LIST_UPDATED, { returns })
},
async clearReturns({ commit }) {
commit(types.RETURN_LIST_UPDATED, { returns: [] })
commit(types.RETURN_CURRENT_UPDATED, { current: {} })
Expand Down
64 changes: 52 additions & 12 deletions src/views/ReturnDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@
<ion-content>
<main>
<ion-item lines="none">
<h1>{{ $t("Shipment ID") }}: {{ current.shipmentId }}</h1>
<ion-list class="ion-text-center">
<ion-title>{{ current.shopifyOrderName ? current.shopifyOrderName : current.hcOrderId }}</ion-title>
<!-- TODO: Fetch Customer name -->
<!-- <ion-label>{{ $t("Customer: <customer name>")}}</ion-label> -->
</ion-list>
<ion-item slot="end" lines="none">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't use ion-item here. Instead we can use an ion-row here or normal div with css

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done sir

<ion-badge :color="statusColorMapping[current.statusDesc]" slot="end">{{ current.statusDesc }}</ion-badge>
<ion-chip v-if="current.trackingCode" slot="end">{{ current.trackingCode }}</ion-chip>
</ion-item>
</ion-item>

<div class="shipment-scanner">
Expand All @@ -35,24 +43,33 @@
<p>{{ getProduct(item.productId).productId }}</p>
</ion-label>
</ion-item>
<ion-item class="product-count">
<ion-item :disabled="true" lines="none">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need an item here? why can't we just put a chip here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do that sir. Fixed it.

<ion-chip outline="true">
<ion-icon :icon="locationOutline" />
<ion-label>{{ current.locationSeqId }}</ion-label>
</ion-chip>
</ion-item>
<ion-item v-if="isReturnReceivable(current.statusId)" class="product-count">
<ion-label position="floating">{{ $t("Qty") }}</ion-label>
<ion-input type="number" min="0" v-model="item.quantityAccepted" />
</ion-item>
<ion-item v-if="!isReturnReceivable(current.statusId)" class="product-count" lines="none">
<ion-label>{{ item.quantityAccepted }} {{ $t("received") }}</ion-label>
</ion-item>
</div>

<ion-item class="border-top" v-if="item.quantityOrdered > 0">
<ion-button @click="receiveAll(item)" slot="start" fill="outline">
<ion-button v-if="isReturnReceivable(current.statusId)" @click="receiveAll(item)" slot="start" fill="outline">
{{ $t("Receive All") }}
</ion-button>
<ion-progress-bar :value="item.quantityAccepted/item.quantityOrdered" />
<p slot="end">{{ item.quantityOrdered }}</p>
<p slot="end">{{ item.quantityOrdered }} {{ $t("returned") }}</p>
</ion-item>
</ion-card>
</main>

<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button v-if="validStatusChange(current.statusId)" @click="completeShipment">
<ion-fab-button v-if="isReturnReceivable(current.statusId)" @click="completeShipment">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should put this on the parent container. we wouldn't want an empty element floating around the ui

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure sir. Placed it inside a div.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dt2patel please have a look.
PR - #138

<ion-icon :icon="checkmarkDone" />
</ion-fab-button>
</ion-fab>
Expand All @@ -63,8 +80,10 @@
<script lang="ts">
import {
IonBackButton,
IonBadge,
IonButton,
IonCard,
IonChip,
IonContent,
IonHeader,
IonFab,
Expand All @@ -73,6 +92,7 @@ import {
IonItem,
IonInput,
IonLabel,
IonList,
IonPage,
IonProgressBar,
IonThumbnail,
Expand All @@ -82,20 +102,24 @@ import {
alertController,
} from '@ionic/vue';
import { defineComponent } from 'vue';
import { checkmarkDone, barcodeOutline } from 'ionicons/icons';
import { checkmarkDone, barcodeOutline, locationOutline } from 'ionicons/icons';
import { mapGetters, useStore } from "vuex";
import AddProductModal from '@/views/AddProductModal.vue'
import Image from "@/components/Image.vue";
import { useRouter } from 'vue-router';
import Scanner from "@/components/Scanner.vue";
import ImageModal from '@/components/ImageModal.vue';
import { showToast } from '@/utils'
import { translate } from '@/i18n'

export default defineComponent({
name: "ReturnDetails",
components: {
IonBackButton,
IonBadge,
IonButton,
IonCard,
IonChip,
IonContent,
IonHeader,
IonFab,
Expand All @@ -104,6 +128,7 @@ export default defineComponent({
IonItem,
IonInput,
IonLabel,
IonList,
IonPage,
IonProgressBar,
IonThumbnail,
Expand All @@ -114,17 +139,28 @@ export default defineComponent({
props: ["shipment"],
data() {
return {
queryString: ''
queryString: '',
statusColorMapping: {
'Received': 'success',
'Approved': 'tertiary',
'Cancelled': 'danger',
'Shipped': 'medium',
'Created': 'medium'
} as any
}
},
mounted() {
this.store.dispatch('return/setCurrent', { shipmentId: this.$route.params.id })
async mounted() {
const current = await this.store.dispatch('return/setCurrent', { shipmentId: this.$route.params.id })
if(!this.isReturnReceivable(current.statusId)) {
showToast(translate("This return has been and cannot be edited.", { status: current?.statusDesc?.toLowerCase() }));
}
},
computed: {
...mapGetters({
current: 'return/getCurrent',
getProduct: 'product/getProduct',
validStatusChange: 'return/isReturnReceivable'
isReturnReceivable: 'return/isReturnReceivable',
returns: 'return/getReturns'
}),
},
methods: {
Expand Down Expand Up @@ -187,8 +223,10 @@ export default defineComponent({
}
})
},
updateProductCount(payload: any){
updateProductCount(payload?: any){
if(this.queryString) payload = this.queryString
// if not a valid status, skip updating the qunatity
if(!this.isReturnReceivable(this.current.statusId)) return;
this.store.dispatch('return/updateReturnProductCount', payload)
},
async scanCode () {
Expand All @@ -210,6 +248,7 @@ export default defineComponent({
return {
barcodeOutline,
checkmarkDone,
locationOutline,
store,
router
};
Expand All @@ -233,9 +272,10 @@ ion-thumbnail {
border-top: 1px solid #ccc;
}


.product-info {
display: grid;
grid-template-columns: 1fr .25fr;
grid-template-columns: 1fr 1fr .30fr;
align-items: center;
padding: 16px;
padding-left: 0;
Expand Down
21 changes: 15 additions & 6 deletions src/views/Returns.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,37 @@ export default defineComponent({
}
},
mounted () {
this.getReturns();
this.store.dispatch('return/fetchValidReturnStatuses');
this.getReturns();
},
methods: {
async getReturns(vSize?: any, vIndex?: any) {
const viewSize = vSize ? vSize : process.env.VUE_APP_VIEW_SIZE;
const viewIndex = vIndex ? vIndex : 0;
const payload = {
"inputFields": {
"shipmentTypeId": "SALES_RETURN",
},
"entityName": "ShipmentAndTypeAndItemCount",
"fieldList" : [ "shipmentId","primaryShipGroupSeqId","partyIdFrom","partyIdTo","estimatedArrivalDate","destinationFacilityId","statusId", "shipmentItemCount" ],
"entityName": "SalesReturnShipmentView",
"inputFields": {},
"fieldList" : [ "shipmentId","externalId","statusId","shopifyOrderName","hcOrderId","trackingCode" ],
"noConditionFind": "Y",
"viewSize": viewSize,
"viewIndex": viewIndex,
"orderBy": "createdDate ASC"
} as any

if(this.queryString){
// Search query done on shipmentId, trackingCode and externalId
payload.inputFields["shipmentId"] = this.queryString;
payload.inputFields["shipmentId_op"] = "contains";
payload.inputFields["shipmentId_ic"] = "Y";
payload.inputFields["shipmentId_grp"] = "1";
payload.inputFields["trackingCode"] = this.queryString;
payload.inputFields["trackingCode_op"] = "contains";
payload.inputFields["trackingCode_ic"] = "Y";
payload.inputFields["trackingCode_grp"] = "2";
payload.inputFields["externalId"] = this.queryString;
payload.inputFields["externalId_op"] = "contains";
payload.inputFields["externalId_ic"] = "Y";
payload.inputFields["externalId_grp"] = "3";
}
await this.store.dispatch("return/findReturn", payload);
},
Expand Down
1 change: 1 addition & 0 deletions src/views/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export default defineComponent({
logout () {
this.store.dispatch('user/logout').then(() => {
this.store.dispatch('shipment/clearShipments');
this.store.dispatch('return/clearReturns');
this.router.push('/login');
})
}
Expand Down