fix(clients): retourner les vraies factures du client (TODO restant)
Le détail client servait `invoices: []` en hardcoded — la liste sur /clients/:id était toujours vide. On préload la relation client + plan sur les factures de l'org filtrées par client_id, on trie par priorité de statut puis échéance, et on serialize via InvoiceTransformer (même shape que GET /invoices, donc le SPA peut réutiliser InvoiceListItem). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
ec2232e4b3
commit
2c2724c634
@ -1,10 +1,22 @@
|
|||||||
import Client from '#models/client'
|
import Client from '#models/client'
|
||||||
|
import Invoice from '#models/invoice'
|
||||||
import ClientTransformer from '#transformers/client_transformer'
|
import ClientTransformer from '#transformers/client_transformer'
|
||||||
|
import InvoiceTransformer from '#transformers/invoice_transformer'
|
||||||
import { createClientValidator, updateClientValidator } from '#validators/client'
|
import { createClientValidator, updateClientValidator } from '#validators/client'
|
||||||
import { bulkComputeClientStats } from '#services/client_stats'
|
import { bulkComputeClientStats } from '#services/client_stats'
|
||||||
import type { HttpContext } from '@adonisjs/core/http'
|
import type { HttpContext } from '@adonisjs/core/http'
|
||||||
import { Exception } from '@adonisjs/core/exceptions'
|
import { Exception } from '@adonisjs/core/exceptions'
|
||||||
|
|
||||||
|
// Priorité d'affichage : ce qui est actionnable en haut.
|
||||||
|
const INVOICE_STATUS_PRIORITY: Record<string, number> = {
|
||||||
|
awaiting_user_confirmation: 0,
|
||||||
|
in_relance: 1,
|
||||||
|
pending: 2,
|
||||||
|
litigation: 3,
|
||||||
|
paid: 4,
|
||||||
|
cancelled: 5,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Petite cohérence d'identification orgnisation : si l'utilisateur
|
* Petite cohérence d'identification orgnisation : si l'utilisateur
|
||||||
* n'en a pas, on est dans un état illégal V1 — on bloque ferme.
|
* n'en a pas, on est dans un état illégal V1 — on bloque ferme.
|
||||||
@ -96,11 +108,27 @@ export default class ClientsController {
|
|||||||
const statsMap = await bulkComputeClientStats(organizationId, [client.id])
|
const statsMap = await bulkComputeClientStats(organizationId, [client.id])
|
||||||
const stats = statsMap.get(client.id)!
|
const stats = statsMap.get(client.id)!
|
||||||
|
|
||||||
|
// Factures du client — actionnables en premier, puis échéance asc.
|
||||||
|
const invoices = await Invoice.query()
|
||||||
|
.where('organization_id', organizationId)
|
||||||
|
.where('client_id', client.id)
|
||||||
|
.preload('client')
|
||||||
|
.preload('plan')
|
||||||
|
.exec()
|
||||||
|
|
||||||
|
invoices.sort((a, b) => {
|
||||||
|
const dp =
|
||||||
|
(INVOICE_STATUS_PRIORITY[a.status] ?? 99) -
|
||||||
|
(INVOICE_STATUS_PRIORITY[b.status] ?? 99)
|
||||||
|
if (dp !== 0) return dp
|
||||||
|
return a.dueDate.toMillis() - b.dueDate.toMillis()
|
||||||
|
})
|
||||||
|
|
||||||
return response.json({
|
return response.json({
|
||||||
data: {
|
data: {
|
||||||
...serializeClient(client),
|
...serializeClient(client),
|
||||||
...stats,
|
...stats,
|
||||||
invoices: [], // TODO: brancher quand le domaine Invoice arrive
|
invoices: invoices.map((inv) => new InvoiceTransformer(inv).toObject()),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user