You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

518 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using NLog;
using POSV.Common.Transport;
using POSV.Common.Util;
using POSV.Entity;
using POSV.HttpApi;
using POSV.HttpResponse;
using POSV.MessageEvent;
namespace POSV.Utils
{
public class SaleClearUtils
{
private static Logger logger = NLog.LogManager.GetCurrentClassLogger();
private static object _lock = new object();
private static SaleClearUtils _instance = null;
public static SaleClearUtils Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
_instance = new SaleClearUtils();
_instance.InitSaleClear();
}
}
return _instance;
}
}
private ObservableDictionary<string , SaleClear> _maps = null;
/// <summary>
/// 加载今日沽清数据
/// </summary>
private void InitSaleClear()
{
try
{
var data = this.GetAvailableSaleClearList();
List<SaleClear> rows = data.Item3;
this._maps = new ObservableDictionary<string , SaleClear>();
foreach (var row in rows)
{
row.Frozen = this.IsFrozen(row);
this._maps[row.ProductId] = row;
}
logger.Info("加载的沽清商品总数量<{0}>" , this._maps.Count);
this._maps.CollectionChanged += OnCollectionChanged;
}
catch (Exception ex)
{
logger.Error(ex , "加载沽清数据异常");
}
}
/// <summary>
/// 加载沽清数据,区分本地数据和共享数据两种
/// </summary>
private Tuple<bool,string,List<SaleClear>> GetAvailableSaleClearList()
{
bool isSuccess = false;
string message = string.Empty;
List<SaleClear> rows = new List<SaleClear>();
try
{
//启用全局沽清,服务中心提供数据
if (MessageCenterUtils.Instance.IsSaleClear)
{
logger.Info("获取服务中心的沽清数据");
var data = MessageCenterUtils.Instance.GetGlobalAvailableSaleClear();
isSuccess = data.Item1;
message = data.Item2;
rows = data.Item3;
}
else
{
logger.Info("加载本地的沽清数据");
//加载本地的今天及未来的沽清数据到内存
var startTime = DateTime.Now.ToString("yyyy-MM-dd 00:00:00");
using (var db = Global.Instance.OpenDataBase)
{
rows = db.Query<SaleClear>("where startTime >=@0 and stopFlag == 0;" , startTime).ToList();
}
isSuccess = true;
message = "本地数据加载成功";
}
}
catch (Exception ex)
{
isSuccess = false;
message = "沽清数据异常";
logger.Error(ex , message);
}
return new Tuple<bool , string , List<SaleClear>>(isSuccess , message , rows);
}
private void OnCollectionChanged(object sender , CollectionChangedEventArgs e)
{
logger.Info("操作沽清业务: {0}" , e.Action);
if (e.NewItem != null && e.NewItem is KeyValuePair<string , SaleClear>)
{
var map = (KeyValuePair<string , SaleClear>)e.NewItem;
var saleClear = map.Value;
bool isSuccess = SaveSaleClear(saleClear);
if (isSuccess)
{
//发送沽清变动通知
MsgEvent.Send(Constant.SALE_CLEAR_CHANGED_NOTIFY , map.Value);
}
}
else
{
logger.Warn("沽清业务数据不合法!");
}
}
/// <summary>
/// 清理本地沽清数据
/// </summary>
public void Expired()
{
try
{
//MessageCenterUtils.Instance.IsAvailable().Item1;
if (MessageCenterUtils.Instance.IsSaleClear)
{
logger.Info("采用共享沽清模式,忽略本机清理操作....");
return;
}
logger.Info("开始清理过期沽清....");
var keys = this._maps.Keys.ToArray<String>();
for (int i = 0; i < keys.Length; i++)
{
var key = keys[i];
var entity = this._maps[key];
//尚未到沽清开始时间或者已经过期
var frozen = IsFrozen(entity);
if (entity.Frozen != frozen)
{
entity.Frozen = frozen;
this._maps[key] = entity;
logger.Info("沽清变动<{0}>" , entity.ProductName);
}
}
}
catch (Exception ex)
{
logger.Error(ex , "清理过期沽清数据异常");
}
}
/// <summary>
/// 检测是否有可用的沽清记录存在
/// </summary>
/// <param name="saleClear"></param>
/// <returns></returns>
public bool CheckSaleClear(SaleClear saleClear)
{
return (saleClear != null && saleClear.StopFlag == 0 && !saleClear.Frozen);
}
/// <summary>
/// 沽清是否符合条件
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool IsFrozen(SaleClear entity)
{
//当前时间
DateTime dateTime = DateTime.Now;
//有效沽清时间
DateTime startTime = Convert.ToDateTime(entity.StartTime);
//结束时间
DateTime endTime = Convert.ToDateTime(entity.EndTime);
return (dateTime.CompareTo(startTime) < 0 || dateTime.CompareTo(endTime) > 0);
}
private bool SaveSaleClear(SaleClear saleClear)
{
bool isSuccess = true;
try
{
//共享沽清模式
if (MessageCenterUtils.Instance.IsSaleClear)
{
//更新剩余数量
saleClear.Quantity = saleClear.TotalQuantity - saleClear.SaleQuantity;
var transport = new TransportMessage<SaleClear>();
transport.MessageType = MessageType.ProxySaleClear;
transport.Data = saleClear;
MqttUtils.Instance.Publish(JsonUtils.Serialize(transport));
logger.Info("发布变动到消息中心<{0} - {1} = {2}>" , saleClear.TotalQuantity, saleClear.SaleQuantity,saleClear.Quantity);
}
else
{
//更新沽清记录的可用状态
saleClear.Frozen = this.IsFrozen(saleClear);
//更新剩余数量
saleClear.Quantity = saleClear.TotalQuantity - saleClear.SaleQuantity;
//保存到本地数据库
lock (Global.Instance.SyncLock)
{
using (var db = Global.Instance.OpenDataBase)
{
using (var trans = db.GetTransaction())
{
db.Save<SaleClear>(saleClear);
trans.Complete();
}
}
}
}
}
catch (Exception ex)
{
isSuccess = false;
logger.Error(ex , "本机保存沽清异常");
}
return isSuccess;
}
public bool SaveOrUpdateNoChanged(SaleClear saleClear)
{
bool isSuccess = true;
this._maps.SaveOrUpdateNoChanged(saleClear.ProductId,saleClear);
if (isSuccess)
{
//发送沽清变动通知
MsgEvent.Send(Constant.SALE_CLEAR_CHANGED_NOTIFY , saleClear);
}
return isSuccess;
}
public ObservableDictionary<string,SaleClear> Maps
{
get
{
return this._maps;
}
}
public static bool UploadSaleClear(SaleClear saleClear)
{
bool isSuccess = true;
try
{
var uploadObject = BuilderUploadObject(saleClear);
string jsonString = JsonUtils.Serialize(uploadObject);
var uploadResult = Uploading(jsonString);
if (uploadResult.Item1)
{
isSuccess = true;
logger.Debug($"沽清数据上传成功:{jsonString}。");
}
}
catch (Exception ex)
{
isSuccess = false;
logger.Error(ex, "沽清数据上传异常");
}
return isSuccess;
}
private static Dictionary<string, object> BuilderUploadObject(SaleClear saleClear)
{
try
{
var uploadObject = new Dictionary<string, object>();
//租户ID
uploadObject["tenantId"] = saleClear.TenantId;
//门店ID
uploadObject["storeId"] = Global.Instance.Worker.StoreId;
//门店编号
uploadObject["storeNo"] = saleClear.StoreNo;
// POS编号
uploadObject["posNo"] = saleClear.PosNo;
// 品牌Id
uploadObject["brandId"] = saleClear.BrandId;
// 类别Id
uploadObject["typeId"] = saleClear.TypeId;
// 分类名称
uploadObject["typeName"] = saleClear.TypeName;
// 商品Id
uploadObject["productId"] = saleClear.ProductId;
// 编号
uploadObject["productNo"] = saleClear.ProductNo;
// 名称
uploadObject["productName"] = saleClear.ProductName;
// 剩余数量
uploadObject["quantity"] = saleClear.Quantity;
// 提醒数量
uploadObject["notify"] = saleClear.NotifyQuantity;
// 已售数量
uploadObject["sales"] = saleClear.SaleQuantity;
// 沽清数量
uploadObject["total"] = saleClear.TotalQuantity;
// 沽清时间
uploadObject["startTime"] = saleClear.StartTime;
// 结束时间
uploadObject["endTime"] = saleClear.EndTime;
// 取消时间
uploadObject["stopTime"] = saleClear.StopTime;
// 停止人
uploadObject["stopUser"] = saleClear.StopUser;
// 单位
uploadObject["unitId"] = saleClear.UnitId;
// 计量单位名称
uploadObject["unitName"] = saleClear.UnitName;
// 商品默认规格Id
uploadObject["specId"] = saleClear.SpecId;
// 商品默认规格名称
uploadObject["specName"] = saleClear.SpecName;
// 是否套餐(0否1是)
uploadObject["suitFlag"] = saleClear.SuitFlag;
// 是否取消(0否1是)
uploadObject["stopFlag"] = saleClear.StopFlag;
// 颜色
uploadObject["memo"] = saleClear.Memo;
// 扩展字段1
uploadObject["ext1"] = saleClear.Ext1;
// 扩展字段2
uploadObject["ext2"] = saleClear.Ext2;
// 扩展字段3
uploadObject["ext3"] = saleClear.Ext3;
return uploadObject;
}
catch (Exception ex)
{
logger.Error(ex, "组装沽清上传数据异常:");
return null;
}
}
private static Tuple<bool, EntityResponse<UploadResult>> Uploading(string jsonString)
{
Tuple<bool, EntityResponse<UploadResult>> result = null;
try
{
logger.Debug("开始上传沽清数据......");
OpenApi api = OpenApiUtils.Instance.NextApi(ApiType.Business);
SortedList<string, string> parameters = OpenApiUtils.Instance.NewParameters(api);
parameters.Add("method", "saleclear.business.upload");
parameters.Add("storeId", Global.Instance.Authc.StoreId);
parameters.Add("jsonString", jsonString);
var ignore = new List<string>();
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<EntityResponse<UploadResult>>(response);
if (status.Status == 1)
{
logger.Info(status.Message);
result = new Tuple<bool, EntityResponse<UploadResult>>(true, status);
}
else if (status.Status == 2)
{
logger.Info(status.Message);
result = new Tuple<bool, EntityResponse<UploadResult>>(false, status);
}
else
{
string message = string.Format("<{0}>-{1}-{2}", status.ErrCode, status.ErrMessage, status.Message);
logger.Error(string.Format("调用接口<upload.business.splitorder>上传出错:{0}", message));
result = new Tuple<bool, EntityResponse<UploadResult>>(false, status);
}
}
else
{
string errorMessage = PaserErrors(response);
logger.Error(string.Format("报文<{0}>解析出错:{1}", response, errorMessage));
//构建错误信息
var resp = new EntityResponse<UploadResult>();
resp.Status = 0;
resp.Message = errorMessage;
resp.ErrCode = string.Empty;
resp.ErrMessage = string.Empty;
resp.Data = null;
result = new Tuple<bool, EntityResponse<UploadResult>>(false, resp);
}
}
catch (Exception ex)
{
string message = string.Format("上传营业分账数据发生异常");
logger.Error(ex, message);
//构建异常错误
var resp = new EntityResponse<UploadResult>();
resp.Status = 0;
resp.Message = message;
resp.ErrCode = string.Empty;
resp.ErrMessage = string.Empty;
resp.Data = null;
result = new Tuple<bool, EntityResponse<UploadResult>>(false, resp);
}
return result;
}
protected static Dictionary<string, string> _errorDesc = new Dictionary<string, string>();
protected static string PaserErrors(string response)
{
string result = string.Empty;
try
{
logger.Error(response);
Errors mainError = JsonUtils.Deserialize<Errors>(response);
if (_errorDesc.ContainsKey(mainError.Code))
{
result = _errorDesc[mainError.Code];
}
else
{
result = mainError.Message;
}
List<SubErrors> subError = mainError.SubErrors;
if (subError != null && subError.Count > 0)
{
SubErrors error = subError[0];
if (_errorDesc.ContainsKey(error.Code))
{
result = _errorDesc[error.Code];
}
else
{
result = error.Message;
}
}
}
catch (Exception ex)
{
logger.Error(ex, "非法的错误信息格式");
result = _errorDesc["9999"];
}
return result;
}
}
}