mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 21:00:31 +00:00
feat: trigger compute items cost once the sale invoice and bill be edited or deleted.
This commit is contained in:
@@ -239,7 +239,7 @@ export default class JournalCommands{
|
||||
.whereIn('reference_id', Array.isArray(referenceId) ? referenceId : [referenceId])
|
||||
.withGraphFetched('account.type');
|
||||
|
||||
this.journal.loadEntries(transactions);
|
||||
this.journal.fromTransactions(transactions);
|
||||
this.journal.removeEntries();
|
||||
}
|
||||
|
||||
|
||||
@@ -392,7 +392,7 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
billId,
|
||||
'IN',
|
||||
billDate,
|
||||
lotNumber,
|
||||
lotNumber
|
||||
);
|
||||
// Records the inventory transactions.
|
||||
await this.inventoryService.recordInventoryTransactions(
|
||||
@@ -418,11 +418,25 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async revertInventoryTransactions(tenantId: number, billId: number) {
|
||||
const { inventoryTransactionRepository } = this.tenancy.repositories(
|
||||
tenantId
|
||||
);
|
||||
|
||||
// Retrieve the inventory transactions of the given sale invoice.
|
||||
const oldInventoryTransactions = await inventoryTransactionRepository.find({
|
||||
transactionId: billId,
|
||||
transactionType: 'Bill',
|
||||
});
|
||||
await this.inventoryService.deleteInventoryTransactions(
|
||||
tenantId,
|
||||
billId,
|
||||
'Bill'
|
||||
);
|
||||
// Triggers 'onInventoryTransactionsDeleted' event.
|
||||
this.eventDispatcher.dispatch(
|
||||
events.bill.onInventoryTransactionsDeleted,
|
||||
{ tenantId, billId, oldInventoryTransactions }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { omit, sumBy, map } from 'lodash';
|
||||
import { omit, sumBy } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import {
|
||||
EventDispatcher,
|
||||
@@ -106,7 +106,8 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
*/
|
||||
async getInvoiceOrThrowError(tenantId: number, saleInvoiceId: number) {
|
||||
const { SaleInvoice } = this.tenancy.models(tenantId);
|
||||
const saleInvoice = await SaleInvoice.query().findById(saleInvoiceId)
|
||||
const saleInvoice = await SaleInvoice.query()
|
||||
.findById(saleInvoiceId)
|
||||
.withGraphFetched('entries');
|
||||
|
||||
if (!saleInvoice) {
|
||||
@@ -183,7 +184,6 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
tenantId,
|
||||
saleInvoiceDTO.entries
|
||||
);
|
||||
|
||||
// Validate items should be sellable items.
|
||||
await this.itemsEntriesService.validateNonSellableEntriesItems(
|
||||
tenantId,
|
||||
@@ -227,7 +227,6 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
tenantId,
|
||||
saleInvoiceId
|
||||
);
|
||||
|
||||
// Transform DTO object to model object.
|
||||
const saleInvoiceObj = this.transformDTOToModel(
|
||||
tenantId,
|
||||
@@ -325,10 +324,17 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
): Promise<void> {
|
||||
const { SaleInvoice, ItemEntry } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieve the given sale invoice with associated entries or throw not found error.
|
||||
const oldSaleInvoice = await this.getInvoiceOrThrowError(
|
||||
tenantId,
|
||||
saleInvoiceId
|
||||
);
|
||||
// Triggers `onSaleInvoiceDelete` event.
|
||||
await this.eventDispatcher.dispatch(events.saleInvoice.onDelete, {
|
||||
tenantId,
|
||||
saleInvoice: oldSaleInvoice,
|
||||
saleInvoiceId,
|
||||
});
|
||||
// Unlink the converted sale estimates from the given sale invoice.
|
||||
await this.saleEstimatesService.unlinkConvertedEstimateFromInvoice(
|
||||
tenantId,
|
||||
@@ -448,6 +454,14 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
tenantId: number,
|
||||
saleInvoiceId: number
|
||||
): Promise<void> {
|
||||
const { inventoryTransactionRepository } = this.tenancy.repositories(tenantId);
|
||||
|
||||
// Retrieve the inventory transactions of the given sale invoice.
|
||||
const oldInventoryTransactions = await inventoryTransactionRepository.find({
|
||||
transactionId: saleInvoiceId,
|
||||
transactionType: 'SaleInvoice',
|
||||
});
|
||||
// Delete the inventory transaction of the given sale invoice.
|
||||
await this.inventoryService.deleteInventoryTransactions(
|
||||
tenantId,
|
||||
saleInvoiceId,
|
||||
@@ -456,7 +470,7 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
// Triggers 'onInventoryTransactionsDeleted' event.
|
||||
this.eventDispatcher.dispatch(
|
||||
events.saleInvoice.onInventoryTransactionsDeleted,
|
||||
{ tenantId, saleInvoiceId }
|
||||
{ tenantId, saleInvoiceId, oldInventoryTransactions }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -482,40 +496,6 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
return saleInvoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules compute sale invoice items cost based on each item
|
||||
* cost method.
|
||||
* @param {ISaleInvoice} saleInvoice
|
||||
* @return {Promise}
|
||||
*/
|
||||
async scheduleComputeInvoiceItemsCost(
|
||||
tenantId: number,
|
||||
saleInvoiceId: number,
|
||||
override?: boolean
|
||||
) {
|
||||
const { SaleInvoice, Item } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieve the sale invoice with associated entries.
|
||||
const saleInvoice: ISaleInvoice = await SaleInvoice.query()
|
||||
.findById(saleInvoiceId)
|
||||
.withGraphFetched('entries');
|
||||
|
||||
// Retrieve the inventory items that associated to the sale invoice entries.
|
||||
const inventoryItems = await Item.query()
|
||||
.whereIn('id', map(saleInvoice.entries, 'itemId'))
|
||||
.where('type', 'inventory');
|
||||
|
||||
const inventoryItemsIds = map(inventoryItems, 'id');
|
||||
|
||||
if (inventoryItemsIds.length > 0) {
|
||||
await this.scheduleComputeItemsCost(
|
||||
tenantId,
|
||||
inventoryItemsIds,
|
||||
saleInvoice.invoiceDate
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve sales invoices filterable and paginated list.
|
||||
* @param {Request} req
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Container, Service, Inject } from 'typedi';
|
||||
import { map } from 'lodash';
|
||||
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, IInventoryLotCost, IItem } from 'interfaces';
|
||||
@@ -21,10 +21,10 @@ export default class SaleInvoicesCost {
|
||||
* @param {Date} startingDate - Starting compute cost date.
|
||||
* @return {Promise<Agenda>}
|
||||
*/
|
||||
async scheduleComputeItemsCost(
|
||||
async scheduleComputeCostByItemsIds(
|
||||
tenantId: number,
|
||||
inventoryItemsIds: number[],
|
||||
startingDate: Date
|
||||
startingDate: Date,
|
||||
) {
|
||||
const asyncOpers: Promise<[]>[] = [];
|
||||
|
||||
@@ -39,6 +39,86 @@ export default class SaleInvoicesCost {
|
||||
return Promise.all([...asyncOpers]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules compute sale invoice items cost based on each item
|
||||
* cost method.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {ISaleInvoice} saleInvoiceId - Sale invoice id.
|
||||
* @param {boolean} override - Allow to override old computes in edit mode.
|
||||
* @return {Promise}
|
||||
*/
|
||||
async scheduleComputeCostByInvoiceId(
|
||||
tenantId: number,
|
||||
saleInvoiceId: number,
|
||||
) {
|
||||
const { SaleInvoice } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieve the sale invoice with associated entries.
|
||||
const saleInvoice: ISaleInvoice = await SaleInvoice.query()
|
||||
.findById(saleInvoiceId)
|
||||
.withGraphFetched('entries');
|
||||
|
||||
// Schedule compute inventory items cost by the given invoice model object.
|
||||
return this.scheduleComputeCostByEntries(
|
||||
tenantId,
|
||||
saleInvoice.entries,
|
||||
saleInvoice.invoiceDate,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the compute inventory items cost by the given bill id.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} billId - Bill id.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async scheduleComputeCostByBillId(
|
||||
tenantId: number,
|
||||
billId: number
|
||||
): Promise<void> {
|
||||
const { Bill } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieve the bill with associated entries.
|
||||
const bill = await Bill.query()
|
||||
.findById(billId)
|
||||
.withGraphFetched('entries');
|
||||
|
||||
return this.scheduleComputeCostByEntries(
|
||||
tenantId,
|
||||
bill.entries,
|
||||
bill.billDate,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the compute inventory items by the given invoice.
|
||||
* @param {number} tenantId
|
||||
* @param {ISaleInvoice & { entries: IItemEntry[] }} saleInvoice
|
||||
* @param {boolean} override
|
||||
*/
|
||||
async scheduleComputeCostByEntries(
|
||||
tenantId: number,
|
||||
entries: IItemEntry[],
|
||||
startingDate: Date,
|
||||
) {
|
||||
const { Item } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieve the inventory items that associated to the sale invoice entries.
|
||||
const inventoryItems = await Item.query()
|
||||
.whereIn('id', map(entries, 'itemId'))
|
||||
.where('type', 'inventory');
|
||||
|
||||
const inventoryItemsIds = map(inventoryItems, 'id');
|
||||
|
||||
if (inventoryItemsIds.length > 0) {
|
||||
await this.scheduleComputeCostByItemsIds(
|
||||
tenantId,
|
||||
inventoryItemsIds,
|
||||
startingDate
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule writing journal entries.
|
||||
* @param {Date} startingDate
|
||||
|
||||
Reference in New Issue
Block a user