using System.Globalization; using Microsoft.Extensions.Options; using Yitter.IdGenerator; namespace Admin.NET.Plugin.AiDOP.Supply; /// /// 采购申请外部事务推送服务。对齐旧 PrSendSAP:写 QadTracking;真实 SAP/QAD 默认关闭。 /// public class PurchaseRequestExternalPushService : ITransient { private readonly ISqlSugarClient _db; private readonly AidopProcurementOptions _options; public PurchaseRequestExternalPushService(ISqlSugarClient db, IOptions options) { _db = db; _options = options.Value ?? new AidopProcurementOptions(); } public async Task CreateQadTrackingForGeneratedRequestsAsync(List requests, string account) { var result = new PurchaseRequestExternalPushResult(); var candidates = SelectPushCandidates(requests); if (candidates.Count == 0) return result; if (_options.EnableRealSapPush) result.Warnings.Add("EnableRealSapPush=true,但真实 SAP/QAD 接口未接入,仍仅写 QadTracking 事务记录。"); if (!await QadTrackingTableExistsAsync()) { result.Warnings.Add("QadTracking 表不存在,已跳过外部事务写入(主事务不回滚)。"); result.SkippedCandidateCount = candidates.Count; return result; } var pushedIds = new List(); foreach (var group in candidates.GroupBy(x => x.TenantId.ToString())) { var seqId = GenerateSeqId(); foreach (var pr in group) { await _db.Ado.ExecuteCommandAsync( """ INSERT INTO QadTracking (Ufld1, Domain, SeqID, TransType, Subject, `Order`, `Int1`, CreateTime, CreateUser, UpdateTime, UpdateUser) VALUES ('C', @Domain, @SeqID, 'nbr-pr-mes', '请购单', @Order, @Int1, @Now, @User, @Now, @User) """, new SugarParameter("@Domain", group.Key), new SugarParameter("@SeqID", seqId), new SugarParameter("@Order", pr.PrBillNo), new SugarParameter("@Int1", pr.Id), new SugarParameter("@Now", DateTime.Now), new SugarParameter("@User", account ?? string.Empty)); pr.State = 2; pr.UpdateByName = account; pr.UpdateTime = DateTime.Now; pushedIds.Add(pr.Id); seqId++; } } result.TrackingCount = pushedIds.Count; result.PushedPrIds = pushedIds; return result; } public static List SelectPushCandidates(IEnumerable requests) { return requests .Where(x => x.IsRequireGoods == 0 && (x.State ?? 0) == 1 && !string.IsNullOrWhiteSpace(x.PrBillNo)) .ToList(); } private async Task QadTrackingTableExistsAsync() { var cnt = await _db.Ado.GetIntAsync( """ SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'QadTracking' """); return cnt > 0; } private static long GenerateSeqId() { var now = DateTime.Now; var value = string.Concat( now.ToString("yyMMddHHmmss", CultureInfo.InvariantCulture), now.Millisecond.ToString("D3", CultureInfo.InvariantCulture), Random.Shared.Next(0, 1000).ToString("D3", CultureInfo.InvariantCulture)); return long.TryParse(value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out var seqId) ? seqId + 1 : YitIdHelper.NextId(); } } public sealed class PurchaseRequestExternalPushResult { public int TrackingCount { get; set; } public int SkippedCandidateCount { get; set; } public List PushedPrIds { get; set; } = new(); public List Warnings { get; set; } = new(); }