Compare commits

..

1 Commits

Author SHA1 Message Date
Ahmed Bouhuolia
c1e9cc8252 fix: discount and adjustment of sale and purchase transactions 2024-12-05 14:45:48 +02:00
33 changed files with 111 additions and 872 deletions

View File

@@ -1,14 +1,3 @@
export const OtherExpensesAccount = {
name: 'Other Expenses',
slug: 'other-expenses',
account_type: 'other-expense',
code: '40011',
description: '',
active: 1,
index: 1,
predefined: 1,
};
export const TaxPayableAccount = { export const TaxPayableAccount = {
name: 'Tax Payable', name: 'Tax Payable',
slug: 'tax-payable', slug: 'tax-payable',
@@ -50,38 +39,8 @@ export const StripeClearingAccount = {
code: '100020', code: '100020',
active: true, active: true,
index: 1, index: 1,
predefined: true, predefined: true,
}; }
export const DiscountExpenseAccount = {
name: 'Discount',
slug: 'discount',
account_type: 'other-income',
code: '40008',
active: true,
index: 1,
predefined: true,
};
export const PurchaseDiscountAccount = {
name: 'Purchase Discount',
slug: 'purchase-discount',
account_type: 'other-expense',
code: '40009',
active: true,
index: 1,
predefined: true,
};
export const OtherChargesAccount = {
name: 'Other Charges',
slug: 'other-charges',
account_type: 'other-income',
code: '40010',
active: true,
index: 1,
predefined: true,
};
export default [ export default [
{ {
@@ -272,7 +231,17 @@ export default [
}, },
// Expenses // Expenses
OtherExpensesAccount, {
name: 'Other Expenses',
slug: 'other-expenses',
account_type: 'other-expense',
parent_account_id: null,
code: '40001',
description: '',
active: 1,
index: 1,
predefined: 1,
},
{ {
name: 'Cost of Goods Sold', name: 'Cost of Goods Sold',
slug: 'cost-of-goods-sold', slug: 'cost-of-goods-sold',
@@ -389,7 +358,4 @@ export default [
}, },
UnearnedRevenueAccount, UnearnedRevenueAccount,
PrepardExpenses, PrepardExpenses,
DiscountExpenseAccount,
PurchaseDiscountAccount,
OtherChargesAccount,
]; ];

View File

@@ -80,13 +80,6 @@ export interface ISaleInvoice {
pdfTemplateId?: number; pdfTemplateId?: number;
paymentMethods?: Array<PaymentIntegrationTransactionLink>; paymentMethods?: Array<PaymentIntegrationTransactionLink>;
adjustment?: number;
adjustmentLocal?: number | null;
discount?: number;
discountAmount?: number;
discountAmountLocal?: number | null;
} }
export enum DiscountType { export enum DiscountType {

View File

@@ -39,9 +39,6 @@ export interface ISaleReceipt {
discountPercentage?: number | null; discountPercentage?: number | null;
adjustment?: number; adjustment?: number;
adjustmentLocal?: number | null;
discountAmountLocal?: number | null;
} }
export interface ISalesReceiptsFilter { export interface ISalesReceiptsFilter {

View File

@@ -1,7 +1,6 @@
import { Model, raw, mixin } from 'objection'; import { Model, raw, mixin } from 'objection';
import { castArray, defaultTo, difference } from 'lodash'; import { castArray, defaultTo, difference } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import * as R from 'ramda';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
import BillSettings from './Bill.Settings'; import BillSettings from './Bill.Settings';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
@@ -56,11 +55,8 @@ export default class Bill extends mixin(TenantModel, [
'amountLocal', 'amountLocal',
'discountAmount', 'discountAmount',
'discountAmountLocal',
'discountPercentage', 'discountPercentage',
'adjustmentLocal',
'subtotal', 'subtotal',
'subtotalLocal', 'subtotalLocal',
'subtotalExludingTax', 'subtotalExludingTax',
@@ -122,15 +118,6 @@ export default class Bill extends mixin(TenantModel, [
: this.subtotal * (this.discount / 100); : this.subtotal * (this.discount / 100);
} }
/**
* Discount amount in local currency.
* @returns {number | null}
*/
get discountAmountLocal() {
return this.discountAmount ? this.discountAmount * this.exchangeRate : null;
}
/**
/** /**
* Discount percentage. * Discount percentage.
* @returns {number | null} * @returns {number | null}
@@ -139,14 +126,6 @@ export default class Bill extends mixin(TenantModel, [
return this.discountType === DiscountType.Percentage ? this.discount : null; return this.discountType === DiscountType.Percentage ? this.discount : null;
} }
/**
* Adjustment amount in local currency.
* @returns {number | null}
*/
get adjustmentLocal() {
return this.adjustment ? this.adjustment * this.exchangeRate : null;
}
/** /**
* Invoice total. (Tax included) * Invoice total. (Tax included)
* @returns {number} * @returns {number}
@@ -154,11 +133,12 @@ export default class Bill extends mixin(TenantModel, [
get total() { get total() {
const adjustmentAmount = defaultTo(this.adjustment, 0); const adjustmentAmount = defaultTo(this.adjustment, 0);
return R.compose( return this.isInclusiveTax
R.add(adjustmentAmount), ? this.subtotal - this.discountAmount - adjustmentAmount
R.subtract(R.__, this.discountAmount), : this.subtotal +
R.when(R.always(this.isInclusiveTax), R.add(this.taxAmountWithheld)) this.taxAmountWithheld -
)(this.subtotal); this.discountAmount -
adjustmentAmount;
} }
/** /**

View File

@@ -51,13 +51,10 @@ export default class CreditNote extends mixin(TenantModel, [
'subtotalLocal', 'subtotalLocal',
'discountAmount', 'discountAmount',
'discountAmountLocal',
'discountPercentage', 'discountPercentage',
'total', 'total',
'totalLocal', 'totalLocal',
'adjustmentLocal',
]; ];
} }
@@ -95,28 +92,14 @@ export default class CreditNote extends mixin(TenantModel, [
: this.subtotal * (this.discount / 100); : this.subtotal * (this.discount / 100);
} }
/**
* Discount amount in local currency.
* @returns {number}
*/
get discountAmountLocal() {
return this.discountAmount ? this.discountAmount * this.exchangeRate : null;
}
/** /**
* Discount percentage. * Discount percentage.
* @returns {number | null} * @returns {number | null}
*/ */
get discountPercentage(): number | null { get discountPercentage(): number | null {
return this.discountType === DiscountType.Percentage ? this.discount : null; return this.discountType === DiscountType.Percentage
} ? this.discount
: null;
/**
* Adjustment amount in local currency.
* @returns {number}
*/
get adjustmentLocal() {
return this.adjustment ? this.adjustment * this.exchangeRate : null;
} }
/** /**
@@ -124,7 +107,7 @@ export default class CreditNote extends mixin(TenantModel, [
* @returns {number} * @returns {number}
*/ */
get total() { get total() {
return this.subtotal - this.discountAmount + this.adjustment; return this.subtotal - this.discountAmount - this.adjustment;
} }
/** /**

View File

@@ -116,7 +116,7 @@ export default class SaleEstimate extends mixin(TenantModel, [
get total() { get total() {
const adjustmentAmount = defaultTo(this.adjustment, 0); const adjustmentAmount = defaultTo(this.adjustment, 0);
return this.subtotal - this.discountAmount + adjustmentAmount; return this.subtotal - this.discountAmount - adjustmentAmount;
} }
/** /**

View File

@@ -1,5 +1,4 @@
import { mixin, Model, raw } from 'objection'; import { mixin, Model, raw } from 'objection';
import * as R from 'ramda';
import { castArray, defaultTo, takeWhile } from 'lodash'; import { castArray, defaultTo, takeWhile } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
@@ -73,14 +72,12 @@ export default class SaleInvoice extends mixin(TenantModel, [
'taxAmountWithheldLocal', 'taxAmountWithheldLocal',
'discountAmount', 'discountAmount',
'discountAmountLocal',
'discountPercentage', 'discountPercentage',
'total', 'total',
'totalLocal', 'totalLocal',
'writtenoffAmountLocal', 'writtenoffAmountLocal',
'adjustmentLocal',
]; ];
} }
@@ -145,28 +142,14 @@ export default class SaleInvoice extends mixin(TenantModel, [
: this.subtotal * (this.discount / 100); : this.subtotal * (this.discount / 100);
} }
/**
* Local discount amount.
* @returns {number | null}
*/
get discountAmountLocal() {
return this.discountAmount ? this.discountAmount * this.exchangeRate : null;
}
/** /**
* Discount percentage. * Discount percentage.
* @returns {number | null} * @returns {number | null}
*/ */
get discountPercentage(): number | null { get discountPercentage(): number | null {
return this.discountType === DiscountType.Percentage ? this.discount : null; return this.discountType === DiscountType.Percentage
} ? this.discount
: null;
/**
* Adjustment amount in local currency.
* @returns {number | null}
*/
get adjustmentLocal(): number | null {
return this.adjustment ? this.adjustment * this.exchangeRate : null;
} }
/** /**
@@ -175,12 +158,11 @@ export default class SaleInvoice extends mixin(TenantModel, [
*/ */
get total() { get total() {
const adjustmentAmount = defaultTo(this.adjustment, 0); const adjustmentAmount = defaultTo(this.adjustment, 0);
const differencies = this.discountAmount + adjustmentAmount;
return R.compose( return this.isInclusiveTax
R.add(adjustmentAmount), ? this.subtotal - differencies
R.subtract(R.__, this.discountAmount), : this.subtotal + this.taxAmountWithheld - differencies;
R.when(R.always(this.isInclusiveTax), R.add(this.taxAmountWithheld))
)(this.subtotal);
} }
/** /**

View File

@@ -49,16 +49,9 @@ export default class SaleReceipt extends mixin(TenantModel, [
'total', 'total',
'totalLocal', 'totalLocal',
'adjustment',
'adjustmentLocal',
'discountAmount', 'discountAmount',
'discountAmountLocal',
'discountPercentage', 'discountPercentage',
'paid',
'paidLocal',
'isClosed', 'isClosed',
'isDraft', 'isDraft',
]; ];
@@ -98,20 +91,14 @@ export default class SaleReceipt extends mixin(TenantModel, [
: this.subtotal * (this.discount / 100); : this.subtotal * (this.discount / 100);
} }
/**
* Discount amount in local currency.
* @returns {number | null}
*/
get discountAmountLocal() {
return this.discountAmount ? this.discountAmount * this.exchangeRate : null;
}
/** /**
* Discount percentage. * Discount percentage.
* @returns {number | null} * @returns {number | null}
*/ */
get discountPercentage(): number | null { get discountPercentage(): number | null {
return this.discountType === DiscountType.Percentage ? this.discount : null; return this.discountType === DiscountType.Percentage
? this.discount
: null;
} }
/** /**
@@ -121,7 +108,7 @@ export default class SaleReceipt extends mixin(TenantModel, [
get total() { get total() {
const adjustmentAmount = defaultTo(this.adjustment, 0); const adjustmentAmount = defaultTo(this.adjustment, 0);
return this.subtotal - this.discountAmount + adjustmentAmount; return this.subtotal - this.discountAmount - adjustmentAmount;
} }
/** /**
@@ -132,30 +119,6 @@ export default class SaleReceipt extends mixin(TenantModel, [
return this.total * this.exchangeRate; return this.total * this.exchangeRate;
} }
/**
* Adjustment amount in local currency.
* @returns {number}
*/
get adjustmentLocal() {
return this.adjustment * this.exchangeRate;
}
/**
* Receipt paid amount.
* @returns {number}
*/
get paid() {
return this.total;
}
/**
* Receipt paid amount in local currency.
* @returns {number}
*/
get paidLocal() {
return this.paid * this.exchangeRate;
}
/** /**
* Detarmine whether the sale receipt closed. * Detarmine whether the sale receipt closed.
* @return {boolean} * @return {boolean}

View File

@@ -60,14 +60,6 @@ export default class VendorCredit extends mixin(TenantModel, [
: this.subtotal * (this.discount / 100); : this.subtotal * (this.discount / 100);
} }
/**
* Discount amount in local currency.
* @returns {number | null}
*/
get discountAmountLocal() {
return this.discountAmount ? this.discountAmount * this.exchangeRate : null;
}
/** /**
* Discount percentage. * Discount percentage.
* @returns {number | null} * @returns {number | null}
@@ -76,20 +68,12 @@ export default class VendorCredit extends mixin(TenantModel, [
return this.discountType === DiscountType.Percentage ? this.discount : null; return this.discountType === DiscountType.Percentage ? this.discount : null;
} }
/**
* Adjustment amount in local currency.
* @returns {number | null}
*/
get adjustmentLocal() {
return this.adjustment ? this.adjustment * this.exchangeRate : null;
}
/** /**
* Vendor credit total. * Vendor credit total.
* @returns {number} * @returns {number}
*/ */
get total() { get total() {
return this.subtotal - this.discountAmount + this.adjustment; return this.subtotal - this.discountAmount - this.adjustment;
} }
/** /**
@@ -196,11 +180,8 @@ export default class VendorCredit extends mixin(TenantModel, [
'localAmount', 'localAmount',
'discountAmount', 'discountAmount',
'discountAmountLocal',
'discountPercentage', 'discountPercentage',
'adjustmentLocal',
'total', 'total',
'totalLocal', 'totalLocal',
]; ];

View File

@@ -3,11 +3,7 @@ import TenantRepository from '@/repositories/TenantRepository';
import { IAccount } from '@/interfaces'; import { IAccount } from '@/interfaces';
import { Knex } from 'knex'; import { Knex } from 'knex';
import { import {
DiscountExpenseAccount,
OtherChargesAccount,
OtherExpensesAccount,
PrepardExpenses, PrepardExpenses,
PurchaseDiscountAccount,
StripeClearingAccount, StripeClearingAccount,
TaxPayableAccount, TaxPayableAccount,
UnearnedRevenueAccount, UnearnedRevenueAccount,
@@ -192,9 +188,9 @@ export default class AccountRepository extends TenantRepository {
/** /**
* Finds or creates the unearned revenue. * Finds or creates the unearned revenue.
* @param {Record<string, string>} extraAttrs * @param {Record<string, string>} extraAttrs
* @param {Knex.Transaction} trx * @param {Knex.Transaction} trx
* @returns * @returns
*/ */
public async findOrCreateUnearnedRevenue( public async findOrCreateUnearnedRevenue(
extraAttrs: Record<string, string> = {}, extraAttrs: Record<string, string> = {},
@@ -223,9 +219,9 @@ export default class AccountRepository extends TenantRepository {
/** /**
* Finds or creates the prepard expenses account. * Finds or creates the prepard expenses account.
* @param {Record<string, string>} extraAttrs * @param {Record<string, string>} extraAttrs
* @param {Knex.Transaction} trx * @param {Knex.Transaction} trx
* @returns * @returns
*/ */
public async findOrCreatePrepardExpenses( public async findOrCreatePrepardExpenses(
extraAttrs: Record<string, string> = {}, extraAttrs: Record<string, string> = {},
@@ -253,11 +249,12 @@ export default class AccountRepository extends TenantRepository {
return result; return result;
} }
/** /**
* Finds or creates the stripe clearing account. * Finds or creates the stripe clearing account.
* @param {Record<string, string>} extraAttrs * @param {Record<string, string>} extraAttrs
* @param {Knex.Transaction} trx * @param {Knex.Transaction} trx
* @returns * @returns
*/ */
public async findOrCreateStripeClearing( public async findOrCreateStripeClearing(
extraAttrs: Record<string, string> = {}, extraAttrs: Record<string, string> = {},
@@ -284,114 +281,4 @@ export default class AccountRepository extends TenantRepository {
} }
return result; return result;
} }
/**
* Finds or creates the discount expense account.
* @param {Record<string, string>} extraAttrs
* @param {Knex.Transaction} trx
* @returns
*/
public async findOrCreateDiscountAccount(
extraAttrs: Record<string, string> = {},
trx?: Knex.Transaction
) {
// Retrieves the given tenant metadata.
const tenantMeta = await TenantMetadata.query().findOne({
tenantId: this.tenantId,
});
const _extraAttrs = {
currencyCode: tenantMeta.baseCurrency,
...extraAttrs,
};
let result = await this.model
.query(trx)
.findOne({ slug: DiscountExpenseAccount.slug, ..._extraAttrs });
if (!result) {
result = await this.model.query(trx).insertAndFetch({
...DiscountExpenseAccount,
..._extraAttrs,
});
}
return result;
}
public async findOrCreatePurchaseDiscountAccount(
extraAttrs: Record<string, string> = {},
trx?: Knex.Transaction
) {
// Retrieves the given tenant metadata.
const tenantMeta = await TenantMetadata.query().findOne({
tenantId: this.tenantId,
});
const _extraAttrs = {
currencyCode: tenantMeta.baseCurrency,
...extraAttrs,
};
let result = await this.model
.query(trx)
.findOne({ slug: PurchaseDiscountAccount.slug, ..._extraAttrs });
if (!result) {
result = await this.model.query(trx).insertAndFetch({
...PurchaseDiscountAccount,
..._extraAttrs,
});
}
return result;
}
public async findOrCreateOtherChargesAccount(
extraAttrs: Record<string, string> = {},
trx?: Knex.Transaction
) {
// Retrieves the given tenant metadata.
const tenantMeta = await TenantMetadata.query().findOne({
tenantId: this.tenantId,
});
const _extraAttrs = {
currencyCode: tenantMeta.baseCurrency,
...extraAttrs,
};
let result = await this.model
.query(trx)
.findOne({ slug: OtherChargesAccount.slug, ..._extraAttrs });
if (!result) {
result = await this.model.query(trx).insertAndFetch({
...OtherChargesAccount,
..._extraAttrs,
});
}
return result;
}
public async findOrCreateOtherExpensesAccount(
extraAttrs: Record<string, string> = {},
trx?: Knex.Transaction
) {
// Retrieves the given tenant metadata.
const tenantMeta = await TenantMetadata.query().findOne({
tenantId: this.tenantId,
});
const _extraAttrs = {
currencyCode: tenantMeta.baseCurrency,
...extraAttrs,
};
let result = await this.model
.query(trx)
.findOne({ slug: OtherExpensesAccount.slug, ..._extraAttrs });
if (!result) {
result = await this.model.query(trx).insertAndFetch({
...OtherExpensesAccount,
..._extraAttrs,
});
}
return result;
}
} }

View File

@@ -238,7 +238,6 @@ export default class Ledger implements ILedger {
return { return {
credit: defaultTo(entry.credit, 0), credit: defaultTo(entry.credit, 0),
debit: defaultTo(entry.debit, 0), debit: defaultTo(entry.debit, 0),
exchangeRate: entry.exchangeRate, exchangeRate: entry.exchangeRate,
currencyCode: entry.currencyCode, currencyCode: entry.currencyCode,

View File

@@ -9,18 +9,15 @@ import {
import HasTenancyService from '@/services/Tenancy/TenancyService'; import HasTenancyService from '@/services/Tenancy/TenancyService';
import { transformLedgerEntryToTransaction } from './utils'; import { transformLedgerEntryToTransaction } from './utils';
// Filter the blank entries.
const filterBlankEntry = (entry: ILedgerEntry) => Boolean(entry.credit || entry.debit);
@Service() @Service()
export class LedgerEntriesStorage { export class LedgerEntriesStorage {
@Inject() @Inject()
private tenancy: HasTenancyService; tenancy: HasTenancyService;
/** /**
* Saves entries of the given ledger. * Saves entries of the given ledger.
* @param {number} tenantId * @param {number} tenantId
* @param {ILedger} ledger * @param {ILedger} ledger
* @param {Knex.Transaction} knex * @param {Knex.Transaction} knex
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
public saveEntries = async ( public saveEntries = async (
@@ -29,7 +26,7 @@ export class LedgerEntriesStorage {
trx?: Knex.Transaction trx?: Knex.Transaction
) => { ) => {
const saveEntryQueue = async.queue(this.saveEntryTask, 10); const saveEntryQueue = async.queue(this.saveEntryTask, 10);
const entries = ledger.filter(filterBlankEntry).getEntries(); const entries = ledger.getEntries();
entries.forEach((entry) => { entries.forEach((entry) => {
saveEntryQueue.push({ tenantId, entry, trx }); saveEntryQueue.push({ tenantId, entry, trx });
@@ -60,8 +57,8 @@ export class LedgerEntriesStorage {
/** /**
* Saves the ledger entry to the account transactions repository. * Saves the ledger entry to the account transactions repository.
* @param {number} tenantId * @param {number} tenantId
* @param {ILedgerEntry} entry * @param {ILedgerEntry} entry
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
private saveEntry = async ( private saveEntry = async (

View File

@@ -12,7 +12,6 @@ import {
import HasTenancyService from '@/services/Tenancy/TenancyService'; import HasTenancyService from '@/services/Tenancy/TenancyService';
import Ledger from '@/services/Accounting/Ledger'; import Ledger from '@/services/Accounting/Ledger';
import LedgerStorageService from '@/services/Accounting/LedgerStorageService'; import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
import { SaleReceipt } from '@/models';
@Service() @Service()
export default class CreditNoteGLEntries { export default class CreditNoteGLEntries {
@@ -30,15 +29,11 @@ export default class CreditNoteGLEntries {
*/ */
private getCreditNoteGLedger = ( private getCreditNoteGLedger = (
creditNote: ICreditNote, creditNote: ICreditNote,
receivableAccount: number, receivableAccount: number
discountAccount: number,
adjustmentAccount: number
): Ledger => { ): Ledger => {
const ledgerEntries = this.getCreditNoteGLEntries( const ledgerEntries = this.getCreditNoteGLEntries(
creditNote, creditNote,
receivableAccount, receivableAccount
discountAccount,
adjustmentAccount
); );
return new Ledger(ledgerEntries); return new Ledger(ledgerEntries);
}; };
@@ -54,16 +49,9 @@ export default class CreditNoteGLEntries {
tenantId: number, tenantId: number,
creditNote: ICreditNote, creditNote: ICreditNote,
payableAccount: number, payableAccount: number,
discountAccount: number,
adjustmentAccount: number,
trx?: Knex.Transaction trx?: Knex.Transaction
): Promise<void> => { ): Promise<void> => {
const ledger = this.getCreditNoteGLedger( const ledger = this.getCreditNoteGLedger(creditNote, payableAccount);
creditNote,
payableAccount,
discountAccount,
adjustmentAccount
);
await this.ledgerStorage.commit(tenantId, ledger, trx); await this.ledgerStorage.commit(tenantId, ledger, trx);
}; };
@@ -110,18 +98,11 @@ export default class CreditNoteGLEntries {
const ARAccount = await accountRepository.findOrCreateAccountReceivable( const ARAccount = await accountRepository.findOrCreateAccountReceivable(
creditNoteWithItems.currencyCode creditNoteWithItems.currencyCode
); );
const discountAccount = await accountRepository.findOrCreateDiscountAccount(
{}
);
const adjustmentAccount =
await accountRepository.findOrCreateOtherChargesAccount({});
// Saves the credit note GL entries. // Saves the credit note GL entries.
await this.saveCreditNoteGLEntries( await this.saveCreditNoteGLEntries(
tenantId, tenantId,
creditNoteWithItems, creditNoteWithItems,
ARAccount.id, ARAccount.id,
discountAccount.id,
adjustmentAccount.id,
trx trx
); );
}; };
@@ -188,7 +169,7 @@ export default class CreditNoteGLEntries {
return { return {
...commonEntry, ...commonEntry,
credit: creditNote.totalLocal, credit: creditNote.localAmount,
accountId: ARAccountId, accountId: ARAccountId,
contactId: creditNote.customerId, contactId: creditNote.customerId,
index: 1, index: 1,
@@ -225,50 +206,6 @@ export default class CreditNoteGLEntries {
} }
); );
/**
* Retrieves the credit note discount entry.
* @param {ICreditNote} creditNote
* @param {number} discountAccountId
* @returns {ILedgerEntry}
*/
private getDiscountEntry = (
creditNote: ICreditNote,
discountAccountId: number
): ILedgerEntry => {
const commonEntry = this.getCreditNoteCommonEntry(creditNote);
return {
...commonEntry,
credit: creditNote.discountAmountLocal,
accountId: discountAccountId,
index: 1,
accountNormal: AccountNormal.CREDIT,
};
};
/**
* Retrieves the credit note adjustment entry.
* @param {ICreditNote} creditNote
* @param {number} adjustmentAccountId
* @returns {ILedgerEntry}
*/
private getAdjustmentEntry = (
creditNote: ICreditNote,
adjustmentAccountId: number
): ILedgerEntry => {
const commonEntry = this.getCreditNoteCommonEntry(creditNote);
const adjustmentAmount = Math.abs(creditNote.adjustmentLocal);
return {
...commonEntry,
credit: creditNote.adjustmentLocal < 0 ? adjustmentAmount : 0,
debit: creditNote.adjustmentLocal > 0 ? adjustmentAmount : 0,
accountId: adjustmentAccountId,
accountNormal: AccountNormal.CREDIT,
index: 1,
};
};
/** /**
* Retrieve the credit note GL entries. * Retrieve the credit note GL entries.
* @param {ICreditNote} creditNote - Credit note. * @param {ICreditNote} creditNote - Credit note.
@@ -277,21 +214,13 @@ export default class CreditNoteGLEntries {
*/ */
public getCreditNoteGLEntries = ( public getCreditNoteGLEntries = (
creditNote: ICreditNote, creditNote: ICreditNote,
ARAccountId: number, ARAccountId: number
discountAccountId: number,
adjustmentAccountId: number
): ILedgerEntry[] => { ): ILedgerEntry[] => {
const AREntry = this.getCreditNoteAREntry(creditNote, ARAccountId); const AREntry = this.getCreditNoteAREntry(creditNote, ARAccountId);
const getItemEntry = this.getCreditNoteItemEntry(creditNote); const getItemEntry = this.getCreditNoteItemEntry(creditNote);
const itemsEntries = creditNote.entries.map(getItemEntry); const itemsEntries = creditNote.entries.map(getItemEntry);
const discountEntry = this.getDiscountEntry(creditNote, discountAccountId); return [AREntry, ...itemsEntries];
const adjustmentEntry = this.getAdjustmentEntry(
creditNote,
adjustmentAccountId
);
return [AREntry, discountEntry, adjustmentEntry, ...itemsEntries];
}; };
} }

View File

@@ -18,18 +18,11 @@ export class CreditNoteTransformer extends Transformer {
'formattedAmount', 'formattedAmount',
'formattedCreditsUsed', 'formattedCreditsUsed',
'formattedSubtotal', 'formattedSubtotal',
'discountAmountFormatted', 'discountAmountFormatted',
'discountAmountLocalFormatted',
'discountPercentageFormatted', 'discountPercentageFormatted',
'adjustmentFormatted', 'adjustmentFormatted',
'adjustmentLocalFormatted',
'totalFormatted', 'totalFormatted',
'totalLocalFormatted', 'totalLocalFormatted',
'entries', 'entries',
'attachments', 'attachments',
]; ];
@@ -46,7 +39,7 @@ export class CreditNoteTransformer extends Transformer {
/** /**
* Retrieve formatted created at date. * Retrieve formatted created at date.
* @param credit * @param credit
* @returns {string} * @returns {string}
*/ */
protected formattedCreatedAt = (credit): string => { protected formattedCreatedAt = (credit): string => {
@@ -97,7 +90,7 @@ export class CreditNoteTransformer extends Transformer {
/** /**
* Retrieves formatted discount amount. * Retrieves formatted discount amount.
* @param credit * @param credit
* @returns {string} * @returns {string}
*/ */
protected discountAmountFormatted = (credit): string => { protected discountAmountFormatted = (credit): string => {
@@ -107,30 +100,20 @@ export class CreditNoteTransformer extends Transformer {
}); });
}; };
/**
* Retrieves the formatted discount amount in local currency.
* @param {ICreditNote} credit
* @returns {string}
*/
protected discountAmountLocalFormatted = (credit): string => {
return formatNumber(credit.discountAmountLocal, {
currencyCode: credit.currencyCode,
excerptZero: true,
});
};
/** /**
* Retrieves formatted discount percentage. * Retrieves formatted discount percentage.
* @param credit * @param credit
* @returns {string} * @returns {string}
*/ */
protected discountPercentageFormatted = (credit): string => { protected discountPercentageFormatted = (credit): string => {
return credit.discountPercentage ? `${credit.discountPercentage}%` : ''; return credit.discountPercentage
? `${credit.discountPercentage}%`
: '';
}; };
/** /**
* Retrieves formatted adjustment amount. * Retrieves formatted adjustment amount.
* @param credit * @param credit
* @returns {string} * @returns {string}
*/ */
protected adjustmentFormatted = (credit): string => { protected adjustmentFormatted = (credit): string => {
@@ -140,21 +123,9 @@ export class CreditNoteTransformer extends Transformer {
}); });
}; };
/**
* Retrieves the formatted adjustment amount in local currency.
* @param {ICreditNote} credit
* @returns {string}
*/
protected adjustmentLocalFormatted = (credit): string => {
return formatNumber(credit.adjustmentLocal, {
currencyCode: this.context.organization.baseCurrency,
excerptZero: true,
});
};
/** /**
* Retrieves the formatted total. * Retrieves the formatted total.
* @param credit * @param credit
* @returns {string} * @returns {string}
*/ */
protected totalFormatted = (credit): string => { protected totalFormatted = (credit): string => {
@@ -165,7 +136,7 @@ export class CreditNoteTransformer extends Transformer {
/** /**
* Retrieves the formatted total in local currency. * Retrieves the formatted total in local currency.
* @param credit * @param credit
* @returns {string} * @returns {string}
*/ */
protected totalLocalFormatted = (credit): string => { protected totalLocalFormatted = (credit): string => {

View File

@@ -52,18 +52,10 @@ export class BillGLEntries {
{}, {},
trx trx
); );
// Find or create other expenses account.
const otherExpensesAccount =
await accountRepository.findOrCreateOtherExpensesAccount({}, trx);
// Find or create purchase discount account.
const purchaseDiscountAccount =
await accountRepository.findOrCreatePurchaseDiscountAccount({}, trx);
const billLedger = this.getBillLedger( const billLedger = this.getBillLedger(
bill, bill,
APAccount.id, APAccount.id,
taxPayableAccount.id, taxPayableAccount.id
purchaseDiscountAccount.id,
otherExpensesAccount.id
); );
// Commit the GL enties on the storage. // Commit the GL enties on the storage.
await this.ledgerStorage.commit(tenantId, billLedger, trx); await this.ledgerStorage.commit(tenantId, billLedger, trx);
@@ -110,7 +102,6 @@ export class BillGLEntries {
return { return {
debit: 0, debit: 0,
credit: 0, credit: 0,
currencyCode: bill.currencyCode, currencyCode: bill.currencyCode,
exchangeRate: bill.exchangeRate || 1, exchangeRate: bill.exchangeRate || 1,
@@ -249,52 +240,6 @@ export class BillGLEntries {
return nonZeroTaxEntries.map(transformTaxEntry); return nonZeroTaxEntries.map(transformTaxEntry);
}; };
/**
* Retrieves the purchase discount GL entry.
* @param {IBill} bill
* @param {number} purchaseDiscountAccountId
* @returns {ILedgerEntry}
*/
private getPurchaseDiscountEntry = (
bill: IBill,
purchaseDiscountAccountId: number
) => {
const commonEntry = this.getBillCommonEntry(bill);
return {
...commonEntry,
credit: bill.discountAmountLocal,
accountId: purchaseDiscountAccountId,
accountNormal: AccountNormal.DEBIT,
index: 1,
indexGroup: 40,
};
};
/**
* Retrieves the purchase other charges GL entry.
* @param {IBill} bill
* @param {number} otherChargesAccountId
* @returns {ILedgerEntry}
*/
private getAdjustmentEntry = (
bill: IBill,
otherExpensesAccountId: number
) => {
const commonEntry = this.getBillCommonEntry(bill);
const adjustmentAmount = Math.abs(bill.adjustmentLocal);
return {
...commonEntry,
debit: bill.adjustmentLocal > 0 ? adjustmentAmount : 0,
credit: bill.adjustmentLocal < 0 ? adjustmentAmount : 0,
accountId: otherExpensesAccountId,
accountNormal: AccountNormal.DEBIT,
index: 1,
indexGroup: 40,
};
};
/** /**
* Retrieves the given bill GL entries. * Retrieves the given bill GL entries.
* @param {IBill} bill * @param {IBill} bill
@@ -304,9 +249,7 @@ export class BillGLEntries {
private getBillGLEntries = ( private getBillGLEntries = (
bill: IBill, bill: IBill,
payableAccountId: number, payableAccountId: number,
taxPayableAccountId: number, taxPayableAccountId: number
purchaseDiscountAccountId: number,
otherExpensesAccountId: number
): ILedgerEntry[] => { ): ILedgerEntry[] => {
const payableEntry = this.getBillPayableEntry(payableAccountId, bill); const payableEntry = this.getBillPayableEntry(payableAccountId, bill);
@@ -319,24 +262,8 @@ export class BillGLEntries {
); );
const taxEntries = this.getBillTaxEntries(bill, taxPayableAccountId); const taxEntries = this.getBillTaxEntries(bill, taxPayableAccountId);
const purchaseDiscountEntry = this.getPurchaseDiscountEntry(
bill,
purchaseDiscountAccountId
);
const adjustmentEntry = this.getAdjustmentEntry(
bill,
otherExpensesAccountId
);
// Allocate cost entries journal entries. // Allocate cost entries journal entries.
return [ return [payableEntry, ...itemsEntries, ...landedCostEntries, ...taxEntries];
payableEntry,
...itemsEntries,
...landedCostEntries,
...taxEntries,
purchaseDiscountEntry,
adjustmentEntry,
];
}; };
/** /**
@@ -348,17 +275,14 @@ export class BillGLEntries {
private getBillLedger = ( private getBillLedger = (
bill: IBill, bill: IBill,
payableAccountId: number, payableAccountId: number,
taxPayableAccountId: number, taxPayableAccountId: number
purchaseDiscountAccountId: number,
otherExpensesAccountId: number
) => { ) => {
const entries = this.getBillGLEntries( const entries = this.getBillGLEntries(
bill, bill,
payableAccountId, payableAccountId,
taxPayableAccountId, taxPayableAccountId
purchaseDiscountAccountId,
otherExpensesAccountId
); );
return new Ledger(entries); return new Ledger(entries);
}; };
} }

View File

@@ -20,21 +20,13 @@ export class PurchaseInvoiceTransformer extends Transformer {
'formattedBalance', 'formattedBalance',
'formattedDueAmount', 'formattedDueAmount',
'formattedExchangeRate', 'formattedExchangeRate',
'subtotalFormatted', 'subtotalFormatted',
'subtotalLocalFormatted', 'subtotalLocalFormatted',
'subtotalExcludingTaxFormatted', 'subtotalExcludingTaxFormatted',
'taxAmountWithheldLocalFormatted', 'taxAmountWithheldLocalFormatted',
'discountAmountFormatted', 'discountAmountFormatted',
'discountAmountLocalFormatted',
'discountPercentageFormatted', 'discountPercentageFormatted',
'adjustmentFormatted', 'adjustmentFormatted',
'adjustmentLocalFormatted',
'totalFormatted', 'totalFormatted',
'totalLocalFormatted', 'totalLocalFormatted',
'taxes', 'taxes',
@@ -183,25 +175,15 @@ export class PurchaseInvoiceTransformer extends Transformer {
}); });
}; };
/**
* Retrieves the formatted discount amount in local currency.
* @param {IBill} bill
* @returns {string}
*/
protected discountAmountLocalFormatted = (bill): string => {
return formatNumber(bill.discountAmountLocal, {
currencyCode: this.context.organization.baseCurrency,
excerptZero: true,
});
};
/** /**
* Retrieves the formatted discount percentage. * Retrieves the formatted discount percentage.
* @param {IBill} bill * @param {IBill} bill
* @returns {string} * @returns {string}
*/ */
protected discountPercentageFormatted = (bill): string => { protected discountPercentageFormatted = (bill): string => {
return bill.discountPercentage ? `${bill.discountPercentage}%` : ''; return bill.discountPercentage
? `${bill.discountPercentage}%`
: '';
}; };
/** /**
@@ -216,18 +198,6 @@ export class PurchaseInvoiceTransformer extends Transformer {
}); });
}; };
/**
* Retrieves the formatted adjustment amount in local currency.
* @param {IBill} bill
* @returns {string}
*/
protected adjustmentLocalFormatted = (bill): string => {
return formatNumber(bill.adjustmentLocal, {
currencyCode: this.context.organization.baseCurrency,
excerptZero: true,
});
};
/** /**
* Retrieves the total formatted. * Retrieves the total formatted.
* @param {IBill} bill * @param {IBill} bill

View File

@@ -56,7 +56,7 @@ export default class VendorCreditGLEntries {
return { return {
...commonEntity, ...commonEntity,
debit: vendorCredit.totalLocal, debit: vendorCredit.localAmount,
accountId: APAccountId, accountId: APAccountId,
contactId: vendorCredit.vendorId, contactId: vendorCredit.vendorId,
accountNormal: AccountNormal.CREDIT, accountNormal: AccountNormal.CREDIT,
@@ -94,52 +94,6 @@ export default class VendorCreditGLEntries {
} }
); );
/**
* Retrieves the vendor credit discount GL entry.
* @param {IVendorCredit} vendorCredit
* @param {number} discountAccountId
* @returns {ILedgerEntry}
*/
public getDiscountEntry = (
vendorCredit: IVendorCredit,
purchaseDiscountAccountId: number
) => {
const commonEntry = this.getVendorCreditGLCommonEntry(vendorCredit);
return {
...commonEntry,
debit: vendorCredit.discountAmountLocal,
accountId: purchaseDiscountAccountId,
accountNormal: AccountNormal.DEBIT,
index: 1,
indexGroup: 40,
};
};
/**
* Retrieves the vendor credit adjustment GL entry.
* @param {IVendorCredit} vendorCredit
* @param {number} adjustmentAccountId
* @returns {ILedgerEntry}
*/
public getAdjustmentEntry = (
vendorCredit: IVendorCredit,
otherExpensesAccountId: number
) => {
const commonEntry = this.getVendorCreditGLCommonEntry(vendorCredit);
const adjustmentAmount = Math.abs(vendorCredit.adjustmentLocal);
return {
...commonEntry,
credit: vendorCredit.adjustmentLocal > 0 ? adjustmentAmount : 0,
debit: vendorCredit.adjustmentLocal < 0 ? adjustmentAmount : 0,
accountId: otherExpensesAccountId,
accountNormal: AccountNormal.DEBIT,
index: 1,
indexGroup: 40,
};
};
/** /**
* Retrieve the vendor credit GL entries. * Retrieve the vendor credit GL entries.
* @param {IVendorCredit} vendorCredit - * @param {IVendorCredit} vendorCredit -
@@ -148,9 +102,7 @@ export default class VendorCreditGLEntries {
*/ */
public getVendorCreditGLEntries = ( public getVendorCreditGLEntries = (
vendorCredit: IVendorCredit, vendorCredit: IVendorCredit,
payableAccountId: number, payableAccountId: number
purchaseDiscountAccountId: number,
otherExpensesAccountId: number
): ILedgerEntry[] => { ): ILedgerEntry[] => {
const payableEntry = this.getVendorCreditPayableGLEntry( const payableEntry = this.getVendorCreditPayableGLEntry(
vendorCredit, vendorCredit,
@@ -159,15 +111,7 @@ export default class VendorCreditGLEntries {
const getItemEntry = this.getVendorCreditGLItemEntry(vendorCredit); const getItemEntry = this.getVendorCreditGLItemEntry(vendorCredit);
const itemsEntries = vendorCredit.entries.map(getItemEntry); const itemsEntries = vendorCredit.entries.map(getItemEntry);
const discountEntry = this.getDiscountEntry( return [payableEntry, ...itemsEntries];
vendorCredit,
purchaseDiscountAccountId
);
const adjustmentEntry = this.getAdjustmentEntry(
vendorCredit,
otherExpensesAccountId
);
return [payableEntry, discountEntry, adjustmentEntry, ...itemsEntries];
}; };
/** /**
@@ -214,17 +158,10 @@ export default class VendorCreditGLEntries {
{}, {},
trx trx
); );
const purchaseDiscountAccount =
await accountRepository.findOrCreatePurchaseDiscountAccount({}, trx);
const otherExpensesAccount =
await accountRepository.findOrCreateOtherExpensesAccount({}, trx);
// Saves the vendor credit GL entries. // Saves the vendor credit GL entries.
const ledgerEntries = this.getVendorCreditGLEntries( const ledgerEntries = this.getVendorCreditGLEntries(
vendorCredit, vendorCredit,
APAccount.id, APAccount.id
purchaseDiscountAccount.id,
otherExpensesAccount.id
); );
const ledger = new Ledger(ledgerEntries); const ledger = new Ledger(ledgerEntries);

View File

@@ -17,15 +17,9 @@ export class VendorCreditTransformer extends Transformer {
'formattedCreatedAt', 'formattedCreatedAt',
'formattedCreditsRemaining', 'formattedCreditsRemaining',
'formattedInvoicedAmount', 'formattedInvoicedAmount',
'discountAmountFormatted', 'discountAmountFormatted',
'discountPercentageFormatted', 'discountPercentageFormatted',
'discountAmountLocalFormatted',
'adjustmentFormatted', 'adjustmentFormatted',
'adjustmentLocalFormatted',
'totalFormatted',
'entries', 'entries',
'attachments', 'attachments',
]; ];
@@ -92,18 +86,6 @@ export class VendorCreditTransformer extends Transformer {
}); });
}; };
/**
* Retrieves the formatted discount amount in local currency.
* @param {IVendorCredit} credit
* @returns {string}
*/
protected discountAmountLocalFormatted = (credit): string => {
return formatNumber(credit.discountAmountLocal, {
currencyCode: this.context.organization.baseCurrency,
excerptZero: true,
});
};
/** /**
* Retrieves the formatted discount percentage. * Retrieves the formatted discount percentage.
* @param {IVendorCredit} credit * @param {IVendorCredit} credit
@@ -125,18 +107,6 @@ export class VendorCreditTransformer extends Transformer {
}); });
}; };
/**
* Retrieves the formatted adjustment amount in local currency.
* @param {IVendorCredit} credit
* @returns {string}
*/
protected adjustmentLocalFormatted = (credit): string => {
return formatNumber(credit.adjustmentLocal, {
currencyCode: this.context.organization.baseCurrency,
excerptZero: true,
});
};
/** /**
* Retrieves the formatted invoiced amount. * Retrieves the formatted invoiced amount.
* @param credit * @param credit
@@ -148,15 +118,6 @@ export class VendorCreditTransformer extends Transformer {
}); });
}; };
/**
* Retrieves the formatted total.
* @param {IVendorCredit} credit
* @returns {string}
*/
protected totalFormatted = (credit) => {
return formatNumber(credit.total, { currencyCode: credit.currencyCode });
};
/** /**
* Retrieves the entries of the bill. * Retrieves the entries of the bill.
* @param {IVendorCredit} vendorCredit * @param {IVendorCredit} vendorCredit

View File

@@ -44,31 +44,18 @@ export class SaleInvoiceGLEntries {
// Find or create the A/R account. // Find or create the A/R account.
const ARAccount = await accountRepository.findOrCreateAccountReceivable( const ARAccount = await accountRepository.findOrCreateAccountReceivable(
saleInvoice.currencyCode, saleInvoice.currencyCode, {}, trx
{},
trx
); );
// Find or create tax payable account. // Find or create tax payable account.
const taxPayableAccount = await accountRepository.findOrCreateTaxPayable( const taxPayableAccount = await accountRepository.findOrCreateTaxPayable(
{}, {},
trx trx
); );
// Find or create the discount expense account.
const discountAccount = await accountRepository.findOrCreateDiscountAccount(
{},
trx
);
// Find or create the other charges account.
const otherChargesAccount =
await accountRepository.findOrCreateOtherChargesAccount({}, trx);
// Retrieves the ledger of the invoice. // Retrieves the ledger of the invoice.
const ledger = this.getInvoiceGLedger( const ledger = this.getInvoiceGLedger(
saleInvoice, saleInvoice,
ARAccount.id, ARAccount.id,
taxPayableAccount.id, taxPayableAccount.id
discountAccount.id,
otherChargesAccount.id
); );
// Commits the ledger entries to the storage as UOW. // Commits the ledger entries to the storage as UOW.
await this.ledegrRepository.commit(tenantId, ledger, trx); await this.ledegrRepository.commit(tenantId, ledger, trx);
@@ -120,16 +107,12 @@ export class SaleInvoiceGLEntries {
public getInvoiceGLedger = ( public getInvoiceGLedger = (
saleInvoice: ISaleInvoice, saleInvoice: ISaleInvoice,
ARAccountId: number, ARAccountId: number,
taxPayableAccountId: number, taxPayableAccountId: number
discountAccountId: number,
otherChargesAccountId: number
): ILedger => { ): ILedger => {
const entries = this.getInvoiceGLEntries( const entries = this.getInvoiceGLEntries(
saleInvoice, saleInvoice,
ARAccountId, ARAccountId,
taxPayableAccountId, taxPayableAccountId
discountAccountId,
otherChargesAccountId
); );
return new Ledger(entries); return new Ledger(entries);
}; };
@@ -144,7 +127,6 @@ export class SaleInvoiceGLEntries {
): Partial<ILedgerEntry> => ({ ): Partial<ILedgerEntry> => ({
credit: 0, credit: 0,
debit: 0, debit: 0,
currencyCode: saleInvoice.currencyCode, currencyCode: saleInvoice.currencyCode,
exchangeRate: saleInvoice.exchangeRate, exchangeRate: saleInvoice.exchangeRate,
@@ -267,50 +249,6 @@ export class SaleInvoiceGLEntries {
return nonZeroTaxEntries.map(transformTaxEntry); return nonZeroTaxEntries.map(transformTaxEntry);
}; };
/**
* Retrieves the invoice discount GL entry.
* @param {ISaleInvoice} saleInvoice
* @param {number} discountAccountId
* @returns {ILedgerEntry}
*/
private getInvoiceDiscountEntry = (
saleInvoice: ISaleInvoice,
discountAccountId: number
): ILedgerEntry => {
const commonEntry = this.getInvoiceGLCommonEntry(saleInvoice);
return {
...commonEntry,
debit: saleInvoice.discountAmountLocal,
accountId: discountAccountId,
accountNormal: AccountNormal.CREDIT,
index: 1,
} as ILedgerEntry;
};
/**
* Retrieves the invoice adjustment GL entry.
* @param {ISaleInvoice} saleInvoice
* @param {number} adjustmentAccountId
* @returns {ILedgerEntry}
*/
private getAdjustmentEntry = (
saleInvoice: ISaleInvoice,
otherChargesAccountId: number
): ILedgerEntry => {
const commonEntry = this.getInvoiceGLCommonEntry(saleInvoice);
const adjustmentAmount = Math.abs(saleInvoice.adjustmentLocal);
return {
...commonEntry,
debit: saleInvoice.adjustmentLocal < 0 ? adjustmentAmount : 0,
credit: saleInvoice.adjustmentLocal > 0 ? adjustmentAmount : 0,
accountId: otherChargesAccountId,
accountNormal: AccountNormal.CREDIT,
index: 1,
};
};
/** /**
* Retrieves the invoice GL entries. * Retrieves the invoice GL entries.
* @param {ISaleInvoice} saleInvoice * @param {ISaleInvoice} saleInvoice
@@ -320,9 +258,7 @@ export class SaleInvoiceGLEntries {
public getInvoiceGLEntries = ( public getInvoiceGLEntries = (
saleInvoice: ISaleInvoice, saleInvoice: ISaleInvoice,
ARAccountId: number, ARAccountId: number,
taxPayableAccountId: number, taxPayableAccountId: number
discountAccountId: number,
otherChargesAccountId: number
): ILedgerEntry[] => { ): ILedgerEntry[] => {
const receivableEntry = this.getInvoiceReceivableEntry( const receivableEntry = this.getInvoiceReceivableEntry(
saleInvoice, saleInvoice,
@@ -335,20 +271,6 @@ export class SaleInvoiceGLEntries {
saleInvoice, saleInvoice,
taxPayableAccountId taxPayableAccountId
); );
const discountEntry = this.getInvoiceDiscountEntry( return [receivableEntry, ...creditEntries, ...taxEntries];
saleInvoice,
discountAccountId
);
const adjustmentEntry = this.getAdjustmentEntry(
saleInvoice,
otherChargesAccountId
);
return [
receivableEntry,
...creditEntries,
...taxEntries,
discountEntry,
adjustmentEntry,
];
}; };
} }

View File

@@ -31,27 +31,13 @@ export class SaleReceiptGLEntries {
trx?: Knex.Transaction trx?: Knex.Transaction
): Promise<void> => { ): Promise<void> => {
const { SaleReceipt } = this.tenancy.models(tenantId); const { SaleReceipt } = this.tenancy.models(tenantId);
const { accountRepository } = this.tenancy.repositories(tenantId);
const saleReceipt = await SaleReceipt.query(trx) const saleReceipt = await SaleReceipt.query(trx)
.findById(saleReceiptId) .findById(saleReceiptId)
.withGraphFetched('entries.item'); .withGraphFetched('entries.item');
// Find or create the discount expense account.
const discountAccount = await accountRepository.findOrCreateDiscountAccount(
{},
trx
);
// Find or create the other charges account.
const otherChargesAccount =
await accountRepository.findOrCreateOtherChargesAccount({}, trx);
// Retrieve the income entries ledger. // Retrieve the income entries ledger.
const incomeLedger = this.getIncomeEntriesLedger( const incomeLedger = this.getIncomeEntriesLedger(saleReceipt);
saleReceipt,
discountAccount.id,
otherChargesAccount.id
);
// Commits the ledger entries to the storage. // Commits the ledger entries to the storage.
await this.ledgerStorage.commit(tenantId, incomeLedger, trx); await this.ledgerStorage.commit(tenantId, incomeLedger, trx);
@@ -101,16 +87,8 @@ export class SaleReceiptGLEntries {
* @param {ISaleReceipt} saleReceipt * @param {ISaleReceipt} saleReceipt
* @returns {Ledger} * @returns {Ledger}
*/ */
private getIncomeEntriesLedger = ( private getIncomeEntriesLedger = (saleReceipt: ISaleReceipt): Ledger => {
saleReceipt: ISaleReceipt, const entries = this.getIncomeGLEntries(saleReceipt);
discountAccountId: number,
otherChargesAccountId: number
): Ledger => {
const entries = this.getIncomeGLEntries(
saleReceipt,
discountAccountId,
otherChargesAccountId
);
return new Ledger(entries); return new Ledger(entries);
}; };
@@ -183,76 +161,24 @@ export class SaleReceiptGLEntries {
return { return {
...commonEntry, ...commonEntry,
debit: saleReceipt.totalLocal, debit: saleReceipt.localAmount,
accountId: saleReceipt.depositAccountId, accountId: saleReceipt.depositAccountId,
index: 1, index: 1,
accountNormal: AccountNormal.DEBIT, accountNormal: AccountNormal.DEBIT,
}; };
}; };
/**
* Retrieves the discount GL entry.
* @param {ISaleReceipt} saleReceipt
* @param {number} discountAccountId
* @returns {ILedgerEntry}
*/
private getDiscountEntry = (
saleReceipt: ISaleReceipt,
discountAccountId: number
): ILedgerEntry => {
const commonEntry = this.getIncomeGLCommonEntry(saleReceipt);
return {
...commonEntry,
debit: saleReceipt.discountAmountLocal,
accountId: discountAccountId,
index: 1,
accountNormal: AccountNormal.CREDIT,
};
};
/**
* Retrieves the adjustment GL entry.
* @param {ISaleReceipt} saleReceipt
* @param {number} adjustmentAccountId
* @returns {ILedgerEntry}
*/
private getAdjustmentEntry = (
saleReceipt: ISaleReceipt,
adjustmentAccountId: number
): ILedgerEntry => {
const commonEntry = this.getIncomeGLCommonEntry(saleReceipt);
const adjustmentAmount = Math.abs(saleReceipt.adjustmentLocal);
return {
...commonEntry,
debit: saleReceipt.adjustmentLocal < 0 ? adjustmentAmount : 0,
credit: saleReceipt.adjustmentLocal > 0 ? adjustmentAmount : 0,
accountId: adjustmentAccountId,
accountNormal: AccountNormal.CREDIT,
index: 1,
};
};
/** /**
* Retrieves the income GL entries. * Retrieves the income GL entries.
* @param {ISaleReceipt} saleReceipt - * @param {ISaleReceipt} saleReceipt -
* @returns {ILedgerEntry[]} * @returns {ILedgerEntry[]}
*/ */
private getIncomeGLEntries = ( private getIncomeGLEntries = (saleReceipt: ISaleReceipt): ILedgerEntry[] => {
saleReceipt: ISaleReceipt,
discountAccountId: number,
otherChargesAccountId: number
): ILedgerEntry[] => {
const getItemEntry = this.getReceiptIncomeItemEntry(saleReceipt); const getItemEntry = this.getReceiptIncomeItemEntry(saleReceipt);
const creditEntries = saleReceipt.entries.map(getItemEntry); const creditEntries = saleReceipt.entries.map(getItemEntry);
const depositEntry = this.getReceiptDepositEntry(saleReceipt); const depositEntry = this.getReceiptDepositEntry(saleReceipt);
const discountEntry = this.getDiscountEntry(saleReceipt, discountAccountId);
const adjustmentEntry = this.getAdjustmentEntry( return [depositEntry, ...creditEntries];
saleReceipt,
otherChargesAccountId
);
return [depositEntry, ...creditEntries, discountEntry, adjustmentEntry];
}; };
} }

View File

@@ -15,22 +15,15 @@ export class SaleReceiptTransformer extends Transformer {
return [ return [
'discountAmountFormatted', 'discountAmountFormatted',
'discountPercentageFormatted', 'discountPercentageFormatted',
'discountAmountLocalFormatted',
'subtotalFormatted', 'subtotalFormatted',
'subtotalLocalFormatted', 'subtotalLocalFormatted',
'totalFormatted', 'totalFormatted',
'totalLocalFormatted', 'totalLocalFormatted',
'adjustmentFormatted', 'adjustmentFormatted',
'adjustmentLocalFormatted',
'formattedAmount', 'formattedAmount',
'formattedReceiptDate', 'formattedReceiptDate',
'formattedClosedAtDate', 'formattedClosedAtDate',
'formattedCreatedAt', 'formattedCreatedAt',
'paidFormatted',
'entries', 'entries',
'attachments', 'attachments',
]; ];
@@ -137,18 +130,6 @@ export class SaleReceiptTransformer extends Transformer {
return receipt.discountPercentage ? `${receipt.discountPercentage}%` : ''; return receipt.discountPercentage ? `${receipt.discountPercentage}%` : '';
}; };
/**
* Retrieves formatted paid amount.
* @param receipt
* @returns {string}
*/
protected paidFormatted = (receipt: ISaleReceipt): string => {
return formatNumber(receipt.paid, {
currencyCode: receipt.currencyCode,
excerptZero: true,
});
};
/** /**
* Retrieves formatted adjustment amount. * Retrieves formatted adjustment amount.
* @param receipt * @param receipt

View File

@@ -42,7 +42,7 @@ export function BillDetailTableFooter() {
textStyle={TotalLineTextStyle.Regular} textStyle={TotalLineTextStyle.Regular}
/> />
)} )}
{bill.adjustment_formatted && ( {bill.adjustment > 0 && (
<TotalLine <TotalLine
title={'Adjustment'} title={'Adjustment'}
value={bill.adjustment_formatted} value={bill.adjustment_formatted}

View File

@@ -33,7 +33,7 @@ export default function CreditNoteDetailTableFooter() {
value={creditNote.discount_amount_formatted} value={creditNote.discount_amount_formatted}
/> />
)} )}
{creditNote.adjustment_formatted && ( {creditNote.adjustment > 0 && (
<TotalLine <TotalLine
title={'Adjustment'} title={'Adjustment'}
value={creditNote.adjustment_formatted} value={creditNote.adjustment_formatted}

View File

@@ -5,12 +5,14 @@ import styled from 'styled-components';
import { defaultTo } from 'lodash'; import { defaultTo } from 'lodash';
import { import {
ButtonLink,
CustomerDrawerLink, CustomerDrawerLink,
CommercialDocHeader, CommercialDocHeader,
CommercialDocTopHeader, CommercialDocTopHeader,
ExchangeRateDetailItem, ExchangeRateDetailItem,
Row, Row,
Col, Col,
FormatDate,
DetailsMenu, DetailsMenu,
DetailItem, DetailItem,
} from '@/components'; } from '@/components';
@@ -64,7 +66,6 @@ export default function ReceiptDetailHeader() {
/> />
</DetailsMenu> </DetailsMenu>
</Col> </Col>
<Col xs={6}> <Col xs={6}>
<DetailsMenu <DetailsMenu
direction={'horizantal'} direction={'horizantal'}

View File

@@ -8,6 +8,7 @@ import {
TotalLine, TotalLine,
TotalLineBorderStyle, TotalLineBorderStyle,
TotalLineTextStyle, TotalLineTextStyle,
FormatNumber,
} from '@/components'; } from '@/components';
import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider'; import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
@@ -35,7 +36,7 @@ export default function ReceiptDetailTableFooter() {
textStyle={TotalLineTextStyle.Regular} textStyle={TotalLineTextStyle.Regular}
/> />
)} )}
{receipt.adjustment_formatted && ( {receipt.adjustment > 0 && (
<TotalLine <TotalLine
title={'Adjustment'} title={'Adjustment'}
value={receipt.adjustment_formatted} value={receipt.adjustment_formatted}
@@ -50,8 +51,8 @@ export default function ReceiptDetailTableFooter() {
/> />
<TotalLine <TotalLine
title={<T id={'receipt.details.payment_amount'} />} title={<T id={'receipt.details.payment_amount'} />}
value={receipt.paid_formatted} value={receipt.formatted_amount}
borderStyle={TotalLineBorderStyle.SingleDark} borderStyle={TotalLineBorderStyle.DoubleDark}
/> />
<TotalLine <TotalLine
title={<T id={'receipt.details.due_amount'} />} title={<T id={'receipt.details.due_amount'} />}

View File

@@ -45,7 +45,7 @@ export default function VendorCreditDetailDrawerFooter() {
)} )}
<TotalLine <TotalLine
title={<T id={'vendor_credit.drawer.label_total'} />} title={<T id={'vendor_credit.drawer.label_total'} />}
value={vendorCredit.total_formatted} value={vendorCredit.formatted_amount}
borderStyle={TotalLineBorderStyle.DoubleDark} borderStyle={TotalLineBorderStyle.DoubleDark}
textStyle={TotalLineTextStyle.Bold} textStyle={TotalLineTextStyle.Bold}
/> />

View File

@@ -5,6 +5,7 @@ import styled from 'styled-components';
import { defaultTo } from 'lodash'; import { defaultTo } from 'lodash';
import { import {
FormatDate,
T, T,
Row, Row,
Col, Col,
@@ -28,14 +29,13 @@ export default function VendorCreditDetailHeader() {
<CommercialDocTopHeader> <CommercialDocTopHeader>
<DetailsMenu> <DetailsMenu>
<AmountItem label={intl.get('amount')}> <AmountItem label={intl.get('amount')}>
<span class="big-number">{vendorCredit.total_formatted}</span> <span class="big-number">{vendorCredit.formatted_amount}</span>
</AmountItem> </AmountItem>
<StatusItem> <StatusItem>
<VendorCreditDetailsStatus vendorCredit={vendorCredit} /> <VendorCreditDetailsStatus vendorCredit={vendorCredit} />
</StatusItem> </StatusItem>
</DetailsMenu> </DetailsMenu>
</CommercialDocTopHeader> </CommercialDocTopHeader>
<Row> <Row>
<Col xs={6}> <Col xs={6}>
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}> <DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>

View File

@@ -415,7 +415,7 @@ export const useBillTotal = () => {
return R.compose( return R.compose(
R.when(R.always(isExclusiveTax), R.add(totalTaxAmount)), R.when(R.always(isExclusiveTax), R.add(totalTaxAmount)),
R.subtract(R.__, discountAmount), R.subtract(R.__, discountAmount),
R.add(R.__, adjustmentAmount), R.subtract(R.__, adjustmentAmount),
)(subtotal); )(subtotal);
}; };

View File

@@ -259,10 +259,7 @@ export const useVendorCreditTotal = () => {
const discountAmount = useVendorCreditDiscountAmount(); const discountAmount = useVendorCreditDiscountAmount();
const adjustment = useVendorCreditAdjustment(); const adjustment = useVendorCreditAdjustment();
return R.compose( return subtotal - discountAmount - adjustment;
R.subtract(R.__, discountAmount),
R.add(R.__, adjustment),
)(subtotal);
}; };
/** /**

View File

@@ -263,10 +263,7 @@ export const useCreditNoteTotal = () => {
const discountAmount = useCreditNoteDiscountAmount(); const discountAmount = useCreditNoteDiscountAmount();
const adjustmentAmount = useCreditNoteAdjustmentAmount(); const adjustmentAmount = useCreditNoteAdjustmentAmount();
return R.compose( return subtotal - discountAmount - adjustmentAmount;
R.subtract(R.__, discountAmount),
R.add(R.__, adjustmentAmount),
)(subtotal);
}; };
/** /**

View File

@@ -299,10 +299,7 @@ export const useEstimateTotal = () => {
const discount = useEstimateDiscount(); const discount = useEstimateDiscount();
const adjustment = useEstimateAdjustment(); const adjustment = useEstimateAdjustment();
return R.compose( return subtotal - discount - adjustment;
R.subtract(R.__, discount),
R.add(R.__, adjustment),
)(subtotal);
}; };
/** /**

View File

@@ -455,7 +455,7 @@ export const useInvoiceTotal = () => {
return R.compose( return R.compose(
R.when(R.always(isExclusiveTax), R.add(totalTaxAmount)), R.when(R.always(isExclusiveTax), R.add(totalTaxAmount)),
R.subtract(R.__, discountAmount), R.subtract(R.__, discountAmount),
R.add(adjustmentAmount), R.subtract(R.__, adjustmentAmount),
)(subtotal); )(subtotal);
}; };

View File

@@ -284,10 +284,7 @@ export const useReceiptTotal = () => {
const adjustmentAmount = useReceiptAdjustmentAmount(); const adjustmentAmount = useReceiptAdjustmentAmount();
const discountAmount = useReceiptDiscountAmount(); const discountAmount = useReceiptDiscountAmount();
return R.compose( return subtotal - discountAmount - adjustmentAmount;
R.add(R.__, adjustmentAmount),
R.subtract(R.__, discountAmount),
)(subtotal);
}; };
/** /**