feat: donne aux immeubles un nom d'usage
Les comptes rendus n'identifient un immeuble que par son code de gestion (« 33689020 »), illisible partout où il s'affiche. La dénomination (« Servient ») le remplace à l'écran sans toucher au code, qui reste la clé venue des PDF. La colonne s'ajoute à une table déjà installée : elle passe donc par le rattrapage de schéma, qui accepte désormais l'absence de valeur de rattrapage. Déduire un nom d'usage du code en inventerait un. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,7 @@ async def list_immeubles(
|
||||
ImmeubleResponse(
|
||||
id=row.Immeuble.id,
|
||||
code=row.Immeuble.code,
|
||||
denomination=row.Immeuble.denomination,
|
||||
adresse=row.Immeuble.adresse,
|
||||
ville=row.Immeuble.ville,
|
||||
code_postal=row.Immeuble.code_postal,
|
||||
|
||||
@@ -6,6 +6,7 @@ from .models import (
|
||||
DepenseDetail,
|
||||
DepensesSummary,
|
||||
DocumentSummary,
|
||||
ImmeubleBody,
|
||||
ImmeubleResponse,
|
||||
LotReferentielResponse,
|
||||
LotResponse,
|
||||
@@ -21,6 +22,7 @@ __all__ = [
|
||||
"DocumentSummary",
|
||||
"DepenseDetail",
|
||||
"DepensesSummary",
|
||||
"ImmeubleBody",
|
||||
"ImmeubleResponse",
|
||||
"LotResponse",
|
||||
"CaracteristiquesBody",
|
||||
|
||||
@@ -72,6 +72,7 @@ class ImmeubleResponse(BaseModel):
|
||||
|
||||
id: int
|
||||
code: str
|
||||
denomination: str | None = None
|
||||
adresse: str | None
|
||||
ville: str | None
|
||||
code_postal: str | None
|
||||
@@ -189,6 +190,20 @@ class DepensesSummary(BaseModel):
|
||||
# ============================================================
|
||||
|
||||
|
||||
class ImmeubleBody(BaseModel):
|
||||
"""Ce qui se saisit sur un immeuble : son nom d'usage."""
|
||||
|
||||
denomination: str | None = None
|
||||
|
||||
@field_validator("denomination")
|
||||
@classmethod
|
||||
def _texte_vide_vaut_absent(cls, value: str | None) -> str | None:
|
||||
"""Effacer le nom doit rendre l'immeuble à son code, pas le nommer « »."""
|
||||
if value is None:
|
||||
return None
|
||||
return value.strip() or None
|
||||
|
||||
|
||||
class CaracteristiquesBody(BaseModel):
|
||||
"""Caractéristiques d'un logement telles que saisies.
|
||||
|
||||
@@ -248,6 +263,8 @@ class LotReferentielResponse(BaseModel):
|
||||
numero: str
|
||||
immeuble_id: int
|
||||
immeuble_code: str | None
|
||||
#: Nom d'usage de l'immeuble ; le tableau retombe sur le code s'il manque.
|
||||
immeuble_denomination: str | None = None
|
||||
|
||||
#: Type de lot vu par l'extraction PDF, conservé tel quel.
|
||||
type_extrait: str | None
|
||||
|
||||
@@ -96,14 +96,19 @@ def init_db(db_path: Path | None = None) -> Path:
|
||||
|
||||
|
||||
#: Colonnes ajoutees apres coup, par table : nom -> (definition SQL, valeur de
|
||||
#: rattrapage pour les lignes existantes). `create_all` ne modifie pas une table
|
||||
#: deja presente, et le projet n'utilise pas d'outil de migration : sans ce
|
||||
#: rattrapage, une base installee cesserait de fonctionner apres mise a jour.
|
||||
#: rattrapage pour les lignes existantes, ou None quand il n'y a rien de vrai a
|
||||
#: y mettre). `create_all` ne modifie pas une table deja presente, et le projet
|
||||
#: n'utilise pas d'outil de migration : sans ce rattrapage, une base installee
|
||||
#: cesserait de fonctionner apres mise a jour.
|
||||
_ADDED_COLUMNS = {
|
||||
"documents": {
|
||||
# Les documents deja en base ont ete extraits lors de leur import.
|
||||
"extracted_at": ("DATETIME", "created_at"),
|
||||
},
|
||||
"immeubles": {
|
||||
# Le nom d'usage se saisit : le deduire du code inventerait un nom.
|
||||
"denomination": ("VARCHAR(100)", None),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -119,8 +124,11 @@ def _apply_schema_updates(engine):
|
||||
for name, (definition, backfill) in columns.items():
|
||||
if name in existing:
|
||||
continue
|
||||
conn.execute(text(f"ALTER TABLE {table} ADD COLUMN {name} {definition}"))
|
||||
conn.execute(text(f"UPDATE {table} SET {name} = {backfill}"))
|
||||
conn.execute(
|
||||
text(f"ALTER TABLE {table} ADD COLUMN {name} {definition}")
|
||||
)
|
||||
if backfill is not None:
|
||||
conn.execute(text(f"UPDATE {table} SET {name} = {backfill}"))
|
||||
|
||||
|
||||
def _seed_tags_if_empty(engine):
|
||||
|
||||
@@ -65,6 +65,9 @@ class Immeuble(Base):
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
code = Column(String(20), unique=True, nullable=False, index=True)
|
||||
#: Nom d'usage ("Servient"), saisi : les PDF ne donnent qu'un code de
|
||||
#: gestion, illisible partout où l'immeuble est cité.
|
||||
denomination = Column(String(100), nullable=True)
|
||||
adresse = Column(String(255), nullable=True)
|
||||
ville = Column(String(100), nullable=True)
|
||||
code_postal = Column(String(10), nullable=True)
|
||||
|
||||
Reference in New Issue
Block a user