| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- using Admin.NET.Plugin.AiDOP.MaterialWarehouse.InventoryPosting.Receipt;
- using Xunit;
- namespace Admin.NET.Plugin.AiDOP.Tests.S5.MaterialWarehouse;
- /// <summary>
- /// Phase 6C-2:C6 采购收货回写对账(据 pr_WMS_UpdatePurOrdRctTransactionProcessing2 LIVE:RctQty+=Accepted;完成 (收-退)>=订)。
- /// 纯计算 + 编排后 shadow 字段填充,供 L4 逐单对账。
- /// </summary>
- public class PurchaseReceiptWritebackTests
- {
- private const long Tenant = 797403760988229L;
- // §九 示例:订100 已收60 本次40 → 收满、余0、完成
- [Fact]
- public void Compute_PartialToComplete_MatchesLive()
- {
- var r = PurchaseReceiptWritebackCalculator.Compute(orderedQty: 100m, beforeReceivedQty: 60m, returnedQty: 0m, acceptedQty: 40m);
- Assert.Equal(60m, r.BeforeReceivedQty);
- Assert.Equal(40m, r.AcceptedQty);
- Assert.Equal(100m, r.AfterReceivedQty);
- Assert.Equal(40m, r.BeforeOutstandingQty);
- Assert.Equal(0m, r.AfterOutstandingQty);
- Assert.True(r.DetailCompleted);
- }
- [Fact]
- public void Compute_PartialNotComplete()
- {
- var r = PurchaseReceiptWritebackCalculator.Compute(100m, 20m, 0m, 30m);
- Assert.Equal(50m, r.AfterReceivedQty);
- Assert.Equal(50m, r.AfterOutstandingQty);
- Assert.False(r.DetailCompleted);
- }
- [Fact]
- public void Compute_WithReturn_CompletionUsesReceivedMinusReturned()
- {
- // 订100 已收100 退20 本次20 → (收120-退20)=100>=订 → 完成
- var r = PurchaseReceiptWritebackCalculator.Compute(100m, 100m, 20m, 20m);
- Assert.Equal(120m, r.AfterReceivedQty);
- Assert.Equal(0m, r.AfterOutstandingQty);
- Assert.True(r.DetailCompleted);
- }
- [Fact]
- public void Compute_OverReceipt_OutstandingNegative_Completed()
- {
- var r = PurchaseReceiptWritebackCalculator.Compute(100m, 90m, 0m, 20m);
- Assert.Equal(110m, r.AfterReceivedQty);
- Assert.Equal(-10m, r.AfterOutstandingQty); // 超收 → 余量负
- Assert.True(r.DetailCompleted);
- }
- // 编排后 C6 shadow 落库并含对账字段
- [Fact]
- public async Task Orchestrator_Populates_C6ShadowReconciliationFields()
- {
- var db = new FakeInventoryDatabase();
- db.SeedMaster(Tenant, "8010", "IT-1", "L1");
- var orch = new IqcReceiptOrchestrator(new FakeIqcReceiptUnitOfWorkFactory(db));
- var receipt = new IqcAcceptedReceipt
- {
- TenantId = Tenant, DomainCode = "8010", PostingId = 1, TransactionGroupId = 100, RctNbr = "RCT-1",
- ItemNum = "IT-1", Location = "L1", AcceptedQty = 40m, UmConversion = 1m,
- PurOrd = "PO-1", PurLine = 1, Potype = "po", OrderedQty = 100m, BeforeReceivedQty = 60m, ReturnedQty = 0m, User = "t",
- };
- var gate = new PurchaseReceiptGateInput { HasPendingReceipt = true, AcceptedQty = 40m, HasReceivableDetails = true };
- var r = await orch.PostAsync(receipt, gate);
- Assert.Equal(IqcReceiptOutcome.Success, r.Outcome);
- var key = $"{Tenant}|8010|1|PO-1|1";
- var wb = db.ReceiptWriteback[key];
- Assert.Equal(40m, wb.AcceptedQty);
- Assert.Equal(100m, wb.AfterReceivedQty);
- Assert.Equal(0m, wb.AfterOutstandingQty);
- Assert.True(wb.DetailCompleted);
- }
- }
|