🔴 Critical from review-bot: column units_count doesn't exist в ekburg_construction_permits (mock tests прошли т.к. db.execute мокается; на проде psycopg.errors.UndefinedColumn для каждого /analyze). Removes (7 refs): - SQL SELECT не выбирает units_count - dict build, PermitsSummary.rve_total_units - RecentPermit.units_count Pydantic field - PermitsSummary.rve_total_units field - 2 fixture rows assertions 🟡 Dedupe _quarter_prefix → reuse existing _quarter_cad (computed ранее для market_price block). Tests adjusted, ruff clean.
This commit is contained in:
parent
7eb686bd7d
commit
3abaf047a9
3 changed files with 6 additions and 15 deletions
|
|
@ -1853,13 +1853,11 @@ def analyze_parcel(
|
|||
# Spatial filter через geom недоступен до Phase 3 (geocoding → geom).
|
||||
# Используем quarter prefix (первые 3 сегмента кад. номера) как прокси.
|
||||
# После Phase 3: заменить на ST_DWithin(..., 500) по geom.
|
||||
_quarter_prefix = ":".join(_cad_parts[:3]) if len(_cad_parts) >= 3 else cad_num
|
||||
recent_permits: list[dict[str, Any]] = []
|
||||
permits_summary: dict[str, Any] = {
|
||||
"rns_count": 0,
|
||||
"rve_count": 0,
|
||||
"rns_total_area_sqm": 0.0,
|
||||
"rve_total_units": 0,
|
||||
"by_developer": [],
|
||||
}
|
||||
try:
|
||||
|
|
@ -1870,14 +1868,14 @@ def analyze_parcel(
|
|||
SELECT
|
||||
permit_type, permit_number, issue_date,
|
||||
developer_name, developer_inn, object_name, object_type,
|
||||
construction_address, total_area_sqm, units_count
|
||||
construction_address, total_area_sqm
|
||||
FROM ekburg_construction_permits
|
||||
WHERE LEFT(cadastral_number, LENGTH(CAST(:q AS text))) = CAST(:q AS text)
|
||||
AND issue_date > NOW() - INTERVAL '24 months'
|
||||
ORDER BY issue_date DESC
|
||||
LIMIT 50
|
||||
"""),
|
||||
{"q": _quarter_prefix},
|
||||
{"q": _quarter_cad},
|
||||
)
|
||||
.mappings()
|
||||
.all()
|
||||
|
|
@ -1893,21 +1891,18 @@ def analyze_parcel(
|
|||
"object_type": r["object_type"],
|
||||
"construction_address": r["construction_address"],
|
||||
"total_area_sqm": float(r["total_area_sqm"]) if r["total_area_sqm"] else None,
|
||||
"units_count": r["units_count"],
|
||||
}
|
||||
for r in permits_rows
|
||||
]
|
||||
rns_list = [p for p in recent_permits if p["permit_type"] == "RNS"]
|
||||
rve_list = [p for p in recent_permits if p["permit_type"] == "RVE"]
|
||||
by_dev: dict[str, int] = {}
|
||||
for p in recent_permits:
|
||||
if p["developer_name"]:
|
||||
by_dev[p["developer_name"]] = by_dev.get(p["developer_name"], 0) + 1
|
||||
permits_summary = {
|
||||
"rns_count": len(rns_list),
|
||||
"rve_count": len(rve_list),
|
||||
"rve_count": len([p for p in recent_permits if p["permit_type"] == "RVE"]),
|
||||
"rns_total_area_sqm": sum(p["total_area_sqm"] or 0.0 for p in rns_list),
|
||||
"rve_total_units": sum(p["units_count"] or 0 for p in rve_list),
|
||||
"by_developer": [
|
||||
{"name": name, "permits_count": cnt}
|
||||
for name, cnt in sorted(by_dev.items(), key=lambda x: -x[1])[:3]
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ class RecentPermit(BaseModel):
|
|||
object_type: str | None
|
||||
construction_address: str | None
|
||||
total_area_sqm: float | None
|
||||
units_count: int | None
|
||||
|
||||
|
||||
class PermitsSummary(BaseModel):
|
||||
|
|
@ -27,7 +26,6 @@ class PermitsSummary(BaseModel):
|
|||
rns_count: int
|
||||
rve_count: int
|
||||
rns_total_area_sqm: float
|
||||
rve_total_units: int
|
||||
by_developer: list[dict[str, Any]]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,6 @@ def test_recent_permits_found_in_quarter() -> None:
|
|||
"object_type": "МКД",
|
||||
"construction_address": "г. Екатеринбург, ул. Ленина, 1",
|
||||
"total_area_sqm": 45000.0,
|
||||
"units_count": None,
|
||||
}
|
||||
rve_permit: dict[str, Any] = {
|
||||
"permit_type": "RVE",
|
||||
|
|
@ -195,7 +194,6 @@ def test_recent_permits_found_in_quarter() -> None:
|
|||
"object_type": "МКД",
|
||||
"construction_address": "г. Екатеринбург, ул. Ленина, 1",
|
||||
"total_area_sqm": None,
|
||||
"units_count": 320,
|
||||
}
|
||||
|
||||
db = _make_db_for_analyze(permits_rows=[rns_permit, rve_permit])
|
||||
|
|
@ -220,14 +218,14 @@ def test_recent_permits_found_in_quarter() -> None:
|
|||
assert rns["total_area_sqm"] == pytest.approx(45000.0)
|
||||
|
||||
rve = next(p for p in permits if p["permit_type"] == "RVE")
|
||||
assert rve["units_count"] == 320
|
||||
assert rve["issue_date"] == "2025-03-10"
|
||||
assert "units_count" not in rve
|
||||
|
||||
summary = body["permits_summary"]
|
||||
assert summary["rns_count"] == 1
|
||||
assert summary["rve_count"] == 1
|
||||
assert summary["rns_total_area_sqm"] == pytest.approx(45000.0)
|
||||
assert summary["rve_total_units"] == 320
|
||||
assert "rve_total_units" not in summary
|
||||
assert len(summary["by_developer"]) == 1
|
||||
assert summary["by_developer"][0]["name"] == "Атомстрой"
|
||||
assert summary["by_developer"][0]["permits_count"] == 2
|
||||
|
|
@ -257,7 +255,7 @@ def test_recent_permits_empty_quarter() -> None:
|
|||
assert summary["rns_count"] == 0
|
||||
assert summary["rve_count"] == 0
|
||||
assert summary["rns_total_area_sqm"] == pytest.approx(0.0)
|
||||
assert summary["rve_total_units"] == 0
|
||||
assert "rve_total_units" not in summary
|
||||
assert summary["by_developer"] == []
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue