mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
fix: writing inventory transactions on invoice and bill created.
This commit is contained in:
@@ -81,7 +81,6 @@ export default () => {
|
||||
dashboard.use(EnsureConfiguredMiddleware);
|
||||
dashboard.use(EnsureTenantIsSeeded);
|
||||
|
||||
|
||||
dashboard.use('/users', Container.get(Users).router());
|
||||
dashboard.use('/invite', Container.get(InviteUsers).authRouter());
|
||||
dashboard.use('/currencies', Container.get(Currencies).router());
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface IInventoryTransaction {
|
||||
rate: number,
|
||||
transactionType: string,
|
||||
transactionId: string,
|
||||
lotNumber: string,
|
||||
};
|
||||
|
||||
export interface IInventoryLotCost {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Container, Service, Inject } from 'typedi';
|
||||
import { IInventoryTransaction, IItem } from 'interfaces'
|
||||
import InventoryAverageCost from 'services/Inventory/InventoryAverageCost';
|
||||
import InventoryCostLotTracker from 'services/Inventory/InventoryCostLotTracker';
|
||||
import TenancyService from 'services/Tenancy/TenancyService';
|
||||
@@ -60,27 +61,30 @@ export default class InventoryService {
|
||||
|
||||
/**
|
||||
* Records the inventory transactions.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {Bill} bill
|
||||
* @param {number} billId
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {Bill} bill - Bill model object.
|
||||
* @param {number} billId - Bill id.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async recordInventoryTransactions(
|
||||
tenantId: number,
|
||||
entries: [],
|
||||
entries: IInventoryTransaction[],
|
||||
deleteOld: boolean,
|
||||
) {
|
||||
): Promise<void> {
|
||||
const { InventoryTransaction, Item } = this.tenancy.models(tenantId);
|
||||
|
||||
const entriesItemsIds = entries.map((e: any) => e.item_id);
|
||||
// Mapping the inventory entries items ids.
|
||||
const entriesItemsIds = entries.map((e: any) => e.itemId);
|
||||
const inventoryItems = await Item.query()
|
||||
.whereIn('id', entriesItemsIds)
|
||||
.where('type', 'inventory');
|
||||
|
||||
const inventoryItemsIds = inventoryItems.map((i: any) => i.id);
|
||||
// Mapping the inventory items ids.
|
||||
const inventoryItemsIds = inventoryItems.map((i: IItem) => i.id);
|
||||
|
||||
// Filter the bill entries that have inventory items.
|
||||
const inventoryEntries = entries.filter(
|
||||
(entry: any) => inventoryItemsIds.indexOf(entry.item_id) !== -1
|
||||
(entry: IInventoryTransaction) => inventoryItemsIds.indexOf(entry.itemId) !== -1
|
||||
);
|
||||
inventoryEntries.forEach(async (entry: any) => {
|
||||
if (deleteOld) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
IPaginationMeta,
|
||||
IFilterMeta,
|
||||
IBillsFilter,
|
||||
IItemEntry,
|
||||
} from 'interfaces';
|
||||
import { ServiceError } from 'exceptions';
|
||||
import ItemsService from 'services/Items/ItemsService';
|
||||
@@ -221,7 +222,6 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
authorizedUser,
|
||||
null
|
||||
);
|
||||
|
||||
// Retrieve vendor or throw not found service error.
|
||||
await this.getVendorOrThrowError(tenantId, billDTO.vendorId);
|
||||
|
||||
@@ -372,29 +372,42 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
* @param {Bill} bill
|
||||
* @param {number} billId
|
||||
*/
|
||||
public recordInventoryTransactions(
|
||||
public async recordInventoryTransactions(
|
||||
tenantId: number,
|
||||
bill: any,
|
||||
billId: number,
|
||||
bill: IBill,
|
||||
override?: boolean
|
||||
) {
|
||||
const inventoryTransactions = bill.entries.map((entry) => ({
|
||||
...pick(entry, ['item_id', 'quantity', 'rate']),
|
||||
): Promise<void> {
|
||||
const invTransactions = bill.entries.map((entry: IItemEntry) => ({
|
||||
...pick(entry, ['itemId', 'quantity', 'rate']),
|
||||
lotNumber: bill.invLotNumber,
|
||||
transactionType: 'Bill',
|
||||
transactionId: billId,
|
||||
transactionId: bill.id,
|
||||
direction: 'IN',
|
||||
date: bill.bill_date,
|
||||
date: bill.billDate,
|
||||
entryId: entry.id,
|
||||
}));
|
||||
|
||||
return this.inventoryService.recordInventoryTransactions(
|
||||
await this.inventoryService.recordInventoryTransactions(
|
||||
tenantId,
|
||||
inventoryTransactions,
|
||||
invTransactions,
|
||||
override
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts the inventory transactions of the given bill id.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} billId - Bill id.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async revertInventoryTransactions(tenantId: number, billId: number) {
|
||||
await this.inventoryService.deleteInventoryTransactions(
|
||||
tenantId,
|
||||
billId,
|
||||
'Bill',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the bill journal transactions.
|
||||
* @async
|
||||
@@ -437,7 +450,6 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
Bill,
|
||||
billsFilter
|
||||
);
|
||||
|
||||
this.logger.info('[bills] trying to get bills data table.', {
|
||||
tenantId,
|
||||
billsFilter,
|
||||
|
||||
@@ -7,13 +7,13 @@ import {
|
||||
} from 'decorators/eventDispatcher';
|
||||
import {
|
||||
ISaleInvoice,
|
||||
ISaleInvoiceDTO,
|
||||
IItemEntry,
|
||||
ISaleInvoiceCreateDTO,
|
||||
ISaleInvoiceEditDTO,
|
||||
IInventoryTransaction,
|
||||
ISalesInvoicesFilter,
|
||||
IPaginationMeta,
|
||||
IFilterMeta,
|
||||
ISaleInvoiceCreateDTO,
|
||||
ISaleInvoiceEditDTO,
|
||||
} from 'interfaces';
|
||||
import events from 'subscribers/events';
|
||||
import JournalPoster from 'services/Accounting/JournalPoster';
|
||||
@@ -351,48 +351,68 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
.where('reference_type', 'SaleInvoice')
|
||||
.delete();
|
||||
|
||||
// Triggers `onSaleInvoiceDeleted` event.
|
||||
await this.eventDispatcher.dispatch(events.saleInvoice.onDeleted, {
|
||||
tenantId,
|
||||
oldSaleInvoice,
|
||||
saleInvoiceId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the inventory transactions from the givne sale invoice input.
|
||||
* @param {SaleInvoice} saleInvoice -
|
||||
* @param {number} saleInvoiceId -
|
||||
* @param {boolean} override -
|
||||
* @parma {number} tenantId - Tenant id.
|
||||
* @param {SaleInvoice} saleInvoice - Sale invoice DTO.
|
||||
* @param {number} saleInvoiceId - Sale invoice id.
|
||||
* @param {boolean} override - Allow to override old transactions.
|
||||
*/
|
||||
private recordInventoryTranscactions(
|
||||
public recordInventoryTranscactions(
|
||||
tenantId: number,
|
||||
saleInvoice,
|
||||
saleInvoiceId: number,
|
||||
saleInvoice: ISaleInvoice,
|
||||
override?: boolean
|
||||
) {
|
||||
this.logger.info('[sale_invoice] saving inventory transactions');
|
||||
const inventortyTransactions = saleInvoice.entries.map((entry) => ({
|
||||
...pick(entry, ['item_id', 'quantity', 'rate']),
|
||||
lotNumber: saleInvoice.invLotNumber,
|
||||
transactionType: 'SaleInvoice',
|
||||
transactionId: saleInvoiceId,
|
||||
direction: 'OUT',
|
||||
date: saleInvoice.invoice_date,
|
||||
entryId: entry.id,
|
||||
}));
|
||||
const invTransactions: IInventoryTransaction[] = saleInvoice.entries.map(
|
||||
(entry: IItemEntry) => ({
|
||||
...pick(entry, ['itemId', 'quantity', 'rate']),
|
||||
lotNumber: 1,
|
||||
transactionType: 'SaleInvoice',
|
||||
transactionId: saleInvoice.id,
|
||||
direction: 'OUT',
|
||||
date: saleInvoice.invoiceDate,
|
||||
entryId: entry.id,
|
||||
})
|
||||
);
|
||||
|
||||
return this.inventoryService.recordInventoryTransactions(
|
||||
tenantId,
|
||||
inventortyTransactions,
|
||||
invTransactions,
|
||||
override
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverting the inventory transactions once the invoice deleted.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} billId - Bill id.
|
||||
*/
|
||||
public revertInventoryTransactions(
|
||||
tenantId: number,
|
||||
billId: number
|
||||
): Promise<void> {
|
||||
return this.inventoryService.deleteInventoryTransactions(
|
||||
tenantId,
|
||||
billId,
|
||||
'SaleInvoice'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the inventory transactions.
|
||||
* @param {string} transactionType
|
||||
* @param {number} transactionId
|
||||
*/
|
||||
private async revertInventoryTransactions(
|
||||
private async revertInventoryTransactions_(
|
||||
tenantId: number,
|
||||
inventoryTransactions: array
|
||||
) {
|
||||
|
||||
@@ -108,4 +108,41 @@ export default class BillSubscriber {
|
||||
oldBill.vendorId
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles writing the inventory transactions once bill created.
|
||||
*/
|
||||
@On(events.bill.onCreated)
|
||||
async handleWritingInventoryTransactions({ tenantId, bill }) {
|
||||
this.logger.info('[bill] writing the inventory transactions', { tenantId });
|
||||
this.billsService.recordInventoryTransactions(
|
||||
tenantId,
|
||||
bill,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the overwriting the inventory transactions once bill edited.
|
||||
*/
|
||||
@On(events.bill.onEdited)
|
||||
async handleOverwritingInventoryTransactions({ tenantId, bill }) {
|
||||
this.logger.info('[bill] overwriting the inventory transactions.', { tenantId });
|
||||
this.billsService.recordInventoryTransactions(
|
||||
tenantId,
|
||||
bill,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the reverting the inventory transactions once the bill deleted.
|
||||
*/
|
||||
@On(events.bill.onDeleted)
|
||||
async handleRevertInventoryTransactions({ tenantId, billId }) {
|
||||
this.logger.info('[bill] reverting the bill inventory transactions', { tenantId, billId });
|
||||
this.billsService.revertInventoryTransactions(
|
||||
tenantId,
|
||||
billId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import events from 'subscribers/events';
|
||||
import TenancyService from 'services/Tenancy/TenancyService';
|
||||
import SettingsService from 'services/Settings/SettingsService';
|
||||
import SaleEstimateService from 'services/Sales/SalesEstimate';
|
||||
import SaleInvoicesService from 'services/Sales/SalesInvoices';
|
||||
|
||||
@EventSubscriber()
|
||||
export default class SaleInvoiceSubscriber {
|
||||
@@ -11,12 +12,14 @@ export default class SaleInvoiceSubscriber {
|
||||
tenancy: TenancyService;
|
||||
settingsService: SettingsService;
|
||||
saleEstimatesService: SaleEstimateService;
|
||||
saleInvoicesService: SaleInvoicesService;
|
||||
|
||||
constructor() {
|
||||
this.logger = Container.get('logger');
|
||||
this.tenancy = Container.get(TenancyService);
|
||||
this.settingsService = Container.get(SettingsService);
|
||||
this.saleEstimatesService = Container.get(SaleEstimateService);
|
||||
this.saleInvoicesService = Container.get(SaleInvoicesService);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,4 +117,32 @@ export default class SaleInvoiceSubscriber {
|
||||
group: 'sales_invoices',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the writing inventory transactions once the invoice created.
|
||||
*/
|
||||
@On(events.saleInvoice.onCreated)
|
||||
public async handleWritingInventoryTransactions({ tenantId, saleInvoice }) {
|
||||
this.logger.info('[sale_invoice] trying to write inventory transactions.', {
|
||||
tenantId,
|
||||
});
|
||||
await this.saleInvoicesService.recordInventoryTranscactions(
|
||||
tenantId,
|
||||
saleInvoice,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles deleting the inventory transactions once the invoice deleted.
|
||||
*/
|
||||
@On(events.saleInvoice.onDeleted)
|
||||
public async handleDeletingInventoryTransactions({ tenantId, saleInvoiceId }) {
|
||||
this.logger.info('[sale_invoice] trying to revert inventory transactions.', {
|
||||
tenantId, saleInvoiceId,
|
||||
});
|
||||
await this.saleInvoicesService.revertInventoryTransactions(
|
||||
tenantId,
|
||||
saleInvoiceId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user