feat(server): add PUT /attachment/config with removal guard

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-08-12 14:01:29 +08:00
parent f155dc671b
commit 7027b91863
4 changed files with 247 additions and 2 deletions

View File

@@ -84,3 +84,113 @@ def test_status_reflects_config_and_boxed(client: TestClient, db: Session):
assert item["expected_qty"] == 80
assert item["boxed_qty"] == 30
assert item["complete"] is False
def test_config_sets_none(client: TestClient):
resp = client.put(
"/CargoTrace/attachment/config",
json={"zongpai_no": "26BW0011", "determination": "none", "items": []},
)
assert resp.status_code == 200
assert resp.json()["determination"] == "none"
assert resp.json()["items"] == []
def test_config_creates_and_updates_items(client: TestClient, db: Session):
cert_id, extra_id, _ = _seed_categories(db)
client.put(
"/CargoTrace/attachment/config",
json={
"zongpai_no": "26BW0011",
"determination": "has",
"items": [
{"category_id": cert_id, "expected_qty": 80},
{"category_id": extra_id, "expected_qty": 5},
],
},
)
# Update: change extra expected, drop nothing
resp = client.put(
"/CargoTrace/attachment/config",
json={
"zongpai_no": "26BW0011",
"determination": "has",
"items": [
{"category_id": cert_id, "expected_qty": 80},
{"category_id": extra_id, "expected_qty": 8},
],
},
)
assert resp.status_code == 200
extra = next(i for i in resp.json()["items"] if i["category_id"] == extra_id)
assert extra["expected_qty"] == 8
def test_config_rejects_removing_type_with_boxes(client: TestClient, db: Session):
cert_id, _, _ = _seed_categories(db)
client.put(
"/CargoTrace/attachment/config",
json={
"zongpai_no": "26BW0011",
"determination": "has",
"items": [{"category_id": cert_id, "expected_qty": 80}],
},
)
client.post(
"/CargoTrace/attachment/box",
json={
"zongpai_no": "26BW0011",
"category_id": cert_id,
"box_no": 922,
"quantity": 10,
},
)
# Try to drop the type that now has boxes
resp = client.put(
"/CargoTrace/attachment/config",
json={
"zongpai_no": "26BW0011",
"determination": "has",
"items": [],
},
)
assert resp.status_code == 409
assert resp.json()["error_code"] == "CATEGORY_HAS_BOXES"
def test_config_allows_removing_type_with_zero_boxes(client: TestClient, db: Session):
cert_id, extra_id, _ = _seed_categories(db)
client.put(
"/CargoTrace/attachment/config",
json={
"zongpai_no": "26BW0011",
"determination": "has",
"items": [
{"category_id": cert_id, "expected_qty": 80},
{"category_id": extra_id, "expected_qty": 5},
],
},
)
resp = client.put(
"/CargoTrace/attachment/config",
json={
"zongpai_no": "26BW0011",
"determination": "has",
"items": [{"category_id": cert_id, "expected_qty": 80}],
},
)
assert resp.status_code == 200
assert {i["category_id"] for i in resp.json()["items"]} == {cert_id}
def test_config_rejects_unknown_category(client: TestClient):
resp = client.put(
"/CargoTrace/attachment/config",
json={
"zongpai_no": "26BW0011",
"determination": "has",
"items": [{"category_id": 9999999, "expected_qty": 1}],
},
)
assert resp.status_code == 404
assert resp.json()["error_code"] == "CATEGORY_NOT_FOUND"