"""手工业务再次准备时保留交接及已封存成本。""" 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, BusinessItem, BusinessRole, Customer, PayrollInput, Personnel, Shipment, ShipmentItem, User, ) from app.schemas.payroll import PayrollSetupIn from app.services import payroll_inputs, payroll_months from tests.unit.test_tplus_workbench import work_session as work_session def test_手工业务再次保存保留交接并拒绝指导单价微小变更(work_session, monkeypatch): session = work_session sales = session.scalar(select(BusinessRole).where(BusinessRole.role_code == "salesperson")) manager_role = BusinessRole(role_name="经理", role_code="sales_manager", calc_template="SALES_MANAGER", sort_order=2) customer = Customer(company_name="手工客户", owner_name="负责人", customer_type="personal") session.add_all([manager_role, customer]) session.flush() owner = Personnel(personnel_name="业务员", business_role_id=sales.id) receiver = Personnel(personnel_name="接手人员", business_role_id=sales.id) manager = Personnel(personnel_name="经理", business_role_id=manager_role.id) session.add_all([owner, receiver, manager]) session.flush() business = Business(business_no="MANUAL-01", customer_id=customer.id) session.add(business) session.flush() session.add(BusinessItem(business_id=business.id, product_name="管材", spec_model="", product_category="municipal_water", quantity=Decimal("5"), sale_amount=Decimal("500"))) shipment = Shipment(business_id=business.id, shipment_no="SH-MANUAL", ship_date=date(2026, 3, 10)) session.add(shipment) session.flush() item = ShipmentItem(shipment_id=shipment.id, product_name="管材", spec_model="", quantity=Decimal("5"), amount=Decimal("500")) session.add(item) session.commit() monkeypatch.setattr(payroll_months, "ensure_allocation_editable", lambda *args: None) payload = {"month": "2026-03", "evidence": "已核实", "opening_balance": "0", "history_confirmed": True, "guidance_finalized": True, "shipment_ownerships": [{"shipment_item_id": item.id, "personnel_id": owner.id, "manager_id": manager.id, "unit_cost": "1"}], "handovers": [{"business_key": business.business_no, "mode": "RESIGNATION", "from_personnel_id": str(owner.id), "to_personnel_id": str(receiver.id), "effective_date": "2026-03-20"}]} payroll_inputs.setup(session, business.id, PayrollSetupIn(**payload), session.get(User, 1)) retry = {**payload, "expected_version": 1} retry.pop("handovers") payroll_inputs.setup(session, business.id, PayrollSetupIn(**retry), session.get(User, 1)) latest = session.scalar(select(PayrollInput).order_by(PayrollInput.version.desc())) assert latest.data_json["facts"]["handovers"][0]["to_personnel_id"] == str(receiver.id) changed = {**retry, "expected_version": 2, "shipment_ownerships": [{**retry["shipment_ownerships"][0], "unit_cost": "1.0001"}]} with pytest.raises(BadRequestError, match="指导成本已封存"): payroll_inputs.setup(session, business.id, PayrollSetupIn(**changed), session.get(User, 1)) equivalent = {**changed, "shipment_ownerships": [{**changed["shipment_ownerships"][0], "unit_cost": "1.0000"}]} payroll_inputs.setup(session, business.id, PayrollSetupIn(**equivalent), session.get(User, 1)) payroll_inputs.setup(session, business.id, PayrollSetupIn(**{**equivalent, "expected_version": 3, "handovers": []}), session.get(User, 1)) latest = session.scalar(select(PayrollInput).order_by(PayrollInput.version.desc())) assert latest.data_json["facts"]["handovers"] == []