From 601434b107fc1f8c0b9c689aa7a72524563ddf74 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 20 Sep 2023 17:22:39 +0200 Subject: [PATCH] feat: avoid invoice writes GL entry with zero amount --- .../core/20230912121909_seed_tax_rates.ts | 14 +++++++ .../src/database/seeds/data/TaxRates.ts | 30 ++++++++++++++ .../src/services/Items/ItemsEntriesService.ts | 9 +++++ .../Sales/Invoices/InvoiceGLEntries.ts | 40 +++++++++++++++---- 4 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 packages/server/src/database/seeds/core/20230912121909_seed_tax_rates.ts create mode 100644 packages/server/src/database/seeds/data/TaxRates.ts diff --git a/packages/server/src/database/seeds/core/20230912121909_seed_tax_rates.ts b/packages/server/src/database/seeds/core/20230912121909_seed_tax_rates.ts new file mode 100644 index 000000000..10856e740 --- /dev/null +++ b/packages/server/src/database/seeds/core/20230912121909_seed_tax_rates.ts @@ -0,0 +1,14 @@ +import { TenantSeeder } from '@/lib/Seeder/TenantSeeder'; +import { InitialTaxRates } from '../data/TaxRates'; + +export default class SeedTaxRates extends TenantSeeder { + /** + * Seeds initial tax rates to the organization. + */ + up(knex) { + return knex('tax_rates').then(async () => { + // Inserts seed entries. + return knex('tax_rates').insert(InitialTaxRates); + }); + } +} diff --git a/packages/server/src/database/seeds/data/TaxRates.ts b/packages/server/src/database/seeds/data/TaxRates.ts new file mode 100644 index 000000000..592b60565 --- /dev/null +++ b/packages/server/src/database/seeds/data/TaxRates.ts @@ -0,0 +1,30 @@ +export const InitialTaxRates = [ + { + name: 'Tax Exempt', + code: 'TAX-EXEMPT', + description: 'Exempts goods or services from taxes.', + rate: 0, + active: 1, + }, + { + name: 'Tax on Purchases', + code: 'TAX-PURCHASES', + description: 'Fee added to the cost when you buy items.', + rate: 0, + active: 1, + }, + { + name: 'Tax on Sales', + code: 'TAX-SALES', + description: 'Fee added to the cost when you sell items.', + rate: 0, + active: 1, + }, + { + name: 'Sales Tax on Imports', + code: 'TAX-IMPORTS', + description: 'Fee added to the cost when you sale to another country.', + rate: 0, + active: 1, + }, +]; diff --git a/packages/server/src/services/Items/ItemsEntriesService.ts b/packages/server/src/services/Items/ItemsEntriesService.ts index b92b821ca..1b97f6fa0 100644 --- a/packages/server/src/services/Items/ItemsEntriesService.ts +++ b/packages/server/src/services/Items/ItemsEntriesService.ts @@ -264,4 +264,13 @@ export default class ItemsEntriesService { public getTotalItemsEntries(entries: ItemEntry[]): number { return sumBy(entries, (e) => ItemEntry.calcAmount(e)); } + + /** + * Retrieve the non-zero tax items entries. + * @param {IItemEntry[]} entries - + * @returns {IItemEntry[]} + */ + public getNonZeroEntries(entries: IItemEntry[]): IItemEntry[] { + return entries.filter((e) => e.taxRate > 0); + } } diff --git a/packages/server/src/services/Sales/Invoices/InvoiceGLEntries.ts b/packages/server/src/services/Sales/Invoices/InvoiceGLEntries.ts index 6f38ad454..e53f05958 100644 --- a/packages/server/src/services/Sales/Invoices/InvoiceGLEntries.ts +++ b/packages/server/src/services/Sales/Invoices/InvoiceGLEntries.ts @@ -6,12 +6,12 @@ import { ILedgerEntry, AccountNormal, ILedger, - ITaxTransaction, } from '@/interfaces'; import { Service, Inject } from 'typedi'; import Ledger from '@/services/Accounting/Ledger'; import LedgerStorageService from '@/services/Accounting/LedgerStorageService'; import HasTenancyService from '@/services/Tenancy/TenancyService'; +import ItemsEntriesService from '@/services/Items/ItemsEntriesService'; @Service() export class SaleInvoiceGLEntries { @@ -21,6 +21,9 @@ export class SaleInvoiceGLEntries { @Inject() private ledegrRepository: LedgerStorageService; + @Inject() + private itemsEntriesService: ItemsEntriesService; + /** * Writes a sale invoice GL entries. * @param {number} tenantId - Tenant id. @@ -53,7 +56,7 @@ export class SaleInvoiceGLEntries { saleInvoice, ARAccount.id, taxPayableAccount.id - ); + ); // Commits the ledger entries to the storage as UOW. await this.ledegrRepository.commit(tenantId, ledger, trx); }; @@ -93,7 +96,7 @@ export class SaleInvoiceGLEntries { 'SaleInvoice', trx ); -}; + }; /** * Retrieves the given invoice ledger. @@ -218,11 +221,33 @@ export class SaleInvoiceGLEntries { index: index + 3, accountNormal: AccountNormal.CREDIT, taxRateId: entry.taxRateId, - taxRate : entry.taxRate, + taxRate: entry.taxRate, }; } ); + /** + * Retrieves the invoice tax GL entries. + * @param {ISaleInvoice} saleInvoice + * @param {number} taxPayableAccountId + * @returns {ILedgerEntry[]} + */ + private getInvoiceTaxEntries = ( + saleInvoice: ISaleInvoice, + taxPayableAccountId: number + ): ILedgerEntry[] => { + // Retrieves the non-zero tax entries. + const nonZeroTaxEntries = this.itemsEntriesService.getNonZeroEntries( + saleInvoice.entries + ); + const transformTaxEntry = this.getInvoiceTaxEntry( + saleInvoice, + taxPayableAccountId + ); + // Transforms the non-zero tax entries to GL entries. + return nonZeroTaxEntries.map(transformTaxEntry); + }; + /** * Retrieves the invoice GL entries. * @param {ISaleInvoice} saleInvoice @@ -239,13 +264,12 @@ export class SaleInvoiceGLEntries { ARAccountId ); const transformItemEntry = this.getInvoiceItemEntry(saleInvoice); - const transformTaxEntry = this.getInvoiceTaxEntry( + const creditEntries = saleInvoice.entries.map(transformItemEntry); + + const taxEntries = this.getInvoiceTaxEntries( saleInvoice, taxPayableAccountId ); - const creditEntries = saleInvoice.entries.map(transformItemEntry); - const taxEntries = saleInvoice.entries.map(transformTaxEntry); - return [receivableEntry, ...creditEntries, ...taxEntries]; }; }