PurchaseOrderTransferService.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. namespace Admin.NET.Plugin.AiDOP.Supply;
  2. /// <summary>
  3. /// 采购申请转 DO/PO 服务。P4 初版仅处理本次生成的要货令 PR,不扫描历史 PR。
  4. /// </summary>
  5. public class PurchaseOrderTransferService : ITransient
  6. {
  7. private readonly ISqlSugarClient _db;
  8. private readonly NumberRuleService _numberRuleService;
  9. private readonly UserManager _userManager;
  10. public PurchaseOrderTransferService(ISqlSugarClient db, NumberRuleService numberRuleService, UserManager userManager)
  11. {
  12. _db = db;
  13. _numberRuleService = numberRuleService;
  14. _userManager = userManager;
  15. }
  16. public async Task<PurchaseOrderTransferResult> TransferGeneratedRequireGoodsAsync(List<PurchaseRequestMain> requests, string account)
  17. {
  18. var candidates = requests.Where(x => x.IsRequireGoods == 1).ToList();
  19. if (candidates.Count == 0) return new PurchaseOrderTransferResult();
  20. var createdOrders = new List<string>();
  21. var transferredPrIds = new List<long>();
  22. var groups = candidates
  23. .GroupBy(x => new
  24. {
  25. x.TenantId,
  26. x.CompanyId,
  27. x.FactoryId,
  28. x.PrPurchaseId,
  29. x.PrPurchaseNumber,
  30. x.PrPurchaseName,
  31. SupplierType = x.SupplierType ?? string.Empty
  32. })
  33. .ToList();
  34. foreach (var tenantGroup in groups.GroupBy(x => x.Key.TenantId.ToString()))
  35. {
  36. var groupList = tenantGroup.ToList();
  37. var purOrdNumbers = await _numberRuleService.NextBatchInCurrentTransactionAsync("DO", tenantGroup.Key, groupList.Count, account);
  38. if (purOrdNumbers.Count < groupList.Count || purOrdNumbers.Any(string.IsNullOrWhiteSpace))
  39. throw Oops.Oh($"当前DO/PO单号生成失败,请检查DO编号规则维护。Domain={tenantGroup.Key}");
  40. for (var i = 0; i < groupList.Count; i++)
  41. {
  42. var group = groupList[i];
  43. var purOrd = purOrdNumbers[i].Trim();
  44. var now = DateTime.Now;
  45. var supplierType = group.Key.SupplierType;
  46. var isOutsource = string.Equals(supplierType, "委外", StringComparison.OrdinalIgnoreCase);
  47. var poType = isOutsource ? "PW" : "po";
  48. var usage = isOutsource ? "委外加工" : supplierType;
  49. var buyer = ResolveBuyer(supplierType);
  50. var rows = group.OrderBy(x => x.PrSarriveDate).ThenBy(x => x.PrBillNo).ToList();
  51. await InsertPurchaseOrderMasterAsync(purOrd, poType, usage, buyer, group.Key.PrPurchaseNumber, now, account, group.Key.TenantId);
  52. var masterId = await _db.Ado.GetIntAsync(
  53. "SELECT IFNULL(MAX(RecID),0) FROM PurOrdMaster WHERE PurOrd=@PurOrd",
  54. new SugarParameter("@PurOrd", purOrd));
  55. if (masterId <= 0) throw Oops.Oh("DO/PO主表生成失败。");
  56. for (var lineIndex = 0; lineIndex < rows.Count; lineIndex++)
  57. {
  58. await InsertPurchaseOrderDetailAsync(purOrd, poType, masterId, lineIndex + 1, rows[lineIndex], account);
  59. rows[lineIndex].State = 4;
  60. rows[lineIndex].UpdateByName = account;
  61. rows[lineIndex].UpdateTime = now;
  62. transferredPrIds.Add(rows[lineIndex].Id);
  63. }
  64. createdOrders.Add(purOrd);
  65. }
  66. }
  67. return new PurchaseOrderTransferResult
  68. {
  69. CreatedOrderCount = createdOrders.Count,
  70. TransferredPrCount = transferredPrIds.Count,
  71. CreatedOrders = createdOrders,
  72. TransferredPrIds = transferredPrIds
  73. };
  74. }
  75. private async Task InsertPurchaseOrderMasterAsync(
  76. string purOrd,
  77. string poType,
  78. string? usage,
  79. string buyer,
  80. string? supplierCode,
  81. DateTime now,
  82. string account,
  83. long tenantId)
  84. {
  85. await _db.Ado.ExecuteCommandAsync(
  86. """
  87. INSERT INTO PurOrdMaster
  88. (
  89. Confirming, CreditTermsInt, Disc, ExchRate, EstVal, ExchRate1, ExchRate2,
  90. FixedPrice, FixedRate, Frt, PartialOK, AmtPrepaid, PrintPO, PST, Recurr,
  91. `Release`, Revision, Scheduled, ServiceCharge, SpecialCharge, Taxable,
  92. Tax1, Tax2, Tax3, TransportDays, IsActive, IsConfirm, Potype, IsChanged,
  93. TaxIn, Amt, IsPriceChanged,
  94. Buyer, Domain, PurOrd, OrdDate, ReqBy, Status, Supp, CreateUser, CreateTime,
  95. UpdateUser, UpdateTime, `Usage`, FSTID, Typed, tenant_id
  96. )
  97. VALUES
  98. (
  99. 0, 0, 0, 1, 0, 1, 1,
  100. 0, 0, 0, 1, 0, 0, 0, 0,
  101. 0, 0, 0, 0, 0, 1,
  102. 0, 0, 0, 0, 1, 1, @PoType, 0,
  103. 1, 0, 0,
  104. @Buyer, @Domain, @PurOrd, @Now, 'DO', '', @Supp, @CreateUser, @Now,
  105. @UpdateUser, @Now, @Usage, @FSTID, @Typed, @TenantId
  106. )
  107. """,
  108. new SugarParameter("@PoType", poType),
  109. new SugarParameter("@Buyer", buyer),
  110. new SugarParameter("@Domain", tenantId.ToString()),
  111. new SugarParameter("@PurOrd", purOrd),
  112. new SugarParameter("@Now", now),
  113. new SugarParameter("@Supp", supplierCode),
  114. new SugarParameter("@CreateUser", account),
  115. new SugarParameter("@UpdateUser", account),
  116. new SugarParameter("@Usage", usage),
  117. new SugarParameter("@FSTID", string.Equals(usage, "VMI", StringComparison.OrdinalIgnoreCase) ? "3" : string.Empty),
  118. new SugarParameter("@Typed", poType == "PW" ? "s" : string.Empty),
  119. new SugarParameter("@TenantId", tenantId <= 0 ? null : tenantId));
  120. }
  121. private async Task InsertPurchaseOrderDetailAsync(string purOrd, string poType, int masterId, int line, PurchaseRequestMain pr, string account)
  122. {
  123. var item = (await _db.Ado.SqlQueryAsync<ItemLookupRow>(
  124. """
  125. SELECT
  126. COALESCE(NULLIF(im.ItemNum,''), ic.number) AS ItemNum,
  127. COALESCE(NULLIF(im.Descr,''), ic.name) AS Descr,
  128. COALESCE(NULLIF(im.UM,''), ic.unit) AS UM,
  129. IFNULL(im.Location, '') AS Location,
  130. IFNULL(im.Rev, '') AS Rev,
  131. IFNULL(im.Drawing, '') AS Drawing
  132. FROM ic_item ic
  133. LEFT JOIN ItemMaster im ON ic.number = im.ItemNum
  134. WHERE ic.Id = @IcitemId
  135. LIMIT 1
  136. """,
  137. new SugarParameter("@IcitemId", pr.IcitemId))).FirstOrDefault();
  138. await _db.Ado.ExecuteCommandAsync(
  139. """
  140. INSERT INTO PurOrdDetail
  141. (
  142. QtyBO, RctCost, CreditTermsInt, UpdateCurrentCost, CumReceived1, CumReceived2,
  143. CumReceived3, CumReceived4, Disc, FixedPrice, InspectReq, SingleLot, SupplyPer,
  144. PurOrd, PST, PackingSlipQty, PayUMConv, PurCost, RctQty, QtyOrded, QtyReceived,
  145. QtyReturned, Active, QtyReleased, RctUMConversion, Scheduled, ScheduledChanged,
  146. SchedMRPReq, SafetyDays, SafetyHours, StdCost, Taxable, TaxIn, MaxTaxableAmt,
  147. TransportHours, UMConversion, VAT, IsActive, IsConfirm, Potype, IsChanged,
  148. TaxRate, IsRounding, ReceiptQty, BarCodeQty, IsClosed, QtyReturnedRefund, CumQtyBO,
  149. Line, ItemNum, Descr, UM, Rev, Drawing, Location, DueDate, NeedDate, LotSerial, PurOrdRecID, Status, Req,
  150. CreateUser, CreateTime, UpdateUser, UpdateTime, tenant_id
  151. )
  152. VALUES
  153. (
  154. 0, 0, 0, 0, 0, 0,
  155. 0, 0, 0, 0, 0, 0, 0,
  156. @PurOrd, 0, 0, 1, 0, 0, @QtyOrded, 0,
  157. 0, 1, 0, 1, 0, 0,
  158. 0, 0, 0, 0, 1, 1, 0,
  159. 0, 1, 0, 1, 1, @PoType, 0,
  160. 0, 0, 0, 0, 0, 0, 0,
  161. @Line, @ItemNum, @Descr, @UM, @Rev, @Drawing, @Location, @DueDate, @NeedDate, '', @PurOrdRecID, 'R', @Req,
  162. @CreateUser, @Now, @UpdateUser, @Now, @TenantId
  163. )
  164. """,
  165. new SugarParameter("@PurOrd", purOrd),
  166. new SugarParameter("@PoType", poType),
  167. new SugarParameter("@QtyOrded", pr.PrAqty ?? pr.PrSqty ?? pr.PrRqty ?? 0),
  168. new SugarParameter("@Line", line),
  169. new SugarParameter("@ItemNum", item?.ItemNum ?? pr.IcitemName ?? string.Empty),
  170. new SugarParameter("@Descr", item?.Descr ?? pr.IcitemName ?? string.Empty),
  171. new SugarParameter("@UM", item?.UM ?? pr.PrUnit ?? string.Empty),
  172. new SugarParameter("@Rev", item?.Rev ?? string.Empty),
  173. new SugarParameter("@Drawing", item?.Drawing ?? string.Empty),
  174. new SugarParameter("@Location", string.IsNullOrWhiteSpace(item?.Location) ? "1001" : item.Location),
  175. new SugarParameter("@DueDate", pr.PrSarriveDate),
  176. new SugarParameter("@NeedDate", pr.PrSarriveDate),
  177. new SugarParameter("@PurOrdRecID", masterId),
  178. new SugarParameter("@Req", pr.PrBillNo),
  179. new SugarParameter("@CreateUser", account),
  180. new SugarParameter("@UpdateUser", account),
  181. new SugarParameter("@Now", DateTime.Now),
  182. new SugarParameter("@TenantId", pr.TenantId <= 0 ? null : pr.TenantId));
  183. }
  184. private static string ResolveBuyer(string? supplierType)
  185. {
  186. return supplierType switch
  187. {
  188. "研发" => "130",
  189. "ECR" => "170",
  190. _ => "110"
  191. };
  192. }
  193. private sealed class ItemLookupRow
  194. {
  195. public string? ItemNum { get; set; }
  196. public string? Descr { get; set; }
  197. public string? UM { get; set; }
  198. public string? Location { get; set; }
  199. public string? Rev { get; set; }
  200. public string? Drawing { get; set; }
  201. }
  202. }
  203. public sealed class PurchaseOrderTransferResult
  204. {
  205. public int CreatedOrderCount { get; set; }
  206. public int TransferredPrCount { get; set; }
  207. public List<string> CreatedOrders { get; set; } = new();
  208. public List<long> TransferredPrIds { get; set; } = new();
  209. }