PurchaseReceiptWritebackTests.cs 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using Admin.NET.Plugin.AiDOP.MaterialWarehouse.InventoryPosting.Receipt;
  2. using Xunit;
  3. namespace Admin.NET.Plugin.AiDOP.Tests.S5.MaterialWarehouse;
  4. /// <summary>
  5. /// Phase 6C-2:C6 采购收货回写对账(据 pr_WMS_UpdatePurOrdRctTransactionProcessing2 LIVE:RctQty+=Accepted;完成 (收-退)>=订)。
  6. /// 纯计算 + 编排后 shadow 字段填充,供 L4 逐单对账。
  7. /// </summary>
  8. public class PurchaseReceiptWritebackTests
  9. {
  10. private const long Tenant = 797403760988229L;
  11. // §九 示例:订100 已收60 本次40 → 收满、余0、完成
  12. [Fact]
  13. public void Compute_PartialToComplete_MatchesLive()
  14. {
  15. var r = PurchaseReceiptWritebackCalculator.Compute(orderedQty: 100m, beforeReceivedQty: 60m, returnedQty: 0m, acceptedQty: 40m);
  16. Assert.Equal(60m, r.BeforeReceivedQty);
  17. Assert.Equal(40m, r.AcceptedQty);
  18. Assert.Equal(100m, r.AfterReceivedQty);
  19. Assert.Equal(40m, r.BeforeOutstandingQty);
  20. Assert.Equal(0m, r.AfterOutstandingQty);
  21. Assert.True(r.DetailCompleted);
  22. }
  23. [Fact]
  24. public void Compute_PartialNotComplete()
  25. {
  26. var r = PurchaseReceiptWritebackCalculator.Compute(100m, 20m, 0m, 30m);
  27. Assert.Equal(50m, r.AfterReceivedQty);
  28. Assert.Equal(50m, r.AfterOutstandingQty);
  29. Assert.False(r.DetailCompleted);
  30. }
  31. [Fact]
  32. public void Compute_WithReturn_CompletionUsesReceivedMinusReturned()
  33. {
  34. // 订100 已收100 退20 本次20 → (收120-退20)=100>=订 → 完成
  35. var r = PurchaseReceiptWritebackCalculator.Compute(100m, 100m, 20m, 20m);
  36. Assert.Equal(120m, r.AfterReceivedQty);
  37. Assert.Equal(0m, r.AfterOutstandingQty);
  38. Assert.True(r.DetailCompleted);
  39. }
  40. [Fact]
  41. public void Compute_OverReceipt_OutstandingNegative_Completed()
  42. {
  43. var r = PurchaseReceiptWritebackCalculator.Compute(100m, 90m, 0m, 20m);
  44. Assert.Equal(110m, r.AfterReceivedQty);
  45. Assert.Equal(-10m, r.AfterOutstandingQty); // 超收 → 余量负
  46. Assert.True(r.DetailCompleted);
  47. }
  48. // 编排后 C6 shadow 落库并含对账字段
  49. [Fact]
  50. public async Task Orchestrator_Populates_C6ShadowReconciliationFields()
  51. {
  52. var db = new FakeInventoryDatabase();
  53. db.SeedMaster(Tenant, "8010", "IT-1", "L1");
  54. var orch = new IqcReceiptOrchestrator(new FakeIqcReceiptUnitOfWorkFactory(db));
  55. var receipt = new IqcAcceptedReceipt
  56. {
  57. TenantId = Tenant, DomainCode = "8010", PostingId = 1, TransactionGroupId = 100, RctNbr = "RCT-1",
  58. ItemNum = "IT-1", Location = "L1", AcceptedQty = 40m, UmConversion = 1m,
  59. PurOrd = "PO-1", PurLine = 1, Potype = "po", OrderedQty = 100m, BeforeReceivedQty = 60m, ReturnedQty = 0m, User = "t",
  60. };
  61. var gate = new PurchaseReceiptGateInput { HasPendingReceipt = true, AcceptedQty = 40m, HasReceivableDetails = true };
  62. var r = await orch.PostAsync(receipt, gate);
  63. Assert.Equal(IqcReceiptOutcome.Success, r.Outcome);
  64. var key = $"{Tenant}|8010|1|PO-1|1";
  65. var wb = db.ReceiptWriteback[key];
  66. Assert.Equal(40m, wb.AcceptedQty);
  67. Assert.Equal(100m, wb.AfterReceivedQty);
  68. Assert.Equal(0m, wb.AfterOutstandingQty);
  69. Assert.True(wb.DetailCompleted);
  70. }
  71. }