feat: average rate cost method.

This commit is contained in:
a.bouhuolia
2020-12-22 22:27:54 +02:00
parent c327c79612
commit 061b50c671
21 changed files with 787 additions and 409 deletions

View File

@@ -3,7 +3,8 @@ import JournalPoster from 'services/Accounting/JournalPoster';
import JournalEntry from 'services/Accounting/JournalEntry';
import InventoryService from 'services/Inventory/Inventory';
import TenancyService from 'services/Tenancy/TenancyService';
import { ISaleInvoice, IItemEntry } from 'interfaces';
import { ISaleInvoice, IItemEntry, IInventoryLotCost, IItem } from 'interfaces';
import JournalCommands from 'services/Accounting/JournalCommands';
@Service()
export default class SaleInvoicesCost {
@@ -45,6 +46,7 @@ export default class SaleInvoicesCost {
*/
scheduleWriteJournalEntries(tenantId: number, startingDate?: Date) {
const agenda = Container.get('agenda');
return agenda.schedule('in 3 seconds', 'rewrite-invoices-journal-entries', {
startingDate, tenantId,
});
@@ -58,16 +60,23 @@ export default class SaleInvoicesCost {
*/
async writeJournalEntries(tenantId: number, startingDate: Date, override: boolean) {
const { AccountTransaction, SaleInvoice, Account } = this.tenancy.models(tenantId);
const { accountRepository } = this.tenancy.repositories(tenantId);
const receivableAccount = await accountRepository.findOne({
slug: 'accounts-receivable',
});
const salesInvoices = await SaleInvoice.query()
.onBuild((builder: any) => {
builder.modify('filterDateRange', startingDate);
builder.orderBy('invoice_date', 'ASC');
builder.withGraphFetched('entries.item')
builder.withGraphFetched('entries.item');
builder.withGraphFetched('costTransactions(groupedEntriesCost)');
});
const accountsDepGraph = await Account.depGraph().query();
const journal = new JournalPoster(accountsDepGraph);
const accountsDepGraph = await accountRepository.getDependencyGraph();
const journal = new JournalPoster(tenantId, accountsDepGraph);
const journalCommands = new JournalCommands(journal);
if (override) {
const oldTransactions = await AccountTransaction.query()
@@ -77,12 +86,14 @@ export default class SaleInvoicesCost {
})
.withGraphFetched('account.type');
journal.loadEntries(oldTransactions);
journal.fromTransactions(oldTransactions);
journal.removeEntries();
}
salesInvoices.forEach((saleInvoice: ISaleInvoice) => {
this.saleInvoiceJournal(saleInvoice, journal);
salesInvoices.forEach((saleInvoice: ISaleInvoice & {
costTransactions: IInventoryLotCost[],
entries: IItemEntry & { item: IItem },
}) => {
journalCommands.saleInvoice(saleInvoice, receivableAccount.id);
});
return Promise.all([
journal.deleteEntries(),
@@ -92,64 +103,39 @@ export default class SaleInvoicesCost {
}
/**
* Writes journal entries for given sale invoice.
* @param {ISaleInvoice} saleInvoice
* @param {JournalPoster} journal
* Writes the sale invoice journal entries.
* @param {SaleInvoice} saleInvoice -
*/
saleInvoiceJournal(saleInvoice: ISaleInvoice, journal: JournalPoster) {
let inventoryTotal: number = 0;
const receivableAccount = { id: 10 };
const commonEntry = {
referenceType: 'SaleInvoice',
referenceId: saleInvoice.id,
date: saleInvoice.invoiceDate,
};
const costTransactions: Map<number, number> = new Map(
saleInvoice?.costTransactions?.map((trans: IItemEntry) => [
trans.entryId, trans.cost,
]),
);
// XXX Debit - Receivable account.
const receivableEntry = new JournalEntry({
...commonEntry,
debit: saleInvoice.balance,
account: receivableAccount.id,
});
journal.debit(receivableEntry);
async writeNonInventoryInvoiceEntries(
tenantId: number,
saleInvoice: ISaleInvoice,
override: boolean
) {
const { accountRepository } = this.tenancy.repositories(tenantId);
const { AccountTransaction } = this.tenancy.models(tenantId);
saleInvoice.entries.forEach((entry: IItemEntry) => {
const cost: number = costTransactions.get(entry.id);
const income: number = entry.quantity * entry.rate;
if (entry.item.type === 'inventory' && cost) {
// XXX Debit - Cost account.
const costEntry = new JournalEntry({
...commonEntry,
debit: cost,
account: entry.item.costAccountId,
note: entry.description,
});
journal.debit(costEntry);
inventoryTotal += cost;
}
// XXX Credit - Income account.
const incomeEntry = new JournalEntry({
...commonEntry,
credit: income,
account: entry.item.sellAccountId,
note: entry.description,
});
journal.credit(incomeEntry);
if (inventoryTotal > 0) {
// XXX Credit - Inventory account.
const inventoryEntry = new JournalEntry({
...commonEntry,
credit: inventoryTotal,
account: entry.item.inventoryAccountId,
});
journal.credit(inventoryEntry);
}
// Receivable account.
const receivableAccount = await accountRepository.findOne({
slug: 'accounts-receivable',
});
const journal = new JournalPoster(tenantId);
const journalCommands = new JournalCommands(journal);
if (override) {
const oldTransactions = await AccountTransaction.query()
.where('reference_type', 'SaleInvoice')
.where('reference_id', saleInvoice.id)
.withGraphFetched('account.type');
journal.fromTransactions(oldTransactions);
journal.removeEntries();
}
journalCommands.saleInvoiceNonInventory(saleInvoice, receivableAccount.id);
await Promise.all([
journal.deleteEntries(),
journal.saveEntries(),
journal.saveBalance(),
]);
}
}