fix: writing inventory transactions on invoice and bill created.

This commit is contained in:
a.bouhuolia
2020-12-19 19:48:38 +02:00
parent 5f8ecddd62
commit 1e8b00d8fe
7 changed files with 145 additions and 41 deletions

View File

@@ -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());

View File

@@ -9,6 +9,7 @@ export interface IInventoryTransaction {
rate: number,
transactionType: string,
transactionId: string,
lotNumber: string,
};
export interface IInventoryLotCost {

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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
) {

View File

@@ -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,
);
}
}

View File

@@ -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,
);
}
}