fix: design flow of writing invoice journal entries.

This commit is contained in:
a.bouhuolia
2021-01-04 17:19:27 +02:00
parent 999e74b405
commit d5151c365e
15 changed files with 377 additions and 473 deletions

View File

@@ -1,10 +1,16 @@
import { Container, Service, Inject } from 'typedi';
import { pick } from 'lodash';
import config from 'config';
import {
EventDispatcher,
EventDispatcherInterface,
} from 'decorators/eventDispatcher';
import { IInventoryLotCost, IInventoryTransaction, IItem, IItemEntry } from 'interfaces'
import {
IInventoryLotCost,
IInventoryTransaction,
IItem,
IItemEntry,
} from 'interfaces';
import InventoryAverageCost from 'services/Inventory/InventoryAverageCost';
import InventoryCostLotTracker from 'services/Inventory/InventoryCostLotTracker';
import TenancyService from 'services/Tenancy/TenancyService';
@@ -27,9 +33,9 @@ export default class InventoryService {
itemEntries: IItemEntry[],
transactionType: string,
transactionId: number,
direction: 'IN'|'OUT',
date: Date|string,
lotNumber: number,
direction: 'IN' | 'OUT',
date: Date | string,
lotNumber: number
) {
return itemEntries.map((entry: IItemEntry) => ({
...pick(entry, ['itemId', 'quantity', 'rate']),
@@ -62,13 +68,21 @@ export default class InventoryService {
let costMethodComputer: IInventoryCostMethod;
// Switch between methods based on the item cost method.
switch('AVG') {
switch ('AVG') {
case 'FIFO':
case 'LIFO':
costMethodComputer = new InventoryCostLotTracker(tenantId, fromDate, itemId);
costMethodComputer = new InventoryCostLotTracker(
tenantId,
fromDate,
itemId
);
break;
case 'AVG':
costMethodComputer = new InventoryAverageCost(tenantId, fromDate, itemId);
costMethodComputer = new InventoryAverageCost(
tenantId,
fromDate,
itemId
);
break;
}
return costMethodComputer.computeItemCost();
@@ -77,20 +91,24 @@ export default class InventoryService {
/**
* Schedule item cost compute job.
* @param {number} tenantId
* @param {number} itemId
* @param {Date} startingDate
* @param {number} itemId
* @param {Date} startingDate
*/
async scheduleComputeItemCost(tenantId: number, itemId: number, startingDate: Date|string) {
async scheduleComputeItemCost(
tenantId: number,
itemId: number,
startingDate: Date | string
) {
const agenda = Container.get('agenda');
// Cancel any `compute-item-cost` in the queue has upper starting date
// Cancel any `compute-item-cost` in the queue has upper starting date
// with the same given item.
await agenda.cancel({
name: 'compute-item-cost',
nextRunAt: { $ne: null },
'data.tenantId': tenantId,
'data.itemId': itemId,
'data.startingDate': { "$gt": startingDate }
'data.startingDate': { $gt: startingDate },
});
// Retrieve any `compute-item-cost` in the queue has lower starting date
@@ -100,23 +118,29 @@ export default class InventoryService {
nextRunAt: { $ne: null },
'data.tenantId': tenantId,
'data.itemId': itemId,
'data.startingDate': { "$lte": startingDate }
'data.startingDate': { $lte: startingDate },
});
if (dependsJobs.length === 0) {
await agenda.schedule('in 30 seconds', 'compute-item-cost', {
startingDate, itemId, tenantId,
});
await agenda.schedule(
config.scheduleComputeItemCost,
'compute-item-cost',
{
startingDate,
itemId,
tenantId,
}
);
// Triggers `onComputeItemCostJobScheduled` event.
await this.eventDispatcher.dispatch(
events.inventory.onComputeItemCostJobScheduled,
{ startingDate, itemId, tenantId },
{ startingDate, itemId, tenantId }
);
}
}
/**
* Records the inventory transactions.
* Records the inventory transactions.
* @param {number} tenantId - Tenant id.
* @param {Bill} bill - Bill model object.
* @param {number} billId - Bill id.
@@ -125,27 +149,23 @@ export default class InventoryService {
async recordInventoryTransactions(
tenantId: number,
inventoryEntries: IInventoryTransaction[],
deleteOld: boolean,
deleteOld: boolean
): Promise<void> {
inventoryEntries.forEach(async (entry: IInventoryTransaction) => {
await this.recordInventoryTransaction(
tenantId,
entry,
deleteOld,
);
await this.recordInventoryTransaction(tenantId, entry, deleteOld);
});
}
/**
*
* @param {number} tenantId
* @param {IInventoryTransaction} inventoryEntry
* @param {boolean} deleteOld
*
* @param {number} tenantId
* @param {IInventoryTransaction} inventoryEntry
* @param {boolean} deleteOld
*/
async recordInventoryTransaction(
tenantId: number,
inventoryEntry: IInventoryTransaction,
deleteOld: boolean = false,
deleteOld: boolean = false
): Promise<IInventoryTransaction> {
const { InventoryTransaction, Item } = this.tenancy.models(tenantId);
@@ -153,7 +173,7 @@ export default class InventoryService {
await this.deleteInventoryTransactions(
tenantId,
inventoryEntry.transactionId,
inventoryEntry.transactionType,
inventoryEntry.transactionType
);
}
return InventoryTransaction.query().insert({
@@ -165,14 +185,14 @@ export default class InventoryService {
/**
* Deletes the given inventory transactions.
* @param {number} tenantId - Tenant id.
* @param {string} transactionType
* @param {number} transactionId
* @param {string} transactionType
* @param {number} transactionId
* @return {Promise}
*/
async deleteInventoryTransactions(
tenantId: number,
transactionId: number,
transactionType: string,
transactionType: string
): Promise<void> {
const { InventoryTransaction } = this.tenancy.models(tenantId);
@@ -184,16 +204,16 @@ export default class InventoryService {
/**
* Records the inventory cost lot transaction.
* @param {number} tenantId
* @param {IInventoryLotCost} inventoryLotEntry
* @param {number} tenantId
* @param {IInventoryLotCost} inventoryLotEntry
* @return {Promise<IInventoryLotCost>}
*/
async recordInventoryCostLotTransaction(
tenantId: number,
inventoryLotEntry: IInventoryLotCost,
inventoryLotEntry: IInventoryLotCost
): Promise<void> {
const { InventoryCostLotTracker } = this.tenancy.models(tenantId);
return InventoryCostLotTracker.query().insert({
...inventoryLotEntry,
});
@@ -209,13 +229,14 @@ export default class InventoryService {
const LOT_NUMBER_KEY = 'lot_number_increment';
const storedLotNumber = settings.find({ key: LOT_NUMBER_KEY });
return (storedLotNumber && storedLotNumber.value) ?
parseInt(storedLotNumber.value, 10) : 1;
return storedLotNumber && storedLotNumber.value
? parseInt(storedLotNumber.value, 10)
: 1;
}
/**
* Increment the next inventory LOT number.
* @param {number} tenantId
* @param {number} tenantId
* @return {Promise<number>}
*/
async incrementNextLotNumber(tenantId: number) {
@@ -236,4 +257,4 @@ export default class InventoryService {
return lotNumber;
}
}
}