2022-05-03 13:13:47 +00:00
|
|
|
import { Doc } from 'fyo/model/doc';
|
|
|
|
import { ModelNameEnum } from 'models/types';
|
|
|
|
import { LedgerPosting } from './LedgerPosting';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* # Transactional
|
|
|
|
*
|
|
|
|
* Any model that creates ledger entries on submit should extend the
|
|
|
|
* `Transactional` model.
|
|
|
|
*
|
|
|
|
* Example of transactional models:
|
|
|
|
* - Invoice
|
|
|
|
* - Payment
|
|
|
|
* - JournalEntry
|
|
|
|
*
|
|
|
|
* Basically it does the following:
|
|
|
|
* - `afterSubmit`: create the ledger entries.
|
|
|
|
* - `afterCancel`: create reverse ledger entries.
|
|
|
|
* - `afterDelete`: delete the normal and reversed ledger entries.
|
|
|
|
*/
|
|
|
|
|
|
|
|
export abstract class Transactional extends Doc {
|
2022-05-11 10:44:31 +00:00
|
|
|
date?: Date;
|
|
|
|
|
2022-05-04 08:19:40 +00:00
|
|
|
get isTransactional() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-11-18 17:31:50 +00:00
|
|
|
abstract getPosting(): Promise<LedgerPosting | null>;
|
2022-05-03 13:13:47 +00:00
|
|
|
|
|
|
|
async validate() {
|
2022-05-11 10:44:31 +00:00
|
|
|
await super.validate();
|
2022-11-18 17:31:50 +00:00
|
|
|
if (!this.isTransactional) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-03 13:13:47 +00:00
|
|
|
const posting = await this.getPosting();
|
2022-11-18 17:31:50 +00:00
|
|
|
if (posting === null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-03 13:13:47 +00:00
|
|
|
posting.validate();
|
|
|
|
}
|
|
|
|
|
|
|
|
async afterSubmit(): Promise<void> {
|
2022-05-11 10:44:31 +00:00
|
|
|
await super.afterSubmit();
|
2022-11-18 17:31:50 +00:00
|
|
|
if (!this.isTransactional) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-03 13:13:47 +00:00
|
|
|
const posting = await this.getPosting();
|
2022-11-18 17:31:50 +00:00
|
|
|
if (posting === null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-03 13:13:47 +00:00
|
|
|
await posting.post();
|
|
|
|
}
|
|
|
|
|
|
|
|
async afterCancel(): Promise<void> {
|
2022-05-11 10:44:31 +00:00
|
|
|
await super.afterCancel();
|
2022-11-18 17:31:50 +00:00
|
|
|
if (!this.isTransactional) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-03 13:13:47 +00:00
|
|
|
const posting = await this.getPosting();
|
2022-11-18 17:31:50 +00:00
|
|
|
if (posting === null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-03 13:13:47 +00:00
|
|
|
await posting.postReverse();
|
|
|
|
}
|
|
|
|
|
|
|
|
async afterDelete(): Promise<void> {
|
2022-05-11 10:44:31 +00:00
|
|
|
await super.afterDelete();
|
2022-11-18 17:31:50 +00:00
|
|
|
if (!this.isTransactional) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-03 13:13:47 +00:00
|
|
|
const ledgerEntryIds = (await this.fyo.db.getAll(
|
|
|
|
ModelNameEnum.AccountingLedgerEntry,
|
|
|
|
{
|
|
|
|
fields: ['name'],
|
|
|
|
filters: {
|
|
|
|
referenceType: this.schemaName,
|
|
|
|
referenceName: this.name!,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
)) as { name: string }[];
|
|
|
|
|
|
|
|
for (const { name } of ledgerEntryIds) {
|
2022-05-04 08:19:40 +00:00
|
|
|
const ledgerEntryDoc = await this.fyo.doc.getDoc(
|
|
|
|
ModelNameEnum.AccountingLedgerEntry,
|
|
|
|
name
|
|
|
|
);
|
|
|
|
await ledgerEntryDoc.delete();
|
2022-05-03 13:13:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|