fix(reports/legacy): active clients only — exclude terminated + non-customer accounts
User flagged that several listed accounts are inactive (Or Viande Inc, Denis Henderson). Root cause: I filtered service.status=1 but NOT the account, so terminated accounts carrying an orphan active service line slipped through. The legacy billing job (LEGACY-ACCOUNTING-ANALYSIS.md §6.1) bills only when BOTH service.status=1 AND account.status=1. Three account-level filters added: - account.status = 1 → drops terminated accounts. Or Viande Inc is status=4, terminated 2014 (terminate_date set), but still had a service.status=1 row. 8602 accounts are status=4 vs 6537 status=1. - account.group_id = 5 → "Client" per account_group. Drops 6 Prospect, 7 Fournisseur, 8 Relais (network infra, e.g. Denis Henderson's REL_CHRY_CHARLES tower account), 10 Équipement motorisé. - customer_id NOT LIKE 'PROPRIO%' → 59 landowner-hosts-our-gear accounts that live in group 5 but aren't paying customers (Denis Henderson's other account PROPRIOH_STCHARLES). A genuine same-name customer (Robert Henderson, ROBEH...) correctly stays. Residential >90$/mo: 983 → 554 (was inflated ~44% by dead/non-customer accounts). Commercial: 255 → 240. Ops page note updated to state "comptes clients actifs uniquement" and list what's excluded. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b631fabf91
commit
8a9df4b85e
|
|
@ -7,11 +7,13 @@
|
||||||
<q-btn flat dense icon="download" label="CSV" :href="csvUrl" :disable="!rows.length" />
|
<q-btn flat dense icon="download" label="CSV" :href="csvUrl" :disable="!rows.length" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-caption text-grey-7 q-mb-md" style="max-width:780px">
|
<div class="text-caption text-grey-7 q-mb-md" style="max-width:820px">
|
||||||
Total mensuel net du service Internet (forfait + rabais récurrents, forfaits annuels
|
Total mensuel net du service Internet (forfait + rabais récurrents, forfaits annuels
|
||||||
ramenés au mois) par adresse de service, depuis la base legacy. Exclut TV, téléphonie
|
ramenés au mois) par adresse de service, depuis la base legacy.
|
||||||
et les frais ponctuels (équipement, installation). Sert à repérer les clients qui
|
<strong>Comptes clients actifs uniquement</strong> — exclut les comptes résiliés,
|
||||||
gagneraient à être déplacés vers un forfait mieux adapté.
|
prospects, relais/infrastructure et propriétaires-hébergeurs. Exclut aussi TV,
|
||||||
|
téléphonie, frais ponctuels (équipement, installation) et crédits promo expirés.
|
||||||
|
Sert à repérer les clients qui gagneraient à être déplacés vers un forfait mieux adapté.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Filters -->
|
<!-- Filters -->
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,24 @@
|
||||||
* → service (delivery_id, status=1) active service line
|
* → service (delivery_id, status=1) active service line
|
||||||
* → product (category, price) the plan; price<0 = recurring discount
|
* → product (category, price) the plan; price<0 = recurring discount
|
||||||
*
|
*
|
||||||
|
* Account-level filters (mirror the legacy recurring-billing logic in
|
||||||
|
* LEGACY-ACCOUNTING-ANALYSIS.md §6.1, which bills only when BOTH
|
||||||
|
* service.status=1 AND account.status=1):
|
||||||
|
* account.status = 1 → active account. status=4 is terminated
|
||||||
|
* (8602 accounts, most with a terminate_date,
|
||||||
|
* e.g. Or Viande Inc closed in 2014 but still
|
||||||
|
* carrying an orphan service.status=1 line).
|
||||||
|
* account.group_id = 5 → "Client" per the account_group table. Excludes
|
||||||
|
* 6 Prospect, 7 Fournisseur, 8 Relais (network
|
||||||
|
* infrastructure accounts like a tower-host),
|
||||||
|
* 10 Équipement motorisé — none are billable
|
||||||
|
* residential/commercial customers.
|
||||||
|
* customer_id NOT LIKE → 59 "PROPRIO*" accounts sit inside group 5 but
|
||||||
|
* 'PROPRIO%' are landowners hosting our relay/antenna gear
|
||||||
|
* under a special arrangement (e.g. Denis
|
||||||
|
* Henderson "PROPRIOH_STCHARLES"), not regular
|
||||||
|
* paying customers. Excluded by their id prefix.
|
||||||
|
*
|
||||||
* Effective monthly price of a service line:
|
* Effective monthly price of a service line:
|
||||||
* base = service.hijack=1 ? service.hijack_price : product.price
|
* base = service.hijack=1 ? service.hijack_price : product.price
|
||||||
* // product.price is ALREADY the monthly unit price regardless of the
|
* // product.price is ALREADY the monthly unit price regardless of the
|
||||||
|
|
@ -116,6 +134,9 @@ function buildQuery (url) {
|
||||||
JOIN service s ON s.delivery_id = d.id AND s.status = 1
|
JOIN service s ON s.delivery_id = d.id AND s.status = 1
|
||||||
JOIN product p ON p.id = s.product_id
|
JOIN product p ON p.id = s.product_id
|
||||||
WHERE p.category IN (${catPlaceholders})
|
WHERE p.category IN (${catPlaceholders})
|
||||||
|
AND a.status = 1
|
||||||
|
AND a.group_id = 5
|
||||||
|
AND a.customer_id NOT LIKE 'PROPRIO%'
|
||||||
AND p.price_recurr_type = 1
|
AND p.price_recurr_type = 1
|
||||||
AND NOT (p.price < 0 AND s.actif_until IS NOT NULL AND s.actif_until > 0 AND s.actif_until < UNIX_TIMESTAMP())
|
AND NOT (p.price < 0 AND s.actif_until IS NOT NULL AND s.actif_until > 0 AND s.actif_until < UNIX_TIMESTAMP())
|
||||||
${commercialClause}
|
${commercialClause}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user