"""订单中心接口服务。本期开放接口 1、3 收件;接口 2 只在 outbound 组装报文。 路径: - POST /api/oms/v1/sales-goods - POST /api/oms/v1/purchase-contracts 鉴权:X-Oms-Token 请求里不跑选品、不录合同。 """ from __future__ import annotations from typing import Annotated, Any from fastapi import Depends, FastAPI, Header from fastapi.responses import JSONResponse from .auth import token_ok from .local_env import load_local_env load_local_env() from .inbound.envelope import EnvelopeError, parse_envelope from .inbound.purchase_contract import receive_purchase_contracts from .inbound.repo import RepoUnavailable from .inbound.sales_goods import receive_sales_goods app = FastAPI(title="洁达 RPA × 订单中心", version="0.1") def get_repo(): # 运行时只走 Oracle。单测用 dependency_overrides 注入内存替身。 from .inbound.oracle_repo import OracleSalesGoodsRepo return OracleSalesGoodsRepo.from_env() def get_contract_repo(): from .inbound.oracle_contract_repo import OraclePurchaseContractRepo return OraclePurchaseContractRepo.from_env() @app.get("/health") def health(): return {"ok": True} @app.post("/api/oms/v1/sales-goods") def post_sales_goods( payload: dict[str, Any] | None = None, x_oms_token: Annotated[str | None, Header()] = None, repo=Depends(get_repo), ): return _post_inbound( payload, x_oms_token, receive=lambda rows: receive_sales_goods(rows, repo), ) @app.post("/api/oms/v1/purchase-contracts") def post_purchase_contracts( payload: dict[str, Any] | None = None, x_oms_token: Annotated[str | None, Header()] = None, repo=Depends(get_contract_repo), ): return _post_inbound( payload, x_oms_token, receive=lambda rows: receive_purchase_contracts(rows, repo), ) def _post_inbound(payload, x_oms_token, receive): if not token_ok(x_oms_token): return JSONResponse( status_code=401, content={"code": 401, "msg": "身份认证失败", "results": []}, ) try: rows = parse_envelope(payload if payload is not None else {}) except EnvelopeError as exc: return JSONResponse( status_code=422, content={"code": 422, "msg": exc.message, "results": []}, ) try: results = receive(rows) except RepoUnavailable as exc: return JSONResponse( status_code=503, content={"code": 503, "msg": exc.message, "results": []}, ) # 逐条有成功/重复/拒绝时 HTTP 仍 200,看 results[].resultCode。 return { "code": 200, "msg": _summary(results), "results": results, } def _summary(results: list[dict]) -> str: codes = {item["resultCode"] for item in results} if codes <= {"ACCEPTED"}: return "批量接收完成" if codes <= {"ACCEPTED", "DUPLICATE"} and "DUPLICATE" in codes: return "批量接收完成,存在重复数据" return "批量接收完成"