fix(工资核算): 排除起付比例中的历史发货
旧应收已经由期初余额承接,启用前发货再次进入分母, 会使新业务足额回款仍未达到起付门槛。 将销售额日期范围与 FIFO 的启用边界保持一致, 补充普通历史日期及二月末的两项回归用例。
This commit is contained in:
parent
108bf87225
commit
019817d6dc
@ -25,7 +25,7 @@ from app.services import audit_service, formula, payroll_months
|
||||
from app.services.audit_service import AuditRecord
|
||||
from app.services.param_service import resolve_snapshot
|
||||
from app.services.tplus.calculation_preview import _parameters
|
||||
from app.services.tplus.fifo import _beneficiary, amount_text, money, preview_group
|
||||
from app.services.tplus.fifo import START, _beneficiary, amount_text, money, preview_group
|
||||
from app.services.tplus.workbench import digest
|
||||
|
||||
|
||||
@ -308,11 +308,13 @@ def _calculate_month(session, business, record, month, reason=None):
|
||||
}
|
||||
if set(previous) - current.keys():
|
||||
raise BadRequestError("历史已核算事件发生变化,请核对更正或调整,不可直接覆盖")
|
||||
# 启用前的发货由期初应收承接,不再进入新业务的起付比例分母。
|
||||
sales = sum(
|
||||
(
|
||||
money(s["amount"])
|
||||
for s in values["shipments"]
|
||||
if s["date"] <= until.isoformat() and not s.get("performance_excluded")
|
||||
if START.isoformat() <= s["date"] <= until.isoformat()
|
||||
and not s.get("performance_excluded")
|
||||
),
|
||||
Decimal(0),
|
||||
)
|
||||
|
||||
@ -22,6 +22,7 @@ from app.models import (
|
||||
Personnel,
|
||||
Product,
|
||||
Receipt,
|
||||
Shipment,
|
||||
ShipmentItem,
|
||||
TPlusSourceLink,
|
||||
TPlusWorkRun,
|
||||
@ -268,6 +269,61 @@ def test_起付百分之六十与平方权重(payroll_case, amount, performance,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("legacy_date", [date(2026, 2, 10), date(2026, 2, 28)])
|
||||
def test_历史发货不重复计入新业务起付分母(payroll_case, legacy_date):
|
||||
"""旧应收先冲抵,启用前发货不得再次压低新业务的回款比例。"""
|
||||
s, user, _ = payroll_case
|
||||
business = imported(payroll_case)
|
||||
record = payroll_calculation.latest_input(s, business.id)
|
||||
data = copy.deepcopy(record.data_json)
|
||||
legacy = Shipment(
|
||||
business_id=business.id,
|
||||
shipment_no="SH-LEGACY",
|
||||
ship_date=legacy_date,
|
||||
total_amount=Decimal("100"),
|
||||
freight_amount=Decimal("0"),
|
||||
)
|
||||
s.add(legacy)
|
||||
s.flush()
|
||||
original = s.get(ShipmentItem, data["maps"]["shipment_items"][data["shipments"][0]["line_id"]])
|
||||
item = ShipmentItem(
|
||||
shipment_id=legacy.id,
|
||||
product_id=original.product_id,
|
||||
product_name=original.product_name,
|
||||
spec_model=original.spec_model,
|
||||
unit=original.unit,
|
||||
quantity=Decimal("2"),
|
||||
sale_price=Decimal("50"),
|
||||
amount=Decimal("100"),
|
||||
)
|
||||
s.add(item)
|
||||
s.flush()
|
||||
data["shipments"].append(
|
||||
{
|
||||
**data["shipments"][0],
|
||||
"source_id": "99",
|
||||
"line_id": "99",
|
||||
"date": legacy_date.isoformat(),
|
||||
}
|
||||
)
|
||||
data["maps"]["shipments"]["99"] = legacy.id
|
||||
data["maps"]["shipment_items"]["99"] = item.id
|
||||
data["group"]["opening_balance"] = "100"
|
||||
data["receipts"][0]["amount"] = "200"
|
||||
s.get(Receipt, data["maps"]["receipts"][data["receipts"][0]["source_id"]]).amount = Decimal(
|
||||
"200"
|
||||
)
|
||||
replace_input(s, record, data)
|
||||
|
||||
result = payroll_calculation.calculate(s, business.id, "2026-03", operator=user)
|
||||
|
||||
assert result["start_payment_ok"] is True
|
||||
assert result["performance"] == result["payable"] == "0.20"
|
||||
allocations = list(s.scalars(select(PayrollAllocation)))
|
||||
assert sum(row.amount for row in allocations) == Decimal("100.00")
|
||||
assert all(row.data_json["shipment_date"] == "2026-03-10" for row in allocations)
|
||||
|
||||
|
||||
def test_跨月续算仅计应付差额且离职未发给接手人(payroll_case):
|
||||
s, user, _manager = payroll_case
|
||||
business = imported(payroll_case)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user