stockmovement: add summary views
This commit is contained in:
@@ -919,25 +919,24 @@ class ReportManager
|
||||
function ($wh) use ($cid) {
|
||||
$table = $this->stockTableNameFromWarehouseId((int)$wh['id']);
|
||||
return "SELECT
|
||||
s.id,
|
||||
s.product_sku,
|
||||
s.lot_number,
|
||||
s.zone,
|
||||
s.aisle,
|
||||
s.rack,
|
||||
ROUND(s.`in`, 2) AS quantity,
|
||||
ROUND(SUM(s.`in`) - SUM(s.`out`), 2) AS quantity,
|
||||
{$wh['id']} AS warehouse_id
|
||||
FROM `{$table}` s
|
||||
WHERE s.company_id = {$cid}
|
||||
AND s.type = 'in'
|
||||
AND s.lot_number IS NOT NULL
|
||||
AND s.status = 1";
|
||||
AND s.status = 1
|
||||
GROUP BY s.product_sku, s.lot_number, s.zone, s.aisle, s.rack
|
||||
HAVING quantity > 0";
|
||||
},
|
||||
$warehouses
|
||||
));
|
||||
|
||||
$sql = "SELECT
|
||||
stock.id,
|
||||
stock.product_sku,
|
||||
stock.lot_number,
|
||||
stock.zone,
|
||||
@@ -982,7 +981,6 @@ class ReportManager
|
||||
else { continue; }
|
||||
|
||||
$items[] = [
|
||||
'id' => (int) $row['id'],
|
||||
'product_sku' => $row['product_sku'],
|
||||
'product_name' => $row['product_name'],
|
||||
'category_name' => $row['category_name'],
|
||||
@@ -1411,13 +1409,17 @@ class ReportManager
|
||||
$product_uom = $product_row['uom'] ?? '';
|
||||
|
||||
// All transactions for this SKU in range, sorted by date then id.
|
||||
// For stock-out rows, si.price is the purchase cost from the source stock-in (via ref_id).
|
||||
// p.cost_price is the product-level fallback when si.price is 0 or ref_id is absent.
|
||||
// Pricing rules per movement type:
|
||||
// PO in — s.price = actual purchase cost (user-defined on PO)
|
||||
// sales out — s.price = selling price; unit_cost from linked stock-in via ref_id
|
||||
// return in — price derived from linked SO stock-out via ref_id; no unit_cost needed
|
||||
// others — s.price = standard cost from md_product.cost_price
|
||||
$sth = $this->pdo->prepare(
|
||||
"SELECT
|
||||
s.id,
|
||||
s.date,
|
||||
s.type,
|
||||
s.source,
|
||||
s.product_sku,
|
||||
s.lot_number,
|
||||
s.serial_number,
|
||||
@@ -1426,14 +1428,19 @@ class ReportManager
|
||||
s.rack,
|
||||
ROUND(COALESCE(s.`in`, 0), 2) AS stock_in,
|
||||
ROUND(COALESCE(s.`out`, 0), 2) AS stock_out,
|
||||
ROUND(s.price, 4) AS price,
|
||||
CASE
|
||||
WHEN s.source = 'return' AND s.`in` > 0
|
||||
THEN ROUND(COALESCE(NULLIF(si.price, 0), s.price, 0), 4)
|
||||
ELSE
|
||||
ROUND(s.price, 4)
|
||||
END AS price,
|
||||
ROUND(COALESCE(NULLIF(si.price, 0), p.cost_price, 0), 4) AS unit_cost,
|
||||
c.contact_name,
|
||||
s.description
|
||||
FROM `{$table}` s
|
||||
LEFT JOIN `{$table}` si
|
||||
ON si.id = s.ref_id
|
||||
AND s.`out` > 0
|
||||
ON si.id = s.ref_id
|
||||
AND (s.`out` > 0 OR s.source = 'return')
|
||||
LEFT JOIN md_product p
|
||||
ON p.company_id = s.company_id
|
||||
AND p.sku = s.product_sku
|
||||
|
||||
@@ -313,7 +313,7 @@ class ReturnManager {
|
||||
|
||||
$stock_out_table = $this->stockTableNameFromWarehouseId($stock_out_wh);
|
||||
$stock_out_sth = $this->pdo->prepare(
|
||||
"SELECT status, lot_number, serial_number
|
||||
"SELECT status, lot_number, serial_number, price
|
||||
FROM `{$stock_out_table}`
|
||||
WHERE company_id = :company_id
|
||||
AND id = :id
|
||||
@@ -341,19 +341,21 @@ class ReturnManager {
|
||||
$quantity = (float)($item['quantity'] ?? 0);
|
||||
|
||||
// INSERT stock-in row — status=1 forced
|
||||
// price comes from the linked SO stock-out row (selling price), not the return form.
|
||||
// ref_id links back to the stock-out row so the report can trace the original sale.
|
||||
$this->pdo->prepare(
|
||||
"INSERT INTO `{$table}`
|
||||
(uuid, company_id, `date`, product_sku, `in`,
|
||||
zone, aisle, rack,
|
||||
contact_id, `description`, `log`, `type`,
|
||||
lot_number, serial_number,
|
||||
source, source_id, price, status)
|
||||
source, source_id, ref_id, price, status)
|
||||
VALUES
|
||||
(:uuid, :company_id, :date, :product_sku, :quantity,
|
||||
:zone, :aisle, :rack,
|
||||
:contact_id, :description, :log, 'in',
|
||||
:lot_number, :serial_number,
|
||||
'return', :source_id, :price, 1)"
|
||||
'return', :source_id, :ref_id, :price, 1)"
|
||||
)->execute([
|
||||
':uuid' => $item_uuid,
|
||||
':company_id' => $this->company_id,
|
||||
@@ -369,7 +371,8 @@ class ReturnManager {
|
||||
':lot_number' => $stock_out['lot_number'] ?? ($item['lot_number'] ?? ''),
|
||||
':serial_number' => $stock_out['serial_number'] ?? ($item['serial_number'] ?? ''),
|
||||
':source_id' => $return_id,
|
||||
':price' => (float)($item['price'] ?? 0),
|
||||
':ref_id' => $stock_out_id,
|
||||
':price' => (float)$stock_out['price'],
|
||||
]);
|
||||
|
||||
$stock_in_id = (int)$this->pdo->lastInsertId();
|
||||
|
||||
Reference in New Issue
Block a user