mirror of
https://github.com/frappe/books.git
synced 2026-08-24 10:04:45 -05:00
Merge pull request #1065 from AbleKSaju/feat-submit-inv
feat: submit and hold invoice for later use in POS
This commit is contained in:
@@ -14,7 +14,6 @@ export class POSSettings extends Doc {
|
||||
checkDigits?: number;
|
||||
itemCodeDigits?: number;
|
||||
itemWeightDigits?: number;
|
||||
|
||||
posUI?: 'Classic' | 'Modern';
|
||||
|
||||
static filters: FiltersMap = {
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
(date) => emitEvent('setTransferClearanceDate', date)
|
||||
"
|
||||
@create-transaction="
|
||||
(createTransaction) => emitEvent('createTransaction', createTransaction)
|
||||
(print, status) => emitEvent('createTransaction', print, status)
|
||||
"
|
||||
/>
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
>
|
||||
<slot>
|
||||
<p class="uppercase text-lg text-white font-semibold">
|
||||
{{ t`Pay` }}
|
||||
{{ t`Buy` }}
|
||||
</p>
|
||||
</slot>
|
||||
</Button>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
(date) => emitEvent('setTransferClearanceDate', date)
|
||||
"
|
||||
@create-transaction="
|
||||
(createTransaction) => emitEvent('createTransaction', createTransaction)
|
||||
(print, status) => emitEvent('createTransaction', print, status)
|
||||
"
|
||||
/>
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
>
|
||||
<slot>
|
||||
<p class="uppercase text-lg text-white font-semibold">
|
||||
{{ t`Pay` }}
|
||||
{{ t`Buy` }}
|
||||
</p>
|
||||
</slot>
|
||||
</Button>
|
||||
|
||||
+40
-16
@@ -138,6 +138,7 @@ import {
|
||||
ItemQtyMap,
|
||||
ItemSerialNumbers,
|
||||
} from 'src/components/POS/types';
|
||||
import { ValidationError } from 'fyo/utils/errors';
|
||||
|
||||
const COMPONENT_NAME = 'POS';
|
||||
|
||||
@@ -466,6 +467,10 @@ export default defineComponent({
|
||||
|
||||
this.sinvDoc = salesInvoiceDoc;
|
||||
this.toggleModal('SavedInvoice', false);
|
||||
|
||||
if (doc.submitted) {
|
||||
this.toggleModal('Payment');
|
||||
}
|
||||
},
|
||||
setTransferAmount(amount: Money = fyo.pesa(0)) {
|
||||
this.transferAmount = amount;
|
||||
@@ -478,19 +483,25 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
async addItem(item: POSItem | Item | undefined, quantity?: number) {
|
||||
await this.sinvDoc.runFormulas();
|
||||
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existingItems =
|
||||
this.sinvDoc.items?.filter(
|
||||
(invoiceItem) =>
|
||||
invoiceItem.item === item.name && !invoiceItem.isFreeItem
|
||||
) ?? [];
|
||||
|
||||
try {
|
||||
await this.sinvDoc.runFormulas();
|
||||
|
||||
if (this.sinvDoc.isSubmitted) {
|
||||
throw new ValidationError(
|
||||
t`Cannot add an item to a submitted invoice.`
|
||||
);
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existingItems =
|
||||
this.sinvDoc.items?.filter(
|
||||
(invoiceItem) =>
|
||||
invoiceItem.item === item.name && !invoiceItem.isFreeItem
|
||||
) ?? [];
|
||||
|
||||
if (item.hasBatch) {
|
||||
for (const invItem of existingItems) {
|
||||
const itemQty = invItem.quantity ?? 0;
|
||||
@@ -571,13 +582,26 @@ export default defineComponent({
|
||||
await this.applyPricingRule();
|
||||
await this.sinvDoc.runFormulas();
|
||||
},
|
||||
|
||||
async createTransaction(shouldPrint = false) {
|
||||
async createTransaction(shouldPrint = false, isPay = false) {
|
||||
try {
|
||||
await this.validate();
|
||||
await this.submitSinvDoc();
|
||||
await this.makePayment(shouldPrint);
|
||||
await this.makeStockTransfer();
|
||||
|
||||
if (this.sinvDoc.stockNotTransferred) {
|
||||
await this.makeStockTransfer();
|
||||
}
|
||||
|
||||
if (isPay) {
|
||||
await this.makePayment(shouldPrint);
|
||||
}
|
||||
|
||||
if (shouldPrint) {
|
||||
await routeTo(
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
`/print/${this.sinvDoc.schemaName}/${this.sinvDoc.name}`
|
||||
);
|
||||
}
|
||||
|
||||
await this.afterTransaction();
|
||||
await this.setItems();
|
||||
} catch (error) {
|
||||
|
||||
@@ -130,12 +130,30 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4 fixed bottom-8" style="width: 25rem">
|
||||
<div class="col-span-2">
|
||||
<div class="grid grid-cols-2 gap-4 bottom-8">
|
||||
<div class="col-span-1">
|
||||
<Button
|
||||
class="w-full bg-violet-500 dark:bg-violet-700"
|
||||
style="padding: 1.35rem"
|
||||
:disabled="disableSubmitButton"
|
||||
@click="submitTransaction()"
|
||||
>
|
||||
<slot>
|
||||
<p
|
||||
class="uppercase text-lg text-white font-semibold"
|
||||
:disabled="sinvDoc.submitted"
|
||||
>
|
||||
{{ t`Submit` }}
|
||||
</p>
|
||||
</slot>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div class="col-span-1">
|
||||
<Button
|
||||
class="w-full bg-red-500 dark:bg-red-700"
|
||||
style="padding: 1.35rem"
|
||||
@click="$emit('toggleModal', 'Payment')"
|
||||
@click="cancelTransaction()"
|
||||
>
|
||||
<slot>
|
||||
<p class="uppercase text-lg text-white font-semibold">
|
||||
@@ -149,26 +167,27 @@
|
||||
<Button
|
||||
class="w-full bg-blue-500 dark:bg-blue-700"
|
||||
style="padding: 1.35rem"
|
||||
:disabled="disableSubmitButton"
|
||||
@click="submitTransaction()"
|
||||
:disabled="disablePayButton"
|
||||
@click="payTransaction()"
|
||||
>
|
||||
<slot>
|
||||
<p class="uppercase text-lg text-white font-semibold">
|
||||
{{ t`Submit` }}
|
||||
{{ t`Pay` }}
|
||||
</p>
|
||||
</slot>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div class="col-span-1">
|
||||
<Button
|
||||
class="w-full bg-green-500 dark:bg-green-700"
|
||||
style="padding: 1.35rem"
|
||||
:disabled="disableSubmitButton"
|
||||
@click="$emit('createTransaction', true)"
|
||||
:disabled="disablePayButton"
|
||||
@click="$emit('createTransaction', true, true)"
|
||||
>
|
||||
<slot>
|
||||
<p class="uppercase text-lg text-white font-semibold">
|
||||
{{ t`Submit & Print` }}
|
||||
{{ t`Pay & Print` }}
|
||||
</p>
|
||||
</slot>
|
||||
</Button>
|
||||
@@ -293,6 +312,26 @@ export default defineComponent({
|
||||
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()
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
this.paymentMethod !== 'Cash' &&
|
||||
(!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()
|
||||
@@ -332,6 +371,13 @@ export default defineComponent({
|
||||
submitTransaction() {
|
||||
this.$emit('createTransaction');
|
||||
},
|
||||
payTransaction() {
|
||||
this.$emit('createTransaction', false, true);
|
||||
},
|
||||
cancelTransaction() {
|
||||
this.$emit('setPaidAmount', fyo.pesa(0));
|
||||
this.$emit('toggleModal', 'Payment');
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,16 +1,33 @@
|
||||
<template>
|
||||
<Modal class="h-auto w-auto p-6" :set-close-listener="false">
|
||||
<p class="text-center font-semibold">{{ t`Saved Invoices` }}</p>
|
||||
<Modal class="h-auto w-auto p-5" :set-close-listener="false">
|
||||
<p class="text-center font-semibold">{{ t`Invoices` }}</p>
|
||||
|
||||
<hr class="mt-2 dark:border-gray-800" />
|
||||
|
||||
<div class="flex justify-around items-center">
|
||||
<Button
|
||||
:background="false"
|
||||
class="w-full h-full p-2 mt-2"
|
||||
:class="{ 'dark:bg-gray-890 underline': savedInvoiceList }"
|
||||
@click="savedInvoiceList = true"
|
||||
>Saved</Button
|
||||
>
|
||||
|
||||
<Button
|
||||
:background="false"
|
||||
class="w-full h-full p-2 mt-2"
|
||||
:class="{ 'dark:bg-gray-890 underline': !savedInvoiceList }"
|
||||
@click="savedInvoiceList = false"
|
||||
>Submitted</Button
|
||||
>
|
||||
</div>
|
||||
<Row
|
||||
:ratio="ratio"
|
||||
class="
|
||||
border
|
||||
flex
|
||||
items-center
|
||||
mt-4
|
||||
mt-2
|
||||
px-2
|
||||
w-full
|
||||
rounded-t-md
|
||||
@@ -28,12 +45,12 @@
|
||||
</Row>
|
||||
|
||||
<div
|
||||
v-if="savedInvoices.length"
|
||||
v-if="savedInvoiceList ? savedInvoices.length : submittedInvoices.length"
|
||||
class="overflow-y-auto custom-scroll custom-scroll-thumb2"
|
||||
style="height: 65vh; width: 60vh"
|
||||
>
|
||||
<Row
|
||||
v-for="row in savedInvoices as SalesInvoice[]"
|
||||
v-for="row in savedInvoiceList ? savedInvoices : submittedInvoices"
|
||||
:key="row.name"
|
||||
:ratio="ratio"
|
||||
:border="true"
|
||||
@@ -88,6 +105,7 @@ import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import { Field } from 'schemas/types';
|
||||
import { Money } from 'pesa';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SavedInvoiceModal',
|
||||
@@ -108,7 +126,9 @@ export default defineComponent({
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
savedInvoiceList: true,
|
||||
savedInvoices: [] as SalesInvoice[],
|
||||
submittedInvoices: [] as SalesInvoice[],
|
||||
isModalVisible: false,
|
||||
};
|
||||
},
|
||||
@@ -152,14 +172,17 @@ export default defineComponent({
|
||||
async modalStatus(newVal) {
|
||||
if (newVal) {
|
||||
await this.setSavedInvoices();
|
||||
await this.setSubmittedInvoices();
|
||||
}
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
await this.setSavedInvoices();
|
||||
await this.setSubmittedInvoices();
|
||||
},
|
||||
async activated() {
|
||||
await this.setSavedInvoices();
|
||||
await this.setSubmittedInvoices();
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -172,6 +195,16 @@ export default defineComponent({
|
||||
}
|
||||
)) as SalesInvoice[];
|
||||
},
|
||||
async setSubmittedInvoices() {
|
||||
const invoices = (await this.fyo.db.getAll(ModelNameEnum.SalesInvoice, {
|
||||
fields: [],
|
||||
filters: { isPOS: true, submitted: true, returnAgainst: null },
|
||||
})) as SalesInvoice[];
|
||||
|
||||
this.submittedInvoices = invoices.filter(
|
||||
(invoice) => !(invoice.outstandingAmount as Money).isZero()
|
||||
);
|
||||
},
|
||||
async selectedInvoice(row: SalesInvoice) {
|
||||
let selectedInvoiceDoc = (await this.fyo.doc.getDoc(
|
||||
ModelNameEnum.SalesInvoice,
|
||||
|
||||
Reference in New Issue
Block a user