200 lines
5.7 KiB
Python
200 lines
5.7 KiB
Python
"""合同完善导出:按段次×产品展开,缺口类型跟本行段。"""
|
|
from datetime import datetime
|
|
|
|
from app.api.pl.plan import (
|
|
CONTRACT_GAP_EXPORT_COLUMNS,
|
|
build_contract_gap_export_rows,
|
|
)
|
|
from app.schemas.pl.plan import (
|
|
PlanContractGapRead,
|
|
PlanContractLink,
|
|
PlanDeliveryRead,
|
|
PlanLoadRead,
|
|
PlanStopProductRead,
|
|
)
|
|
from app.services.pl_internal_customer import INTERNAL_CUSTOMER_NAMES
|
|
|
|
NOW = datetime(2026, 10, 11, 0, 0, 0)
|
|
INTERNAL = next(iter(INTERNAL_CUSTOMER_NAMES))
|
|
|
|
|
|
def _stop_product(name: str, *, product_id: str) -> PlanStopProductRead:
|
|
return PlanStopProductRead(
|
|
id=f"sp-{product_id}",
|
|
planId="p1",
|
|
tenantNo="t1",
|
|
productId=product_id,
|
|
productNo=f"NO-{product_id}",
|
|
productName=name,
|
|
createTime=NOW,
|
|
updateTime=NOW,
|
|
)
|
|
|
|
|
|
def _load(*, customer_name: str, contracts: list, products: list) -> PlanLoadRead:
|
|
return PlanLoadRead(
|
|
id="load1",
|
|
planId="p1",
|
|
tenantNo="t1",
|
|
customerName=customer_name,
|
|
products=products,
|
|
contracts=contracts,
|
|
createTime=NOW,
|
|
updateTime=NOW,
|
|
)
|
|
|
|
|
|
def _delivery(
|
|
*,
|
|
stop_id: str,
|
|
seq: int,
|
|
customer_name: str,
|
|
delivery_time: str,
|
|
contracts: list,
|
|
products: list,
|
|
) -> PlanDeliveryRead:
|
|
return PlanDeliveryRead(
|
|
id=stop_id,
|
|
planId="p1",
|
|
tenantNo="t1",
|
|
seq=seq,
|
|
customerName=customer_name,
|
|
deliveryTime=delivery_time,
|
|
products=products,
|
|
contracts=contracts,
|
|
createTime=NOW,
|
|
updateTime=NOW,
|
|
)
|
|
|
|
|
|
def _gap_item() -> PlanContractGapRead:
|
|
return PlanContractGapRead(
|
|
id="p1",
|
|
planNo="PL001",
|
|
planDate="2026-10-11",
|
|
planType="direct",
|
|
followStatus="arranged",
|
|
supplierName="供方甲",
|
|
customerName="需方乙",
|
|
supplierContractExempt=False,
|
|
demanderContractExempt=False,
|
|
)
|
|
|
|
|
|
def test_contract_gap_export_columns_match_segment_rows():
|
|
assert [column.field for column in CONTRACT_GAP_EXPORT_COLUMNS] == [
|
|
"planNo",
|
|
"stopSegment",
|
|
"planDate",
|
|
"deliveryTimes",
|
|
"planType",
|
|
"followStatus",
|
|
"loadCustomer",
|
|
"deliveryCustomer",
|
|
"productName",
|
|
"supplierName",
|
|
"customerName",
|
|
"gapType",
|
|
]
|
|
assert [column.title for column in CONTRACT_GAP_EXPORT_COLUMNS] == [
|
|
"计划编号",
|
|
"段次",
|
|
"计划日期",
|
|
"送货时间",
|
|
"单据类型",
|
|
"跟进状态",
|
|
"装货客户",
|
|
"送货客户",
|
|
"产品名称",
|
|
"供方",
|
|
"需方",
|
|
"缺口类型",
|
|
]
|
|
|
|
|
|
def test_build_contract_gap_export_rows_expands_multi_segment_products():
|
|
"""装货缺合同 + 两送货段(一段有合同、一段两产品缺合同)展开为 4 行。"""
|
|
load = _load(
|
|
customer_name="外部装货客户",
|
|
contracts=[],
|
|
products=[_stop_product("甲醇", product_id="prod-load")],
|
|
)
|
|
delivery_ok = _delivery(
|
|
stop_id="d1",
|
|
seq=1,
|
|
customer_name="外部送货客户A",
|
|
delivery_time="2026-10-12",
|
|
contracts=[PlanContractLink(contractId="c1", contractNo="HT001")],
|
|
products=[_stop_product("甲醇", product_id="prod-d1")],
|
|
)
|
|
delivery_gap = _delivery(
|
|
stop_id="d2",
|
|
seq=2,
|
|
customer_name="外部送货客户B",
|
|
delivery_time="2026-10-13",
|
|
contracts=[],
|
|
products=[
|
|
_stop_product("乙醇", product_id="prod-d2a"),
|
|
_stop_product("丙酮", product_id="prod-d2b"),
|
|
],
|
|
)
|
|
|
|
rows = build_contract_gap_export_rows(
|
|
[_gap_item()],
|
|
{"p1": (load, [delivery_ok, delivery_gap])},
|
|
)
|
|
|
|
assert len(rows) == 4
|
|
assert [row["stopSegment"] for row in rows] == ["装货", "送货 #1", "送货 #2", "送货 #2"]
|
|
assert [row["productName"] for row in rows] == ["甲醇", "甲醇", "乙醇", "丙酮"]
|
|
assert [row["gapType"] for row in rows] == ["缺供方合同", "", "缺需方合同", "缺需方合同"]
|
|
|
|
load_row = rows[0]
|
|
assert load_row["loadCustomer"] == "外部装货客户"
|
|
assert load_row["deliveryCustomer"] == ""
|
|
assert load_row["deliveryTimes"] == ""
|
|
|
|
ok_row = rows[1]
|
|
assert ok_row["loadCustomer"] == ""
|
|
assert ok_row["deliveryCustomer"] == "外部送货客户A"
|
|
assert ok_row["deliveryTimes"] == "2026-10-12"
|
|
|
|
gap_row = rows[3]
|
|
assert gap_row["deliveryCustomer"] == "外部送货客户B"
|
|
assert gap_row["deliveryTimes"] == "2026-10-13"
|
|
assert gap_row["loadCustomer"] == ""
|
|
|
|
for row in rows:
|
|
assert row["planNo"] == "PL001"
|
|
assert row["planDate"] == "2026-10-11"
|
|
assert row["planType"] == "直销单"
|
|
assert row["followStatus"] == "已安排"
|
|
assert row["supplierName"] == "供方甲"
|
|
assert row["customerName"] == "需方乙"
|
|
|
|
|
|
def test_build_contract_gap_export_rows_internal_side_has_empty_gap_type():
|
|
"""内置客户免合同:装货行缺口为空,外送段仍标缺需方合同。"""
|
|
load = _load(
|
|
customer_name=INTERNAL,
|
|
contracts=[],
|
|
products=[_stop_product("甲醇", product_id="prod-load")],
|
|
)
|
|
delivery = _delivery(
|
|
stop_id="d1",
|
|
seq=1,
|
|
customer_name="外部送货客户",
|
|
delivery_time="2026-10-12T08:30:00",
|
|
contracts=[],
|
|
products=[_stop_product("甲醇", product_id="prod-d1")],
|
|
)
|
|
|
|
rows = build_contract_gap_export_rows(
|
|
[_gap_item()],
|
|
{"p1": (load, [delivery])},
|
|
)
|
|
|
|
assert [row["stopSegment"] for row in rows] == ["装货", "送货 #1"]
|
|
assert [row["gapType"] for row in rows] == ["", "缺需方合同"]
|
|
assert rows[1]["deliveryTimes"] == "2026-10-12"
|