-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bug(Stock Value report crashes server with too much data) #4556
Changes from all commits
1bf9347
0f656cb
a4c475b
a118113
299cb15
e87b689
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,6 @@ function stockValue(req, res, next) { | |
} | ||
|
||
async function reporting(_options, session) { | ||
|
||
const data = {}; | ||
const enterpriseId = session.enterprise.id; | ||
|
||
|
@@ -30,21 +29,87 @@ async function reporting(_options, session) { | |
|
||
const report = new ReportManager(STOCK_VALUE_REPORT_TEMPLATE, session, optionReport); | ||
|
||
|
||
const options = (typeof (_options.params) === 'string') ? JSON.parse(_options.params) : _options.params; | ||
data.dateTo = options.dateTo; | ||
data.depot = await db.one('SELECT * FROM depot WHERE uuid=?', [db.bid(options.depot_uuid)]); | ||
const stockValues = await db.exec('CALL stockValue(?,?,?);', [ | ||
db.bid(options.depot_uuid), options.dateTo, options.currency_id, | ||
]); | ||
|
||
// Get inventories movemented | ||
const sqlGetInventories = ` | ||
SELECT DISTINCT(BUID(mov.inventory_uuid)) AS inventory_uuid, mov.text AS inventory_name | ||
FROM( | ||
SELECT inv.uuid AS inventory_uuid, inv.text, sm.date | ||
FROM stock_movement AS sm | ||
JOIN lot AS l ON l.uuid = sm.lot_uuid | ||
JOIN inventory AS inv ON inv.uuid = l.inventory_uuid | ||
WHERE sm.depot_uuid = ? AND DATE(sm.date) <= DATE(?) | ||
) AS mov | ||
ORDER BY mov.text ASC; | ||
`; | ||
|
||
/* | ||
* Here we first search for all the products that have | ||
* been stored in stock in a warehouse, | ||
* then we collect all the movements of stocks linked to a warehouse, | ||
* then we calculate the unit cost weighted average for each product | ||
*/ | ||
const stockValues = await db.exec(sqlGetInventories, [db.bid(options.depot_uuid), options.dateTo]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sp, if I am understanding this correctly, this code will generate ... I'm not sure how optimal this is in low-end hardware like a Raspberry Pi. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the way I understood the logic of the stock value report came down to retrieving the last line of the stock card report, my idea was to launch several requests on the stock movement table in order to calculate for each unit cost weight and the stock value after each transaction There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had given up on the idea of using an aggregation table because of the risk of having backdated stock movements |
||
|
||
const sqlGetMovementByDepot = ` | ||
SELECT sm.document_uuid, sm.depot_uuid, sm.lot_uuid, sm.quantity, sm.unit_cost, sm.date, sm.is_exit, | ||
sm.created_at, BUID(inv.uuid) AS inventory_uuid, inv.text AS inventory_text, map.text AS docRef | ||
FROM stock_movement AS sm | ||
JOIN lot AS l ON l.uuid = sm.lot_uuid | ||
JOIN inventory AS inv ON inv.uuid = l.inventory_uuid | ||
JOIN document_map AS map ON map.uuid = sm.document_uuid | ||
WHERE sm.depot_uuid = ? AND DATE(sm.date) <= DATE(?) | ||
ORDER BY inv.text, DATE(sm.date), sm.created_at ASC | ||
`; | ||
|
||
const allMovements = await db.exec(sqlGetMovementByDepot, [db.bid(options.depot_uuid), options.dateTo]); | ||
|
||
stockValues.forEach(stock => { | ||
stock.movements = allMovements.filter(movement => (movement.inventory_uuid === stock.inventory_uuid)); | ||
}); | ||
|
||
let stockTotal = 0; | ||
const exchangeRate = await Exchange.getExchangeRate(enterpriseId, options.currency_id, new Date()); | ||
const rate = exchangeRate.rate || 1; | ||
|
||
stockValues.forEach(stock => { | ||
let quantityInStock = 0; | ||
let weightedAverageUnitCost = 0; | ||
|
||
stock.movements.forEach(item => { | ||
const isExit = item.is_exit ? (-1) : 1; | ||
|
||
if (!item.is_exit && (quantityInStock > 0)) { | ||
weightedAverageUnitCost = ((quantityInStock * weightedAverageUnitCost) + (item.quantity * item.unit_cost)) | ||
/ (item.quantity + quantityInStock); | ||
} else if (!item.is_exit && (quantityInStock === 0)) { | ||
weightedAverageUnitCost = item.unit_cost; | ||
} | ||
|
||
quantityInStock += (item.quantity * isExit); | ||
item.quantityInStock = quantityInStock; | ||
item.weightedAverageUnitCost = weightedAverageUnitCost; | ||
}); | ||
|
||
stock.stockQtt = quantityInStock; | ||
stock.stockUnitCost = weightedAverageUnitCost * rate; | ||
stock.stockValue = (quantityInStock * weightedAverageUnitCost) * rate; | ||
stockTotal += (stock.stockValue * rate); | ||
}); | ||
|
||
const stockValueElements = options.exclude_zero_value | ||
? stockValues[0].filter(item => item.stockValue > 0) : stockValues[0]; | ||
? stockValues.filter(item => item.stockValue > 0) : stockValues; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there anyway we can apply this filter higher in logic? Preferably in the SQL. It would probably improve performance. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it will be difficult seeing that the products we see the stock shortage of a product after on the last line, after having noted all the entries and exits from Stock |
||
|
||
|
||
data.stockValues = stockValueElements || []; | ||
const stokTolal = stockValues[1][0] || {}; | ||
data.stocktotal = stokTolal.total; | ||
|
||
data.stocktotal = stockTotal; | ||
data.emptyResult = data.stockValues.length === 0; | ||
data.rate = Exchange.getExchangeRate(enterpriseId, options.currency_id, new Date()); | ||
|
||
data.currency_id = options.currency_id; | ||
return report.render(data); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are not longer using the
stockValue()
procedure, let's remove it from the stored procedures.