feat: wip line-level discount

This commit is contained in:
Ahmed Bouhuolia
2024-12-11 12:37:15 +02:00
parent 6323e2ffec
commit 5a8d9cc7e8
8 changed files with 67 additions and 14 deletions

View File

@@ -243,6 +243,10 @@ export default class SaleInvoicesController extends BaseController {
.optional({ nullable: true })
.isNumeric()
.toFloat(),
check('entries.*.discount_type')
.default(DiscountType.Percentage)
.isString()
.isIn([DiscountType.Percentage, DiscountType.Amount]),
check('entries.*.description').optional({ nullable: true }).trim(),
check('entries.*.tax_code')
.optional({ nullable: true })

View File

@@ -0,0 +1,19 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function (knex) {
return knex.schema.alterTable('items_entries', (table) => {
table.string('discount_type').defaultTo('percentage').after('discount');
});
};
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = function (knex) {
return knex.schema.alterTable('items_entries', (table) => {
table.dropColumn('discount_type');
});
};

View File

@@ -19,8 +19,8 @@ export interface IItemEntry {
amount: number;
total: number;
amountInclusingTax: number;
amountExludingTax: number;
subtotalInclusingTax: number;
subtotalExcludingTax: number;
discountAmount: number;
landedCost: number;

View File

@@ -1,6 +1,12 @@
import { Model } from 'objection';
import TenantModel from 'models/TenantModel';
import { getExlusiveTaxAmount, getInclusiveTaxAmount } from '@/utils/taxRate';
import { DiscountType } from '@/interfaces';
// Subtotal (qty * rate) (tax inclusive)
// Subtotal Tax Exclusive (Subtotal - Tax Amount)
// Discount (Is percentage ? amount * discount : discount)
// Total (Subtotal - Discount)
export default class ItemEntry extends TenantModel {
public taxRate: number;
@@ -8,7 +14,7 @@ export default class ItemEntry extends TenantModel {
public quantity: number;
public rate: number;
public isInclusiveTax: number;
public discountType: DiscountType;
/**
* Table name.
* @returns {string}
@@ -31,10 +37,24 @@ export default class ItemEntry extends TenantModel {
*/
static get virtualAttributes() {
return [
// Amount (qty * rate)
'amount',
'taxAmount',
'amountExludingTax',
'amountInclusingTax',
// Subtotal (qty * rate) + (tax inclusive)
'subtotalInclusingTax',
// Subtotal Tax Exclusive (Subtotal - Tax Amount)
'subtotalExcludingTax',
// Subtotal (qty * rate) + (tax inclusive)
'subtotal',
// Discount (Is percentage ? amount * discount : discount)
'discountAmount',
// Total (Subtotal - Discount)
'total',
];
}
@@ -45,7 +65,7 @@ export default class ItemEntry extends TenantModel {
* @returns {number}
*/
get total() {
return this.amountInclusingTax;
return this.subtotal - this.discountAmount;
}
/**
@@ -57,19 +77,27 @@ export default class ItemEntry extends TenantModel {
return this.quantity * this.rate;
}
/**
* Subtotal amount (tax inclusive).
* @returns {number}
*/
get subtotal() {
return this.subtotalInclusingTax;
}
/**
* Item entry amount including tax.
* @returns {number}
*/
get amountInclusingTax() {
get subtotalInclusingTax() {
return this.isInclusiveTax ? this.amount : this.amount + this.taxAmount;
}
/**
* Item entry amount excluding tax.
* Subtotal amount (tax exclusive).
* @returns {number}
*/
get amountExludingTax() {
get subtotalExcludingTax() {
return this.isInclusiveTax ? this.amount - this.taxAmount : this.amount;
}
@@ -78,7 +106,9 @@ export default class ItemEntry extends TenantModel {
* @returns {number}
*/
get discountAmount() {
return this.amount * (this.discount / 100);
return this.discountType === DiscountType.Percentage
? this.amount * (this.discount / 100)
: this.discount;
}
/**

View File

@@ -140,7 +140,7 @@ export class BillGLEntries {
(bill: IBill, entry: IItemEntry, index: number): ILedgerEntry => {
const commonJournalMeta = this.getBillCommonEntry(bill);
const localAmount = bill.exchangeRate * entry.amountExludingTax;
const localAmount = bill.exchangeRate * entry.subtotalExcludingTax;
const landedCostAmount = sumBy(entry.allocatedCostEntries, 'cost');
return {

View File

@@ -154,6 +154,6 @@ export class CommandSaleInvoiceDTOTransformer {
* @returns {number}
*/
private getDueBalanceItemEntries = (entries: ItemEntry[]) => {
return sumBy(entries, (e) => e.amount);
return sumBy(entries, (e) => e.total);
};
}

View File

@@ -199,7 +199,7 @@ export class SaleInvoiceGLEntries {
index: number
): ILedgerEntry => {
const commonEntry = this.getInvoiceGLCommonEntry(saleInvoice);
const localAmount = entry.amountExludingTax * saleInvoice.exchangeRate;
const localAmount = entry.total * saleInvoice.exchangeRate;
return {
...commonEntry,

View File

@@ -2,7 +2,7 @@ import { Inject, Service } from 'typedi';
import { keyBy, sumBy } from 'lodash';
import { ItemEntry } from '@/models';
import HasTenancyService from '../Tenancy/TenancyService';
import { IItem, IItemEntry, IItemEntryDTO } from '@/interfaces';
import { IItemEntry } from '@/interfaces';
@Service()
export class ItemEntriesTaxTransactions {