From 244bc93d83f0f25983ed462aa2383929a20fafde Mon Sep 17 00:00:00 2001 From: Gadha2311 Date: Mon, 21 Jul 2025 09:53:13 +0530 Subject: [PATCH 1/5] Feat: add arrows for quantity adjustment --- src/components/Controls/MultiLabelLink.vue | 42 +++++-- .../POS/Classic/SelectedItemRow.vue | 114 ++++++++++-------- src/pages/POS/ClassicPOS.vue | 5 +- src/pages/POS/POS.vue | 106 +++++++++++++--- 4 files changed, 189 insertions(+), 78 deletions(-) diff --git a/src/components/Controls/MultiLabelLink.vue b/src/components/Controls/MultiLabelLink.vue index 5a4fcd73..528bc102 100644 --- a/src/components/Controls/MultiLabelLink.vue +++ b/src/components/Controls/MultiLabelLink.vue @@ -72,18 +72,25 @@ export default { const schema = fyo.schemaMap[schemaName]; const filters = await this.getFilters(); - const fields = [ - ...new Set([ - 'name', - this.secondaryLink, - schema.titleField, - this.df.groupBy, - ]), + const baseFields = [ + 'name', + this.secondaryLink, + schema.titleField, + this.df.groupBy, ].filter(Boolean); + try { + const tableInfo = await fyo.db.getSchemaInfo(schemaName); + if (tableInfo.columns.barcode) { + baseFields.push('barcode'); + } + } catch (error) { + console.debug('Could not check for barcode column', error); + } + const results = await fyo.db.getAll(schemaName, { filters, - fields, + fields: baseFields, }); return (this.results = results @@ -91,10 +98,11 @@ export default { const option = { label: r[this.secondaryLink] && this.showSecondaryLink - ? `${r[schema.titleField]} ` + ` ${r[this.secondaryLink]}` + ? `${r[schema.titleField]} ${r[this.secondaryLink]}` : r[schema.titleField], value: r.name, value2: r[this.secondaryLink], + barcode: r.barcode || null, }; if (this.df.groupBy) { @@ -108,8 +116,22 @@ export default { let options = await this.getOptions(); if (keyword) { + const hasBarcode = options.some( + (opt) => opt.barcode !== undefined && opt.barcode !== null + ); + if (hasBarcode) { + const barcodeMatch = options.find((opt) => opt.barcode === keyword); + if (barcodeMatch) return [barcodeMatch]; + } + options = options - .map((item) => ({ ...fuzzyMatch(keyword, item.label), item })) + .map((item) => { + const searchString = `${item.label} ${item.barcode || ''}`; + return { + ...fuzzyMatch(keyword, searchString), + item, + }; + }) .filter(({ isMatch }) => isMatch) .sort((a, b) => a.distance - b.distance) .map(({ item }) => item); diff --git a/src/components/POS/Classic/SelectedItemRow.vue b/src/components/POS/Classic/SelectedItemRow.vue index cc579f49..0d507dee 100644 --- a/src/components/POS/Classic/SelectedItemRow.vue +++ b/src/components/POS/Classic/SelectedItemRow.vue @@ -27,17 +27,31 @@

- +
+ +
+ + +
+
@@ -302,12 +316,19 @@ export default defineComponent({ isReadOnly() { return this.row.isFreeItem; }, + isReturnDocument(): boolean { + return this.row.parentdoc?.isReturn ?? false; + }, + displayQuantity() { + if (this.isReturnDocument) { + return this.row.transferQuantity + ? -Math.abs(this.row.transferQuantity) + : -Math.abs(this.row.quantity); + } + return this.row.quantity; + }, }, - async mounted() { - // this.$watch('row.quantity', (newVal: number) => { - // this.setQuantity(newVal); - // }); const posProfileName = this.fyo.singles.POSSettings?.posProfile; if (posProfileName) { @@ -330,8 +351,23 @@ export default defineComponent({ this.profileRateSetting = !!this.fyo.singles.POSSettings?.canChangeRate; } }, - methods: { + adjustQuantity(change: number) { + let currentQuantity = this.row.quantity ?? 1; + if (this.isReturnDocument) { + currentQuantity = Math.abs(currentQuantity); + } + + let newQuantity = currentQuantity + change; + + if (this.isReturnDocument) { + newQuantity = -Math.abs(newQuantity); + } else if (newQuantity < 1) { + return; + } + + this.setQuantity(newQuantity); + }, async getAvailableQtyInBatch(): Promise { if (!this.row.batch) { return 0; @@ -372,7 +408,6 @@ export default defineComponent({ itemVisibility === 'Inventory Items' ); }, - isDiscountsReadOnly(isValidDiscount: boolean) { const canEditDiscount = this.profileDiscountSetting; @@ -390,7 +425,7 @@ export default defineComponent({ validateSerialNumberCount( serialNumber, - this.row.quantity ?? 0, + Math.abs(this.row.quantity ?? 0), this.row.item! ); }, @@ -412,22 +447,24 @@ export default defineComponent({ this.$emit('runSinvFormulas'); }, async setQuantity(quantity: number) { - const hasManualDiscount = this.row.setItemDiscountAmount; - const isPercentageDiscount = - !hasManualDiscount && this.row.itemDiscountPercent !== 0; - const manualDiscountAmount = this.row.itemDiscountAmount; - const manualDiscountPercent = this.row.itemDiscountPercent; - if (!this.row.isReturn && quantity <= 0) { + const workingQuantity = this.isReturnDocument + ? Math.abs(quantity) + : quantity; + + if (!this.isReturnDocument && workingQuantity <= 0) { showToast({ type: 'error', message: 'Quantity must be greater than zero.', duration: 'short', }); - - quantity = this.row.quantity ?? 1; + return; } - this.row.set('quantity', quantity); + const storedQuantity = this.isReturnDocument + ? -Math.abs(quantity) + : quantity; + + this.row.set('quantity', storedQuantity); const existingItems = (this.row.parentdoc as SalesInvoice).items?.filter( @@ -435,8 +472,6 @@ export default defineComponent({ invoiceItem.item === this.row.item && !invoiceItem.isFreeItem ) ?? []; - quantity = this.row.quantity ?? 1; - try { await validateQty( this.row.parentdoc as SalesInvoice, @@ -444,8 +479,7 @@ export default defineComponent({ existingItems ); } catch (error) { - this.row.set('quantity', quantity); - + this.row.set('quantity', storedQuantity); return showToast({ type: 'error', message: this.t`${error as string}`, @@ -456,20 +490,6 @@ export default defineComponent({ if (!this.row.isFreeItem) { this.$emit('applyPricingRule'); this.$emit('runSinvFormulas'); - - if (!hasManualDiscount && !isPercentageDiscount) { - this.row.set('setItemDiscountAmount', false); - this.row.set('itemDiscountPercent', 0); - } - this.row.set('rate', this.fyo.pesa(0)); - - if (hasManualDiscount) { - this.row.set('setItemDiscountAmount', true); - this.row.set('itemDiscountAmount', manualDiscountAmount); - } else if (isPercentageDiscount) { - this.row.set('setItemDiscountAmount', false); - this.row.set('itemDiscountPercent', manualDiscountPercent); - } } }, async removeAddedItem(row: SalesInvoiceItem) { diff --git a/src/pages/POS/ClassicPOS.vue b/src/pages/POS/ClassicPOS.vue index c8190c9a..d339eecd 100644 --- a/src/pages/POS/ClassicPOS.vue +++ b/src/pages/POS/ClassicPOS.vue @@ -257,7 +257,6 @@ fyo.singles.Defaults?.saveButtonColour, }" :class="`${isReturnInvoiceEnabledReturn ? 'py-5' : 'py-6'}`" - :disabled="!sinvDoc?.party || !sinvDoc?.items?.length" @click="$emit('saveInvoiceAction')" > @@ -274,7 +273,6 @@ fyo.singles.Defaults?.cancelButtonColour, }" :class="`${isReturnInvoiceEnabledReturn ? 'py-5' : 'py-6'}`" - :disabled="!sinvDoc?.items?.length" @click="() => $emit('clearValues')" > @@ -332,7 +330,6 @@ fyo.singles.Defaults?.payButtonColour, }" :class="`${isReturnInvoiceEnabledReturn ? 'py-5' : 'py-6'}`" - :disabled="disablePayButton" @click="emitEvent('toggleModal', 'Payment', true)" > @@ -350,7 +347,6 @@ profile?.payButtonColour || fyo.singles.Defaults?.payButtonColour, }" - :disabled="disablePayButton" @click="emitEvent('toggleModal', 'Payment', true)" > @@ -506,6 +502,7 @@ export default defineComponent({ 'selectedReturnInvoice', 'setTransferClearanceDate', 'saveAndContinue', + 'handlePayClick', ], data() { return { diff --git a/src/pages/POS/POS.vue b/src/pages/POS/POS.vue index 9e19cbf1..f6a499bd 100644 --- a/src/pages/POS/POS.vue +++ b/src/pages/POS/POS.vue @@ -62,6 +62,7 @@ @selected-return-invoice="selectedReturnInvoice" @set-transfer-clearance-date="setTransferClearanceDate" @save-and-continue="handleSaveAndContinue" + @handle-pay-click="handlePayClick" /> i.item === item.name && !existingItems.includes(i) + ); + + if (newItems?.length) { + const newItem = newItems[newItems.length - 1]; + await newItem.set('transferQuantity', transferQty); + } + await this.applyPricingRule(); await this.sinvDoc.runFormulas(); - return; } if (existingItems.length) { @@ -739,7 +773,7 @@ export default defineComponent({ } const currentQty = existingItems[0].quantity ?? 0; - const addQty = quantity ?? 1; + const addQty = qty; if (isInventoryItem) { const availableQty = this.itemQtyMap[item.name as string]?.availableQty ?? 0; @@ -751,6 +785,9 @@ export default defineComponent({ } await existingItems[0].set('quantity', currentQty + addQty); + if (transferQuantity !== undefined) { + await existingItems[0].set('transferQuantity', transferQty); + } await this.sinvDoc.runFormulas(); if (isInventoryItem) { await validateQty( @@ -762,26 +799,34 @@ export default defineComponent({ return; } - await this.sinvDoc.append('items', { + const success = await this.sinvDoc.append('items', { rate: item.rate as Money, item: item.name, - quantity: quantity ? quantity : 1, + quantity: qty, + transferQuantity: transferQty, hsnCode: itemsHsncode, }); - if (this.sinvDoc.priceList) { - let itemData = this.sinvDoc.items?.filter( - (val) => val.item == item.name - ) as SalesInvoiceItem[]; + if (!success) { + throw new Error('Failed to add item'); + } - itemData[0].rate = await getItemRateFromPriceList( - itemData[0], - this.sinvDoc.priceList + if (this.sinvDoc.priceList) { + const newItems = this.sinvDoc.items?.filter( + (i) => i.item === item.name && !existingItems.includes(i) ); + + if (newItems?.length) { + const newItem = newItems[newItems.length - 1]; + + newItem.rate = await getItemRateFromPriceList( + newItem, + this.sinvDoc.priceList + ); + } } await this.applyPricingRule(); - await this.sinvDoc.runFormulas(); } catch (error) { return showToast({ @@ -1058,9 +1103,36 @@ export default defineComponent({ }); } }, + handlePayClick() { + if (!this.sinvDoc.items?.length) { + return showToast({ + type: 'error', + message: t`Please add items before payment`, + }); + } + + if (!this.sinvDoc.party) { + return showToast({ + type: 'error', + message: t`Please select a customer before payment`, + }); + } + + this.toggleModal('Payment', true); + }, async saveInvoiceAction() { - if (!this.sinvDoc.party && !this.sinvDoc.items?.length) { - return; + if (!this.sinvDoc.items?.length) { + return showToast({ + type: 'error', + message: t`Please add items before saving`, + }); + } + + if (!this.sinvDoc.party) { + return showToast({ + type: 'error', + message: t`Please select a customer before saving`, + }); } await this.saveOrder(); From 2229c7e7caee286c6a78a560d85a6b8c2d6436d7 Mon Sep 17 00:00:00 2001 From: Gadha2311 Date: Tue, 22 Jul 2025 13:58:52 +0530 Subject: [PATCH 2/5] fix: applied recommended changes --- src/components/Controls/MultiLabelLink.vue | 42 +++-------- .../POS/Classic/SelectedItemRow.vue | 60 +++++++--------- .../POS/Classic/SelectedItemTable.vue | 3 +- src/pages/POS/POS.vue | 72 ++++--------------- 4 files changed, 53 insertions(+), 124 deletions(-) diff --git a/src/components/Controls/MultiLabelLink.vue b/src/components/Controls/MultiLabelLink.vue index 528bc102..5a4fcd73 100644 --- a/src/components/Controls/MultiLabelLink.vue +++ b/src/components/Controls/MultiLabelLink.vue @@ -72,25 +72,18 @@ export default { const schema = fyo.schemaMap[schemaName]; const filters = await this.getFilters(); - const baseFields = [ - 'name', - this.secondaryLink, - schema.titleField, - this.df.groupBy, + const fields = [ + ...new Set([ + 'name', + this.secondaryLink, + schema.titleField, + this.df.groupBy, + ]), ].filter(Boolean); - try { - const tableInfo = await fyo.db.getSchemaInfo(schemaName); - if (tableInfo.columns.barcode) { - baseFields.push('barcode'); - } - } catch (error) { - console.debug('Could not check for barcode column', error); - } - const results = await fyo.db.getAll(schemaName, { filters, - fields: baseFields, + fields, }); return (this.results = results @@ -98,11 +91,10 @@ export default { const option = { label: r[this.secondaryLink] && this.showSecondaryLink - ? `${r[schema.titleField]} ${r[this.secondaryLink]}` + ? `${r[schema.titleField]} ` + ` ${r[this.secondaryLink]}` : r[schema.titleField], value: r.name, value2: r[this.secondaryLink], - barcode: r.barcode || null, }; if (this.df.groupBy) { @@ -116,22 +108,8 @@ export default { let options = await this.getOptions(); if (keyword) { - const hasBarcode = options.some( - (opt) => opt.barcode !== undefined && opt.barcode !== null - ); - if (hasBarcode) { - const barcodeMatch = options.find((opt) => opt.barcode === keyword); - if (barcodeMatch) return [barcodeMatch]; - } - options = options - .map((item) => { - const searchString = `${item.label} ${item.barcode || ''}`; - return { - ...fuzzyMatch(keyword, searchString), - item, - }; - }) + .map((item) => ({ ...fuzzyMatch(keyword, item.label), item })) .filter(({ isMatch }) => isMatch) .sort((a, b) => a.distance - b.distance) .map(({ item }) => item); diff --git a/src/components/POS/Classic/SelectedItemRow.vue b/src/components/POS/Classic/SelectedItemRow.vue index 0d507dee..d21d3ec7 100644 --- a/src/components/POS/Classic/SelectedItemRow.vue +++ b/src/components/POS/Classic/SelectedItemRow.vue @@ -36,7 +36,7 @@ }" size="small" :border="false" - :value="displayQuantity" + :value="row.quantity" :read-only="true" />
@@ -54,6 +54,7 @@
@@ -316,17 +317,6 @@ export default defineComponent({ isReadOnly() { return this.row.isFreeItem; }, - isReturnDocument(): boolean { - return this.row.parentdoc?.isReturn ?? false; - }, - displayQuantity() { - if (this.isReturnDocument) { - return this.row.transferQuantity - ? -Math.abs(this.row.transferQuantity) - : -Math.abs(this.row.quantity); - } - return this.row.quantity; - }, }, async mounted() { const posProfileName = this.fyo.singles.POSSettings?.posProfile; @@ -354,15 +344,9 @@ export default defineComponent({ methods: { adjustQuantity(change: number) { let currentQuantity = this.row.quantity ?? 1; - if (this.isReturnDocument) { - currentQuantity = Math.abs(currentQuantity); - } - let newQuantity = currentQuantity + change; - if (this.isReturnDocument) { - newQuantity = -Math.abs(newQuantity); - } else if (newQuantity < 1) { + if (newQuantity === 0) { return; } @@ -447,30 +431,28 @@ export default defineComponent({ this.$emit('runSinvFormulas'); }, async setQuantity(quantity: number) { - const workingQuantity = this.isReturnDocument - ? Math.abs(quantity) - : quantity; - - if (!this.isReturnDocument && workingQuantity <= 0) { + const hasManualDiscount = this.row.setItemDiscountAmount; + const isPercentageDiscount = + !hasManualDiscount && this.row.itemDiscountPercent !== 0; + const manualDiscountAmount = this.row.itemDiscountAmount; + const manualDiscountPercent = this.row.itemDiscountPercent; + if (!this.row.isReturn && quantity <= 0) { showToast({ type: 'error', message: 'Quantity must be greater than zero.', duration: 'short', }); - return; + quantity = this.row.quantity ?? 1; } - const storedQuantity = this.isReturnDocument - ? -Math.abs(quantity) - : quantity; - - this.row.set('quantity', storedQuantity); + this.row.set('quantity', quantity); const existingItems = (this.row.parentdoc as SalesInvoice).items?.filter( (invoiceItem: InvoiceItem) => invoiceItem.item === this.row.item && !invoiceItem.isFreeItem ) ?? []; + quantity = this.row.quantity ?? 1; try { await validateQty( @@ -479,7 +461,7 @@ export default defineComponent({ existingItems ); } catch (error) { - this.row.set('quantity', storedQuantity); + this.row.set('quantity', quantity); return showToast({ type: 'error', message: this.t`${error as string}`, @@ -490,6 +472,18 @@ export default defineComponent({ if (!this.row.isFreeItem) { this.$emit('applyPricingRule'); this.$emit('runSinvFormulas'); + if (!hasManualDiscount && !isPercentageDiscount) { + this.row.set('setItemDiscountAmount', false); + this.row.set('itemDiscountPercent', 0); + } + this.row.set('rate', this.fyo.pesa(0)); + if (hasManualDiscount) { + this.row.set('setItemDiscountAmount', true); + this.row.set('itemDiscountAmount', manualDiscountAmount); + } else if (isPercentageDiscount) { + this.row.set('setItemDiscountAmount', false); + this.row.set('itemDiscountPercent', manualDiscountPercent); + } } }, async removeAddedItem(row: SalesInvoiceItem) { diff --git a/src/components/POS/Classic/SelectedItemTable.vue b/src/components/POS/Classic/SelectedItemTable.vue index 8eb99226..9248f380 100644 --- a/src/components/POS/Classic/SelectedItemTable.vue +++ b/src/components/POS/Classic/SelectedItemTable.vue @@ -97,8 +97,9 @@ export default defineComponent({ emits: ['applyPricingRule'], computed: { ratio() { - return [0.1, 1, 0.8, 0.8, 0.8, 0.8, 0.2]; + return [0.1, 0.9, 1.1, 0.6, 0.8, 0.8, 0.2]; }, + tableFields() { return [ { diff --git a/src/pages/POS/POS.vue b/src/pages/POS/POS.vue index f6a499bd..8ed2ab31 100644 --- a/src/pages/POS/POS.vue +++ b/src/pages/POS/POS.vue @@ -325,7 +325,6 @@ export default defineComponent({ if (!addItem) return; let quantity = 1; - let transferQuantity = 1; const posSettings = fyo.singles.POSSettings; const isWeightEnabledBarcode = posSettings?.weightEnabledBarcode; @@ -385,16 +384,14 @@ export default defineComponent({ const weightValue = parseInt(weightPart, 10); if ((matchedItem.unit as string)?.toLowerCase() === 'kg') { quantity = weightValue / 1000; - transferQuantity = quantity; } else { quantity = weightValue; - transferQuantity = quantity; } } const itemDoc = this.getItem(matchedItem.name as string); if (itemDoc && addItem) { - await this.addItem(itemDoc as POSItem, quantity, transferQuantity); + await this.addItem(itemDoc as POSItem, quantity); this.itemSearchTerm = ''; } }, @@ -557,13 +554,6 @@ export default defineComponent({ if (!returnDoc || !returnDoc.name) { return; } - if (returnDoc.items) { - for (const item of returnDoc.items) { - if (item.hasBatch && item.transferQuantity) { - await item.set('quantity', Math.abs(item.transferQuantity)); - } - } - } this.sinvDoc = returnDoc; }, @@ -664,11 +654,7 @@ export default defineComponent({ ); } }, - async addItem( - item: POSItem | Item | undefined, - quantity?: number, - transferQuantity?: number - ) { + async addItem(item: POSItem | Item | undefined, quantity?: number) { try { await this.sinvDoc.runFormulas(); this.validateInvoice(); @@ -711,11 +697,6 @@ export default defineComponent({ 'hsnCode' )) as number; - const qty = quantity ?? 1; - - const transferQty = - transferQuantity !== undefined ? transferQuantity : qty; - if (item.hasBatch) { const addQty = quantity ?? 1; @@ -742,29 +723,16 @@ export default defineComponent({ } } - const success = await this.sinvDoc.append('items', { + await this.sinvDoc.append('items', { rate: item.rate as Money, item: item.name, quantity: addQty, - transferQuantity: transferQty, hsnCode: itemsHsncode, }); - if (!success) { - throw new Error('Failed to add item'); - } - - const newItems = this.sinvDoc.items?.filter( - (i) => i.item === item.name && !existingItems.includes(i) - ); - - if (newItems?.length) { - const newItem = newItems[newItems.length - 1]; - await newItem.set('transferQuantity', transferQty); - } - await this.applyPricingRule(); await this.sinvDoc.runFormulas(); + return; } if (existingItems.length) { @@ -773,7 +741,7 @@ export default defineComponent({ } const currentQty = existingItems[0].quantity ?? 0; - const addQty = qty; + const addQty = quantity ?? 1; if (isInventoryItem) { const availableQty = this.itemQtyMap[item.name as string]?.availableQty ?? 0; @@ -785,9 +753,6 @@ export default defineComponent({ } await existingItems[0].set('quantity', currentQty + addQty); - if (transferQuantity !== undefined) { - await existingItems[0].set('transferQuantity', transferQty); - } await this.sinvDoc.runFormulas(); if (isInventoryItem) { await validateQty( @@ -799,31 +764,22 @@ export default defineComponent({ return; } - const success = await this.sinvDoc.append('items', { + await this.sinvDoc.append('items', { rate: item.rate as Money, item: item.name, - quantity: qty, - transferQuantity: transferQty, + quantity: quantity ? quantity : 1, hsnCode: itemsHsncode, }); - if (!success) { - throw new Error('Failed to add item'); - } - if (this.sinvDoc.priceList) { - const newItems = this.sinvDoc.items?.filter( - (i) => i.item === item.name && !existingItems.includes(i) + let itemData = this.sinvDoc.items?.filter( + (val) => val.item == item.name + ) as SalesInvoiceItem[]; + + itemData[0].rate = await getItemRateFromPriceList( + itemData[0], + this.sinvDoc.priceList ); - - if (newItems?.length) { - const newItem = newItems[newItems.length - 1]; - - newItem.rate = await getItemRateFromPriceList( - newItem, - this.sinvDoc.priceList - ); - } } await this.applyPricingRule(); From 9ba7e2bfe8add993328dfa71c29fcaa8a1bab2c9 Mon Sep 17 00:00:00 2001 From: Gadha2311 Date: Tue, 22 Jul 2025 14:52:40 +0530 Subject: [PATCH 3/5] fix: adjust spacing issue --- src/components/POS/Classic/SelectedItemRow.vue | 10 +++++++++- src/components/POS/Classic/SelectedItemTable.vue | 2 +- src/pages/POS/POS.vue | 2 -- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/POS/Classic/SelectedItemRow.vue b/src/components/POS/Classic/SelectedItemRow.vue index d21d3ec7..dd48f416 100644 --- a/src/components/POS/Classic/SelectedItemRow.vue +++ b/src/components/POS/Classic/SelectedItemRow.vue @@ -54,7 +54,7 @@

@@ -347,7 +347,7 @@ profile?.payButtonColour || fyo.singles.Defaults?.payButtonColour, }" - @click="emitEvent('toggleModal', 'Payment', true)" + @click="emitEvent('showPayButtonToast')" >

@@ -502,7 +502,7 @@ export default defineComponent({ 'selectedReturnInvoice', 'setTransferClearanceDate', 'saveAndContinue', - 'handlePayClick', + 'showPayButtonToast', ], data() { return { diff --git a/src/pages/POS/POS.vue b/src/pages/POS/POS.vue index f29aa9fb..fd02b8e4 100644 --- a/src/pages/POS/POS.vue +++ b/src/pages/POS/POS.vue @@ -62,7 +62,7 @@ @selected-return-invoice="selectedReturnInvoice" @set-transfer-clearance-date="setTransferClearanceDate" @save-and-continue="handleSaveAndContinue" - @handle-pay-click="handlePayClick" + @show-pay-button-toast="showPayButtonToast" /> -

+

{{ t`Submit` }}

@@ -170,7 +166,7 @@ backgroundColor: fyo.singles.Defaults?.cancelButtonColour, }" style="padding: 1.35rem" - @click="cancelTransaction()" + @click="cancelTransaction" >

@@ -185,8 +181,7 @@ class="w-full" :style="{ backgroundColor: fyo.singles.Defaults?.payButtonColour }" style="padding: 1.35rem" - :disabled="disablePayButton" - @click="payTransaction()" + @click="payTransaction" >

@@ -203,8 +198,7 @@ backgroundColor: fyo.singles.Defaults?.payAndPrintButtonColour, }" style="padding: 1.35rem" - :disabled="disablePayButton" - @click="$emit('createTransaction', true, true)" + @click="payAndPrintTransaction" >

@@ -230,6 +224,7 @@ import { defineComponent, inject } from 'vue'; import { fyo } from 'src/initFyo'; import { isPesa } from 'fyo/utils'; import { ModelNameEnum } from 'models/types'; +import { showToast } from 'src/utils/interactive'; export default defineComponent({ name: 'PaymentModal', @@ -331,45 +326,6 @@ export default defineComponent({ return true; } - return false; - }, - disableSubmitButton(): boolean { - if (this.sinvDoc.submitted) { - return true; - } - - if ( - (this.sinvDoc.grandTotal?.float as number) < 1 && - this.fyo.pesa(this.paidAmount.float).isZero() && - !this.sinvDoc.returnAgainst - ) { - return true; - } - - if ( - !this.paymentMethod && - (!this.transferRefNo || !this.transferClearanceDate) - ) { - return true; - } - return false; - }, - disablePayButton(): boolean { - if ( - (this.sinvDoc.grandTotal?.float as number) < 1 && - this.fyo.pesa(this.paidAmount.float).isZero() && - !this.sinvDoc.returnAgainst - ) { - return true; - } - - if ( - !this.paymentMethod && - (!this.transferRefNo || !this.transferClearanceDate) - ) { - return true; - } - return false; }, }, @@ -394,11 +350,39 @@ export default defineComponent({ ).map((d) => d.name); }, submitTransaction() { + if (!this.paymentMethod) { + return showToast({ + type: 'error', + message: this.fyo + .t`Please select a payment method before submitting.`, + }); + return; + } this.$emit('createTransaction'); }, payTransaction() { + if (!this.paymentMethod) { + return showToast({ + type: 'error', + message: this.fyo + .t`Please select a payment method before proceeding with payment.`, + }); + return; + } this.$emit('createTransaction', false, true); }, + payAndPrintTransaction() { + if (!this.paymentMethod) { + return showToast({ + type: 'error', + message: this.fyo + .t`Please select a payment method before proceeding with payment.`, + }); + return; + } + + this.$emit('createTransaction', true, true); + }, cancelTransaction() { this.$emit('setPaidAmount', fyo.pesa(0)); this.$emit('toggleModal', 'Payment'); From 9a92629574aaeb21f3d5d2e4de91618dfed0c881 Mon Sep 17 00:00:00 2001 From: Gadha2311 Date: Wed, 23 Jul 2025 12:03:34 +0530 Subject: [PATCH 5/5] fix: unify invoice validation toast logic --- .../POS/Classic/SelectedItemTable.vue | 1 - src/components/POS/types.ts | 2 +- src/pages/POS/ClassicPOS.vue | 6 +-- src/pages/POS/POS.vue | 35 +++++++--------- src/pages/POS/POSQuickActions.vue | 42 +++++++++---------- 5 files changed, 41 insertions(+), 45 deletions(-) diff --git a/src/components/POS/Classic/SelectedItemTable.vue b/src/components/POS/Classic/SelectedItemTable.vue index 800f8386..3eae4c99 100644 --- a/src/components/POS/Classic/SelectedItemTable.vue +++ b/src/components/POS/Classic/SelectedItemTable.vue @@ -99,7 +99,6 @@ export default defineComponent({ ratio() { return [0.1, 0.9, 0.8, 0.8, 0.8, 0.8, 0.2]; }, - tableFields() { return [ { diff --git a/src/components/POS/types.ts b/src/components/POS/types.ts index 3de3315c..1cddd609 100644 --- a/src/components/POS/types.ts +++ b/src/components/POS/types.ts @@ -43,7 +43,7 @@ export type PosEmits = | 'selectedInvoiceName' | 'selectedReturnInvoice' | 'saveAndContinue' - | 'showPayButtonToast' + | 'handlePaymentAction' | 'setTransferClearanceDate'; export interface POSItem { diff --git a/src/pages/POS/ClassicPOS.vue b/src/pages/POS/ClassicPOS.vue index 95accb67..d4dd89f9 100644 --- a/src/pages/POS/ClassicPOS.vue +++ b/src/pages/POS/ClassicPOS.vue @@ -330,7 +330,7 @@ fyo.singles.Defaults?.payButtonColour, }" :class="`${isReturnInvoiceEnabledReturn ? 'py-5' : 'py-6'}`" - @click="emitEvent('showPayButtonToast')" + @click="emitEvent('handlePaymentAction')" >

@@ -347,7 +347,7 @@ profile?.payButtonColour || fyo.singles.Defaults?.payButtonColour, }" - @click="emitEvent('showPayButtonToast')" + @click="emitEvent('handlePaymentAction')" >

@@ -502,7 +502,7 @@ export default defineComponent({ 'selectedReturnInvoice', 'setTransferClearanceDate', 'saveAndContinue', - 'showPayButtonToast', + 'handlePaymentAction', ], data() { return { diff --git a/src/pages/POS/POS.vue b/src/pages/POS/POS.vue index fd02b8e4..fc4a5b74 100644 --- a/src/pages/POS/POS.vue +++ b/src/pages/POS/POS.vue @@ -62,7 +62,7 @@ @selected-return-invoice="selectedReturnInvoice" @set-transfer-clearance-date="setTransferClearanceDate" @save-and-continue="handleSaveAndContinue" - @show-pay-button-toast="showPayButtonToast" + @handle-payment-action="handlePaymentAction" />