This commit is contained in:
zlwu committed 2026-09-29 07:07:51 +08:00
1 parent c9fb39395c
commit 4f364bc9a0
58 files changed
+1040829 -6729

No files matched your search

+235 -21
View File
@@ -1,14 +1,36 @@
from decimal import Decimal
from unittest.mock import MagicMock, patch
from app.schemas.pl.plan import PlanDeliveryRead, PlanLoadRead, PlanStopProductRead
from app.services.pl_internal_customer import INTERNAL_CUSTOMER_NAMES
from app.services.pl_plan_archive_export import (
_append_paired_product_rows,
_append_stop_product_rows,
_plan_common_export_fields,
build_plan_archive_export_rows,
resolve_archive_list_io_column,
)
def _stop_product(**kwargs) -> PlanStopProductRead:
defaults = {
"id": "sp1",
"planId": "p1",
"tenantNo": "t1",
"productId": "prod1",
"productNo": "P001",
"productName": "甲醇",
"model": "99%",
"unit": "吨",
"packageSpec": "散装",
"planQty": Decimal("10"),
"createTime": "2026-08-27T00:00:00",
"updateTime": "2026-08-27T00:00:00",
}
defaults.update(kwargs)
return PlanStopProductRead(**defaults)
def test_resolve_archive_list_io_column():
internal = next(iter(INTERNAL_CUSTOMER_NAMES))
assert resolve_archive_list_io_column("load", internal) == "outbound"
@@ -19,22 +41,10 @@ def test_resolve_archive_list_io_column():
def test_append_stop_product_rows_io_and_amount():
internal = next(iter(INTERNAL_CUSTOMER_NAMES))
product = PlanStopProductRead(
id="sp1",
planId="p1",
tenantNo="t1",
productId="prod1",
productNo="P001",
productName="甲醇",
model="99%",
unit="吨",
packageSpec="散装",
planQty=Decimal("10"),
product = _stop_product(
inboundQty=Decimal("9.5"),
inboundPrice=Decimal("100"),
inboundAmount=None,
createTime="2026-08-27T00:00:00",
updateTime="2026-08-27T00:00:00",
)
load = PlanLoadRead(
id="load1",
@@ -58,26 +68,23 @@ def test_append_stop_product_rows_io_and_amount():
row = rows[0]
assert row["stopKind"] == "装货"
assert row["stopCustomer"] == internal
assert row["loadCustomer"] == internal
assert row["actualQty"] == Decimal("9.5")
assert row["outboundQty"] == Decimal("9.5")
assert row["loadOutboundQty"] == Decimal("9.5")
assert row["inboundQty"] is None
assert row["unitPrice"] == Decimal("100")
assert row["loadUnitPrice"] == Decimal("100")
assert row["amount"] == Decimal("950")
assert row["loadAmount"] == Decimal("950")
def test_append_stop_product_rows_delivery_external_outbound():
product = PlanStopProductRead(
product = _stop_product(
id="sp2",
planId="p1",
tenantNo="t1",
productId="prod1",
productNo="P001",
productName="甲醇",
outboundQty=Decimal("8"),
outboundPrice=Decimal("120"),
outboundAmount=Decimal("960"),
createTime="2026-08-27T00:00:00",
updateTime="2026-08-27T00:00:00",
)
delivery = PlanDeliveryRead(
id="del1",
@@ -94,10 +101,217 @@ def test_append_stop_product_rows_delivery_external_outbound():
rows: list[dict] = []
row_no = _append_stop_product_rows(rows, 0, {"planNo": "P1"}, "delivery", delivery, 1, delivery.products)
row = rows[0]
assert row_no == 1
assert row["stopKind"] == "送货 #1"
assert row["deliveryCustomer"] == "外部客户"
assert row["outboundQty"] == Decimal("8")
assert row["deliveryOutboundQty"] == Decimal("8")
assert row["inboundQty"] is None
assert row["amount"] == Decimal("960")
assert row["deliveryAmount"] == Decimal("960")
def test_append_paired_product_rows_inner_join_one_row_per_product():
internal = next(iter(INTERNAL_CUSTOMER_NAMES))
load_a = _stop_product(
id="lp1",
productId="prod-a",
productName="甲醇",
packageSpec="散装",
inboundQty=Decimal("10"),
inboundPrice=Decimal("100"),
)
load_b = _stop_product(
id="lp2",
productId="prod-b",
productName="乙醇",
packageSpec="桶装",
inboundQty=Decimal("5"),
inboundPrice=Decimal("80"),
)
# 装货独有,送货无匹配 → 不出行
load_only = _stop_product(
id="lp3",
productId="prod-c",
productName="仅装货",
packageSpec="散装",
inboundQty=Decimal("1"),
)
delivery_a = _stop_product(
id="dp1",
productId="prod-a",
productName="甲醇",
packageSpec="散装",
outboundQty=Decimal("9.5"),
outboundPrice=Decimal("120"),
outboundAmount=Decimal("1140"),
)
# 同产品不同包装 → 不匹配
delivery_a_other_pkg = _stop_product(
id="dp1b",
productId="prod-a",
productName="甲醇",
packageSpec="桶装",
outboundQty=Decimal("1"),
outboundPrice=Decimal("1"),
)
delivery_b = _stop_product(
id="dp2",
productId="prod-b",
productName="乙醇",
packageSpec="桶装",
outboundQty=Decimal("4"),
outboundPrice=Decimal("90"),
)
# 送货独有 → 不出行
delivery_only = _stop_product(
id="dp3",
productId="prod-d",
productName="仅送货",
packageSpec="散装",
outboundQty=Decimal("2"),
)
load = PlanLoadRead(
id="load1",
planId="p1",
tenantNo="t1",
customerName=internal,
address="装货地址",
loadTime="2026-08-27T08:00:00",
products=[load_a, load_b, load_only],
createTime="2026-08-27T00:00:00",
updateTime="2026-08-27T00:00:00",
)
delivery = PlanDeliveryRead(
id="del1",
planId="p1",
tenantNo="t1",
seq=1,
customerName="外部客户",
address="送货地址",
deliveryTime="2026-08-28T10:00:00",
products=[delivery_a, delivery_a_other_pkg, delivery_b, delivery_only],
createTime="2026-08-27T00:00:00",
updateTime="2026-08-27T00:00:00",
)
rows: list[dict] = []
row_no = _append_paired_product_rows(rows, 0, {"planNo": "PL001"}, load, delivery, 1)
assert row_no == 2
assert len(rows) == 2
by_name = {r["productName"]: r for r in rows}
assert set(by_name) == {"甲醇", "乙醇"}
methanol = by_name["甲醇"]
assert methanol["loadCustomer"] == internal
assert methanol["deliveryCustomer"] == "外部客户"
assert methanol["deliveryStopKind"] == "送货 #1"
assert methanol["packageSpec"] == "散装"
assert methanol["loadOutboundQty"] == Decimal("10") # 内部客户装货 → 出库
assert methanol["loadInboundQty"] is None
assert methanol["loadUnitPrice"] == Decimal("100")
assert methanol["loadAmount"] == Decimal("1000")
assert methanol["deliveryOutboundQty"] == Decimal("9.5")
assert methanol["deliveryInboundQty"] is None
assert methanol["deliveryUnitPrice"] == Decimal("120")
assert methanol["deliveryAmount"] == Decimal("1140")
ethanol = by_name["乙醇"]
assert ethanol["loadOutboundQty"] == Decimal("5")
assert ethanol["deliveryOutboundQty"] == Decimal("4")
assert ethanol["deliveryAmount"] == Decimal("360")
def test_build_plan_archive_export_rows_pair_mode_and_single_side():
internal = next(iter(INTERNAL_CUSTOMER_NAMES))
load_product = _stop_product(
inboundQty=Decimal("10"),
inboundPrice=Decimal("100"),
)
delivery_product = _stop_product(
id="dp1",
outboundQty=Decimal("9"),
outboundPrice=Decimal("110"),
outboundAmount=Decimal("990"),
)
load = PlanLoadRead(
id="load1",
planId="p1",
tenantNo="t1",
customerName=internal,
address="装货地址",
loadTime="2026-08-27T08:00:00",
products=[load_product],
createTime="2026-08-27T00:00:00",
updateTime="2026-08-27T00:00:00",
)
delivery = PlanDeliveryRead(
id="del1",
planId="p1",
tenantNo="t1",
seq=2,
customerName="外部客户",
address="送货地址",
deliveryTime="2026-08-28T10:00:00",
products=[delivery_product],
createTime="2026-08-27T00:00:00",
updateTime="2026-08-27T00:00:00",
)
plan = MagicMock()
plan.id = "p1"
plan.plan_no = "PL001"
plan.contract_no = "C1"
plan.plan_date = "2026-08-27"
plan.archive_status = "archived"
plan.follow_status = "arranged"
plan.plan_type = "direct"
plan.license_plate = "皖A12345"
plan.trailer_no = None
plan.erp_entered = 0
plan.freight_amount = None
plan.remark = ""
plan.transport_id = None
plan.customer_name = "外部客户"
plan.supplier_name = None
plan.destination_name = None
plan.delivery_time = None
with patch(
"app.services.pl_plan_archive_export.load_plan_stops_grouped",
return_value={"p1": (load, [delivery])},
), patch(
"app.services.pl_plan_archive_export._load_legacy_products_by_plan",
return_value={},
), patch(
"app.services.pl_plan_archive_export._load_contract_nos_by_plan",
return_value={"p1": []},
):
paired = build_plan_archive_export_rows(
MagicMock(), "t1", [plan], {}, stop_kind=None
)
load_only = build_plan_archive_export_rows(
MagicMock(), "t1", [plan], {}, stop_kind="load"
)
delivery_only = build_plan_archive_export_rows(
MagicMock(), "t1", [plan], {}, stop_kind="delivery"
)
assert len(paired) == 1
assert paired[0]["productName"] == "甲醇"
assert paired[0]["loadCustomer"] == internal
assert paired[0]["deliveryCustomer"] == "外部客户"
assert paired[0]["deliveryStopKind"] == "送货 #2"
assert "stopKind" not in paired[0]
assert len(load_only) == 1
assert load_only[0]["stopKind"] == "装货"
assert load_only[0]["loadCustomer"] == internal
assert load_only[0]["deliveryCustomer"] == ""
assert len(delivery_only) == 1
assert delivery_only[0]["stopKind"] == "送货 #2"
assert delivery_only[0]["deliveryCustomer"] == "外部客户"
assert delivery_only[0]["loadCustomer"] == ""
class _FakePlan: