"""接口 1 收件契约。内存仓库,不连 Oracle。""" from __future__ import annotations import os import pytest from fastapi.testclient import TestClient os.environ["OMS_INBOUND_TOKEN"] = "test-oms-token" from app.inbound.memory_repo import MemorySalesGoodsRepo from app.inbound.repo import RepoUnavailable from app.main import app, get_repo TOKEN = "test-oms-token" PATH = "/api/oms/v1/sales-goods" def _item(**overrides): row = { "omsId": 2026092801, "barCode": "06901234567890", "orderDate": "2026-09-28", "salePrice": "128.5000", "saleQty": 10, "planPurchaseQty": 10, "goodsId": "G000123456789", "goodsName": "阿莫西林胶囊", "goodsSpec": "0.25g*24粒", "manufacturer": "示例制药有限公司", "approvalNo": "国药准字H20201234", "unit": "盒", "customerId": "C00010001", "customerName": "示例医院", "orgCode": "901", "goodsMdmCode": "QX0100167583", "customerMdmCode": "DW0100079727", } row.update(overrides) return row @pytest.fixture def client(): repo = MemorySalesGoodsRepo() app.dependency_overrides[get_repo] = lambda: repo with TestClient(app) as test_client: yield test_client, repo app.dependency_overrides.clear() def _post(client, body, token=TOKEN): headers = {"X-Oms-Token": token} if token is not None else {} return client.post(PATH, json=body, headers=headers) def test_missing_token_returns_401(client): test_client, _ = client resp = _post(test_client, {"data": [_item()]}, token=None) assert resp.status_code == 401 body = resp.json() assert body["code"] == 401 assert body["results"] == [] def test_wrong_token_returns_401(client): test_client, _ = client resp = _post(test_client, {"data": [_item()]}, token="bad") assert resp.status_code == 401 assert resp.json()["code"] == 401 def test_missing_data_returns_422(client): test_client, _ = client resp = _post(test_client, {}) assert resp.status_code == 422 assert resp.json()["code"] == 422 assert resp.json()["results"] == [] def test_empty_data_returns_422(client): test_client, _ = client resp = _post(test_client, {"data": []}) assert resp.status_code == 422 assert resp.json()["code"] == 422 def test_over_100_rows_returns_422(client): test_client, repo = client rows = [_item(omsId=i) for i in range(1, 102)] resp = _post(test_client, {"data": rows}) assert resp.status_code == 422 assert repo.count() == 0 def test_accepts_valid_row(client): test_client, repo = client resp = _post(test_client, {"data": [_item()]}) assert resp.status_code == 200 body = resp.json() assert body["code"] == 200 assert body["results"] == [ { "omsId": 2026092801, "resultCode": "ACCEPTED", "message": "接收成功,等待RPA处理", } ] stored = repo.get(2026092801) assert stored["deal_flag"] == 0 assert stored["bar_code"] == "06901234567890" assert stored["goods_mdm_code"] == "QX0100167583" def test_existing_oms_id_is_duplicate_and_not_updated(client): # 跨请求同 omsId:DUPLICATE,库里品名不改。 test_client, repo = client _post(test_client, {"data": [_item()]}) resp = _post(test_client, {"data": [_item(goodsName="不应覆盖")]}) assert resp.status_code == 200 result = resp.json()["results"][0] assert result["resultCode"] == "DUPLICATE" assert repo.get(2026092801)["goods_name"] == "阿莫西林胶囊" def test_duplicate_oms_id_in_same_batch_is_conflict(client): # 同一 POST 里两条相同 omsId:后一条 CONFLICT,只落第一条。 test_client, repo = client resp = _post( test_client, {"data": [_item(), _item(barCode="06901234567891")]}, ) assert resp.status_code == 200 results = resp.json()["results"] assert results[0]["resultCode"] == "ACCEPTED" assert results[1]["resultCode"] == "CONFLICT" assert results[1]["omsId"] == 2026092801 assert repo.count() == 1 def test_missing_mdm_is_rejected_and_not_stored(client): test_client, repo = client resp = _post(test_client, {"data": [_item(goodsMdmCode="")]}) assert resp.status_code == 200 result = resp.json()["results"][0] assert result["resultCode"] == "REJECTED" assert "goodsMdmCode" in result["message"] assert repo.count() == 0 def test_mixed_batch_still_http_200(client): test_client, repo = client _post(test_client, {"data": [_item(omsId=1)]}) resp = _post( test_client, { "data": [ _item(omsId=1), _item(omsId=2), _item(omsId=3, orgCode=""), ] }, ) assert resp.status_code == 200 codes = [r["resultCode"] for r in resp.json()["results"]] assert codes == ["DUPLICATE", "ACCEPTED", "REJECTED"] assert repo.count() == 2 def test_string_oms_id_is_rejected(client): # JSON 字符串 "2026092801" 不转整数。 test_client, repo = client resp = _post(test_client, {"data": [_item(omsId="2026092801")]}) assert resp.status_code == 200 assert resp.json()["results"][0]["resultCode"] == "REJECTED" assert repo.count() == 0 def test_repo_unavailable_returns_503(client): test_client, _ = client class Boom: def insert(self, record): raise RepoUnavailable("数据库不可用") app.dependency_overrides[get_repo] = lambda: Boom() resp = _post(test_client, {"data": [_item()]}) assert resp.status_code == 503 assert resp.json()["code"] == 503 assert resp.json()["results"] == []