AutoRpa/rpa_oms/app/inbound/purchase_contract.py

169 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""接口 3 逐条校验与落表。不跑合同作业。
入参 camelCase,落表 snake_case。幂等键是对方 fid。
请求里不录合同。
"""
from __future__ import annotations
from datetime import date, datetime
from .repo import DuplicateFid
from .sales_goods import _parse_decimal, _parse_int, _parse_oms_id, _parse_str
_STRING_FIELDS = (
("supplierId", "supplier_id", 20),
("supplierName", "supplier_name", 200),
("goodsId", "goods_id", 20),
("goodsName", "goods_name", 200),
("regNo", "reg_no", 100),
("spec", "spec", 100),
("unit", "unit", 20),
("goodsSourceId", "goods_source_id", 20),
("purchaserId", "purchaser_id", 20),
("purchaserName", "purchaser_name", 100),
("plannerId", "planner_id", 20),
("plannerName", "planner_name", 100),
("orgCode", "org_code", 10),
("goodsMdmCode", "goods_mdm_code", 100),
("supplierMdmCode", "supplier_mdm_code", 100),
)
_DATE_FIELDS = (
("contractSignDate", "contract_sign_date"),
("contractStartDate", "contract_start_date"),
("contractEndDate", "contract_end_date"),
)
_DECIMAL_FIELDS = (
("qty", "qty"),
("purchaseTaxRate", "purchase_tax_rate"),
("unitPrice", "unit_price"),
)
def receive_purchase_contracts(rows: list, repo) -> list[dict]:
seen: set[int] = set()
results: list[dict] = []
for row in rows:
results.append(_receive_one(row, repo, seen))
return results
def _receive_one(row: object, repo, seen: set[int]) -> dict:
if not isinstance(row, dict):
return _result(None, "REJECTED", "明细必须是对象")
fid, fid_error = _parse_fid(row.get("fid"))
if fid is not None and fid in seen:
return _result(fid, "CONFLICT", "同一请求中 fid 重复")
if fid is not None:
seen.add(fid)
parsed, error = _parse_row(row, fid, fid_error)
if error:
_camel, message = error
return _result(row.get("fid"), "REJECTED", message)
try:
repo.insert(parsed)
except DuplicateFid:
return _result(parsed["fid"], "DUPLICATE", "序号已存在,未重复入库")
return _result(parsed["fid"], "ACCEPTED", "采购合同数据已接收,等待处理")
def _parse_row(row: dict, fid: int | None, fid_error: str | None):
if fid_error:
return None, ("fid", fid_error)
oms_id, oms_error = _parse_oms_id(row.get("omsId"))
if oms_error:
return None, ("omsId", oms_error)
record: dict = {"fid": fid, "oms_id": oms_id, "process_status": 0}
for camel, snake, max_len in _STRING_FIELDS:
value, error = _parse_str(row.get(camel), camel, max_len)
if error:
return None, (camel, error)
record[snake] = value
for camel, snake in _DATE_FIELDS:
value, error = _parse_date(row.get(camel), camel)
if error:
return None, (camel, error)
record[snake] = value
if record["contract_end_date"] < record["contract_start_date"]:
return None, ("contractEndDate", "contractEndDate 不得早于 contractStartDate")
payment_term, error = _parse_int(row.get("paymentTerm"), "paymentTerm")
if error:
return None, ("paymentTerm", error)
record["payment_term"] = payment_term
for camel, snake in _DECIMAL_FIELDS:
value, error = _parse_decimal(row.get(camel), camel)
if error:
return None, (camel, error)
record[snake] = value
customer_type, error = _parse_int(row.get("customerType"), "customerType")
if error:
return None, ("customerType", error)
record["customer_type"] = customer_type
entry_status, error = _parse_entry_status(row.get("contractEntryStatus"))
if error:
return None, ("contractEntryStatus", error)
record["contract_entry_status"] = entry_status
contract_no, error = _parse_contract_no(row.get("contractNo"), entry_status)
if error:
return None, ("contractNo", error)
record["contract_no"] = contract_no
return record, None
def _parse_fid(value) -> tuple[int | None, str | None]:
if value is None or value == "":
return None, "缺少必填字段 fid"
if type(value) is int and 0 < value < 10**19:
return value, None
return None, "fid 必须是整数"
def _parse_date(value, camel: str) -> tuple[date | None, str | None]:
if value is None or value == "":
return None, f"缺少必填字段 {camel}"
if isinstance(value, datetime):
return value.date(), None
if isinstance(value, date):
return value, None
if not isinstance(value, str):
return None, f"{camel} 必须是 YYYY-MM-DD"
try:
return date.fromisoformat(value.strip()), None
except ValueError:
return None, f"{camel} 必须是 YYYY-MM-DD"
def _parse_entry_status(value) -> tuple[int | None, str | None]:
if value is None or value == "":
return None, None
if type(value) is int and value in (0, 1):
return value, None
return None, "contractEntryStatus 必须是 0 或 1"
def _parse_contract_no(value, entry_status: int | None) -> tuple[str | None, str | None]:
if entry_status == 0:
return _parse_str(value, "contractNo", 40)
if value is None or value == "":
return None, None
return _parse_str(value, "contractNo", 40)
def _result(fid, result_code: str, message: str) -> dict:
return {"fid": fid, "resultCode": result_code, "message": message}