using NLog; using POSV.Entity; using POSV.HttpApi; using POSV.HttpResponse; using POSV.MessageEvent; using POSV.ShoppingCart; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace POSV.Utils { public class SplitPayUtils : BaseApi { private static Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static object _lock = new object(); private static SplitPayUtils _instance = null; public static SplitPayUtils Instance { get { if (_instance == null) { lock (_lock) { _instance = new SplitPayUtils(); } } return _instance; } } public bool SaveSplitPayInfo(OrderObject orderObject) { Stopwatch sw = new Stopwatch(); var isExist = false; try { sw.Start(); logger.Info($"开始保存订单<{orderObject.TradeNo}>的分账信息"); var _pid = IdWorkerUtils.Instance.NextId(); using (var db = Global.Instance.OpenDataBase) { using (var trans = db.GetTransaction()) { var tmpLst = db.Query($"where busNo='{orderObject.TradeNo}'").ToList(); if (tmpLst != null) { if (tmpLst.Count() > 0) { isExist = true; logger.Info($"订单<{orderObject.TradeNo}>的分账信息已存在,不需要分账"); if (orderObject.IsSplited == 0) { var sql = $"update pos_order set isSplited=1 where id={orderObject.Id};"; logger.Info($"日订单<{orderObject.TradeNo}>分账信息已存在,更改分账状态isSplited==>1"); db.Execute(sql); } } } if (!isExist) { #region subin 2023-07-24 add 分账信息 var productIds = ""; //var accountIds = ""; var splitStorePayLst = new List(); var splitFoodList = new List(); var productIdList = orderObject.Items.Select(item => item.ProductId).Distinct(); if (productIdList != null && productIdList.Count() > 0) { productIds = string.Join(",", productIdList); splitFoodList = db.Query($"where goodId in ('{productIds.Replace(",", "','")}');").ToList(); } var _fromBizUserId = ""; if (!string.IsNullOrEmpty(Global.Instance.Worker.StoreInfo.Ext1)) { _fromBizUserId = JsonUtils.Deserialize(Global.Instance.Worker.StoreInfo.Ext1).BizUserId; } else { logger.Info($"订单<{orderObject.TradeNo}>分账,未配置门店扩展信息(Ext1)"); } if (orderObject.OrderType == OrderType.堂食 || orderObject.OrderType == OrderType.外带 || orderObject.OrderType == OrderType.餐桌) { int i = 0; foreach (var item in orderObject.Items) { foreach (var p in item.ItemPayList) { //if (p.No != "50") continue; var s = splitFoodList.FirstOrDefault(m => m.ProductId == p.ProductId); if (s != null) { var pay = orderObject.Pays.FirstOrDefault(m => m.Id == p.PayId); var ssp = new SplitStorePay { Id = IdWorkerUtils.Instance.NextId(), ClientId = "", ProgramId = "", TenantId = p.TenantId, StoreId = orderObject.StoreId, SplitStoreId = s.ShopId, StoreNo = orderObject.StoreNo, PayNo = pay.PayNo, TicketId = orderObject.TicketId, BusNo = pay.TradeNo, PayTypeNo = p.No, PayType = p.Name, Paid = p.ShareAmount, Rchange = 0, Money = p.ShareAmount, OverAmount = 0, VoucherNo = pay.TradeVoucherNo, PayDate = pay.FinishDate, CardNo = pay.CardNo, IncomeFlag = pay.IncomeFlag, OtherRateType = pay.OtherRateType, OtherRateValue = pay.OtherRateValue, OtherRate = pay.OtherRate, PayClientType = -1, PayChannel = (int)pay.PayChannel, DeductionRate = 0, ChargeBack = 0, Memo = orderObject.Ext1, IsInvalid = "0", OrderId = pay.OrderId, OrderItemId = item.Id, PayId = p.PayId, PayItemId = p.Id, SyncStatus = 0, UploadErrors = 0, UploadStatus = 0, UploadMessage = "", ProductId = item.ProductId, RefundAmount = item.MiddleRefundQuantity * item.SalePrice, FromBizUserld = _fromBizUserId, OrderType = (int)orderObject.OrderType, IsRefund = item.MiddleRefundQuantity > 0 ? 1 : 0, Quantity = item.Quantity, RefundQuantity = item.MiddleRefundQuantity, Pid = _pid }; if (i == 0) { ssp.fee = string.IsNullOrEmpty(pay.Ext2) ? 0 : Convert.ToDecimal(pay.Ext2); //ssp.Paid = ssp.Paid - ssp.fee; } splitStorePayLst.Add(ssp); //logger.Info($"订单<{orderObject.TradeNo}>[orderType:{orderObject.OrderType}]分账组装数据,data:{JsonUtils.Serialize(ssp)}"); } i++; } } } else if (orderObject.OrderType == OrderType.微信点餐) { int i = 0; var splitShopList = db.Fetch(); foreach (var pay in orderObject.Pays) { //if (pay.No != "50") continue; foreach (var item in orderObject.Items) { var s = splitFoodList.FirstOrDefault(m => m.ProductId == item.ProductId); if (s != null) { var _fromBizUser = splitShopList.FirstOrDefault(m => m.Id == s.ShopId); _fromBizUserId = _fromBizUser != null ? _fromBizUser.BizUserId : ""; var ssp = new SplitStorePay { Id = IdWorkerUtils.Instance.NextId(), ClientId = "", ProgramId = "", TenantId = item.TenantId, StoreId = orderObject.StoreId, SplitStoreId = s.ShopId, StoreNo = orderObject.StoreNo, PayNo = pay.PayNo, TicketId = orderObject.TicketId, BusNo = pay.TradeNo, PayTypeNo = pay.No, PayType = pay.Name, Paid = item.TotalAmonut, Rchange = 0, Money = item.TotalAmonut, OverAmount = 0, VoucherNo = pay.TradeVoucherNo, PayDate = pay.FinishDate, CardNo = pay.CardNo, IncomeFlag = pay.IncomeFlag, OtherRateType = pay.OtherRateType, OtherRateValue = pay.OtherRateValue, OtherRate = pay.OtherRate, PayClientType = -1, PayChannel = (int)pay.PayChannel, DeductionRate = 0, ChargeBack = 0, Memo = orderObject.Ext1, IsInvalid = "0", OrderId = orderObject.Id, PayId = pay.Id, SyncStatus = 0, UploadErrors = 0, UploadStatus = 0, UploadMessage = "", ProductId = item.ProductId, OrderItemId = item.Id, PayItemId = "", RefundAmount = item.MiddleRefundQuantity * item.SalePrice, //FromBizUserld = JsonUtils.Deserialize(Global.Instance.Worker.StoreInfo.Ext1).BizUserId, FromBizUserld = _fromBizUserId, OrderType = (int)orderObject.OrderType, IsRefund = item.MiddleRefundQuantity > 0 ? 1 : 0, Quantity = item.Quantity, RefundQuantity = item.MiddleRefundQuantity, Pid = _pid }; if (i == 0) { ssp.fee = string.IsNullOrEmpty(pay.Ext2) ? 0 : Convert.ToDecimal(pay.Ext2); //ssp.Paid = ssp.Paid - ssp.fee; } splitStorePayLst.Add(ssp); //logger.Info($"订单<{orderObject.TradeNo}>[orderType:{orderObject.OrderType}]分账组装数据,data:{JsonUtils.Serialize(ssp)}"); } i++; } } } else if (orderObject.OrderType == OrderType.美团外卖) { int i = 0; var splitShopList = db.Fetch(); foreach (var pay in orderObject.Pays) { //if (pay.No != "50") continue; foreach (var item in orderObject.Items) { var s = splitFoodList.FirstOrDefault(m => m.ProductId == item.ProductId); if (s != null) { var _fromBizUser = splitShopList.FirstOrDefault(m => m.Id == s.ShopId); _fromBizUserId = _fromBizUser != null ? _fromBizUser.BizUserId : ""; var ssp = new SplitStorePay { Id = IdWorkerUtils.Instance.NextId(), ClientId = "", ProgramId = "", TenantId = item.TenantId, StoreId = orderObject.StoreId, SplitStoreId = s.ShopId, StoreNo = orderObject.StoreNo, PayNo = pay.PayNo, TicketId = orderObject.TicketId, BusNo = pay.TradeNo, PayTypeNo = pay.No, PayType = pay.Name, Paid = item.TotalAmonut, Rchange = 0, Money = item.TotalAmonut, OverAmount = 0, VoucherNo = pay.TradeVoucherNo, PayDate = pay.FinishDate, CardNo = pay.CardNo, IncomeFlag = pay.IncomeFlag, OtherRateType = pay.OtherRateType, OtherRateValue = pay.OtherRateValue, OtherRate = pay.OtherRate, PayClientType = -1, PayChannel = (int)pay.PayChannel, DeductionRate = 0, ChargeBack = 0, Memo = orderObject.Ext1, IsInvalid = "0", OrderId = orderObject.Id, PayId = pay.Id, SyncStatus = 0, UploadErrors = 0, UploadStatus = 0, UploadMessage = "", ProductId = item.ProductId, OrderItemId = item.Id, PayItemId = "", RefundAmount = item.RefundQuantity * item.SalePrice, //FromBizUserld = JsonUtils.Deserialize(Global.Instance.Worker.StoreInfo.Ext1).BizUserId, FromBizUserld = _fromBizUserId, OrderType = (int)orderObject.OrderType, IsRefund = item.RefundQuantity > 0 ? 1 : 0, Quantity = item.Quantity, RefundQuantity = item.RefundQuantity, Pid = _pid }; if (i == 0) { ssp.fee = string.IsNullOrEmpty(pay.Ext2) ? 0 : Convert.ToDecimal(pay.Ext2); //ssp.Paid = ssp.Paid - ssp.fee; } splitStorePayLst.Add(ssp); //logger.Info($"订单<{orderObject.TradeNo}>[orderType:{orderObject.OrderType}]分账组装数据,data:{JsonUtils.Serialize(ssp)}"); } i++; } } } var splitStoreProductLst = splitStorePayLst.Select(item => item.ProductId).Distinct().ToList(); if (productIdList.Count() > splitStorePayLst.Count) { isExist = true; logger.Info($"订单<{orderObject.TradeNo}>分账数据异常!,订单菜品数量({productIds})>分店关联菜品数量({string.Join(",", splitStoreProductLst)})"); } if (splitStorePayLst.Count > 0) { //增加订单的分账总记录 var pssp = new SplitStorePay { Id = _pid, ClientId = "", ProgramId = "", TenantId = Global.Instance.Worker.TenantId, StoreId = Global.Instance.Worker.StoreId, SplitStoreId = "", StoreNo = Global.Instance.Worker.StoreInfo.No, PayNo = splitStorePayLst[0].PayNo, TicketId = orderObject.TicketId, BusNo = orderObject.TradeNo, PayTypeNo = splitStorePayLst.Where(m => m.PayTypeNo == "50").Count() > 0 ? "50" : "0", PayType = splitStorePayLst.Where(m => m.PayTypeNo == "50").Count() > 0 ? "通联支付" : "", Paid = splitStorePayLst.Sum(m => m.Paid), Rchange = splitStorePayLst.Sum(m => m.Rchange), Money = splitStorePayLst.Sum(m => m.Money), OverAmount = splitStorePayLst.Sum(m => m.OverAmount), VoucherNo = splitStorePayLst[0].VoucherNo, PayDate = splitStorePayLst[0].PayDate, CardNo = "", IncomeFlag = 1, OtherRateType = 0, OtherRateValue = 0, OtherRate = splitStorePayLst.Sum(m => m.OtherRate), PayClientType = -1, PayChannel = 50, DeductionRate = 0, ChargeBack = splitStorePayLst.Sum(m => m.ChargeBack), Memo = orderObject.Ext1, IsInvalid = "0", OrderId = orderObject.Id, PayId = "", SyncStatus = 0,//0-新增,1-已同步,2-问题单 UploadErrors = 0, UploadStatus = 0, UploadMessage = "", ProductId = "", OrderItemId = "", PayItemId = "", RefundAmount = splitStorePayLst.Sum(m => m.RefundAmount), //FromBizUserld = JsonUtils.Deserialize(Global.Instance.Worker.StoreInfo.Ext1).BizUserId, FromBizUserld = _fromBizUserId, OrderType = (int)orderObject.OrderType, IsRefund = splitStorePayLst.Where(m => m.IsRefund == 1).Count() > 0 ? 1 : 0, fee = splitStorePayLst.Sum(m => m.fee), Quantity = splitStorePayLst.Sum(m => m.Quantity), RefundQuantity = splitStorePayLst.Sum(m => m.RefundQuantity) }; splitStorePayLst.Add(pssp); db.InsertBatch(splitStorePayLst.OrderBy(m => m.Id)); //logger.Info("有需要上传的营业分账数据,isHaveUpLoadSplitPay = true"); Global.isHaveUpLoadSplitPay = true; trans.Complete(); } else { isExist = true; logger.Info($"订单<{orderObject.TradeNo}没有要分账的菜品信息,将不保存分账信息。"); } #endregion } else { trans.Complete(); } } } logger.Info($"完成保存订单<{orderObject.TradeNo}>的分账信息"); } catch (Exception ex) { isExist = true; logger.Error(ex, $"保存订单<{orderObject.TradeNo}的分账信息异常"); } finally { sw.Stop(); logger.Info($"保存订单<{orderObject.TradeNo}>的分账信息时长<{sw.ElapsedMilliseconds}>"); } return isExist; } /// /// /// /// 原订单信息 /// 退款订单信息 public void UpdateRefund(OrderObject orderObject, OrderObject backOrderObject) { var oldSplitPay = new SplitStorePay(); var updateData = new List(); var SplitStorePayEntityLst = new List(); Stopwatch sw = new Stopwatch(); sw.Start(); logger.Info("退款成功后开始修改分账信息"); try { using (var db = Global.Instance.OpenDataBase) { var splitPayLst = db.Fetch("where orderId=@0;", orderObject.Id); decimal fee = 0; var allinPay = backOrderObject.Pays.FirstOrDefault(m => m.No == "50"); if (allinPay != null) { var str = allinPay.Ext2; if (!string.IsNullOrEmpty(str)) { fee = Convert.ToDecimal(str); } } if (backOrderObject.OrderType == OrderType.堂食 || backOrderObject.OrderType == OrderType.外带 || backOrderObject.OrderType == OrderType.餐桌) { foreach (var item in backOrderObject.Items) { //var splitPay = splitPayLst.FirstOrDefault(m => m.OrderId == orderObject.Id && m.OrderItemId == item.Id && m.PayItemId == pay.Id); var splitPay = splitPayLst.FirstOrDefault(m => m.OrderId == orderObject.Id && m.ProductId == item.ProductId); if (splitPay != null) { splitPay.IsRefund = 1; splitPay.RefundAmount += item.TotalAmonut; splitPay.RefundQuantity += item.RefundQuantity; updateData.Add(splitPay); var parent = splitPayLst.FirstOrDefault(m => m.Id == splitPay.Pid); if (parent != null) { parent.IsRefund = 1; parent.RefundAmount += item.TotalAmonut; parent.RefundQuantity += item.RefundQuantity; updateData.Add(parent); } if (!string.IsNullOrEmpty(splitPay.TicketId) && splitPay.SyncStatus == 1) { var entity = new SplitStorePayEntity { Id = splitPay.Id, ClientId = splitPay.ClientId, ProgramId = splitPay.ProductId, TenantId = splitPay.TenantId, StoreId = splitPay.StoreId, SplitStoreId = splitPay.SplitStoreId, StoreNo = splitPay.StoreNo, PayNo = splitPay.PayNo, TicketId = splitPay.TicketId, BusNo = splitPay.BusNo, PayTypeNo = splitPay.PayTypeNo, PayType = splitPay.PayType, Paid = splitPay.Paid, Rchange = splitPay.Rchange, Money = splitPay.Money, OverAmount = splitPay.OverAmount, VoucherNo = splitPay.VoucherNo, PayDate = splitPay.PayDate, CardNo = splitPay.CardNo, IncomeFlag = splitPay.IncomeFlag, OtherRateType = splitPay.OtherRateType, OtherRateValue = splitPay.OtherRateValue, OtherRate = splitPay.OtherRate, PayClientType = splitPay.PayClientType, PayChannel = splitPay.PayChannel, DeductionRate = splitPay.DeductionRate, ChargeBack = splitPay.ChargeBack, Memo = splitPay.Memo, IsInvalid = splitPay.IsInvalid, OrderId = splitPay.OrderId, OrderItemId = splitPay.OrderItemId, PayId = splitPay.PayId, PayItemId = splitPay.PayItemId, SyncStatus = splitPay.SyncStatus, UploadErrors = splitPay.UploadErrors, UploadStatus = splitPay.UploadStatus, UploadMessage = splitPay.UploadMessage, ProductId = splitPay.ProductId, RefundAmount = splitPay.RefundAmount, FromBizUserld = splitPay.FromBizUserld, OrderType = splitPay.OrderType, IsRefund = splitPay.IsRefund, Quantity = splitPay.Quantity, RefundQuantity = splitPay.RefundQuantity, TableNo = orderObject.TableNo, People = orderObject.People.ToString(), OrdTicketId = orderObject.TicketId, WorkerNo = orderObject.WorkerNo, UploadErrCode = splitPay.UploadErrCode, UploadErrMessage = splitPay.UploadErrMessage, UploadTime = splitPay.UploadTime, fee = splitPay.fee, Goodid = splitPay.ProductId, //UnitPrice="" }; SplitStorePayEntityLst.Add(entity); } } } } else if (backOrderObject.OrderType == OrderType.微信点餐) { foreach (var item in backOrderObject.Items) { var splitPay = splitPayLst.FirstOrDefault(m => m.OrderId == orderObject.Id && m.ProductId == item.ProductId); if (splitPay != null) { splitPay.IsRefund = 1; splitPay.RefundAmount += item.TotalAmonut * -1; splitPay.RefundQuantity = item.RefundQuantity; updateData.Add(splitPay); var parent = splitPayLst.FirstOrDefault(m => m.Id == splitPay.Pid); if (parent != null) { parent.IsRefund = 1; parent.RefundAmount += splitPay.RefundAmount; parent.RefundQuantity += item.MiddleRefundQuantity; //parent.fee += fee; updateData.Add(parent); } if (!string.IsNullOrEmpty(splitPay.TicketId) && splitPay.SyncStatus == 1) { var entity = new SplitStorePayEntity { Id = splitPay.Id, ClientId = splitPay.ClientId, ProgramId = splitPay.ProductId, TenantId = splitPay.TenantId, StoreId = splitPay.StoreId, SplitStoreId = splitPay.SplitStoreId, StoreNo = splitPay.StoreNo, PayNo = splitPay.PayNo, TicketId = splitPay.TicketId, BusNo = splitPay.BusNo, PayTypeNo = splitPay.PayTypeNo, PayType = splitPay.PayType, Paid = splitPay.Paid, Rchange = splitPay.Rchange, Money = splitPay.Money, OverAmount = splitPay.OverAmount, VoucherNo = splitPay.VoucherNo, PayDate = splitPay.PayDate, CardNo = splitPay.CardNo, IncomeFlag = splitPay.IncomeFlag, OtherRateType = splitPay.OtherRateType, OtherRateValue = splitPay.OtherRateValue, OtherRate = splitPay.OtherRate, PayClientType = splitPay.PayClientType, PayChannel = splitPay.PayChannel, DeductionRate = splitPay.DeductionRate, ChargeBack = splitPay.ChargeBack, Memo = splitPay.Memo, IsInvalid = splitPay.IsInvalid, OrderId = splitPay.OrderId, OrderItemId = splitPay.OrderItemId, PayId = splitPay.PayId, PayItemId = splitPay.PayItemId, SyncStatus = splitPay.SyncStatus, UploadErrors = splitPay.UploadErrors, UploadStatus = splitPay.UploadStatus, UploadMessage = splitPay.UploadMessage, ProductId = splitPay.ProductId, RefundAmount = splitPay.RefundAmount, FromBizUserld = splitPay.FromBizUserld, OrderType = splitPay.OrderType, IsRefund = splitPay.IsRefund, Quantity = splitPay.Quantity, RefundQuantity = splitPay.RefundQuantity, TableNo = orderObject.TableNo, People = orderObject.People.ToString(), OrdTicketId = orderObject.TicketId, WorkerNo = orderObject.WorkerNo, UploadErrCode = splitPay.UploadErrCode, UploadErrMessage = splitPay.UploadErrMessage, UploadTime = splitPay.UploadTime, fee = splitPay.fee, Goodid = splitPay.ProductId, //UnitPrice="" }; SplitStorePayEntityLst.Add(entity); } } } } var feeSplitPay = splitPayLst.FirstOrDefault(m => m.fee > 0 && m.Pid != null); if (feeSplitPay != null) { feeSplitPay.IsRefund = 1; feeSplitPay.fee -= Math.Abs(fee); updateData.Add(feeSplitPay); var parent = splitPayLst.FirstOrDefault(m => m.Id == feeSplitPay.Pid); if (parent != null) { parent.fee -= Math.Abs(fee); updateData.Add(parent); } } using (var trans = db.GetTransaction()) { foreach (var item in updateData) { db.Update(item); } trans.Complete(); //logger.Info($"退款成功后,更新本地分账信息:成功,json:" + JsonUtils.Serialize(updateData)); logger.Info($"退款成功后,更新本地分账信息:成功"); } } } catch (Exception ex) { logger.Error(ex, $"退款成功后修改分账信息错误,订单号:{backOrderObject.TradeNo},原订单号:{orderObject.TradeNo}"); } finally { sw.Stop(); logger.Info("退款成功后本地修改分账信息结束<{0}>", sw.ElapsedMilliseconds); } if (SplitStorePayEntityLst.Count > 0) { sw.Start(); logger.Info("退款成功后开始修改服务端分账信息"); var api = new SplitPayApi(); foreach (var entity in SplitStorePayEntityLst) { var result = api.UpdateSplitPay(entity); if (result.Item1) { //logger.Info($"退款成功后,更新服务端原分账信息:成功,json:" + JsonUtils.Serialize(entity)); logger.Info($"退款成功后,更新服务端原分账信息:成功。"); } else { //logger.Info($"退款成功后,更新服务端原分账信息:失败,json:" + JsonUtils.Serialize(entity)); logger.Info($"退款成功后,更新服务端原分账信息:失败。"); } Thread.Sleep(100); } sw.Stop(); logger.Info("退款成功后修改服务端分账信息结束<{0}>", sw.ElapsedMilliseconds); } else { logger.Info("退款成功后未查询到服务端分账信息,不做更新"); } } public bool Order2Split(DateTime date) { lock (Global.Instance.SyncLock) { bool isException = false; var count = 0; var sDate = date.ToString("yyyy-MM-dd 00:00:00"); var eDate = date.AddDays(1).ToString("yyyy-MM-dd 00:00:00"); logger.Info($"开始日订单[{date.ToString("yyyy-MM-dd")}]的分账信息存储处理..."); var proValue = 0; var proMaxValue = 400; Stopwatch sw = new Stopwatch(); sw.Start(); var pageSize = 150; var lists = new List(); //单据明细 var items = new List(); //支付明细 var pays = new List(); //支付方式分摊明细 var itemPays = new List(); var index = 0; try { while (index < 2) { using (var db = Global.Instance.OpenDataBase) { //var delSql = "delete from pos_split_store_pay where syncStatus = 1 and uploadStatus = 1;"; //db.Execute(delSql); count = db.Query($"where isSplited = 0 and finishDate between '{sDate}' and '{eDate}';").Count(); //主单数据 //lists = db.Query("where syncStatus = 0 and uploadErrors < 3000 order by uploadErrors limit @0;", 1).ToList(); var tmpPress = 0; if (count != 0) { tmpPress = proMaxValue / 2 / count == 0 ? 1 : proMaxValue / 2 / count; } var pageCount = count % pageSize != 0 ? (count / pageSize) + 1 : count / pageSize; logger.Info($"日订单[{date.ToString("yyyy-MM-dd")}]<{count}>条,页尺寸<{pageSize}>,共<{pageCount}>页"); var sqlList = new ConcurrentQueue(); for (int i = 0; i < pageCount; i++) { logger.Info($"日订单[{date.ToString("yyyy-MM-dd")}],分账[index:{index + 1}]第<{i + 1}>页订单数据"); lists = db.Query($"where isSplited = 0 and finishDate between '{sDate}' and '{eDate}' limit ({i * pageSize}), {pageSize};").ToList(); var ids = string.Join("','", lists.ConvertAll(x => x.Id).ToArray()); var nos = string.Join("','", lists.ConvertAll(x => x.TradeNo).ToArray()); logger.Info($"日订单[{date.ToString("yyyy-MM-dd")}],分账[index:{index + 1}]第<{i + 1}>页订单数据:{nos}"); var condition = " where orderId in ('" + ids + "');"; //单据明细 items = db.Query(condition).ToList(); //支付明细 pays = db.Query(condition).ToList(); itemPays = db.Query(condition).ToList(); foreach (var orderObject in lists) { orderObject.Items = items.FindAll(x => x.OrderId == orderObject.Id); //将支付方式附加到主单 orderObject.Pays = pays.FindAll(x => x.OrderId == orderObject.Id); foreach (var item in orderObject.Items) { item.ItemPayList = itemPays.FindAll(x => x.OrderId == orderObject.Id & x.ItemId == item.Id); } } if (lists.Count > 0) { var p = 0; foreach (var orderObject in lists) { logger.Info($"日订单[{date.ToString("yyyy-MM-dd")}]<{orderObject.TradeNo}>分账信息处理..."); var isExist = SaveSplitPayInfo(orderObject); if (!isExist) { var sql = $"update pos_order set isSplited=1 where id={orderObject.Id};"; logger.Info($"日订单[{date.ToString("yyyy-MM-dd")}]<{orderObject.TradeNo}>更改分账状态isSplited==>1"); sqlList.Enqueue(sql); } else { logger.Info($"日订单[{date.ToString("yyyy-MM-dd")}]<{orderObject.TradeNo}>的分账信息存储异常"); } Thread.Sleep(100); //if (proValue < proMaxValue / (2 - index)) // proValue = (proMaxValue / (2 - index) * index) + tmpPress * ((p + 1) + pageSize * i); proValue++; MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, proValue); p++; } } else { logger.Info($"日订单[{date.ToString("yyyy-MM-dd")}],[index:{index + 1}]第<{i + 1}>页订单数据无可分账数据"); //proValue = pageSize * (i + 1); //if (proValue < proMaxValue / (2 - index)) //{ // MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, proValue); //} //else //{ // MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, proMaxValue / (2 - index)); //} proValue = count * (index + 1); MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, proValue); } } SqliteUtils.ExecuteTransaction(sqlList); index++; } } } catch (Exception ex) { isException = true; logger.Error(ex, "日订单的分账信息存储错误<{0}>"); } finally { sw.Stop(); logger.Info("日订单<{0}>的分账信息存储结束<{1}>", count, sw.ElapsedMilliseconds); MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, count * 2); } return isException; } } public Tuple SplitData2Server(DateTime date, int proIndexValue = 0) { Tuple result = null; var sDate = date.ToString("yyyy-MM-dd 00:00:00"); var eDate = date.AddDays(1).ToString("yyyy-MM-dd 00:00:00"); logger.Info($"开始日订单[{date.ToString("yyyy-MM-dd")}]的分账信息上传..."); var pageSize = 1500; Stopwatch sw = new Stopwatch(); sw.Start(); int index = 0; //proIndexValue = 401; var proValue = proIndexValue; MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, proValue); var proMaxValue = 990; var flg = false; var tmpPress = 0; lock (Global.Instance.SyncLock) { while (index < 3) { tmpPress = proIndexValue + (proMaxValue - proIndexValue) / (3 - index); var icount = 0; var count = 0; var total = 0; try { using (var db = Global.Instance.OpenDataBase) { count = db.Query($"where syncStatus = 0 and uploadStatus < 4 and pid isnull and payDate between '{sDate}' and '{eDate}' order by payDate;").ToList().Count; //count = db.Query($"where uploadStatus < 4 and pid isnull and payDate between '{sDate}' and '{eDate}' order by payDate;").ToList().Count; if (count > 0) { var pageCount = count % pageSize != 0 ? count / pageSize + 1 : count / pageSize; //tmpPress = tmpPress / count == 0 ? 1 : tmpPress / count; for (int i = 0; i < pageCount; i++) { var condition = $" where syncStatus = 0 and uploadStatus < 4 and pid is null and payDate between '{sDate}' and '{eDate}' order by payDate limit {pageSize};"; //var condition = $" where uploadStatus < 4 and pid is null and payDate between '{sDate}' and '{eDate}' order by payDate limit {pageSize};"; var pSplitLst = db.Query(condition).ToList(); var list = new ConcurrentQueue(); foreach (var item in pSplitLst) { StringBuilder strBil = new StringBuilder(); strBil.Append("select ord.ticketId as ordTicketId,ord.tableNo,ord.people,ord.workerNo,oi.price as unitPrice,oi.productId as goodid,ssp.* from pos_split_store_pay ssp "); strBil.Append("left join pos_order_item oi on oi.id=ssp.orderItemId and oi.productId=ssp.productId "); strBil.Append("left join pos_order ord on ord.id=ssp.orderId "); strBil.Append("where ssp.pid='{0}';"); string sql = string.Format(strBil.ToString(), item.Id); var lists = db.Query(sql); var succLst = new List(); var errLst = new List(); //logger.Info($"需要上传日订单[{date.ToString("yyyy-MM-dd")}]<{item.BusNo}>明细的分账信息<{list.Count()}>条"); if (lists.Count() > 0) { total += lists.Count(); var _uploadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); var uploadObject = BuilderUploadObject(lists.ToList()); string jsonString = JsonUtils.Serialize(uploadObject); var uploadResult = this.Uploading(jsonString); if (uploadResult.Item1) { //logger.Info($"日订单<{item.BusNo}>明细的分账信息上传操作成功"); var _clientIds = uploadResult.Item2.Data.ClientIds; if (!string.IsNullOrEmpty(_clientIds)) { _clientIds = _clientIds.Substring(0, _clientIds.Length - 1); var succIdLst = _clientIds.Split(',').ToList(); succLst = lists.Where(m => succIdLst.Exists(t => t.Equals(m.Id))).ToList(); icount += succLst.Count(); errLst = lists.Where(m => !succIdLst.Exists(t => t.Equals(m.Id))).ToList(); } foreach (var splitPay in succLst) { var strSql = $"update pos_split_store_pay set syncStatus = 1, uploadErrors = 0, uploadTime = '{_uploadTime}', uploadStatus = 1, uploadMessage = '', uploadErrCode = '', uploadErrMessage = '' where id = '{splitPay.Id}'; "; list.Enqueue(strSql); } logger.Info($"分账信息第<{index + 1}>次上传,日订单[{date.ToString("yyyy-MM-dd")}]<{item.BusNo}>明细的分账信息<{lists.Count()}>条,上传成功<{succLst.Count()}>"); var errorOrderNo = new List(); foreach (var splitPay in errLst) { errorOrderNo.Add(splitPay.ClientId); splitPay.UploadErrors += 1; var strSql = $"update pos_split_store_pay set syncStatus = 0, uploadErrors = { splitPay.UploadErrors }, uploadTime = '{_uploadTime}', uploadStatus = 0, uploadMessage = '', uploadErrCode = '{uploadResult.Item2.ErrCode.Replace("'", "")}', uploadErrMessage = '接口调用成功,但上传失败:{splitPay.Id}' where id = '{splitPay.Id}'; "; list.Enqueue(strSql); } if (errorOrderNo.Count() > 0) { item.UploadErrors += 1; var strSql = $"update pos_split_store_pay set syncStatus = 1, uploadErrors = {item.UploadErrors}, uploadTime = '{_uploadTime}', uploadStatus = 0, uploadMessage = '', uploadErrCode = '', uploadErrMessage = '' where id = '{item.Id}'; "; list.Enqueue(strSql); var noStrs = string.Join(",", errorOrderNo); logger.Info($"分账信息第<{index + 1}>次上传,日订单[{date.ToString("yyyy-MM-dd")}]<{item.BusNo}>明细的分账信息<{lists.Count()}>条,上传错误<{errorOrderNo.Count()}>"); } else { var strSql = $"update pos_split_store_pay set syncStatus = 1, uploadErrors = 0, uploadTime = '{_uploadTime}', uploadStatus = 1, uploadMessage = '', uploadErrCode = '', uploadErrMessage = '' where id = '{item.Id}'; "; list.Enqueue(strSql); } } else { foreach (var splitPay in lists) { splitPay.UploadErrors += 1; var strSql = $"update pos_split_store_pay set syncStatus = 0, uploadErrors = { splitPay.UploadErrors }, uploadTime = '', uploadStatus = 0, uploadMessage = '', uploadErrCode = '', uploadErrMessage = '' where id = '{splitPay.Id}'; "; list.Enqueue(strSql); } item.UploadErrors += 1; var strPSql = $"update pos_split_store_pay set syncStatus = 0, uploadErrors = { item.UploadErrors }, uploadTime = '', uploadStatus = 0, uploadMessage = '', uploadErrCode = '', uploadErrMessage = '' where id = '{item.Id}'; "; list.Enqueue(strPSql); logger.Info($"分账信息第<{index + 1}>次上传,日订单[{date.ToString("yyyy-MM-dd")}]<{item.BusNo}>明细的分账信息上传操作失败"); } Thread.Sleep(100); } //if (proValue < tmpPress) // proValue++; //MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, proValue); proValue++; MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, proValue); } SqliteUtils.ExecuteTransaction(list); } } else { logger.Info($"分账信息第<{index + 1}>次上传,日订单[{date.ToString("yyyy-MM-dd")}]无分账信息要上传"); } } flg = true; } catch (Exception ex) { flg = false; logger.Error(ex, $"分账信息第<{index + 1}>次上传,日订单[{date.ToString("yyyy-MM-dd")}]的分账信息上传错误"); //MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, proMaxValue / 3 * index); } finally { sw.Stop(); logger.Info($"分账信息第<{index + 1}>次上传,日订单<{count}>条,应上传明细<{total}>条,实传<{icount}>条,时长<{sw.ElapsedMilliseconds}>"); //var pressValue = count == 0 ? proValue * (index + 1) : proValue; //MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, tmpPress); proValue = proIndexValue + count * (index + 1); MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, proValue); index++; } } //MsgEvent.Send(Constant.SPLITPAY_UPLOAD_PROGRESS, 1000); if (!flg) { result = new Tuple(false, "日订单的分账信息上传错误"); } else { result = new Tuple(true, ""); } return result; } } private List> BuilderUploadObject(List list) { try { //var newUploadObject = new Dictionary(); var newLst = new List>(); foreach (var splitPay in list) { var uploadObject = new Dictionary(); //租户ID uploadObject["tenantId"] = splitPay.TenantId; //前台系统ID uploadObject["clientId"] = splitPay.Id; //设置ID if (string.IsNullOrEmpty(splitPay.ProgramId)) { uploadObject["programId"] = "-1"; } else { uploadObject["programId"] = splitPay.ProgramId; } //门店ID uploadObject["storeId"] = splitPay.StoreId; //分店ID uploadObject["splitStoreId"] = splitPay.SplitStoreId; //门店编号 uploadObject["storeNo"] = splitPay.StoreNo; //付款单号 uploadObject["payNo"] = splitPay.PayNo; //销售单号 uploadObject["busNo"] = splitPay.BusNo; //付款方式编号 uploadObject["payTypeNo"] = splitPay.PayTypeNo; //付款方式 uploadObject["payType"] = splitPay.PayType; //实收金额 uploadObject["paid"] = splitPay.Paid; //找零金额 uploadObject["rchange"] = splitPay.Rchange; //已收金额 uploadObject["money"] = splitPay.Money; //溢出金额 uploadObject["overAmount"] = splitPay.OverAmount; //凭证号 uploadObject["voucherNo"] = splitPay.VoucherNo; //付款时间 uploadObject["payDate"] = splitPay.PayDate; //付款卡号 uploadObject["cardNo"] = splitPay.CardNo; //是否实收 uploadObject["incomeFlag"] = splitPay.IncomeFlag; //第三方扣费类型 uploadObject["otherRateType"] = splitPay.OtherRateType; //第三方扣费值 uploadObject["otherRateValue"] = splitPay.OtherRateValue; //第三方扣费 uploadObject["otherRate"] = splitPay.OtherRate; //支付客户端类型 uploadObject["payClientType"] = splitPay.PayClientType; //支付渠道 uploadObject["payChannel"] = splitPay.PayChannel; //扣率 uploadObject["deductionRate"] = splitPay.DeductionRate; //扣款 uploadObject["chargeBack"] = splitPay.ChargeBack; //备注 //uploadObject["memo"] = splitPay.Memo; uploadObject["memo"] = ""; uploadObject["isInvalid"] = splitPay.IsInvalid; uploadObject["createUser"] = splitPay.CreateUser; uploadObject["createDate"] = splitPay.CreateDate; uploadObject["ticketId"] = splitPay.TicketId; uploadObject["fromBizUserId"] = splitPay.FromBizUserld; uploadObject["refundAmount"] = splitPay.RefundAmount; uploadObject["orderType"] = splitPay.OrderType.ToString(); uploadObject["isRefund"] = splitPay.IsRefund; uploadObject["tableNo"] = splitPay.TableNo; uploadObject["people"] = splitPay.People; uploadObject["workNo"] = splitPay.WorkerNo; uploadObject["unitPrice"] = splitPay.UnitPrice; uploadObject["goodid"] = splitPay.ProductId; uploadObject["number"] = Convert.ToInt32(splitPay.Quantity); uploadObject["rnumber"] = Convert.ToInt32(splitPay.RefundQuantity); uploadObject["fee"] = Convert.ToInt32(splitPay.fee * 100); newLst.Add(uploadObject); } return newLst; } catch (Exception ex) { logger.Error(ex, "组装营业分账LIST上传数据异常:"); return null; } } private Tuple> Uploading(string jsonString) { Tuple> result = null; var isTest = false; #region 模拟上传操作 if (isTest) { logger.Debug("开始构建上传成功模拟数据......"); //构建上传成功模拟数据 var resp2 = new EntityResponse(); resp2.Status = 1; resp2.Message = "模拟上传"; resp2.ErrCode = string.Empty; resp2.ErrMessage = string.Empty; resp2.Data = new UploadResult { TicketId = "11112211", UploadDate = DateTime.Now }; logger.Info("模拟上传返回结果:{0}", resp2); result = new Tuple>(false, resp2); return result; } #endregion try { logger.Debug("开始上传营业分账数据*......"); OpenApi api = OpenApiUtils.Instance.NextApi(ApiType.Business); SortedList parameters = OpenApiUtils.Instance.NewParameters(api); parameters.Add("method", "upload.business.splitorder"); parameters.Add("storeId", Global.Instance.Authc.StoreId); parameters.Add("jsonString", jsonString); var ignore = new List(); ignore.Add("jsonString"); parameters.Add("sign", OpenApiUtils.Instance.Sign(api, parameters, ignore)); string response = HttpClientUtils.PostAsync(api, api.Url, parameters); logger.Info("上传返回结果*:{0}", response); if (Constant.IsSuccessful(response)) { var status = JsonUtils.Deserialize>(response); if (status.Status == 1) { logger.Info(status.Message); result = new Tuple>(true, status); } else if (status.Status == 2) { logger.Info(status.Message); result = new Tuple>(false, status); } else { string message = string.Format("<{0}>-{1}-{2}", status.ErrCode, status.ErrMessage, status.Message); logger.Error(string.Format("调用接口上传出错*:{0}", message)); result = new Tuple>(false, status); } } else { string errorMessage = PaserErrors(response); logger.Error(string.Format("报文<{0}>解析出错*:{1}", response, errorMessage)); //构建错误信息 var resp = new EntityResponse(); resp.Status = 0; resp.Message = errorMessage; resp.ErrCode = string.Empty; resp.ErrMessage = string.Empty; resp.Data = null; result = new Tuple>(false, resp); } } catch (Exception ex) { string message = string.Format("上传营业分账数据发生异常*"); logger.Error(ex, message); //构建异常错误 var resp = new EntityResponse(); resp.Status = 0; resp.Message = message; resp.ErrCode = string.Empty; resp.ErrMessage = string.Empty; resp.Data = null; result = new Tuple>(false, resp); } return result; } } }