Files
bigcapital/packages/server-nest/src/modules/InventoryCost/commands/InventoryAverageCostMethod.ts
2025-03-11 22:12:08 +02:00

121 lines
3.7 KiB
TypeScript

import { pick } from 'lodash';
import { Knex } from 'knex';
import { InventoryTransaction } from '../models/InventoryTransaction';
export class InventoryAverageCostMethod {
/**
* Constructor method.
* @param {number} tenantId - The given tenant id.
* @param {Date} startingDate -
* @param {number} itemId - The given inventory item id.
*/
constructor() {}
/**
* Computes the cost of the given rate and quantity.
* @param {number} rate - The given rate.
* @param {number} quantity - The given quantity.
* @returns {number}
*/
private getCost(rate: number, quantity: number) {
return quantity ? rate * quantity : rate;
}
/**
* Records the journal entries from specific item inventory transactions.
* @param {IInventoryTransaction[]} invTransactions
* @param {number} openingAverageCost
* @param {string} referenceType
* @param {number} referenceId
* @param {JournalCommand} journalCommands
*/
public trackingCostTransactions(
invTransactions: InventoryTransaction[],
openingQuantity: number = 0,
openingCost: number = 0,
) {
const costTransactions: any[] = [];
// Cumulative item quantity and cost. This will decrement after
// each out transactions depends on its quantity and cost.
let accQuantity: number = openingQuantity;
let accCost: number = openingCost;
invTransactions.forEach((invTransaction: InventoryTransaction) => {
const commonEntry = {
invTransId: invTransaction.id,
...pick(invTransaction, [
'date',
'direction',
'itemId',
'quantity',
'rate',
'entryId',
'transactionId',
'transactionType',
'createdAt',
'costAccountId',
'branchId',
'warehouseId',
]),
inventoryTransactionId: invTransaction.id,
};
switch (invTransaction.direction) {
case 'IN':
const inCost = this.getCost(
invTransaction.rate,
invTransaction.quantity,
);
// Increases the quantity and cost in `IN` inventory transactions.
accQuantity += invTransaction.quantity;
accCost += inCost;
costTransactions.push({
...commonEntry,
cost: inCost,
});
break;
case 'OUT':
// Average cost = Total cost / Total quantity
const averageCost = accQuantity ? accCost / accQuantity : 0;
const quantity =
accQuantity > 0
? Math.min(invTransaction.quantity, accQuantity)
: invTransaction.quantity;
// Cost = the transaction quantity * Average cost.
const cost = this.getCost(averageCost, quantity);
// Revenue = transaction quanity * rate.
// const revenue = quantity * invTransaction.rate;
costTransactions.push({
...commonEntry,
quantity,
cost,
});
accQuantity = Math.max(accQuantity - quantity, 0);
accCost = Math.max(accCost - cost, 0);
if (invTransaction.quantity > quantity) {
const remainingQuantity = Math.max(
invTransaction.quantity - quantity,
0,
);
const remainingIncome = remainingQuantity * invTransaction.rate;
costTransactions.push({
...commonEntry,
quantity: remainingQuantity,
cost: 0,
});
accQuantity = Math.max(accQuantity - remainingQuantity, 0);
accCost = Math.max(accCost - remainingIncome, 0);
}
break;
}
});
return costTransactions;
}
}