M8-T12: scope energy contracts
This commit is contained in:
@@ -55,6 +55,7 @@ from sqlalchemy import create_engine, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models.energy import EnergyContract, EnergyContractVersion
|
||||
from app.services.contracts import activate_contract
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Shared helpers
|
||||
@@ -567,6 +568,72 @@ def test_deactivate_contract(contracts_client):
|
||||
assert resp.json()["active"] is False
|
||||
|
||||
|
||||
def test_scope_defaults_filtering_and_kind_mismatch(contracts_client):
|
||||
"""Old clients default to electricity; a supplied incompatible scope is rejected."""
|
||||
client, engine = contracts_client
|
||||
_login(client)
|
||||
created = client.post(
|
||||
"/api/energy/contracts",
|
||||
json=_manual_payload(),
|
||||
headers={"X-CSRF-Token": _CSRF},
|
||||
)
|
||||
assert created.status_code == 201
|
||||
assert created.json()["scope"] == "electricity"
|
||||
assert client.get("/api/energy/contracts").json()["total"] == 1
|
||||
assert client.get("/api/energy/contracts?scope=thermal").json()["items"] == []
|
||||
|
||||
mismatch = client.post(
|
||||
"/api/energy/contracts",
|
||||
json=_manual_payload(scope="thermal"),
|
||||
headers={"X-CSRF-Token": _CSRF},
|
||||
)
|
||||
assert mismatch.status_code == 422
|
||||
with Session(engine) as session:
|
||||
assert len(session.execute(select(EnergyContract)).scalars().all()) == 1
|
||||
|
||||
|
||||
def test_activation_is_scope_local_and_transaction_rollback_is_safe(contracts_client):
|
||||
"""A thermal activation neither deactivates electricity nor survives rollback."""
|
||||
client, engine = contracts_client
|
||||
_login(client)
|
||||
electricity = client.post(
|
||||
"/api/energy/contracts",
|
||||
json=_manual_payload(name="Electricity"),
|
||||
headers={"X-CSRF-Token": _CSRF},
|
||||
).json()
|
||||
client.patch(
|
||||
f"/api/energy/contracts/{electricity['id']}",
|
||||
json={"active": True},
|
||||
headers={"X-CSRF-Token": _CSRF},
|
||||
)
|
||||
now = datetime.now(UTC)
|
||||
with Session(engine) as session:
|
||||
thermal = EnergyContract(
|
||||
name="Future thermal", kind="district_heating", scope="thermal", active=False,
|
||||
currency="EUR", created_at=now, updated_at=now,
|
||||
)
|
||||
session.add(thermal)
|
||||
session.commit()
|
||||
thermal_id = thermal.id
|
||||
|
||||
with Session(engine) as session:
|
||||
thermal = session.get(EnergyContract, thermal_id)
|
||||
assert thermal is not None
|
||||
activate_contract(session, thermal)
|
||||
session.rollback() # Simulate a later write failure in this transaction.
|
||||
|
||||
with Session(engine) as session:
|
||||
rows = {row.scope: row for row in session.execute(select(EnergyContract)).scalars()}
|
||||
assert rows["electricity"].active is True
|
||||
assert rows["thermal"].active is False
|
||||
activate_contract(session, rows["thermal"])
|
||||
session.commit()
|
||||
|
||||
with Session(engine) as session:
|
||||
active = session.execute(select(EnergyContract).where(EnergyContract.active.is_(True))).scalars().all()
|
||||
assert {row.scope for row in active} == {"electricity", "thermal"}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# POST /api/energy/contracts/{id}/versions
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user