打通 T+ 快照、业务、发货、回款和核算准备链路,保留来源差异并提供待补状态。 新增业务自动接入任务、跨平台读取服务托管、权限复核、来源关联和前端核对页面。 补充迁移、隔离集成测试、浏览器模拟验收及角色授权边界修复。
96 lines
4.5 KiB
Python
96 lines
4.5 KiB
Python
"""月度指导价检查必须读取同账套的历史封存发货。"""
|
|
|
|
from datetime import date
|
|
from decimal import Decimal
|
|
|
|
import pytest
|
|
from sqlalchemy import select
|
|
|
|
from app.core.exceptions import BadRequestError
|
|
from app.models import (
|
|
Business,
|
|
Customer,
|
|
PayrollInput,
|
|
Product,
|
|
Shipment,
|
|
ShipmentItem,
|
|
TPlusBusinessDocument,
|
|
TPlusSourceLink,
|
|
User,
|
|
)
|
|
from app.schemas.business_source import GuidanceConfirmIn
|
|
from app.services import business_source
|
|
from app.services.tplus.guidance import frozen_guidance_shipments
|
|
from tests.unit.test_tplus_business_sync import dataset, sync
|
|
from tests.unit.test_tplus_workbench import work_session as work_session
|
|
|
|
|
|
def test_登记指导成本校验已应用的发货单版本(work_session, monkeypatch):
|
|
session = work_session
|
|
dataset(session, shipping=True)
|
|
sync(session)
|
|
business = session.scalar(select(Business))
|
|
item = session.scalar(select(ShipmentItem))
|
|
actor = session.get(User, 1)
|
|
monkeypatch.setattr(business_source, "source_snapshot_ready", lambda *_: True)
|
|
payload = GuidanceConfirmIn(shipment_item_id=item.id, amount="2.1234", evidence="核对指导成本")
|
|
|
|
created = business_source.confirm_guidance(session, business.id, payload, actor)
|
|
assert created["status"] == "CREATED"
|
|
assert business_source.confirm_guidance(session, business.id, payload, actor)["status"] == "REUSED"
|
|
parent = session.scalar(select(TPlusBusinessDocument).where(
|
|
TPlusBusinessDocument.entity_type == "shipments"
|
|
))
|
|
line = session.scalar(select(TPlusBusinessDocument).where(
|
|
TPlusBusinessDocument.entity_type == "shipment_items"
|
|
))
|
|
parent.applied_record_id = line.applied_record_id
|
|
session.commit()
|
|
with pytest.raises(BadRequestError, match="来源单据已变化"):
|
|
business_source.confirm_guidance(session, business.id, payload, actor)
|
|
|
|
|
|
def test_只返回来源产品与历史月份匹配的已封存发货(work_session):
|
|
session = work_session
|
|
customer = Customer(company_name="测试客户", owner_name="", customer_type="personal")
|
|
product = Product(product_name="测试产品", spec_model="", unit="根", product_category="municipal_water")
|
|
session.add_all([customer, product])
|
|
session.flush()
|
|
session.add(TPlusSourceLink(source_database="test_source", entity_type="products", source_id="9", target_id=product.id))
|
|
business = Business(business_no="GUIDE-HISTORY", customer_id=customer.id)
|
|
session.add(business)
|
|
session.flush()
|
|
shipment = Shipment(business_id=business.id, shipment_no="GUIDE-SHIP", ship_date=date(2026, 4, 1))
|
|
session.add(shipment)
|
|
session.flush()
|
|
item = ShipmentItem(shipment_id=shipment.id, product_id=product.id, product_name="测试产品", spec_model="",
|
|
unit="根", quantity=Decimal("2"), amount=Decimal("100"))
|
|
session.add(item)
|
|
session.flush()
|
|
record = {"line_id": "source-line-999", "product_id": "9", "date": "2026-03-10", "unit": "根", "unit_cost": "10"}
|
|
session.add_all([
|
|
PayrollInput(business_id=business.id, version=1, source_database="test_source", group_key="g",
|
|
fingerprint="a" * 64, data_json={"shipments": [record]}, requested_by=1),
|
|
PayrollInput(business_id=business.id, version=2, source_database="test_source", group_key="g",
|
|
fingerprint="b" * 64, data_json={"shipments": [{**record, "unit_cost": "11"}]}, requested_by=1),
|
|
])
|
|
session.flush()
|
|
rows = list(frozen_guidance_shipments(session, "test_source", "9", "2026-03"))
|
|
assert [row["unit_cost"] for row in rows] == ["10", "11"]
|
|
assert list(frozen_guidance_shipments(session, "test_source", "9", "2026-04")) == []
|
|
assert list(frozen_guidance_shipments(session, "other_source", "9", "2026-03")) == []
|
|
assert list(frozen_guidance_shipments(session, "test_source", "10", "2026-03")) == []
|
|
session.delete(item)
|
|
session.flush()
|
|
assert len(list(frozen_guidance_shipments(session, "test_source", "9", "2026-03"))) == 2
|
|
broken = session.get(PayrollInput, 1)
|
|
broken.data_json = {"shipments": [{**record, "product_id": None}]}
|
|
session.flush()
|
|
with pytest.raises(BadRequestError, match="缺少来源产品身份"):
|
|
list(frozen_guidance_shipments(session, "test_source", "9", "2026-03"))
|
|
broken = session.get(PayrollInput, 1)
|
|
broken.data_json = {"shipments": [{"date": "2026-03-10", "unit_cost": "10"}]}
|
|
session.flush()
|
|
with pytest.raises(BadRequestError, match="已封存发货数据异常"):
|
|
list(frozen_guidance_shipments(session, "test_source", "9", "2026-03"))
|