Bug check fee sql

This commit is contained in:
2026-05-15 11:26:39 +02:00
parent 60f26ddc9d
commit b20c3d54a4
5 changed files with 36 additions and 9 deletions

View File

@@ -43,7 +43,9 @@ executer.
</li>
<li style="margin:0.38rem 0;">Regle de conservation: <code>sum(lots physiques) + lot virtuel = quantity_theorical</code>.
</li>
<li style="margin:0.38rem 0;">Regle du forecast ouvert: <code>sum(lot.qt non zero) = max(lot virtuel, 0)</code>.
<li style="margin:0.38rem 0;">Regle du forecast ouvert minimal: <code>sum(lot.qt non zero) &gt;= max(lot virtuel, 0)</code>.
</li>
<li style="margin:0.38rem 0;">Un surplus de forecast ouvert est accepte apres surconsommation physique: <code>lot.qt</code> s&#x27;arrete a zero, alors que le lot virtuel absorbe toute la quantite physique.
</li>
<li style="margin:0.38rem 0;">Les lignes <code>lot.qt</code> a zero sont ignorees par les checks: elles peuvent servir de memoire d&#x27;une prevision consommee.
</li>

View File

@@ -89,6 +89,11 @@ For every other fee, it recomputes the expected quantity from the effective
</li>
</ul>
The diagnostic is grouped by `fee_id`. Purchase and sale columns are displayed
only to help identify related contracts; they do not split the expected
quantity. This matters for purchase fees whose linked lots may also be matched
to several sale lines.
Run it on a restored test database:
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>\i modules/purchase_trade/docs/business/sql/fee_quantity_consistency_checks.sql</code></pre>

View File

@@ -4,6 +4,9 @@ Read-only diagnostic for fee quantity consistency.
Business rule:
For every fee except Per packing, fee.quantity must equal the sum of the
applicable net/gross quantities of its effective lots.
The diagnostic is grouped by fee_id. Purchase/sale references are only
displayed to help identify the contracts involved; they must not split the
expected quantity.
Effective lots:
- physical lots if at least one physical lot is linked to the fee;
@@ -149,10 +152,20 @@ computed_fees AS (
fee_id,
mode,
fee_quantity,
purchase_id,
purchase_number,
sale_id,
sale_number,
CASE
WHEN count(DISTINCT purchase_id) FILTER (WHERE purchase_id IS NOT NULL) = 1
THEN min(purchase_id)
ELSE NULL
END AS purchase_id,
string_agg(DISTINCT purchase_number, ', ')
FILTER (WHERE purchase_number IS NOT NULL) AS purchase_number,
CASE
WHEN count(DISTINCT sale_id) FILTER (WHERE sale_id IS NOT NULL) = 1
THEN min(sale_id)
ELSE NULL
END AS sale_id,
string_agg(DISTINCT sale_number, ', ')
FILTER (WHERE sale_number IS NOT NULL) AS sale_number,
bool_or(selected_qt_state IS NULL) AS has_missing_state,
bool_or(
lot_unit_category IS NULL
@@ -163,8 +176,7 @@ computed_fees AS (
round(sum(computed_quantity)::numeric, 5) AS expected_quantity
FROM computed_lot_quantities
GROUP BY
fee_id, mode, fee_quantity,
purchase_id, purchase_number, sale_id, sale_number
fee_id, mode, fee_quantity
)
SELECT
'fee_quantity_mismatch' AS check_name,

View File

@@ -36,8 +36,11 @@ executer.
existants et des `lot.qt` deja matches ou shippes.
- Regle de conservation:
`sum(lots physiques) + lot virtuel = quantity_theorical`.
- Regle du forecast ouvert:
`sum(lot.qt non zero) = max(lot virtuel, 0)`.
- Regle du forecast ouvert minimal:
`sum(lot.qt non zero) >= max(lot virtuel, 0)`.
- Un surplus de forecast ouvert est accepte apres surconsommation physique:
`lot.qt` s'arrete a zero, alors que le lot virtuel absorbe toute la quantite
physique.
- Les lignes `lot.qt` a zero sont ignorees par les checks: elles peuvent servir
de memoire d'une prevision consommee.
- Le check applicatif est centralise dans

View File

@@ -71,6 +71,11 @@ For every other fee, it recomputes the expected quantity from the effective
- `lot.qt.hist.quantity` for net fees and `lot.qt.hist.gross_quantity` for gross
fees.
The diagnostic is grouped by `fee_id`. Purchase and sale columns are displayed
only to help identify related contracts; they do not split the expected
quantity. This matters for purchase fees whose linked lots may also be matched
to several sale lines.
Run it on a restored test database:
```sql