mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 05:10:31 +00:00
149 lines
4.8 KiB
TypeScript
149 lines
4.8 KiB
TypeScript
import { InventoryTransaction, Item } from '@/models';
|
|
import InventoryCostLotTracker from './InventoryCostLotTracker';
|
|
import { IInventoryTransaction, IInventoryLotCost } from '@/interfaces/InventoryTransaction';
|
|
import { IInventoryLotCost, IInventoryLotCost } from '../../interfaces/InventoryTransaction';
|
|
import { pick } from 'lodash';
|
|
|
|
export default class InventoryService {
|
|
/**
|
|
* Records the inventory transactions.
|
|
* @param {Bill} bill
|
|
* @param {number} billId
|
|
*/
|
|
static async recordInventoryTransactions(
|
|
entries: [],
|
|
date: Date,
|
|
transactionType: string,
|
|
transactionId: number,
|
|
) {
|
|
const storedOpers: any = [];
|
|
const entriesItemsIds = entries.map((e: any) => e.item_id);
|
|
const inventoryItems = await Item.tenant()
|
|
.query()
|
|
.whereIn('id', entriesItemsIds)
|
|
.where('type', 'inventory');
|
|
|
|
const inventoryItemsIds = inventoryItems.map((i) => i.id);
|
|
|
|
// Filter the bill entries that have inventory items.
|
|
const inventoryEntries = entries.filter(
|
|
(entry) => inventoryItemsIds.indexOf(entry.item_id) !== -1
|
|
);
|
|
inventoryEntries.forEach((entry: any) => {
|
|
const oper = InventoryTransaction.tenant().query().insert({
|
|
date,
|
|
|
|
item_id: entry.item_id,
|
|
quantity: entry.quantity,
|
|
rate: entry.rate,
|
|
|
|
transaction_type: transactionType,
|
|
transaction_id: transactionId,
|
|
});
|
|
storedOpers.push(oper);
|
|
});
|
|
return Promise.all(storedOpers);
|
|
}
|
|
|
|
/**
|
|
* Deletes the given inventory transactions.
|
|
* @param {string} transactionType
|
|
* @param {number} transactionId
|
|
* @return {Promise}
|
|
*/
|
|
static deleteInventoryTransactions(
|
|
transactionId: number,
|
|
transactionType: string,
|
|
) {
|
|
return InventoryTransaction.tenant().query()
|
|
.where('transaction_type', transactionType)
|
|
.where('transaction_id', transactionId)
|
|
.delete();
|
|
}
|
|
|
|
revertInventoryLotsCost(fromDate?: Date) {
|
|
|
|
}
|
|
|
|
/**
|
|
* Records the journal entries transactions.
|
|
* @param {IInventoryLotCost[]} inventoryTransactions -
|
|
*
|
|
*/
|
|
static async recordJournalEntries(inventoryLots: IInventoryLotCost[]) {
|
|
|
|
}
|
|
|
|
/**
|
|
* Tracking the given inventory transactions to lots costs transactions.
|
|
* @param {IInventoryTransaction[]} inventoryTransactions - Inventory transactions.
|
|
* @return {IInventoryLotCost[]}
|
|
*/
|
|
static async trackingInventoryLotsCost(inventoryTransactions: IInventoryTransaction[]) {
|
|
// Collect cost lots transactions to insert them to the storage in bulk.
|
|
const costLotsTransactions: IInventoryLotCost[] = [];
|
|
|
|
// Collect inventory transactions by item id.
|
|
const inventoryByItem: any = {};
|
|
// Collection `IN` inventory tranaction by transaction id.
|
|
const inventoryINTrans: any = {};
|
|
|
|
inventoryTransactions.forEach((transaction: IInventoryTransaction) => {
|
|
const { itemId, id } = transaction;
|
|
(inventoryByItem[itemId] || (inventoryByItem[itemId] = []));
|
|
|
|
const commonLotTransaction: IInventoryLotCost = {
|
|
...pick(transaction, [
|
|
'date', 'rate', 'itemId', 'quantity',
|
|
'direction', 'transactionType', 'transactionId',
|
|
]),
|
|
};
|
|
// Record inventory `IN` cost lot transaction.
|
|
if (transaction.direction === 'IN') {
|
|
inventoryByItem[itemId].push(id);
|
|
inventoryINTrans[id] = {
|
|
...commonLotTransaction,
|
|
remaining: commonLotTransaction.quantity,
|
|
};
|
|
costLotsTransactions.push(inventoryINTrans[id]);
|
|
|
|
// Record inventory 'OUT' cost lots from 'IN' transactions.
|
|
} else if (transaction.direction === 'OUT') {
|
|
let invRemaining = transaction.quantity;
|
|
|
|
inventoryByItem?.[itemId]?.forEach((
|
|
_invTransactionId: number,
|
|
index: number,
|
|
) => {
|
|
const _invINTransaction = inventoryINTrans[_invTransactionId];
|
|
|
|
// Detarmines the 'OUT' lot tranasctions whether bigger than 'IN' remaining transaction.
|
|
const biggerThanRemaining = (_invINTransaction.remaining - transaction.quantity) > 0;
|
|
const decrement = (biggerThanRemaining) ? transaction.quantity : _invINTransaction.remaining;
|
|
|
|
_invINTransaction.remaining = Math.max(
|
|
_invINTransaction.remaining - decrement, 0,
|
|
);
|
|
invRemaining = Math.max(invRemaining - decrement, 0);
|
|
|
|
costLotsTransactions.push({
|
|
...commonLotTransaction,
|
|
quantity: decrement,
|
|
});
|
|
// Pop the 'IN' lots that has zero remaining.
|
|
if (_invINTransaction.remaining === 0) {
|
|
inventoryByItem?.[itemId].splice(index, 1);
|
|
}
|
|
});
|
|
if (invRemaining > 0) {
|
|
costLotsTransactions.push({
|
|
...commonLotTransaction,
|
|
quantity: invRemaining,
|
|
});
|
|
}
|
|
}
|
|
});
|
|
return costLotsTransactions;
|
|
}
|
|
|
|
} |