feat: décrit les logements dans un référentiel saisi à la main

Les lots n'étaient connus que par l'extraction PDF : un numéro, un type
souvent vide, et rien sur le bien lui-même. Cette table de caractéristiques
(surface, étage, bâtiment, chauffage, DPE, rapprochement impôts) donne au
référentiel une source de vérité indépendante des comptes rendus.

Table séparée de `lots` à dessein : une ré-extraction ne peut alors pas
écraser la saisie, et le désaccord sur le type de lot reste visible au lieu
d'être arbitré en silence. La fiche gagne, le PDF comble les trous.

Échéance du DPE et écart de surface ne sont pas stockés mais calculés : une
colonne dérivée finirait par mentir après une correction.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 18:00:42 +02:00
parent ac63922896
commit 5a08b0c7e5
13 changed files with 720 additions and 31 deletions

View File

@@ -9,6 +9,7 @@ from sqlalchemy.orm import Session
from ...database import get_session
from ...database.models import Depense, Document, Immeuble, Lot, Tag
from ...services.referentiel import TYPE_LOT_EFFECTIF, joindre_fiche
from ..schemas.models import (
CategorySummary,
DepenseDetail,
@@ -77,11 +78,15 @@ async def list_lots(
- **immeuble_id**: ID de l'immeuble pour filtrer (optionnel)
"""
stmt = (
select(Lot, Immeuble.code.label("immeuble_code"))
.join(Immeuble, Lot.immeuble_id == Immeuble.id)
.order_by(Immeuble.code, Lot.numero)
)
stmt = joindre_fiche(
select(
Lot.id,
Lot.numero,
Lot.immeuble_id,
TYPE_LOT_EFFECTIF.label("type"),
Immeuble.code.label("immeuble_code"),
).join(Immeuble, Lot.immeuble_id == Immeuble.id)
).order_by(Immeuble.code, Lot.numero)
if immeuble_id is not None:
stmt = stmt.where(Lot.immeuble_id == immeuble_id)
@@ -91,10 +96,10 @@ async def list_lots(
return [
LotResponse(
id=row.Lot.id,
numero=row.Lot.numero,
type=row.Lot.type,
immeuble_id=row.Lot.immeuble_id,
id=row.id,
numero=row.numero,
type=row.type,
immeuble_id=row.immeuble_id,
immeuble_code=row.immeuble_code,
)
for row in rows