Repository navigation
fix(suppliers): do not cascade facility rows that arrive during removal #3523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
298c578
52e955d
5cfd41f
aa0e068
bb6bb8d
c57711f
995086a
ef99d3f
ee850b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ | |
|
|
||
| from __future__ import annotations | ||
|
|
||
| from datetime import datetime, timezone | ||
| from unittest.mock import MagicMock, patch | ||
| from uuid import UUID | ||
|
|
||
|
|
@@ -519,7 +520,7 @@ def test_lots_with_facility_filter(self, client: TestClient, db_session: Session | |
| supplier_user_id=TEST_USER_ID, | ||
| facility_id=f.id, | ||
| tlc_code="TLC-FILTER-001", | ||
| product_description="Spinach", | ||
| product_description="", | ||
| status="active", | ||
| ) | ||
| db_session.add(lot) | ||
|
|
@@ -596,3 +597,98 @@ def _deny_owner(): | |
| resp = member_client.delete("/v1/supplier/facilities/00000000-0000-0000-0000-000000000000") | ||
| assert resp.status_code == 403 | ||
|
|
||
| def test_delete_empty_facility(self, client: TestClient, db_session: Session): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add unauthenticated and replay tests for facility deletion. The existing
|
||
| facility = _make_facility(db_session) | ||
| resp = client.delete(f"/v1/supplier/facilities/{facility.id}") | ||
| assert resp.status_code == 200 | ||
| assert resp.json()["status"] == "deleted" | ||
| db_session.expire_all() | ||
| assert db_session.get(SupplierFacilityModel, facility.id) is None | ||
|
|
||
| def test_linked_lot_returns_409(self, client: TestClient, db_session: Session): | ||
| facility = _make_facility(db_session) | ||
| db_session.add( | ||
| SupplierTraceabilityLotModel( | ||
| tenant_id=TEST_TENANT_ID, | ||
| supplier_user_id=TEST_USER_ID, | ||
| facility_id=facility.id, | ||
| tlc_code="", | ||
| product_description="", | ||
| status="active", | ||
| ) | ||
| ) | ||
| db_session.commit() | ||
|
|
||
| resp = client.delete(f"/v1/supplier/facilities/{facility.id}") | ||
| assert resp.status_code == 409 | ||
| db_session.expire_all() | ||
| assert db_session.get(SupplierFacilityModel, facility.id) is not None | ||
|
|
||
| def test_stale_empty_count_does_not_cascade_lot(self, client: TestClient, db_session: Session, monkeypatch: pytest.MonkeyPatch): | ||
| """A lot committed after the pre-check must not be deleted with the facility. | ||
|
|
||
| Lots use ON DELETE CASCADE. The pre-check and the DELETE used to be | ||
| separate statements, so a lot that landed in between was cascaded away. | ||
| """ | ||
| import app.supplier_facilities_routes as fac_routes | ||
|
|
||
| facility = _make_facility(db_session) | ||
| lot = SupplierTraceabilityLotModel( | ||
| tenant_id=TEST_TENANT_ID, | ||
| supplier_user_id=TEST_USER_ID, | ||
| facility_id=facility.id, | ||
| tlc_code="", | ||
| product_description="", | ||
| status="active", | ||
| ) | ||
| db_session.add(lot) | ||
| db_session.commit() | ||
| monkeypatch.setattr(fac_routes, "_linked_record_counts", lambda *_args, **_kwargs: (0, 0, 0)) | ||
|
|
||
| resp = client.delete(f"/v1/supplier/facilities/{facility.id}") | ||
| assert resp.status_code == 409 | ||
| db_session.expire_all() | ||
| assert db_session.get(SupplierFacilityModel, facility.id) is not None | ||
| assert db_session.get(SupplierTraceabilityLotModel, lot.id) is not None | ||
|
|
||
| def test_stale_empty_count_does_not_cascade_cte_event( | ||
| self, client: TestClient, db_session: Session, monkeypatch: pytest.MonkeyPatch | ||
| ): | ||
| """An event filed on this facility must survive even when its lot lives elsewhere.""" | ||
| import app.supplier_facilities_routes as fac_routes | ||
|
|
||
| target = _make_facility(db_session, "Target") | ||
| other = _make_facility(db_session, "Other") | ||
| lot = SupplierTraceabilityLotModel( | ||
| tenant_id=TEST_TENANT_ID, | ||
| supplier_user_id=TEST_USER_ID, | ||
| facility_id=other.id, | ||
| tlc_code="", | ||
| product_description="", | ||
| status="active", | ||
| ) | ||
| db_session.add(lot) | ||
| db_session.commit() | ||
| event = SupplierCTEEventModel( | ||
| tenant_id=TEST_TENANT_ID, | ||
| supplier_user_id=TEST_USER_ID, | ||
| facility_id=target.id, | ||
| lot_id=lot.id, | ||
| cte_type="shipping", | ||
| event_time=datetime.now(timezone.utc), | ||
| kde_data={}, | ||
| payload_sha256="", | ||
| merkle_hash="", | ||
| sequence_number=1, | ||
| obligation_ids=[], | ||
| ) | ||
| db_session.add(event) | ||
| db_session.commit() | ||
| monkeypatch.setattr(fac_routes, "_linked_record_counts", lambda *_args, **_kwargs: (0, 0, 0)) | ||
|
|
||
| resp = client.delete(f"/v1/supplier/facilities/{target.id}") | ||
| assert resp.status_code == 409 | ||
| db_session.expire_all() | ||
| assert db_session.get(SupplierFacilityModel, target.id) is not None | ||
| assert db_session.get(SupplierCTEEventModel, event.id) is not None | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.