Les PDF et les saisies manuelles écrivent le même lot de plusieurs façons
("6", "06", "0006"), et chaque forme créait jusqu'ici un lot distinct en
base. utils/lots.py fixe la forme canonique sur 2 chiffres et sert de point
d'entrée unique pour la normalisation.
Elle est appliquée à la source dans les parseurs (locataires texte et
tableau, codes lot des opérations), et en dernier recours dans
get_or_create_lot et save_document, pour couvrir les extractions éditées à
la main via l'API. Les numéros à plus de 2 chiffres significatifs ne sont
pas tronqués.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
122 lines
3.7 KiB
Python
122 lines
3.7 KiB
Python
"""Tests de la normalisation des numéros de lot."""
|
|
|
|
import pytest
|
|
|
|
from plesna_gerance.parsers.operations import _extract_lot_code_from_description
|
|
from plesna_gerance.utils.lots import normalize_extraction_lots, normalize_lot_numero
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"raw,expected",
|
|
[
|
|
("0006", "06"),
|
|
("06", "06"),
|
|
("6", "06"),
|
|
(6, "06"),
|
|
("0020", "20"),
|
|
("20", "20"),
|
|
("Lot 6", "06"),
|
|
(" 7 ", "07"),
|
|
("0000", "00"),
|
|
("0", "00"),
|
|
# Plus de 2 chiffres significatifs : on ne tronque pas
|
|
("0123", "123"),
|
|
# Rien d'exploitable
|
|
(None, None),
|
|
("", None),
|
|
("abc", None),
|
|
],
|
|
)
|
|
def test_normalize_lot_numero(raw, expected):
|
|
assert normalize_lot_numero(raw) == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"description,expected",
|
|
[
|
|
("M06 - Commande moteur pompe", "06"),
|
|
("S05 - Mise en service", "05"),
|
|
("B01 - Plaques", "01"),
|
|
("S10 - Reparation", "10"),
|
|
("S 17 - Espace dans le code", "17"),
|
|
("S01 SOLDE LOCATAIRE", "01"),
|
|
("Nettoyage immeuble", None),
|
|
("", None),
|
|
],
|
|
)
|
|
def test_extract_lot_code_from_description(description, expected):
|
|
assert _extract_lot_code_from_description(description) == expected
|
|
|
|
|
|
def test_normalize_extraction_lots():
|
|
data = {
|
|
"situation_locataires": [
|
|
{"lot": {"numero": "0006", "type": "Appartement T3"}},
|
|
{"lot": {"numero": "7", "type": "Studio"}},
|
|
{"lot": {"numero": None, "type": "Garage"}},
|
|
],
|
|
"recapitulatif_operations": [
|
|
{"lot_numero": "0013"},
|
|
{"lot_numero": "1"},
|
|
{"lot_numero": None},
|
|
],
|
|
}
|
|
|
|
normalize_extraction_lots(data)
|
|
|
|
assert [s["lot"]["numero"] for s in data["situation_locataires"]] == [
|
|
"06",
|
|
"07",
|
|
None,
|
|
]
|
|
assert [o["lot_numero"] for o in data["recapitulatif_operations"]] == [
|
|
"13",
|
|
"01",
|
|
None,
|
|
]
|
|
|
|
|
|
def test_normalize_extraction_lots_tolerates_missing_sections():
|
|
# Une extraction partielle ne doit pas lever
|
|
assert normalize_extraction_lots({}) == {}
|
|
assert normalize_extraction_lots({"situation_locataires": None}) == {
|
|
"situation_locataires": None
|
|
}
|
|
|
|
|
|
def test_get_or_create_lot_deduplicates_formats(db_session):
|
|
""""0006", "06" et "6" désignent le même lot : un seul enregistrement."""
|
|
from plesna_gerance.database.models import Immeuble, Lot
|
|
from plesna_gerance.database.service import DatabaseService
|
|
|
|
service = DatabaseService(db_session)
|
|
immeuble = service.get_or_create_immeuble(code="IMM1")
|
|
|
|
lots = [
|
|
service.get_or_create_lot(immeuble_id=immeuble.id, numero=numero)
|
|
for numero in ("0006", "06", "6")
|
|
]
|
|
|
|
assert {lot.id for lot in lots} == {lots[0].id}
|
|
assert lots[0].numero == "06"
|
|
assert db_session.query(Lot).filter_by(immeuble_id=immeuble.id).count() == 1
|
|
assert db_session.query(Immeuble).count() == 1
|
|
|
|
|
|
def test_save_document_normalizes_lot_numero(db_session, sample_data):
|
|
from plesna_gerance.database.models import Lot
|
|
from plesna_gerance.database.service import DatabaseService
|
|
|
|
sample_data["situation_locataires"][0]["lot"]["numero"] = "0001"
|
|
sample_data["recapitulatif_operations"][0]["lot_numero"] = "1"
|
|
|
|
service = DatabaseService(db_session)
|
|
doc = service.save_document(data=sample_data)
|
|
|
|
# Le lot du locataire et celui de l'opération sont le même
|
|
assert db_session.query(Lot).count() == 1
|
|
assert db_session.query(Lot).first().numero == "01"
|
|
# Le JSON persisté est normalisé lui aussi
|
|
assert '"numero": "01"' in doc.json_data
|
|
assert '"lot_numero": "01"' in doc.json_data
|