fix: Date format in sales/purchases APIs.

fix: Algorithm FIFO cost calculate method.
This commit is contained in:
Ahmed Bouhuolia
2020-08-19 00:13:53 +02:00
parent a202a21df5
commit 52d01b4ed8
21 changed files with 291 additions and 133 deletions

View File

@@ -1,9 +1,11 @@
import {
InventoryTransaction,
Item
Item,
Option,
} from '@/models';
import InventoryAverageCost from '@/services/Inventory/InventoryAverageCost';
import InventoryCostLotTracker from '@/services/Inventory/InventoryCostLotTracker';
import { option } from 'commander';
type TCostMethod = 'FIFO' | 'LIFO' | 'AVG';
@@ -38,10 +40,7 @@ export default class InventoryService {
*/
static async recordInventoryTransactions(
entries: [],
date: Date,
transactionType: string,
transactionId: number,
direction: string,
deleteOld: boolean,
) {
const storedOpers: any = [];
const entriesItemsIds = entries.map((e: any) => e.item_id);
@@ -56,19 +55,22 @@ export default class InventoryService {
const inventoryEntries = entries.filter(
(entry: any) => inventoryItemsIds.indexOf(entry.item_id) !== -1
);
inventoryEntries.forEach((entry: any) => {
inventoryEntries.forEach(async (entry: any) => {
if (deleteOld) {
await this.deleteInventoryTransactions(
entry.transactionId,
entry.transactionType,
);
}
const oper = InventoryTransaction.tenant().query().insert({
date,
direction,
item_id: entry.item_id,
quantity: entry.quantity,
rate: entry.rate,
transaction_type: transactionType,
transaction_id: transactionId,
...entry,
lotNumber: entry.lotNumber,
});
storedOpers.push(oper);
});
return Promise.all(storedOpers);
});
return Promise.all([
...storedOpers,
]);
}
/**
@@ -90,4 +92,24 @@ export default class InventoryService {
revertInventoryLotsCost(fromDate?: Date) {
}
/**
* Retrieve the lot number after the increment.
*/
static async nextLotNumber() {
const LOT_NUMBER_KEY = 'lot_number_increment';
const effectRows = await Option.tenant().query()
.where('key', LOT_NUMBER_KEY)
.increment('value', 1);
if (effectRows) {
await Option.tenant().query()
.insert({
key: LOT_NUMBER_KEY,
value: 1,
});
}
const options = await Option.tenant().query();
return options.getMeta(LOT_NUMBER_KEY, 1);
}
}

View File

@@ -1,5 +1,4 @@
import { omit, pick, chain } from 'lodash';
import uniqid from 'uniqid';
import {
InventoryTransaction,
InventoryLotCostTracker,
@@ -62,6 +61,7 @@ export default class InventoryCostLotTracker implements IInventoryCostMethod {
.query()
.where('date', '>=', this.startingDate)
.orderBy('date', 'ASC')
.orderBy('lot_number', 'ASC')
.where('item_id', this.itemId)
.withGraphFetched('item');
@@ -70,6 +70,7 @@ export default class InventoryCostLotTracker implements IInventoryCostMethod {
.query()
.where('date', '<', this.startingDate)
.orderBy('date', 'ASC')
.orderBy('lot_number', 'ASC')
.where('item_id', this.itemId)
.where('direction', 'IN')
.whereNot('remaining', 0);
@@ -267,17 +268,16 @@ export default class InventoryCostLotTracker implements IInventoryCostMethod {
...commonLotTransaction,
decrement: 0,
remaining: commonLotTransaction.remaining || commonLotTransaction.quantity,
lotNumber: commonLotTransaction.lotNumber || uniqid.time(),
};
costLotsTransactions.push(inventoryINTrans[id]);
// Record inventory 'OUT' cost lots from 'IN' transactions.
} else if (transaction.direction === 'OUT') {
let invRemaining = transaction.quantity;
const idsShouldDel: number[] = [];
inventoryByItem?.[itemId]?.some((
_invTransactionId: number,
index: number,
) => {
const _invINTransaction = inventoryINTrans[_invTransactionId];
if (invRemaining <= 0) { return true; }
@@ -285,22 +285,23 @@ export default class InventoryCostLotTracker implements IInventoryCostMethod {
// 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;
const maxDecrement = Math.min(decrement, invRemaining);
_invINTransaction.decrement += decrement;
_invINTransaction.decrement += maxDecrement;
_invINTransaction.remaining = Math.max(
_invINTransaction.remaining - decrement,
_invINTransaction.remaining - maxDecrement,
0,
);
invRemaining = Math.max(invRemaining - decrement, 0);
invRemaining = Math.max(invRemaining - maxDecrement, 0);
costLotsTransactions.push({
...commonLotTransaction,
quantity: decrement,
quantity: maxDecrement,
lotNumber: _invINTransaction.lotNumber,
});
// Pop the 'IN' lots that has zero remaining.
if (_invINTransaction.remaining === 0) {
inventoryByItem?.[itemId].splice(index, 1);
idsShouldDel.push(_invTransactionId);
}
return false;
});
@@ -310,6 +311,9 @@ export default class InventoryCostLotTracker implements IInventoryCostMethod {
quantity: invRemaining,
});
}
// Remove the IN transactions that has zero remaining amount.
inventoryByItem[itemId] = inventoryByItem?.[itemId]
?.filter((transId: number) => idsShouldDel.indexOf(transId) === -1);
}
});
return costLotsTransactions;