using FluentScheduler; using POSV.Entity; using POSV.HandOver; using POSV.HttpApi; using POSV.HttpResponse; using POSV.StoreBusiness; using POSV.Utils; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; namespace POSV.Job { class HandOverUpLoadJob : BaseApi, IJob { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private bool isRunning = false; public void Execute() { try { if (!Global.Instance.IsLogin) { logger.Debug("未登录忽略本次上传"); return; } if (!Global.Instance.Online) { logger.Debug("脱机状态,忽略本次上传"); return; } if (!Global.Instance.AllowUpload) { logger.Info("正在点单,暂不上传"); return; } if (isRunning) { logger.Debug("执行中,请稍候..."); return; } isRunning = true; //上传交班单 InstallAndUploadHandover(); //上传熟客信息 InstallAndUploadVisitor(5); //上传操作日志 InstallAndUploadBusLog(5); } catch (Exception ex) { logger.Error(ex, "交班单上传任务异常"); } finally { isRunning = false; } } #region 操作日志上传 private void InstallAndUploadBusLog(int limit) { var sw = new Stopwatch(); if (!Global.isHaveUpLoadBusLog) { //没有上传的数据之间返回 logger.Debug("没有需要上传的操作日志,isHaveUpLoadBusLog=false"); return; } List lists = new List(); try { sw.Start(); using (var db = Global.Instance.OpenDataBase) { //主单数据 lists = db.Query("where uploadStatus = 0 order by uploadErrors limit @0;", limit).ToList(); if (lists.Count <= 0) { logger.Debug("没有需要上传的操作日志,isHaveUpLoadBusLog=false"); Global.isHaveUpLoadBusLog = false; } } } catch (Exception ex) { logger.Error(ex, "操作日志上传异常"); Global.Instance.BugReport(ex, "操作日志上传异常"); } finally { if (lists.Count > 0) { ProcessBusLog(lists); sw.Stop(); logger.Info("操作日志上传<{0}>条数据耗时<{1}>", lists.Count, sw.ElapsedMilliseconds); } this.isRunning = false; } } private bool ProcessBusLog(List logList) { bool isSuccess = true; try { var uploadObject = BuilderUploadObject(logList); string jsonString = JsonUtils.Serialize(uploadObject); var uploadResult = this.Uploading(jsonString); if (uploadResult.Item1) { foreach (StoreOperationLogEntity storeOperationLogEntity in logList) { storeOperationLogEntity.UploadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); } //上传失败 isSuccess = true; } else { //上传失败 isSuccess = false; } foreach (StoreOperationLogEntity storeOperationLogEntity in logList) { storeOperationLogEntity.UploadStatus = uploadResult.Item2.Status; storeOperationLogEntity.UploadMessage = uploadResult.Item2.Message; storeOperationLogEntity.UploadErrMessage = uploadResult.Item2.ErrMessage; } } catch (Exception ex) { isSuccess = false; logger.Error(ex, "操作日志上传任务异常"); Global.Instance.BugReport(ex, "操作日志上传任务异常"); } finally { if (!isSuccess) { foreach (StoreOperationLogEntity storeOperationLogEntity in logList) { storeOperationLogEntity.UploadErrors += 1; } } lock (Global.Instance.SyncLock) { foreach (StoreOperationLogEntity storeOperationLogEntity in logList) { string sql = @"update pos_store_operation_log set uploadStatus = {0}, uploadMessage = '{1}', uploadErrors = {2}, uploadErrMessage = '{3}', uploadTime = '{4}' where id = '{5}';"; SqliteUtils.Execute(string.Format(sql, storeOperationLogEntity.UploadStatus, storeOperationLogEntity.UploadMessage, storeOperationLogEntity.UploadErrors, storeOperationLogEntity.UploadErrMessage, storeOperationLogEntity.UploadTime, storeOperationLogEntity.Id)); } } } return isSuccess; } private List> BuilderUploadObject(List logList) { //耗料数据上传 var ticket_info = new List>(); if (logList != null) { foreach (var log in logList) { var p = new Dictionary(); //前台系统ID p["id"] = log.Id; //企业编号 p["tenantId"] = log.TenantId; //门店ID p["storeId"] = log.StoreId; //门店编号 p["storeNo"] = log.StoreNo; //门店 p["storeName"] = log.StoreName; //工号 p["workerNo"] = log.WorkerNo; //班次编号 p["shiftNo"] = log.ShiftNo; //班次名称 p["shiftName"] = log.ShiftName; //设备名称 p["deviceName"] = log.DeviceName; //设备MC p["deviceMac"] = (!string.IsNullOrEmpty(log.DeviceMac) && log.DeviceMac.Length > 32) ? log.DeviceMac.Substring(0, 24) : log.DeviceMac; //IP地址 p["deviceIp"] = log.DeviceIp; //POS编号 p["posNo"] = log.PosNo; //操作时间 p["operationTime"] = log.OperationTime; //类型 p["type"] = log.Type; //类型说明 p["typeTxt"] = log.TypeTxt; //备注说明 p["memo"] = log.Memo; ticket_info.Add(p); } } return ticket_info; } private Tuple> Uploading(string jsonString) { Tuple> result = null; try { logger.Debug("开始上传数据......"); OpenApi api = OpenApiUtils.Instance.NextApi(ApiType.Business); SortedList parameters = OpenApiUtils.Instance.NewParameters(api); parameters.Add("method", "upload.business.log"); 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.Info(string.Format("上传出错:{0}", message)); result = new Tuple>(false, status); } } else { string errorMessage = PaserErrors(response); logger.Info(string.Format("报文解析出错:{0}", 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; } #endregion #region 熟客信息 private void InstallAndUploadVisitor(int limit) { var sw = new Stopwatch(); List visitorList = new List(); if (!Global.isHaveUpLoadVisitor) { //没有上传的数据之间返回 logger.Debug("没有需要上传的熟客数据,isHaveUpLoadVisitor=false"); return; } try { sw.Start(); List visitorAddressList = new List(); List visitorTagList = new List(); using (var db = Global.Instance.OpenDataBase) { visitorList = db.Fetch("where upload = 0"); if (visitorList.Count > 0) { var ids = string.Join("','", visitorList.ConvertAll(x => x.Id).ToArray()); var condition = " where visitorId in ('" + ids + "');"; visitorAddressList = db.Fetch(condition); visitorTagList = db.Fetch(condition); } else { //没有要上传的数据 logger.Debug("没有需要上传的熟客信息,isHaveUpLoadVisitor=false"); Global.isHaveUpLoadVisitor = false; return; } } foreach (var vi in visitorList) { var addList = visitorAddressList.FindAll(x => x.VisitorId == vi.Id); var tagList = visitorTagList.FindAll(x => x.VisitorId == vi.Id); var result = UploadVisitor(vi, addList, tagList); if (result.Item1) { vi.Upload = 1; lock (Global.Instance.SyncLock) { using (var db = Global.Instance.OpenDataBase) { using (var trans = db.GetTransaction()) { db.Save(vi); trans.Complete(); } } } } Thread.Sleep(10); } } catch(Exception ex) { logger.Error(ex, "熟客信息上传异常"); Global.Instance.BugReport(ex, "熟客信息上传异常"); } finally { sw.Stop(); logger.Info("熟客上传<{0}>条数据耗时<{1}>", visitorList.Count, sw.ElapsedMilliseconds); } } private Tuple> UploadVisitor(Visitor visitor, List addressList, List tagList) { Tuple> result = null; try { var visitorObject = new Dictionary(); visitorObject["id"] = visitor.Id; visitorObject["tel"] = visitor.Tel; visitorObject["name"] = visitor.Name; visitorObject["spell"] = visitor.Spell; visitorObject["sex"] = visitor.Sex; visitorObject["title"] = visitor.Title; visitorObject["position"] = visitor.Position; visitorObject["fphone"] = visitor.Phone1; visitorObject["sphone"] = visitor.Phone2; visitorObject["description"] = visitor.Description; visitorObject["createUser"] = visitor.CreateUser; visitorObject["createDate"] = visitor.CreateDate; visitorObject["modifyUser"] = visitor.ModifyUser; visitorObject["modifyDate"] = visitor.ModifyDate; //地址 List> uploadAddList = new List>(); foreach(var add in addressList) { var visitorAddObject = new Dictionary(); visitorAddObject["name"] = add.Name; visitorAddObject["telephone"] = add.Telephone; visitorAddObject["areaName"] = add.AreaName; visitorAddObject["address"] = add.Address; visitorAddObject["description"] = add.Description; visitorAddObject["createUser"] = add.CreateUser; visitorAddObject["createDate"] = add.CreateDate; visitorAddObject["modifyUser"] = add.ModifyUser; visitorAddObject["modifyDate"] = add.ModifyDate; uploadAddList.Add(visitorAddObject); } visitorObject["addressList"] = uploadAddList; //标签 List> uploadTagList = new List>(); foreach(var tag in tagList) { var visitorTagObject = new Dictionary(); visitorTagObject["name"] = tag.Name; visitorTagObject["createUser"] = tag.CreateUser; visitorTagObject["createDate"] = tag.CreateDate; visitorTagObject["modifyUser"] = tag.ModifyUser; visitorTagObject["modifyDate"] = tag.ModifyDate; uploadTagList.Add(visitorTagObject); } visitorObject["tagList"] = uploadTagList; OpenApi api = OpenApiUtils.Instance.NextApi(ApiType.Business); SortedList parameters = OpenApiUtils.Instance.NewParameters(api); parameters.Add("method", "visitor.add"); parameters.Add("storeId", Global.Instance.Authc.StoreId); parameters.Add("jsonString", JsonUtils.Serialize(visitorObject)); logger.Debug("开始上传熟客数据......"); var ignore = new List(); ignore.Add("jsonString"); parameters.Add("sign", OpenApiUtils.Instance.Sign(api, parameters, ignore)); string response = HttpClientUtils.PostAsync(api, api.Url, parameters); if (Constant.IsSuccessful(response)) { var status = JsonUtils.Deserialize>(response); if (status.Status == 1) { logger.Info(status.Message); result = new Tuple>(true, "上传成功!", status); } else { string message = string.Format("<{0}>-{1}", status.ErrCode, status.Message); logger.Info(string.Format("熟客上传出错:{0}", message)); result = new Tuple>(false, message, status); } } else { string errorMessage = PaserErrors(response); logger.Info(string.Format("熟客上传报文解析出错:{0}", 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) { logger.Error(ex, "熟客信息上传异常"); result = new Tuple>(false, "上传错误", null); } return result; } #endregion #region 交班单 private void InstallAndUploadHandover() { bool isSuccess = true; //上传数据 UploadHandoverObject upload = null; //交班单信息 HandOverTicket ticket = null; try { if (!Global.isHaveUpLoadShift) { //没有上传的数据之间返回 logger.Debug("没有需要上传的交班数据,isHaveUpLoadShift=false"); return; } using (var db = Global.Instance.OpenDataBase) { upload = db.Query().Where(x => x.SyncStatus == 0).OrderBy(x => x.UploadErrors).Limit(1).FirstOrDefault(); if (upload != null) { ticket = upload.HandOverTicket; } else { //没有要上传的数据 logger.Debug("没有需要上传的交班数据,isHaveUpLoadShift=false"); Global.isHaveUpLoadShift = false; return; } } if (ticket == null) { return; } var uploadObject = new Dictionary(); //前台系统ID uploadObject["id"] = ticket.Id; uploadObject["no"] = ticket.No;// 单据编号 uploadObject["storeId"] = ticket.StoreId;// 门店ID uploadObject["storeNo"] = ticket.StoreNo;// 门店编号 uploadObject["storeName"] = ticket.StoreName;// 门店名称 uploadObject["workId"] = ticket.WorkId;// 员工ID uploadObject["workNo"] = ticket.WorkNo;// 员工编号 uploadObject["workName"] = ticket.WorkName;// 员工名称 uploadObject["shiftNo"] = ticket.ShiftNo;// 班次 uploadObject["shiftName"] = ticket.ShiftName;// 班次名称 uploadObject["datetimeBegin"] = ticket.DatetimeBegin;// 开始时间 uploadObject["datetimeEnd"] = ticket.DatetimeEnd;// 结束时间 uploadObject["datetimeShift"] = ticket.DatetimeShift;// 交班时间 uploadObject["acceptWorkerNo"] = ticket.AcceptWorkerNo;// 交单工号 uploadObject["posNo"] = ticket.PosNo;// 交单POS uploadObject["memo"] = ticket.Memo;// 备注 uploadObject["peopleCount"] = ticket.PeopleCount;// 总人数 uploadObject["dealTicketCount"] = ticket.DealTicketCount;// 成交单数 uploadObject["dealAmount"] = ticket.DealAmount;// 成交金额 uploadObject["backTicketCount"] = ticket.BackTicketCount;// 退单次数 uploadObject["backAmount"] = ticket.BackAmount;// 退单金额 uploadObject["ticketCount"] = ticket.TicketCount;// 合计次数 uploadObject["amount"] = ticket.Amount;// 合计金额 uploadObject["discountMoney"] = ticket.DiscountMoney;// 优惠金额 uploadObject["couponDiscountMoney"] = ticket.CouponDiscountMoney;// 电子券优惠金额 uploadObject["otherDiscountMoney"] = ticket.OtherDiscountMoney;// 其他优惠金额 uploadObject["receivable"] = ticket.Receivable;// 应收金额 uploadObject["maling"] = ticket.Maling;// 抹零金额 uploadObject["paid"] = ticket.Paid;// 实收金额 uploadObject["cardCount"] = ticket.CardCount;// 充值笔数 uploadObject["cardRealMoney"] = ticket.CardRealMoney;// 卡充值金额 uploadObject["cardRefundCount"] = ticket.CardRefundCount;// 退卡笔数 uploadObject["cardRefundMoney"] = ticket.CardRefundMoney;// 退卡金额 uploadObject["sumRealMoney"] = ticket.SumRealMoney;// 总收入金额 uploadObject["inmoney"] = ticket.Inmoney;// 非营业收入 uploadObject["outmoney"] = ticket.Outmoney;// 非营业支出 uploadObject["distributionFee"] = ticket.DistributionFee;// 配送费信息 uploadObject["shiftAmount"] = ticket.ShiftAmount;// 班次总收入金额 uploadObject["imprest"] = ticket.Imprest;// 备用金 uploadObject["deviceName"] = ticket.DeviceName;// 设备名称 uploadObject["deviceMac"] = ticket.DeviceMac;// 设备MAC uploadObject["deviceIp"] = ticket.DeviceIp;// 设备IP //整单优惠明细 var detail = new List>(); var ticktDetail = ticket.Detail; if (ticktDetail != null) { foreach (var promotion in ticktDetail) { var p = new Dictionary(); //前台系统ID p["id"] = promotion.Id; // 收银方式编号 p["payModeNo"] = promotion.PayModeNo; //收银方式名称 p["payModeName"] = promotion.PayModeName; //数量 p["count"] = promotion.Count; // 金额 p["money"] = promotion.Money; // 手工金额 p["handsMoney"] = promotion.HandsMoney; // 卡务次数 p["cardCount"] = promotion.CardCount; // 卡务金额 p["cardMoney"] = promotion.CardMoney; // 总金额 p["sumMoney"] = promotion.SumMoney; detail.Add(p); } } uploadObject["detail"] = detail; //杯子盘点明细 var part = new List>(); var ticktPart = ticket.Part; if (ticktPart != null) { foreach (var promotion in ticktPart) { var p = new Dictionary(); //前台系统ID p["id"] = promotion.Id; //规格名称 p["specName"] = promotion.SpecName; //初始数量 p["preCount"] = promotion.PreCount; //系统数量 p["count"] = promotion.Count; // 手工数量 p["handsCount"] = promotion.HandsCount; // 差异数量 p["difCount"] = promotion.DifCount; part.Add(p); } } uploadObject["part"] = part; //支付方式明细 var pay = new List>(); var ticktPay = ticket.Pay; if (ticktPay != null) { foreach (var pays in ticktPay) { var p = new Dictionary(); //前台系统ID p["id"] = pays.Id; //支付方式编号 p["payModeNo"] = pays.PayModeNo; //支付方式名称 p["payModeName"] = pays.PayModeName; //营业模式 p["busMode"] = pays.BusMode; // 业务类型 p["busType"] = pays.BusType; // 笔数 p["count"] = pays.Count; //金额 p["money"] = pays.Money; pay.Add(p); } } uploadObject["pay"] = pay; string jsonString = JsonUtils.Serialize(uploadObject); this.UploadingHandover(upload, jsonString); isSuccess = true; } catch (Exception ex) { isSuccess = false; logger.Error(ex, "组装上传交班单信息异常"); } finally { //zhhangy 2020-03-02 Add 修复因一行交班数据有问题,造成一直执行一行数据 if (upload != null && ticket != null) { if (!isSuccess) { upload.SyncStatus = 0; upload.UploadErrors += 1; } else { upload.SyncStatus = 1; upload.UploadErrors = +1; } lock (Global.Instance.SyncLock) { string sql = @"update pos_upload_handover_json set syncStatus = {0}, uploadErrors = {1} where id = '{2}';"; SqliteUtils.Execute(string.Format(sql, upload.SyncStatus, upload.UploadErrors, upload.Id)); } } } } private void UploadingHandover(UploadHandoverObject upload, string jsonString) { try { if (upload == null) { logger.Error(">>>>交班数据上传对象为空了..............."); return; } logger.Debug("开始上传数据......"); OpenApi api = OpenApiUtils.Instance.NextApi(ApiType.Business); SortedList parameters = OpenApiUtils.Instance.NewParameters(api); parameters.Add("method", "upload.business.handover"); 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); if (Constant.IsSuccessful(response)) { var result = JsonUtils.Deserialize>(response); if (result.Status == 1) { logger.Info("上传交班数据:" + result.Message); upload.SyncStatus = 1; upload.UploadErrors = upload.UploadErrors + 1; upload.ModifyDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); upload.ModifyUser = Constant.DEFAULT_SYNC_USER; upload.Ext1 = result.Data.BusNo; upload.Ext2 = result.Data.HandoverId; upload.Ext3 = result.Message; } else { upload.SyncStatus = 0; upload.UploadErrors = upload.UploadErrors + 1; upload.ModifyDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); upload.ModifyUser = Constant.DEFAULT_SYNC_USER; upload.Ext1 = ""; upload.Ext2 = ""; string message = string.Format("<{0}>-{1}", result.ErrCode, result.ErrMessage); upload.Ext3 = message; logger.Info(string.Format("交班数据上传出错:{0}", message)); } using (var db = Global.Instance.OpenDataBase) { using (var trans = db.GetTransaction()) { db.Update(upload); trans.Complete(); } } } else { string errorMessage = PaserErrors(response); logger.Info(string.Format("报文解析出错:{0}", errorMessage)); } } catch (Exception ex) { logger.Error(ex, "上传交班发生异常"); Global.Instance.BugReport(ex, "上传交班发生异常"); } } #endregion } }