From a1fc203e8b95dfecf72c13d9202c70f156202e31 Mon Sep 17 00:00:00 2001 From: akshayitzme Date: Sat, 23 Sep 2023 16:45:22 +0530 Subject: [PATCH] feat: invoice returns --- backend/database/bespoke.ts | 43 +++++++++++++------ models/baseModels/Payment/types.ts | 10 +++++ .../PurchaseInvoice/PurchaseInvoice.ts | 20 ++++++++- models/helpers.ts | 19 +++++++- src/components/StatusPill.vue | 16 +++---- 5 files changed, 84 insertions(+), 24 deletions(-) diff --git a/backend/database/bespoke.ts b/backend/database/bespoke.ts index 4723f25f..b9b3af74 100644 --- a/backend/database/bespoke.ts +++ b/backend/database/bespoke.ts @@ -185,7 +185,7 @@ export class BespokeQueries { static async getReturnBalanceItemsQty( db: DatabaseCore, - schemaName: string, + schemaName: ModelNameEnum, docName: string ): Promise | undefined> { const returnDocNames = ( @@ -200,21 +200,41 @@ export class BespokeQueries { return; } - const returnedItems: DocItem[] = await db.knex!(`${schemaName}Item`) - .select('item', 'batch', 'serialNumber') + const returnedItemsQuery = db.knex!(`${schemaName}Item`) .sum({ quantity: 'quantity' }) - .whereIn('parent', returnDocNames) - .groupBy('item', 'batch', 'serialNumber'); + .whereIn('parent', returnDocNames); + const docItemsQuery = db.knex!(`${schemaName}Item`) + .where('parent', docName) + .sum({ quantity: 'quantity' }); + + if ( + [ModelNameEnum.SalesInvoice, ModelNameEnum.PurchaseInvoice].includes( + schemaName + ) + ) { + returnedItemsQuery.select('item', 'batch').groupBy('item', 'batch'); + docItemsQuery.select('name', 'item', 'batch').groupBy('item', 'batch'); + } + + if ( + [ModelNameEnum.Shipment, ModelNameEnum.PurchaseReceipt].includes( + schemaName + ) + ) { + returnedItemsQuery + .select('item', 'batch', 'serialNumber') + .groupBy('item', 'batch', 'serialNumber'); + docItemsQuery + .select('name', 'item', 'batch', 'serialNumber') + .groupBy('item', 'batch', 'serialNumber'); + } + + const returnedItems = (await returnedItemsQuery) as DocItem[]; if (!returnedItems.length) { return; } - - const docItems: DocItem[] = await db.knex!(`${schemaName}Item`) - .select('name', 'item', 'batch', 'serialNumber') - .where('parent', docName) - .groupBy('item', 'batch', 'serialNumber') - .sum({ quantity: 'quantity' }); + const docItems = (await docItemsQuery) as DocItem[]; const docItemsMap = BespokeQueries.#getDocItemMap(docItems); const returnedItemsMap = BespokeQueries.#getDocItemMap(returnedItems); @@ -223,7 +243,6 @@ export class BespokeQueries { docItemsMap, returnedItemsMap ); - return returnBalanceItems; } diff --git a/models/baseModels/Payment/types.ts b/models/baseModels/Payment/types.ts index 03108ef7..e51fc16b 100644 --- a/models/baseModels/Payment/types.ts +++ b/models/baseModels/Payment/types.ts @@ -1,2 +1,12 @@ export type PaymentType = 'Receive' | 'Pay'; export type PaymentMethod = 'Cash' | 'Cheque' | 'Transfer'; + +export enum PaymentTypeEnum{ + Receive = 'Receive', + Pay = 'Pay' +} + +export enum AccountFieldEnum{ + Account = 'account', + PaymentAccount = 'paymentAccount' +} diff --git a/models/baseModels/PurchaseInvoice/PurchaseInvoice.ts b/models/baseModels/PurchaseInvoice/PurchaseInvoice.ts index 8da038bf..24403eed 100644 --- a/models/baseModels/PurchaseInvoice/PurchaseInvoice.ts +++ b/models/baseModels/PurchaseInvoice/PurchaseInvoice.ts @@ -12,14 +12,26 @@ export class PurchaseInvoice extends Invoice { async getPosting() { const exchangeRate = this.exchangeRate ?? 1; const posting: LedgerPosting = new LedgerPosting(this, this.fyo); - await posting.credit(this.account!, this.baseGrandTotal!); + if (this.isReturn) { + await posting.debit(this.account!, this.baseGrandTotal!); + } else { + await posting.credit(this.account!, this.baseGrandTotal!); + } for (const item of this.items!) { + if (this.isReturn) { + await posting.credit(item.account!, item.amount!.mul(exchangeRate)); + continue; + } await posting.debit(item.account!, item.amount!.mul(exchangeRate)); } if (this.taxes) { for (const tax of this.taxes) { + if (this.isReturn) { + await posting.credit(tax.account!, tax.amount!.mul(exchangeRate)); + continue; + } await posting.debit(tax.account!, tax.amount!.mul(exchangeRate)); } } @@ -28,7 +40,11 @@ export class PurchaseInvoice extends Invoice { const discountAccount = this.fyo.singles.AccountingSettings ?.discountAccount as string | undefined; if (discountAccount && discountAmount.isPositive()) { - await posting.credit(discountAccount, discountAmount.mul(exchangeRate)); + if (this.isReturn) { + await posting.debit(discountAccount, discountAmount.mul(exchangeRate)); + } else { + await posting.credit(discountAccount, discountAmount.mul(exchangeRate)); + } } await posting.makeRoundOffEntry(); diff --git a/models/helpers.ts b/models/helpers.ts index 4f95ef57..89f78a03 100644 --- a/models/helpers.ts +++ b/models/helpers.ts @@ -23,6 +23,7 @@ export function getInvoiceActions( getMakePaymentAction(fyo), getMakeStockTransferAction(fyo, schemaName), getLedgerLinkAction(fyo), + getMakeReturnDocAction(fyo), ]; } @@ -166,11 +167,17 @@ export function getMakeReturnDocAction(fyo: Fyo): Action { label: fyo.t`Return`, group: fyo.t`Create`, condition: (doc: Doc) => - !!fyo.singles.InventorySettings?.enableStockReturns && + (!!fyo.singles.AccountingSettings?.enableInvoiceReturns || + !!fyo.singles.InventorySettings?.enableStockReturns) && doc.isSubmitted && !doc.isReturn, action: async (doc: Doc) => { - const returnDoc = await (doc as StockTransfer)?.getReturnDoc(); + let returnDoc: Invoice | StockTransfer | undefined; + + if (doc instanceof Invoice || doc instanceof StockTransfer) { + returnDoc = await doc.getReturnDoc(); + } + if (!returnDoc || !returnDoc.name) { return; } @@ -297,6 +304,14 @@ function getSubmittableDocStatus(doc: RenderData | Doc) { } export function getInvoiceStatus(doc: RenderData | Doc): InvoiceStatus { + if (doc.submitted && !doc.cancelled && doc.returnAgainst) { + return 'Return'; + } + + if (doc.submitted && !doc.cancelled && doc.isReturned) { + return 'ReturnIssued'; + } + if ( doc.submitted && !doc.cancelled && diff --git a/src/components/StatusPill.vue b/src/components/StatusPill.vue index a6cafe24..0c97c805 100644 --- a/src/components/StatusPill.vue +++ b/src/components/StatusPill.vue @@ -92,6 +92,14 @@ function getSubmittableStatus(doc: Doc) { return 'Cancelled'; } + if (doc.returnAgainst && doc.isSubmitted) { + return 'Return'; + } + + if (doc.isReturned && doc.isSubmitted) { + return 'ReturnIssued'; + } + const isInvoice = doc instanceof Invoice; if ( doc.isSubmitted && @@ -113,14 +121,6 @@ function getSubmittableStatus(doc: Doc) { return 'Paid'; } - if (doc.returnAgainst && doc.isSubmitted) { - return 'Return'; - } - - if (doc.isReturned && doc.isSubmitted) { - return 'ReturnIssued'; - } - if (doc.isSubmitted) { return 'Submitted'; }