mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-23 08:10:32 +00:00
feat: advanced payments
This commit is contained in:
@@ -40,7 +40,7 @@ export interface ILedgerEntry {
|
|||||||
date: Date | string;
|
date: Date | string;
|
||||||
|
|
||||||
transactionType: string;
|
transactionType: string;
|
||||||
transactionSubType: string;
|
transactionSubType?: string;
|
||||||
|
|
||||||
transactionId: number;
|
transactionId: number;
|
||||||
|
|
||||||
|
|||||||
@@ -187,3 +187,11 @@ export interface PaymentReceiveMailPresendEvent {
|
|||||||
paymentReceiveId: number;
|
paymentReceiveId: number;
|
||||||
messageOptions: PaymentReceiveMailOptsDTO;
|
messageOptions: PaymentReceiveMailOptsDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PaymentReceiveUnearnedRevenueAppliedEventPayload {
|
||||||
|
tenantId: number;
|
||||||
|
paymentReceiveId: number;
|
||||||
|
saleInvoiceId: number;
|
||||||
|
appliedAmount: number;
|
||||||
|
trx?: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|||||||
@@ -216,3 +216,9 @@ export interface ISaleInvoiceMailSent {
|
|||||||
saleInvoiceId: number;
|
saleInvoiceId: number;
|
||||||
messageOptions: SendInvoiceMailDTO;
|
messageOptions: SendInvoiceMailDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SaleInvoiceAppliedUnearnedRevenueOnCreatedEventPayload {
|
||||||
|
tenantId: number;
|
||||||
|
saleInvoiceId: number;
|
||||||
|
trx?: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export class AutoApplyPrepardExpensesOnBillCreated {
|
|||||||
*/
|
*/
|
||||||
public attach(bus) {
|
public attach(bus) {
|
||||||
bus.subscribe(
|
bus.subscribe(
|
||||||
events.saleInvoice.onCreated,
|
events.bill.onCreated,
|
||||||
this.handleAutoApplyPrepardExpensesOnBillCreated.bind(this)
|
this.handleAutoApplyPrepardExpensesOnBillCreated.bind(this)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,34 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import PromisePool from '@supercharge/promise-pool';
|
import PromisePool, { ProcessHandler } from '@supercharge/promise-pool';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||||
|
import events from '@/subscribers/events';
|
||||||
|
import {
|
||||||
|
IPaymentReceive,
|
||||||
|
PaymentReceiveUnearnedRevenueAppliedEventPayload,
|
||||||
|
SaleInvoiceAppliedUnearnedRevenueOnCreatedEventPayload,
|
||||||
|
} from '@/interfaces';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class AutoApplyUnearnedRevenue {
|
export class AutoApplyUnearnedRevenue {
|
||||||
@Inject()
|
@Inject()
|
||||||
private tenancy: HasTenancyService;
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private eventPublisher: EventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto apply invoice to advanced payment received transactions.
|
* Auto apply invoice to advanced payment received transactions.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {number} invoiceId
|
* @param {number} invoiceId
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async autoApplyUnearnedRevenueToInvoice(
|
public async autoApplyUnearnedRevenueToInvoice(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
invoiceId: number,
|
saleInvoiceId: number,
|
||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
) {
|
): Promise<void> {
|
||||||
const { PaymentReceive, SaleInvoice } = this.tenancy.models(tenantId);
|
const { PaymentReceive, SaleInvoice } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
const unappliedPayments = await PaymentReceive.query(trx).where(
|
const unappliedPayments = await PaymentReceive.query(trx).where(
|
||||||
@@ -25,26 +37,51 @@ export class AutoApplyUnearnedRevenue {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
const invoice = await SaleInvoice.query(trx)
|
const invoice = await SaleInvoice.query(trx)
|
||||||
.findById(invoiceId)
|
.findById(saleInvoiceId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
let unappliedAmount = invoice.balance;
|
let unappliedAmount = invoice.total;
|
||||||
|
let appliedTotalAmount = 0;
|
||||||
|
|
||||||
|
const processHandler: ProcessHandler<
|
||||||
|
IPaymentReceive,
|
||||||
|
Promise<void>
|
||||||
|
> = async (unappliedPayment: IPaymentReceive, index: number, pool) => {
|
||||||
|
const appliedAmount = Math.min(unappliedAmount, unappliedAmount);
|
||||||
|
unappliedAmount = unappliedAmount - appliedAmount;
|
||||||
|
appliedTotalAmount += appliedAmount;
|
||||||
|
|
||||||
|
if (appliedAmount <= 0) {
|
||||||
|
pool.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.applyInvoiceToPaymentReceived(
|
||||||
|
tenantId,
|
||||||
|
unappliedPayment.id,
|
||||||
|
invoice.id,
|
||||||
|
appliedAmount,
|
||||||
|
trx
|
||||||
|
);
|
||||||
|
};
|
||||||
await PromisePool.withConcurrency(1)
|
await PromisePool.withConcurrency(1)
|
||||||
.for(unappliedPayments)
|
.for(unappliedPayments)
|
||||||
.process(async (unappliedPayment: any) => {
|
.process(processHandler);
|
||||||
const appliedAmount = unappliedAmount;
|
|
||||||
|
|
||||||
await this.applyInvoiceToPaymentReceived(
|
|
||||||
tenantId,
|
|
||||||
unappliedPayment.id,
|
|
||||||
invoice.id,
|
|
||||||
appliedAmount,
|
|
||||||
trx
|
|
||||||
);
|
|
||||||
});
|
|
||||||
// Increase the paid amount of the sale invoice.
|
// Increase the paid amount of the sale invoice.
|
||||||
await SaleInvoice.changePaymentAmount(invoiceId, unappliedAmount, trx);
|
await SaleInvoice.changePaymentAmount(
|
||||||
|
saleInvoiceId,
|
||||||
|
appliedTotalAmount,
|
||||||
|
trx
|
||||||
|
);
|
||||||
|
// Triggers event `onSaleInvoiceUnearnedRevenue`.
|
||||||
|
await this.eventPublisher.emitAsync(
|
||||||
|
events.saleInvoice.onUnearnedRevenueApplied,
|
||||||
|
{
|
||||||
|
tenantId,
|
||||||
|
saleInvoiceId,
|
||||||
|
trx,
|
||||||
|
} as SaleInvoiceAppliedUnearnedRevenueOnCreatedEventPayload
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,6 +91,7 @@ export class AutoApplyUnearnedRevenue {
|
|||||||
* @param {number} invoiceId
|
* @param {number} invoiceId
|
||||||
* @param {number} appliedAmount
|
* @param {number} appliedAmount
|
||||||
* @param {Knex.Transaction} trx
|
* @param {Knex.Transaction} trx
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public applyInvoiceToPaymentReceived = async (
|
public applyInvoiceToPaymentReceived = async (
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
@@ -61,7 +99,7 @@ export class AutoApplyUnearnedRevenue {
|
|||||||
invoiceId: number,
|
invoiceId: number,
|
||||||
appliedAmount: number,
|
appliedAmount: number,
|
||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
) => {
|
): Promise<void> => {
|
||||||
const { PaymentReceiveEntry, PaymentReceive } =
|
const { PaymentReceiveEntry, PaymentReceive } =
|
||||||
this.tenancy.models(tenantId);
|
this.tenancy.models(tenantId);
|
||||||
|
|
||||||
@@ -71,5 +109,17 @@ export class AutoApplyUnearnedRevenue {
|
|||||||
paymentAmount: appliedAmount,
|
paymentAmount: appliedAmount,
|
||||||
});
|
});
|
||||||
await PaymentReceive.query(trx).increment('usedAmount', appliedAmount);
|
await PaymentReceive.query(trx).increment('usedAmount', appliedAmount);
|
||||||
|
|
||||||
|
// Triggers the event `onPaymentReceivedUnearnedRevenue`.
|
||||||
|
await this.eventPublisher.emitAsync(
|
||||||
|
events.paymentReceive.onUnearnedRevenueApplied,
|
||||||
|
{
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
saleInvoiceId: invoiceId,
|
||||||
|
appliedAmount,
|
||||||
|
trx,
|
||||||
|
} as PaymentReceiveUnearnedRevenueAppliedEventPayload
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
import { sumBy } from 'lodash';
|
import { sumBy } from 'lodash';
|
||||||
import {
|
import {
|
||||||
AccountNormal,
|
AccountNormal,
|
||||||
@@ -5,7 +6,6 @@ import {
|
|||||||
IPaymentReceive,
|
IPaymentReceive,
|
||||||
IPaymentReceiveGLCommonEntry,
|
IPaymentReceiveGLCommonEntry,
|
||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
import { Knex } from 'knex';
|
|
||||||
import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
||||||
|
|
||||||
export class PaymentReceivedGLCommon {
|
export class PaymentReceivedGLCommon {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
|
||||||
import { TenantMetadata } from '@/system/models';
|
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
|
import { flatten } from 'lodash';
|
||||||
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
import { TenantMetadata } from '@/system/models';
|
||||||
import { PaymentReceivedGLCommon } from './PaymentReceivedGLCommon';
|
import { PaymentReceivedGLCommon } from './PaymentReceivedGLCommon';
|
||||||
import {
|
import {
|
||||||
AccountNormal,
|
AccountNormal,
|
||||||
@@ -10,12 +11,17 @@ import {
|
|||||||
IPaymentReceive,
|
IPaymentReceive,
|
||||||
IPaymentReceiveEntry,
|
IPaymentReceiveEntry,
|
||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
|
import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
||||||
|
import Ledger from '@/services/Accounting/Ledger';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class PaymentReceivedUnearnedGLEntries extends PaymentReceivedGLCommon {
|
export class PaymentReceivedUnearnedGLEntries extends PaymentReceivedGLCommon {
|
||||||
@Inject()
|
@Inject()
|
||||||
private tenancy: HasTenancyService;
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private ledgerStorage: LedgerStorageService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes payment GL entries to the storage.
|
* Writes payment GL entries to the storage.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
@@ -30,38 +36,118 @@ export class PaymentReceivedUnearnedGLEntries extends PaymentReceivedGLCommon {
|
|||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const { PaymentReceive } = this.tenancy.models(tenantId);
|
const { PaymentReceive } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
// Retrieves the given tenant metadata.
|
|
||||||
const tenantMeta = await TenantMetadata.query().findOne({ tenantId });
|
|
||||||
|
|
||||||
// Retrieves the payment receive with associated entries.
|
// Retrieves the payment receive with associated entries.
|
||||||
const paymentReceive = await PaymentReceive.query(trx)
|
const paymentReceive = await PaymentReceive.query(trx)
|
||||||
.findById(paymentReceiveId)
|
.findById(paymentReceiveId)
|
||||||
.withGraphFetched('entries.invoice');
|
.withGraphFetched('entries.invoice');
|
||||||
|
|
||||||
if (paymentReceive.unearnedRevenueAccountId) {
|
// Stop early if
|
||||||
|
if (!paymentReceive.unearnedRevenueAccountId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Retrieves the given tenant metadata.
|
||||||
|
const tenantMeta = await TenantMetadata.query().findOne({ tenantId });
|
||||||
|
|
||||||
|
const ledger = await this.getPaymentReceiveGLedger(
|
||||||
|
tenantId,
|
||||||
|
paymentReceive
|
||||||
|
);
|
||||||
|
// Commit the ledger entries to the storage.
|
||||||
|
await this.ledgerStorage.commit(tenantId, ledger, trx);
|
||||||
};
|
};
|
||||||
|
|
||||||
private getPaymentGLEntries = (paymentReceive: IPaymentReceive) => {};
|
/**
|
||||||
|
* Rewrites the given payment receive GL entries.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} paymentReceiveId
|
||||||
|
* @param {Knex.Transaction} trx
|
||||||
|
*/
|
||||||
|
public rewritePaymentGLEntries = async (
|
||||||
|
tenantId: number,
|
||||||
|
paymentReceiveId: number,
|
||||||
|
trx?: Knex.Transaction
|
||||||
|
) => {
|
||||||
|
// Reverts the payment GL entries.
|
||||||
|
await this.revertPaymentGLEntries(tenantId, paymentReceiveId, trx);
|
||||||
|
|
||||||
private getPaymentUnearnedGLEntries = R.curry(() => {});
|
// Writes the payment GL entries.
|
||||||
|
await this.writePaymentGLEntries(tenantId, paymentReceiveId, trx);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the payment received GL entries.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {IPaymentReceive} paymentReceive
|
||||||
|
* @returns {Promise<Ledger>}
|
||||||
|
*/
|
||||||
|
private getPaymentReceiveGLedger = async (
|
||||||
|
tenantId: number,
|
||||||
|
paymentReceive: IPaymentReceive
|
||||||
|
) => {
|
||||||
|
const { accountRepository } = this.tenancy.repositories(tenantId);
|
||||||
|
|
||||||
|
// Retrieve the A/R account of the given currency.
|
||||||
|
const receivableAccount =
|
||||||
|
await accountRepository.findOrCreateAccountReceivable(
|
||||||
|
paymentReceive.currencyCode
|
||||||
|
);
|
||||||
|
// Retrieve the payment GL entries.
|
||||||
|
const entries = this.getPaymentGLEntries(
|
||||||
|
receivableAccount.id,
|
||||||
|
paymentReceive
|
||||||
|
);
|
||||||
|
const unearnedRevenueEntries =
|
||||||
|
this.getUnearnedRevenueEntries(paymentReceive);
|
||||||
|
|
||||||
|
const combinedEntries = [...unearnedRevenueEntries, ...entries];
|
||||||
|
|
||||||
|
return new Ledger(combinedEntries);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the payment received GL entries.
|
||||||
|
* @param {number} ARAccountId - A/R account id.
|
||||||
|
* @param {IPaymentReceive} paymentReceive -
|
||||||
|
* @returns {Array<ILedgerEntry>}
|
||||||
|
*/
|
||||||
|
private getPaymentGLEntries = R.curry(
|
||||||
|
(
|
||||||
|
ARAccountId: number,
|
||||||
|
paymentReceive: IPaymentReceive
|
||||||
|
): Array<ILedgerEntry> => {
|
||||||
|
const getPaymentEntryGLEntries = this.getPaymentEntryGLEntries(
|
||||||
|
ARAccountId,
|
||||||
|
paymentReceive
|
||||||
|
);
|
||||||
|
const entriesGroup = paymentReceive.entries.map((paymentEntry) => {
|
||||||
|
return getPaymentEntryGLEntries(paymentEntry);
|
||||||
|
});
|
||||||
|
return flatten(entriesGroup);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the payment entry GL entries.
|
||||||
* @param {IPaymentReceiveEntry} paymentReceivedEntry -
|
* @param {IPaymentReceiveEntry} paymentReceivedEntry -
|
||||||
* @param {IPaymentReceive} paymentReceive -
|
* @param {IPaymentReceive} paymentReceive -
|
||||||
|
* @returns {Array<ILedgerEntry>}
|
||||||
*/
|
*/
|
||||||
private getPaymentEntryGLEntries = R.curry(
|
private getPaymentEntryGLEntries = R.curry(
|
||||||
(
|
(
|
||||||
paymentReceivedEntry: IPaymentReceiveEntry,
|
ARAccountId: number,
|
||||||
paymentReceive: IPaymentReceive
|
paymentReceive: IPaymentReceive,
|
||||||
) => {
|
paymentReceivedEntry: IPaymentReceiveEntry
|
||||||
const depositEntry = this.getPaymentDepositGLEntry(
|
): Array<ILedgerEntry> => {
|
||||||
|
const unearnedRevenueEntry = this.getDebitUnearnedRevenueGLEntry(
|
||||||
paymentReceivedEntry.paymentAmount,
|
paymentReceivedEntry.paymentAmount,
|
||||||
paymentReceive
|
paymentReceive
|
||||||
);
|
);
|
||||||
|
const AREntry = this.getPaymentReceivableEntry(
|
||||||
|
paymentReceivedEntry.paymentAmount,
|
||||||
|
paymentReceive,
|
||||||
|
ARAccountId
|
||||||
|
);
|
||||||
|
return [unearnedRevenueEntry, AREntry];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -70,7 +156,7 @@ export class PaymentReceivedUnearnedGLEntries extends PaymentReceivedGLCommon {
|
|||||||
* @param {IPaymentReceive} paymentReceive
|
* @param {IPaymentReceive} paymentReceive
|
||||||
* @returns {ILedgerEntry}
|
* @returns {ILedgerEntry}
|
||||||
*/
|
*/
|
||||||
private getPaymentDepositGLEntry = (
|
private getDebitUnearnedRevenueGLEntry = (
|
||||||
amount: number,
|
amount: number,
|
||||||
paymentReceive: IPaymentReceive
|
paymentReceive: IPaymentReceive
|
||||||
): ILedgerEntry => {
|
): ILedgerEntry => {
|
||||||
@@ -78,10 +164,11 @@ export class PaymentReceivedUnearnedGLEntries extends PaymentReceivedGLCommon {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...commonJournal,
|
...commonJournal,
|
||||||
credit: amount,
|
debit: amount,
|
||||||
accountId: paymentReceive.unearnedRevenueAccountId,
|
accountId: paymentReceive.unearnedRevenueAccountId,
|
||||||
accountNormal: AccountNormal.CREDIT,
|
accountNormal: AccountNormal.CREDIT,
|
||||||
index: 2,
|
index: 2,
|
||||||
|
indexGroup: 20,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -100,11 +187,66 @@ export class PaymentReceivedUnearnedGLEntries extends PaymentReceivedGLCommon {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...commonJournal,
|
...commonJournal,
|
||||||
debit: amount,
|
credit: amount,
|
||||||
contactId: paymentReceive.customerId,
|
contactId: paymentReceive.customerId,
|
||||||
accountId: ARAccountId,
|
accountId: ARAccountId,
|
||||||
accountNormal: AccountNormal.DEBIT,
|
accountNormal: AccountNormal.DEBIT,
|
||||||
index: 1,
|
index: 1,
|
||||||
|
indexGroup: 20,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the unearned revenue entries.
|
||||||
|
* @param {IPaymentReceive} paymentReceived -
|
||||||
|
* @returns {Array<ILedgerEntry>}
|
||||||
|
*/
|
||||||
|
private getUnearnedRevenueEntries = (
|
||||||
|
paymentReceive: IPaymentReceive
|
||||||
|
): Array<ILedgerEntry> => {
|
||||||
|
const depositEntry = this.getDepositPaymentGLEntry(paymentReceive);
|
||||||
|
const unearnedEntry = this.getUnearnedRevenueEntry(paymentReceive);
|
||||||
|
|
||||||
|
return [depositEntry, unearnedEntry];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the payment deposit entry.
|
||||||
|
* @param {IPaymentReceive} paymentReceived -
|
||||||
|
* @returns {ILedgerEntry}
|
||||||
|
*/
|
||||||
|
private getDepositPaymentGLEntry = (
|
||||||
|
paymentReceive: IPaymentReceive
|
||||||
|
): ILedgerEntry => {
|
||||||
|
const commonJournal = this.getPaymentReceiveCommonEntry(paymentReceive);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...commonJournal,
|
||||||
|
debit: paymentReceive.amount,
|
||||||
|
accountId: paymentReceive.depositAccountId,
|
||||||
|
accountNormal: AccountNormal.DEBIT,
|
||||||
|
indexGroup: 10,
|
||||||
|
index: 1,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the unearned revenue entry.
|
||||||
|
* @param {IPaymentReceive} paymentReceived -
|
||||||
|
* @returns {ILedgerEntry}
|
||||||
|
*/
|
||||||
|
private getUnearnedRevenueEntry = (
|
||||||
|
paymentReceived: IPaymentReceive
|
||||||
|
): ILedgerEntry => {
|
||||||
|
const commonJournal = this.getPaymentReceiveCommonEntry(paymentReceived);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...commonJournal,
|
||||||
|
credit: paymentReceived.amount,
|
||||||
|
accountId: paymentReceived.unearnedRevenueAccountId,
|
||||||
|
accountNormal: AccountNormal.CREDIT,
|
||||||
|
indexGroup: 10,
|
||||||
|
index: 1,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,20 @@ import {
|
|||||||
IPaymentReceiveCreatedPayload,
|
IPaymentReceiveCreatedPayload,
|
||||||
IPaymentReceiveDeletedPayload,
|
IPaymentReceiveDeletedPayload,
|
||||||
IPaymentReceiveEditedPayload,
|
IPaymentReceiveEditedPayload,
|
||||||
|
PaymentReceiveUnearnedRevenueAppliedEventPayload,
|
||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
import events from '@/subscribers/events';
|
import events from '@/subscribers/events';
|
||||||
import { PaymentReceiveGLEntries } from '@/services/Sales/PaymentReceives/PaymentReceiveGLEntries';
|
import { PaymentReceiveGLEntries } from '@/services/Sales/PaymentReceives/PaymentReceiveGLEntries';
|
||||||
|
import { PaymentReceivedUnearnedGLEntries } from '@/services/Sales/PaymentReceives/PaymentReceivedUnearnedGLEntries';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class PaymentReceivesWriteGLEntriesSubscriber {
|
export default class PaymentReceivesWriteGLEntriesSubscriber {
|
||||||
@Inject()
|
@Inject()
|
||||||
private paymentReceiveGLEntries: PaymentReceiveGLEntries;
|
private paymentReceiveGLEntries: PaymentReceiveGLEntries;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private paymentReceivedUnearnedGLEntries: PaymentReceivedUnearnedGLEntries;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches events with handlers.
|
* Attaches events with handlers.
|
||||||
*/
|
*/
|
||||||
@@ -20,6 +25,14 @@ export default class PaymentReceivesWriteGLEntriesSubscriber {
|
|||||||
events.paymentReceive.onCreated,
|
events.paymentReceive.onCreated,
|
||||||
this.handleWriteJournalEntriesOnceCreated
|
this.handleWriteJournalEntriesOnceCreated
|
||||||
);
|
);
|
||||||
|
bus.subscribe(
|
||||||
|
events.paymentReceive.onCreated,
|
||||||
|
this.handleWriteUnearnedRevenueGLEntriesOnCreated.bind(this)
|
||||||
|
);
|
||||||
|
bus.subscribe(
|
||||||
|
events.paymentReceive.onUnearnedRevenueApplied,
|
||||||
|
this.handleRewriteUnearnedRevenueGLEntriesOnApply
|
||||||
|
);
|
||||||
bus.subscribe(
|
bus.subscribe(
|
||||||
events.paymentReceive.onEdited,
|
events.paymentReceive.onEdited,
|
||||||
this.handleOverwriteJournalEntriesOnceEdited
|
this.handleOverwriteJournalEntriesOnceEdited
|
||||||
@@ -32,6 +45,7 @@ export default class PaymentReceivesWriteGLEntriesSubscriber {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle journal entries writing once the payment receive created.
|
* Handle journal entries writing once the payment receive created.
|
||||||
|
* @param {IPaymentReceiveCreatedPayload} payload -
|
||||||
*/
|
*/
|
||||||
private handleWriteJournalEntriesOnceCreated = async ({
|
private handleWriteJournalEntriesOnceCreated = async ({
|
||||||
tenantId,
|
tenantId,
|
||||||
@@ -45,8 +59,41 @@ export default class PaymentReceivesWriteGLEntriesSubscriber {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles rewrite payment GL entries on unearned revenue payload.
|
||||||
|
* @param {PaymentReceiveUnearnedRevenueAppliedEventPayload} payload -
|
||||||
|
*/
|
||||||
|
private handleWriteUnearnedRevenueGLEntriesOnCreated = async ({
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
trx,
|
||||||
|
}: IPaymentReceiveCreatedPayload) => {
|
||||||
|
await this.paymentReceivedUnearnedGLEntries.writePaymentGLEntries(
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
trx
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles rewrite unearned revenue GL entries on payment received applied.
|
||||||
|
* @param {PaymentReceiveUnearnedRevenueAppliedEventPayload} payload -
|
||||||
|
*/
|
||||||
|
private handleRewriteUnearnedRevenueGLEntriesOnApply = async ({
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
trx,
|
||||||
|
}: PaymentReceiveUnearnedRevenueAppliedEventPayload) => {
|
||||||
|
await this.paymentReceivedUnearnedGLEntries.rewritePaymentGLEntries(
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
trx
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle journal entries writing once the payment receive edited.
|
* Handle journal entries writing once the payment receive edited.
|
||||||
|
* @param {IPaymentReceiveEditedPayload} payload -
|
||||||
*/
|
*/
|
||||||
private handleOverwriteJournalEntriesOnceEdited = async ({
|
private handleOverwriteJournalEntriesOnceEdited = async ({
|
||||||
tenantId,
|
tenantId,
|
||||||
@@ -62,6 +109,7 @@ export default class PaymentReceivesWriteGLEntriesSubscriber {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles revert journal entries once deleted.
|
* Handles revert journal entries once deleted.
|
||||||
|
* @param {IPaymentReceiveDeletedPayload} payload -
|
||||||
*/
|
*/
|
||||||
private handleRevertJournalEntriesOnceDeleted = async ({
|
private handleRevertJournalEntriesOnceDeleted = async ({
|
||||||
tenantId,
|
tenantId,
|
||||||
|
|||||||
@@ -142,6 +142,8 @@ export default {
|
|||||||
|
|
||||||
onMailReminderSend: 'onSaleInvoiceMailReminderSend',
|
onMailReminderSend: 'onSaleInvoiceMailReminderSend',
|
||||||
onMailReminderSent: 'onSaleInvoiceMailReminderSent',
|
onMailReminderSent: 'onSaleInvoiceMailReminderSent',
|
||||||
|
|
||||||
|
onUnearnedRevenueApplied: 'onSaleInvoiceUnearnedRevenue',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,6 +232,8 @@ export default {
|
|||||||
onPreMailSend: 'onPaymentReceivePreMailSend',
|
onPreMailSend: 'onPaymentReceivePreMailSend',
|
||||||
onMailSend: 'onPaymentReceiveMailSend',
|
onMailSend: 'onPaymentReceiveMailSend',
|
||||||
onMailSent: 'onPaymentReceiveMailSent',
|
onMailSent: 'onPaymentReceiveMailSent',
|
||||||
|
|
||||||
|
onUnearnedRevenueApplied: 'onPaymentReceivedUnearnedRevenue',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user