2025-03-28 09:49:56 +08:00

1670 lines
80 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using BreakpointTransmission.Client;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using Transmission.SDK.ThreadPool;
using TransmissionClient.Model;
namespace TransmissionClient
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// 注:修改上传/下发的内容:在本页对应配置方法中修改
/// 修改上传/下发需要传输的表及传输类型、传输表时间间隔比例【分钟】、
/// 查询服务区本地数据表SQL语句、初始化传输时间字段、初始化表信息、
/// 定义表传输状态字段、单次最大传输数量在ConfigThread.cs类中修改
/// 修改传输方法在Transmission.SDK中ClientThread.cs类中修改
/// OpenTopThreads、OpenDownThreads、DownLoadDataByServerpaertCode、IsStartDownData方法
/// </summary>
public partial class MainWindow : Window
{
#region Config参数
//protected string _TransferType = ConfigurationManager.AppSettings["TransferType"].ToString();
protected string _OracleConnStr = ConfigurationManager.AppSettings["OracleConnStr"].ToString();
//protected string _HostIP = ConfigurationManager.AppSettings["HostIP"].ToString();
//protected string _HostPort = ConfigurationManager.AppSettings["HostPort"].ToString();
//protected string _ToolListen = ConfigurationManager.AppSettings["ToolListen"].ToString();
//protected string _StartApp = ConfigurationManager.AppSettings["StartApp"].ToString();
//protected string _Connectport = ConfigurationManager.AppSettings["Connectport"].ToString();
//protected string _DownloadConnString = ConfigurationManager.AppSettings["DownloadConnString"].ToString();
//protected string _ScanUpdateURL = ConfigurationManager.AppSettings["ScanUpdateURL"].ToString();
protected string _TimerInterval = ConfigurationManager.AppSettings["Interval"].ToString();
#endregion
#region
/// <summary>
/// 运行状态上报时间
/// </summary>
DateTime StateUploadTime;
/// <summary>
/// 运行状态上报线程
/// </summary>
Thread StateUploadThread { get; set; }
/// <summary>
/// 当天已采集统计数量
/// </summary>
int TodayCount = 0;
/// <summary>
/// 十分钟数据统计线程
/// </summary>
Thread CreateDataCollectionThread { get; set; }
/// <summary>
/// 客单时段区段统计线程
/// </summary>
Thread CreateSalesIntervalAnalysisThread { get; set; }
/// <summary>
/// 在线订单线程
/// </summary>
Thread OnlineOrderThread { get; set; }
/// <summary>
/// 在线订单线程
/// </summary>
Thread OldSystemExceptionThread { get; set; }
/// <summary>
/// 压缩文件上传线程
/// </summary>
Thread FileUploadThread { get; set; }
/// <summary>
/// 内部会员数据传输线程
/// </summary>
ClientThread MemberClientThread = new ClientThread();
/// <summary>
/// 内部会员数据传输配置
/// </summary>
ConfigThread MemberConfigThread = null; //配置类
/// <summary>
/// 大数据上传线程
/// </summary>
ClientThread StateClientThread = new ClientThread();
/// <summary>
/// 大数据上传配置
/// </summary>
ConfigThread StateConfigThread = null; //配置类
/// <summary>
/// 移动支付相关数据上传线程
/// </summary>
ClientThread MobilePayClientThread = new ClientThread();
/// <summary>
/// 移动支付相关数据上传配置
/// </summary>
ConfigThread MobilePayConfigThread = null;
/// <summary>
/// 日结营收数据上传线程
/// </summary>
ClientThread BusinessClientThread = new ClientThread();
/// <summary>
/// 日结营收数据上传配置
/// </summary>
ConfigThread BusinessConfigThread = null;
/// <summary>
/// 服务区数据下载线程
/// </summary>
ClientThread ServerPartClientThread = new ClientThread();
/// <summary>
/// 服务区数据下载配置
/// </summary>
ConfigThread ServerPartConfigThread = null;
/// <summary>
/// 传输客户端定时器
/// </summary>
DispatcherTimer CilentTimer = new DispatcherTimer();
/// <summary>
/// 在线订单传输定时器
/// </summary>
DispatcherTimer OnlineOrderTimer = new DispatcherTimer();
/// <summary>
/// 公共数据库连接类
/// </summary>
Transmission.SDK.OracleHelper LocalOracle;
/// <summary>
/// 运行日志记录
/// </summary>
DataTable TransResultTable;
/// <summary>
/// 服务区信息缓存表
/// </summary>
DataTable ServerPartTable;
/// <summary>
/// 服务区信息缓存有效期
/// </summary>
DateTime ServerPartCacheTime;
/// <summary>
/// 多链路配置信息
/// </summary>
List<Model.TransLinkConfigModel> TransLinkConfigList { get; set; }
/// <summary>
/// 多链路传输参数库配置
/// </summary>
ConcurrentDictionary<int, MulLinkConfigThread> MulLinkConfigThreadList { get; set; }
/// <summary>
/// 多链路传输线程库配置
/// </summary>
ConcurrentDictionary<int, MulLinkCilentThread> MulLinkCilentThreadList { get; set; }
List<TransferErrorNotifyModel> TransferErrorNotify { get; set; }
bool IsFirstRun = true;
bool IsReplaceColumn = false;
string ServerPartCode { get; set; }
#endregion
#region Socket客户端
private SuperSocketClient SocketClient { get; set; }
private string SocketServerpartCode { get; set; }
#endregion
#region ->
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// 主窗体加载事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
#region
if (LocalOracle == null || !LocalOracle.ConnTest())
{
LocalOracle = new Transmission.SDK.OracleHelper(_OracleConnStr.Split(',')[0], _OracleConnStr.Split(',')[4],
_OracleConnStr.Split(',')[1], _OracleConnStr.Split(',')[2], _OracleConnStr.Split(',')[3]);
}
//DataSet dataSet = LocalOracle.ExcuteSqlGetDataSet(@"select * from highway_exchange.T_COMMODITYSALE ");
//绑定大数据上传回调事件
StateClientThread.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent);
//绑定移动支付数据上传回调事件
MobilePayClientThread.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent);
//绑定日结营收数据上传回调事件
BusinessClientThread.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent);
//绑定服务区基础数据下载回调事件
ServerPartClientThread.DownloadStringEvent += new ClientThread.OutputResultsDownArg(ClientThread_DownloadStringEvent);
//绑定内部会员数据上传回调事件(暂无上传)
MemberClientThread.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent);
//绑定内部会员数据下载回调事件
MemberClientThread.DownloadStringEvent += new ClientThread.OutputResultsDownArg(ClientThread_DownloadStringEvent);
//初始化数据传输计时器
CilentTimer.Tick += CilentTimer_Tick;
double timeInterval = 0;
try
{
if (!double.TryParse(_TimerInterval, out timeInterval) || timeInterval < 1 || timeInterval > 10)
{
timeInterval = 5;
}
}
catch
{
timeInterval = 5;
}
timeInterval = timeInterval * 60 * 1000;
CilentTimer.Interval = TimeSpan.FromMilliseconds(timeInterval);
CilentTimer.Start();
//初始化在线订单传输定时器
OnlineOrderTimer.Tick += OnlineOrderTimer_Tick;
OnlineOrderTimer.Interval = TimeSpan.FromSeconds(3);
OnlineOrderTimer.Start();
BtnTimerState.Content = "停止";
Title = "服务区数据传输工具 TCv" + System.Windows.Forms.Application.ProductVersion;
int _FileCount = 0;
string[] _masks = { ".log" };
try
{
//清理过期日志文件
Transmission.SDK.LogHelper.DeleteFiles(
AppDomain.CurrentDomain.BaseDirectory + "\\log",
new string[] { ".log" }, false, false, ref _FileCount);
}
catch { }
#endregion
}
#endregion
#region -> 线
/// <summary>
/// 在线订单传输定时器事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnlineOrderTimer_Tick(object sender, EventArgs e)
{
try
{
string _OnlineService;
try
{
_OnlineService = ConfigurationManager.AppSettings["OnlineService"];
}
catch
{
_OnlineService = "";
}
if (string.IsNullOrWhiteSpace(_OnlineService))
{
TransResultBeginInvoke(DateTime.Now, $"线上订单数据同步线程启动失败。原因:参数[OnlineService]未配置。");
OnlineOrderTimer.Stop();
return;
}
if (LocalOracle == null || !LocalOracle.ConnTest())
{
//初始化Oracle数据库连接字符串
LocalOracle = new Transmission.SDK.OracleHelper(_OracleConnStr.Split(',')[0], _OracleConnStr.Split(',')[4],
_OracleConnStr.Split(',')[1], _OracleConnStr.Split(',')[2], _OracleConnStr.Split(',')[3]);
}
//启动线上订单线程
if (OnlineOrderThread == null || !OnlineOrderThread.IsAlive)
{
OnlineOrderThread = new Thread(() => OnlineOrder(LocalOracle))
{
IsBackground = true
};
OnlineOrderThread.Start();
}
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "在线订单传输启动失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("在线订单传输启动失败:" + ex.Message);
}
}
#endregion
#region ->
/// <summary>
/// 主窗体按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click(object sender, RoutedEventArgs e)
{
Button _Button = (Button)sender;
switch (_Button.Name)
{
case "BtnTimerState":
if (CilentTimer != null)
{
if (CilentTimer.IsEnabled)
{
CilentTimer.Stop();
_Button.Content = "启动";
TransResultBeginInvoke(DateTime.Now, "数据传输定时器已停止");
}
else
{
CilentTimer.Start();
_Button.Content = "停止";
TransResultBeginInvoke(DateTime.Now, "数据传输定时器已启动");
}
}
else
{
TransResultBeginInvoke(DateTime.Now, "数据传输定时器初始化失败,请重启程序!");
}
break;
case "BtnClosed":
if (CilentTimer != null && CilentTimer.IsEnabled)
{
CilentTimer.Stop();
}
Close();
break;
}
}
#endregion
#region -> 线
/// <summary>
/// 主线程定时器
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CilentTimer_Tick(object sender, EventArgs e)
{
try
{
#region
//初始化数据库连接实例
if (LocalOracle == null || !LocalOracle.ConnTest())
{
LocalOracle = new Transmission.SDK.OracleHelper(_OracleConnStr.Split(',')[0], _OracleConnStr.Split(',')[4],
_OracleConnStr.Split(',')[1], _OracleConnStr.Split(',')[2], _OracleConnStr.Split(',')[3]);
}
#endregion
#region
//检查服务区编码参数,未设置时,从数据库中获取
if (string.IsNullOrWhiteSpace(ServerPartCode))
{
try
{
//从数据库中读取服务区编码信息
var _ServerPartList =
from t in LocalOracle.ExcuteSqlGetDataSet(
"SELECT SERVERPARTCODE FROM HIGHWAY_EXCHANGE.T_SYSCODE").Tables[0].AsEnumerable()
group t by new
{
t1 = t.Field<string>("SERVERPARTCODE")
} into m
select new
{
serverPartCode = m.Key.t1
};
//判断数据库中是否已读取到服务区信息
if (_ServerPartList.ToList().Count() > 0)
{
//多个服务区编码信息用英文逗号( , )拼接在一起,并保存到服务区信息参数属性中
ServerPartCode = string.Join(",", _ServerPartList.Select(p => p.serverPartCode));
}
}
catch { }
}
#endregion
#region
TransResultBeginInvoke(DateTime.Now, "正在预启动上传子线程......");
//初始化门店日结营收数据上传线程配置
if (BusinessConfigThreadConfigure())
{
//启动门店日结营收数据上传线程
if (BusinessClientThread.onState(LocalOracle))
{
TransResultBeginInvoke(DateTime.Now, "日结营收上传线程预启动成功");
}
else
{
TransResultBeginInvoke(DateTime.Now, "日结营收上传线程预启动失败");
}
}
//初始化服务区基础数据下载线程配置
if (ServerPartConfigThreadConfigure())
{
//启动服务区基础数据下载线程
if (ServerPartClientThread.onState(LocalOracle))
{
TransResultBeginInvoke(DateTime.Now, "服务区数据下载线程预启动成功");
}
else
{
TransResultBeginInvoke(DateTime.Now, "服务区数据下载线程预启动失败");
}
}
#endregion
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "传输启动失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("传输启动失败:" + ex.Message);
}
}
#endregion
#region -> Socket客户端消息通知事件
/// <summary>
/// Socket客户端消息通知事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SocketClient_NotifyEvent(object sender, Transmission.SDK.Model.Common.NotifyEventArgs e)
{
string DirectoryName = AppDomain.CurrentDomain.BaseDirectory + "/SocketLog";
//记录文本日志
Transmission.SDK.LogHelper.WriteLog(e.NotifyLoggerMessage, "", DirectoryName);
#region /WebSocket/RecordLogToOracleSocket消息通知执行结果到云端
try
{
Transmission.SDK.LogHelper.WriteServiceLog($"是否调用日志上传接口:" + e.NotifyUploadState);
//只有通知上传状态为True的消息才上传到云端
if (e.NotifyUploadState)
{
//文件上传耗时记录
string str_HttpURL = "http://pos.eshangtech.com:7198/webApi_publish/WebSocket/RecordLogToOracle";
string str_PostData = $"ServerpartCode={SocketServerpartCode}&ShopCode=000000&" +
$"MachineCode=0000&LogCentent={e.NotifyLoggerMessage}&TableName={(int)e.NotifyLoggerType}" +
$"&OperateTime={e.NotifyLoggerTime.ToString("yyyyMMddHHmmss")}";
string Result = Transmission.SDK.HttpDataHelper.OnPost($"{str_HttpURL}?{str_PostData}", str_PostData);
Transmission.SDK.LogHelper.WriteServiceLog($"开始上传日志【{str_PostData}】,上传结果:" + Result);
}
}
catch (Exception ex)
{
Transmission.SDK.LogHelper.WriteLog($"{ e.NotifyLoggerType }执行结果上报失败。原因:{ex.Message}", "", DirectoryName);
}
#endregion
//界面显示消息内容
TransResultBeginInvoke(e.NotifyLoggerTime, e.NotifyLoggerMessage);
}
#endregion
#region ->
/// <summary>
/// 检测本地数据表字段
/// </summary>
/// <param name="localOracle">本地数据库链接</param>
private void CheckTableColumn(Transmission.SDK.OracleHelper localOracle)
{
DataBaseUpdate _DataBaseUpdate = new DataBaseUpdate(localOracle);
//收银状态反馈表更新
_DataBaseUpdate.AlterTableColumn("T_STATEFEEDBACK");
//智能稽查任务表更新
_DataBaseUpdate.AlterTableColumn("T_AUDITTASKS");
//移动支付记录表更新
_DataBaseUpdate.AlterTableColumn("T_MOBILE_PAY");
//新日结营收表更新
_DataBaseUpdate.AlterTableColumn("T_ENDACCOUNT_NEW");
//旧日结营收表更新
_DataBaseUpdate.AlterTableColumn("T_ENDACCOUNT");
//门店信息表更新
_DataBaseUpdate.AlterTableColumn("T_SHOPMESSAGE_EX");
#region
try
{
localOracle.ExcuteSql("SELECT TRANSFER_STATE FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA WHERE 1 = 0");
}
catch
{
try
{
localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA ADD TRANSFER_STATE NUMBER(4,0)");
}
catch { }
}
try
{
//修正T_BUSINESSCONFIG【业态收银配置表】主键值字段名
localOracle.ExcuteSql("SELECT USINESSCONFIG_ID FROM HIGHWAY_EXCHANGE.T_BUSINESSCONFIG WHERE 1=0");
localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_BUSINESSCONFIG RENAME COLUMN USINESSCONFIG_ID TO BUSINESSCONFIG_ID");
}
catch { }
try
{
localOracle.ExcuteSql("SELECT MEMBERSHIP_COMPANY FROM HIGHWAY_EXCHANGE.T_MEMBERSHIP WHERE 1 = 0");
}
catch
{
try
{
//会员信息表增加字段所属单位【MEMBERSHIP_COMPANY】
localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_MEMBERSHIP ADD MEMBERSHIP_COMPANY NUMBER(9,0)");
}
catch { }
}
try
{
localOracle.ExcuteSql("SELECT EXTERNALMEMBER_ID FROM HIGHWAY_EXCHANGE.T_MEMBERSHIP WHERE 1 = 0");
}
catch
{
try
{
//会员信息表增加字段外部会员内码【EXTERNALMEMBER_ID】
localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_MEMBERSHIP ADD EXTERNALMEMBER_ID NUMBER(9,0)");
}
catch { }
}
//自定义类别表增加数据来源字段
if (LocalOracle.ExcuteSqlGetDataSet("SELECT COLUMN_NAME FROM SYS.ALL_TAB_COLUMNS WHERE OWNER = 'HIGHWAY_EXCHANGE' AND " +
"TABLE_NAME = 'T_USERDEFINEDTYPE' AND COLUMN_NAME IN ('DATA_SOURCE')").Tables[0].Rows.Count == 0)
{
localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_USERDEFINEDTYPE ADD (DATA_SOURCE NUMBER(1,0) DEFAULT 0)");
}
#endregion
}
#endregion
#region -> 线
private void BigData_ResultEvent(DateTime triggerTime, string resultMessage)
{
TransResultBeginInvoke(triggerTime, resultMessage);
}
#endregion
#region ->
/// <summary>
/// 校验并更新数据库表结构
/// </summary>
/// <param name="localOracle"></param>
/// <param name="checkList"></param>
private void CheckOracleTable(Transmission.SDK.OracleHelper localOracle, Dictionary<string, string> checkList)
{
DataBaseUpdate _DataBaseUpdate = new DataBaseUpdate(localOracle);
foreach (string _Key in checkList.Keys)
{
if (string.IsNullOrWhiteSpace(checkList[_Key]))
{
_DataBaseUpdate.CreateTable(_Key);
}
else
{
try
{
if (LocalOracle.ExcuteSqlGetDataSet("SELECT 1 FROM SYS.DBA_ALL_TABLES WHERE TABLE_NAME = '" +
_Key + "' AND OWNER = 'HIGHWAY_EXCHANGE'").Tables[0].Rows.Count == 0)
{
if (_DataBaseUpdate.CreateTable(_Key))
{
TransResultBeginInvoke(DateTime.Now, $"{checkList[_Key]}创建成功。");
}
else
{
TransResultBeginInvoke(DateTime.Now, $"{checkList[_Key]}创建失败。");
}
}
}
catch (Exception ex)
{
Transmission.SDK.LogHelper.WriteServiceLog("校验并更新数据库表结构失败:" + ex.Message);
}
}
}
}
#endregion
#region -> APP运行状态上报
/// <summary>
/// APP运行状态上报
/// </summary>
/// <param name="localOracle">数据库连接类</param>
private void AppStateUpload(Transmission.SDK.OracleHelper localOracle)
{
try
{
if (ServerPartTable == null || ServerPartCacheTime < DateTime.Now)
{
//重置服务区信息缓存表
ServerPartTable = localOracle.ExcuteSqlGetDataSet(
@"SELECT SERVERPART_CODE,PROVINCE_CODE,SERVERPART_NAME
FROM HIGHWAY_EXCHANGE.T_SERVERPART").Tables[0];
if (ServerPartTable.Rows.Count == 0)
{
ServerPartCacheTime = DateTime.Now.AddMinutes(5);
}
else
{
ServerPartCacheTime = DateTime.Now.AddHours(1);
}
}
//定义APP运行状态上报传输地址
string _UploadRuningStateUrl = ConfigurationManager.AppSettings["UploadRuningStateUrl"];
if (string.IsNullOrWhiteSpace(_UploadRuningStateUrl))
{
TransResultBeginInvoke(DateTime.Now, $"APP运行状态上报失败。原因参数[UploadRuningStateUrl]未配置。");
return;
}
foreach (DataRow ServerPartRow in ServerPartTable.Rows)
{
Hashtable hashtable = new Hashtable
{
//省份编码
{ "provinceCode", ServerPartRow["PROVINCE_CODE"].ToString() },
//省份名称
{ "provinceName", "" },
//服务区编码
{ "serverPartCode", ServerPartRow["SERVERPART_CODE"].ToString() },
//服务区名称
{ "serverPartName", ServerPartRow["SERVERPART_NAME"].ToString() },
//运行工具名称
{ "appName", System.Windows.Forms.Application.ProductName },
//运行工具版本号
{ "appVersion", $"TCv{System.Windows.Forms.Application.ProductVersion}" }
};
//上传运行工具状态信息
Transmission.SDK.SoapWSHelper.QuerySoapWebServiceString(
$"{_UploadRuningStateUrl}/Service.asmx", "UploadTransClientState", hashtable);
}
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, $"APP运行状态上报失败。原因{ex.Message}");
}
}
#endregion
#region -> 线
/// <summary>
/// 线上订单传输
/// </summary>
/// <param name="localOracle">数据库连接类</param>
private void OnlineOrder(Transmission.SDK.OracleHelper localOracle)
{
TransResultBeginInvoke(DateTime.Now, $"正在启动线上订单数据同步线程......");
try
{
//定义线上订单数据同步地址
string _OnlineService;
try
{
_OnlineService = ConfigurationManager.AppSettings["OnlineService"];
}
catch
{
_OnlineService = "";
}
if (string.IsNullOrWhiteSpace(_OnlineService))
{
TransResultBeginInvoke(DateTime.Now, $"线上订单数据同步线程启动失败。原因:参数[OnlineService]未配置。");
return;
}
if (ServerPartTable == null || ServerPartCacheTime < DateTime.Now)
{
//重置服务区信息缓存表
ServerPartTable = localOracle.ExcuteSqlGetDataSet(
@"SELECT SERVERPART_CODE,PROVINCE_CODE,SERVERPART_NAME
FROM HIGHWAY_EXCHANGE.T_SERVERPART").Tables[0];
if (ServerPartTable.Rows.Count == 0)
{
ServerPartCacheTime = DateTime.Now.AddMinutes(5);
}
else
{
ServerPartCacheTime = DateTime.Now.AddHours(1);
}
}
OrderOnline.OnlineTransferResult transferResult;
foreach (DataRow ServerPartRow in ServerPartTable.Rows)
{
//分服务区下载已付款线上订单
TransResultBeginInvoke(DateTime.Now, $"正在下载[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单数据......");
transferResult = OrderOnline.OrderBillDown(localOracle, _OnlineService,
ServerPartRow["SERVERPART_CODE"].ToString(), ServerPartRow["PROVINCE_CODE"].ToString());
TransResultBeginInvoke(DateTime.Now, $"[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单下载完成;" +
$"\n本次订单获取总数{transferResult.TotalCount}条;成功:{transferResult.SuccessCount}条;" +
$"失败:{transferResult.FailCount}条;过滤:{transferResult.FilterCount}条;耗时:{transferResult.TotalSeconds.ToString("F2")}秒。");
//分服务区上传已完成、已制作订单结果
TransResultBeginInvoke(DateTime.Now, $"正在上传[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单接收结果数据......");
transferResult = OrderOnline.OrderBillUpload(localOracle, _OnlineService,
ServerPartRow["SERVERPART_CODE"].ToString(), ServerPartRow["PROVINCE_CODE"].ToString());
TransResultBeginInvoke(DateTime.Now, $"[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单接收结果数据上传完成;" +
$"\n本次订单结果上传总数{transferResult.TotalCount}条;成功:{transferResult.SuccessCount}条;" +
$"失败:{transferResult.FailCount}条;过滤:{transferResult.FilterCount}条;耗时:{transferResult.TotalSeconds.ToString("F2")}秒。");
}
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, $"线上订单数据同步线程启动失败。原因:{ex.Message}");
}
}
#endregion
#region ->
/// <summary>
/// 数据库历史数据迁移清理
/// </summary>
/// <param name="localOracle">数据库连接</param>
private void ClearHistoryData(Transmission.SDK.OracleHelper localOracle)
{
try
{
//删除不完整的账期记录
localOracle.ExecuteSqlTran("DELETE FROM HIGHWAY_EXCHANGE.T_ENDACCOUNT_NEW WHERE ENDDATE IS NULL");
//删除不完整的工班记录
localOracle.ExecuteSqlTran("DELETE FROM HIGHWAY_EXCHANGE.T_PERSONSELL_NEW WHERE ENDDATE IS NULL");
//迁移30天以上的移动支付记录到历史表
localOracle.ExecuteSqlTran(
@"INSERT INTO HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA_HIS
(SELLDATA_ID,SELLDATA_TYPE,SELLDATA_DATE,SERVERPARTCODE,
SHOPCODE,MACHINECODE,TICKETCODE,WORKERCODE,COMMODITY_CODE,
SELLCOUNT,SELLPRICE,OFFPRICE,FACTAMOUNT,LINENUM,FLAG,
SELLDATA_EXTRA_DESC,TRANSFER_STATE)
SELECT SELLDATA_ID,SELLDATA_TYPE,SELLDATA_DATE,SERVERPARTCODE,
SHOPCODE,MACHINECODE,TICKETCODE,WORKERCODE,COMMODITY_CODE,
SELLCOUNT,SELLPRICE,OFFPRICE,FACTAMOUNT,LINENUM,FLAG,
SELLDATA_EXTRA_DESC,TRANSFER_STATE
FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA
WHERE SELLDATA_DATE < TRUNC(SYSDATE) - 30 ");
localOracle.ExecuteSqlTran(@"DELETE FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA
WHERE SELLDATA_DATE < TRUNC(SYSDATE) - 30 ");
//迁移15天以上并已上传的移动支付记录到历史表
localOracle.ExecuteSqlTran(
@"INSERT INTO HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA_HIS
(SELLDATA_ID,SELLDATA_TYPE,SELLDATA_DATE,SERVERPARTCODE,
SHOPCODE,MACHINECODE,TICKETCODE,WORKERCODE,COMMODITY_CODE,
SELLCOUNT,SELLPRICE,OFFPRICE,FACTAMOUNT,LINENUM,FLAG,
SELLDATA_EXTRA_DESC,TRANSFER_STATE)
SELECT SELLDATA_ID,SELLDATA_TYPE,SELLDATA_DATE,SERVERPARTCODE,
SHOPCODE,MACHINECODE,TICKETCODE,WORKERCODE,COMMODITY_CODE,
SELLCOUNT,SELLPRICE,OFFPRICE,FACTAMOUNT,LINENUM,FLAG,
SELLDATA_EXTRA_DESC,TRANSFER_STATE
FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA
WHERE SELLDATA_DATE < TRUNC(SYSDATE) - 15 AND NVL(TRANSFER_STATE,0) = 9");
localOracle.ExecuteSqlTran(@"DELETE FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA
WHERE SELLDATA_DATE < TRUNC(SYSDATE) - 15 AND NVL(TRANSFER_STATE,0) = 9");
TransResultBeginInvoke(DateTime.Now, $"数据库移动支付历史数据迁移清理完成。");
//删除重复商品促销记录
localOracle.ExecuteSqlTran(@"DELETE FROM HIGHWAY_EXCHANGE.T_SALESPROMOTE B
WHERE (B.SERVERPARTCODE,B.SHOPCODE,B.PROMOTION_ID,B.COMMODITY_CODE) IN
(SELECT A.SERVERPARTCODE,A.SHOPCODE,A.PROMOTION_ID,A.COMMODITY_CODE
FROM HIGHWAY_EXCHANGE.T_SALESPROMOTE A
GROUP BY A.SERVERPARTCODE,A.SHOPCODE,A.PROMOTION_ID,A.COMMODITY_CODE
HAVING COUNT(1) > 1) AND B.SALESPROMOTE_ID NOT IN
(SELECT MAX(A.SALESPROMOTE_ID)
FROM HIGHWAY_EXCHANGE.T_SALESPROMOTE A
GROUP BY A.SERVERPARTCODE,A.SHOPCODE,A.PROMOTION_ID,A.COMMODITY_CODE
HAVING COUNT(1) > 1)");
TransResultBeginInvoke(DateTime.Now, $"重复商品促销记录清理完成。");
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, $"历史数据迁移清理失败。原因:{ex.Message}");
}
}
#endregion
#region ->
/// <summary>
/// 十分钟数据采集统计
/// </summary>
/// <param name="localOracle">数据库连接类</param>
private void CreateDataCollection(Transmission.SDK.OracleHelper localOracle)
{
try
{
TransResultBeginInvoke(DateTime.Now, "正在生成今日实时采集统计数据......");
//查询已固化的每十分钟营收数据
DataTable _DataCollectionTable = localOracle.ExcuteSqlGetDataSet(
@"SELECT
A.SERVERPARTCODE,A.DATACOLLECTION_DATE
FROM
HIGHWAY_EXCHANGE.T_DATACOLLECTION A,HIGHWAY_EXCHANGE.T_SYSCODE B
WHERE
TRUNC(A.DATACOLLECTION_DATE) = TRUNC(SYSDATE) AND
A.DATACOLLECTION_TYPE = 3000 AND A.SERVERPARTCODE = B.SERVERPARTCODE").Tables[0];
//计算已统计的服务区
int _ServerPartCount = _DataCollectionTable.DefaultView.ToTable(true, new string[] { "SERVERPARTCODE" }).Rows.Count;
//获取截止当前时间,今日每个服务区应统计的条数
int _TotalCount = (int)(DateTime.Now - DateTime.Today).TotalMinutes / 10;
TransResultBeginInvoke(DateTime.Now, string.Format("本次统计截止:{0}", DateTime.Today.AddMinutes((double)_TotalCount * 10).ToString()));
//判断是否有未统计的营收数据
if (_DataCollectionTable.Rows.Count == 0 || _DataCollectionTable.Rows.Count < _ServerPartCount * _TotalCount)
{
//从T_DATACOLLECTION统计每十分钟营收数据
List<DATACOLLECTION> _DataCollectionList = (List<DATACOLLECTION>)Transmission.SDK.DataTableHelper.DataTableToIList<DATACOLLECTION>(
localOracle.ExcuteSqlGetDataSet(string.Format(
@"SELECT A.SERVERPARTCODE,3000 AS DATACOLLECTION_TYPE,
(CASE FLOOR((TO_CHAR(A.DATACOLLECTION_DATE, 'MI')) /10)
WHEN 0 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((00+10) * 60-1)/86400
WHEN 1 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((10+10) * 60-1)/86400
WHEN 2 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((20+10) * 60-1)/86400
WHEN 3 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((30+10) * 60-1)/86400
WHEN 4 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((40+10) * 60-1)/86400
WHEN 5 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((50+10) * 60-1)/86400
END) AS DATACOLLECTION_DATE,
NVL(SUM(A.TOTAL_COUNT),0) AS TOTAL_COUNT,NVL(SUM(A.TOTALSELL_AMOUNT),0) AS TOTALSELL_AMOUNT,
NVL(SUM(A.TICKET_COUNT),0) AS TICKET_COUNT
FROM
HIGHWAY_EXCHANGE.T_DATACOLLECTION A,HIGHWAY_EXCHANGE.T_SYSCODE B
WHERE
A.DATACOLLECTION_DATE BETWEEN TRUNC(SYSDATE) AND TO_DATE('{0}','YYYY/MM/DD HH24:MI:SS') AND
A.DATACOLLECTION_TYPE IN (1000,2000) AND A.SERVERPARTCODE = B.SERVERPARTCODE
GROUP BY
A.SERVERPARTCODE,
CASE FLOOR((TO_CHAR(A.DATACOLLECTION_DATE, 'MI')) /10)
WHEN 0 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((00+10) * 60-1)/86400
WHEN 1 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((10+10) * 60-1)/86400
WHEN 2 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((20+10) * 60-1)/86400
WHEN 3 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((30+10) * 60-1)/86400
WHEN 4 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((40+10) * 60-1)/86400
WHEN 5 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'),
'YYYY/MM/DD HH24:MI:SS') + ((50+10) * 60-1)/86400
END
ORDER BY DATACOLLECTION_DATE", DateTime.Today.AddMinutes((double)_TotalCount * 10).ToString())).Tables[0]);
//var _MaxDate = _DataCollectionList.Max(p => p.DATACOLLECTION_DATE);
List<DATACOLLECTION> _InsertList = new List<DATACOLLECTION>();
foreach (DATACOLLECTION _DATACOLLECTION in _DataCollectionList)
{
//过滤已插入数据库的每十分钟营收数据
if (_DataCollectionTable.Select(string.Format("SERVERPARTCODE = '{0}' AND DATACOLLECTION_DATE = '{1}'",
_DATACOLLECTION.SERVERPARTCODE, _DATACOLLECTION.DATACOLLECTION_DATE)).Count() == 0)
{
_InsertList.Add(_DATACOLLECTION);
}
}
if (_InsertList.Count > 0)
{
Transmission.SDK.OperationDataHelper<DATACOLLECTION>.InsertTableData(localOracle, _InsertList,
"HIGHWAY_EXCHANGE.T_DATACOLLECTION", true, "DATACOLLECTION_ID", "HIGHWAY_EXCHANGE.SEQ_DATACOLLECTION.NEXTVAL");
}
TransResultBeginInvoke(DateTime.Now, string.Format("今日实时采集数据统计完成:总数:{0};新增:{1}",
_DataCollectionList.Count, _InsertList.Count));
TodayCount = _TotalCount;
}
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "今日实时采集数据统计失败:" + ex.Message);
}
try
{
TransResultBeginInvoke(DateTime.Now, "正在清理过期实时采集数据......");
int _DeleteCount = localOracle.ExcuteSql("DELETE FROM HIGHWAY_EXCHANGE.T_DATACOLLECTION WHERE DATACOLLECTION_DATE < SYSDATE - 15");
TransResultBeginInvoke(DateTime.Now, string.Format("过期实时采集数据清理完成:本次清理{0}条。", _DeleteCount));
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "过期实时采集数据清理失败:" + ex.Message);
}
}
#endregion
#region ->
/// <summary>
/// 文件上传
/// </summary>
/// <param name="uploadURL">上传地址</param>
/// <returns></returns>
private void UploadDataZipFile(string uploadURL)
{
try
{
string str_BaseDirectory = Transmission.SDK.IISWorkerHelper.GetPhysicPath("PosDataUpload");
if (string.IsNullOrWhiteSpace(str_BaseDirectory))
{
//区服不存在文件接收站点
TransResultBeginInvoke(DateTime.Now, $"文件接收站点【PosDataUpload】不存在。");
return;
}
//压缩文件保存的路径
string str_ZipFileDir = Path.Combine(str_BaseDirectory, "Upload");
if (!Directory.Exists(str_ZipFileDir))
{
//压缩文件不存在,直接结束
TransResultBeginInvoke(DateTime.Now, $"无未上传的数据文件。");
return;
}
BreakpointUploader DataBreakpointUploader = new BreakpointUploader(1024 * 1024 * 1, UploadType.Append);
DataBreakpointUploader.OnUploading += Uploader_OnUploading;
//读取压缩文件存储目录下全部压缩文件
FileInfo[] file_DataFileList = new DirectoryInfo(str_ZipFileDir).GetFiles("*.zip", SearchOption.AllDirectories);
foreach (FileInfo file_DataFile in file_DataFileList)
{
//判断压缩文件是否已上传,未上传的有效压缩文件才进行上传
if (file_DataFile.Length > 0)
{
TransResultBeginInvoke(DateTime.Now, $"正在上传数据文件:{file_DataFile.Name}");
Internal.Header.M_Headers = new KeyValuePair<string, string>(
"x-app-name", System.Web.HttpUtility.UrlEncode("TransmissionClient"));
UploadStatus status = DataBreakpointUploader.Upload(file_DataFile.Directory.Name,file_DataFile.FullName, uploadURL);
if (status == UploadStatus.Completed)
{
//等待1秒用于释放被传输占用的文件资源
Thread.Sleep(1000);
if (!Directory.Exists(Path.Combine(str_BaseDirectory, "Zip", file_DataFile.Directory.Name)))
{
Directory.CreateDirectory(Path.Combine(str_BaseDirectory, "Zip", file_DataFile.Directory.Name));
}
if (File.Exists(Path.Combine(str_BaseDirectory, "Zip", file_DataFile.Directory.Name, file_DataFile.Name)))
{
//删除已经存在的文件
File.Delete(Path.Combine(str_BaseDirectory, "Zip", file_DataFile.Directory.Name, file_DataFile.Name));
//暂停300毫秒等待资源释放
Thread.Sleep(300);
}
//移动已上传的文件到备份文件夹
File.Move(file_DataFile.FullName, Path.Combine(str_BaseDirectory,
"Zip", file_DataFile.Directory.Name, file_DataFile.Name));
TransResultBeginInvoke(DateTime.Now, $"数据文件:【{file_DataFile.Name}】上传成功。");
}
}
}
}
catch (Exception ex)
{
Transmission.SDK.LogHelper.WriteServiceLog("数据文件压缩包上传失败:" + ex.Message);
}
}
/// <summary>
/// 文件传输进度处理事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Uploader_OnUploading(object sender, UploadEventArgs e)
{
TransResultBeginInvoke(DateTime.Now, $"正在上传数据文件:【{e.FileName}】已上传:{e.Position}。");
}
#endregion
#region ->
private bool MemberConfigThreadConfigure()
{
//定义内部会员数据传输地址
string _MemberUrl;
try
{
_MemberUrl = ConfigurationManager.AppSettings["MemberUrl"];
}
catch
{
_MemberUrl = "";
}
if (string.IsNullOrWhiteSpace(_MemberUrl))
{
TransResultBeginInvoke(DateTime.Now, $"内部会员数据传输线程启动失败。原因:参数[MemberUrl]未配置。");
return false;
}
//初始化内部会员相关数据传输配置
if (MemberConfigThread == null)
{
MemberConfigThread = new ConfigThread("");
}
//上传数据配置
MemberClientThread.IsUpload(true, new List<string>
{
"T_RECHARGERECORD" //消费记录表【离线支付交易记录】
});
//下载数据配置
MemberClientThread.IsDownload(true, new List<string>
{
"T_MEMBERSHIP", //内部会员钱包表
"T_ICCARDINFO", //IC卡信息表
"T_COMPANYAUTHORIZE" //内部会员禁止消费门店表
});
try
{
MemberClientThread.setConfiguration($"{_MemberUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 20, 2);
MemberClientThread.setConfigThread(MemberConfigThread);
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "内部会员数据传输配置失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("内部会员数据传输配置失败:" + ex.Message);
}
return true;
}
#endregion
#region ->
/// <summary>
/// 大数据平台相关信息上传配置
/// </summary>
private bool StateConfigThreadConfigure()
{
//初始化大数据传输地址
string _BigDataUrl;
try
{
_BigDataUrl = ConfigurationManager.AppSettings["BigDataUrl"];
}
catch
{
_BigDataUrl = "";
}
if (string.IsNullOrWhiteSpace(_BigDataUrl))
{
TransResultBeginInvoke(DateTime.Now, $"大数据平台上传线程启动失败。原因:参数[BigDataUrl]未配置。");
return false;
}
//初始化大数据平台相关信息上传配置
if (StateConfigThread == null)
{
StateConfigThread = new ConfigThread("");
}
//定义上传表内容
StateClientThread.IsUpload(true, new List<string>
{
//"T_DATACOLLECTION", //十分钟营收数据表
//"T_CUSTOMERINFO", //客群消费信息表
//"T_SATISFACTIONFLOW", //满意度统计表
//"T_PASSENGERFLOW", //客流统计表
//"T_VEHICLEFLOW", //车流统计表
//"T_CONNECTPOINT", //旧状态反馈表
//"T_STATEFEEDBACK", //新状态反馈表
//"T_COMMODITYANALYSIS", //单品排行统计表前后10位【自然日】
//"T_CUSTOMERANALYSIS", //客群分析汇总表【自然日】
//"T_SALESANALYSIS", //客单金额段统计分析表【自然日】
//"T_SALESINTERVALANALYSIS" //客单金额时段统计分析表【自然日】
});
StateClientThread.IsDownload(false);
try
{
//设置配置参数
StateClientThread.setConfiguration($"{_BigDataUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 20, 2);
//配置线程参数
StateClientThread.setConfigThread(StateConfigThread);
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "大数据平台上传配置失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("大数据平台上传配置失败:" + ex.Message);
}
return true;
}
#endregion
#region ->
/// <summary>
/// 移动支付、稽核数据上传线程配置
/// </summary>
private bool MobilePayConfigThreadConfigure()
{
//初始化移动支付、稽核上传地址
string _MobilePayDataUrl;
try
{
_MobilePayDataUrl = ConfigurationManager.AppSettings["MobilePayDataUrl"];
}
catch
{
_MobilePayDataUrl = "";
}
if (string.IsNullOrWhiteSpace(_MobilePayDataUrl))
{
TransResultBeginInvoke(DateTime.Now, $"移动支付数据上传线程启动失败。原因:参数[MobilePayDataUrl]未配置。");
return false;
}
//初始化移动支付、稽核数据上传线程配置
if (MobilePayConfigThread == null)
{
MobilePayConfigThread = new ConfigThread("");
}
//定义上传表内容
MobilePayClientThread.IsUpload(true, new List<string>
{
//"T_MOBILE_PAY", //收银前端异常支付数据表
//"T_EXCEPTION", //旧异常稽核数据表
//"T_CONSUMPTIONRECORD", //促销明细流水表
//"T_PROMOTIONRECORD", //促销明细流水表【新】--2021.04
//"T_ABNOEMALITYANALYSIS", //异常稽核汇总报表【新】
//"T_ABNORMALITY", //异常稽核主表【新】
//"T_ABNORMALITYDETAIL", //异常稽核明细表【新】
//"T_COMMODITYSALE_EX" //三方系统单品表(湖北)
});
MobilePayClientThread.IsDownload(false);
try
{
//设置配置参数
MobilePayClientThread.setConfiguration($"{_MobilePayDataUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 50, 2);
//配置线程参数
MobilePayClientThread.setConfigThread(MobilePayConfigThread);
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "移动支付、稽核数据上传配置失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("移动支付、稽核数据上传配置失败:" + ex.Message);
}
return true;
}
#endregion
#region ->
/// <summary>
/// 日结营收数据上传线程配置
/// </summary>
private bool BusinessConfigThreadConfigure()
{
//初始化日结营收数据上传地址
string _SalesDataUrl;
try
{
_SalesDataUrl = ConfigurationManager.AppSettings["SalesDataUrl"];
}
catch
{
_SalesDataUrl = "";
}
if (string.IsNullOrWhiteSpace(_SalesDataUrl))
{
TransResultBeginInvoke(DateTime.Now, $"日结营收数据上传线程启动失败。原因:参数[SalesDataUrl]未配置。");
return false;
}
//初始化日结营收数据上传线程配置
if (BusinessConfigThread == null)
{
BusinessConfigThread = new ConfigThread("", IsReplaceColumn);
}
//定义上传表内容
BusinessClientThread.IsUpload(true, new List<string>
{
"T_ENDACCOUNT_NEW", //日结账期表【新】
"T_ENDACCOUNT", //日结账期表【旧】
"T_PERSONSELL_NEW", //收银员交班表【新】
"T_PERSONSELL", //收银员交班表【旧】
//"T_TRANSFER_SALE", //单品集合表
//"T_COMMODITYSALE", //PB老系统单品明细表
//"T_COMMODITYSALE_NEW", //新系统单品明细表
//"T_COMMODITYSALE_EXTAR" //特殊单品报表
});
BusinessClientThread.IsDownload(false);
try
{
//设置配置参数
BusinessClientThread.setConfiguration($"{_SalesDataUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 20, 1);
//配置线程参数
BusinessClientThread.setConfigThread(BusinessConfigThread);
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "日结营收数据上传配置失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("日结营收数据上传配置失败:" + ex.Message);
}
return true;
}
#endregion
#region ->
/// <summary>
/// 基础数据下载配置
/// </summary>
/// <returns></returns>
private bool ServerPartConfigThreadConfigure()
{
string _MasterDataUrl;
//设置基础数据下载配置传输地址
try
{
_MasterDataUrl = ConfigurationManager.AppSettings["MasterDataUrl"];
}
catch
{
_MasterDataUrl = "";
}
//运行日志委托处理事件
if (string.IsNullOrWhiteSpace(_MasterDataUrl))
{
TransResultBeginInvoke(DateTime.Now, $"基础数据下载线程启动失败。原因:参数[MasterDataUrl]未配置。");
return false;
}
//初始化基础数据下载配置对象
if (ServerPartConfigThread == null)
{
ServerPartConfigThread = new ConfigThread(ServerPartCode);
}
//设置传输模式为下载
ServerPartClientThread.IsUpload(false);
//设置需要下载的表信息
ServerPartClientThread.IsDownload(true, new List<string>
{
"T_SERVERPART", //服务区
"T_SHOPMESSAGE_EX", //门店
"T_SELLWORKER_UNIT", //业主管理收银员数据
"T_SELLWORKER_CLOUD", //商户管理收银员数据
"T_COMMODITYEX_UNIT", //业主审批商品数据
"T_COMMODITYEX_CLOUD", //商户审批商品数据
"T_USERDEFINEDTYPE_UNIT", //业主管理自定义类
"T_USERDEFINEDTYPE_CLOUD", //商户管理自定义类
"T_SALESPROMOTE_EX", //促销数据表
//"T_PROMOTION", //新促销数据表
"T_MOBILEPAYCODE", //移动支付配置表【待优化】
"T_MACHINEINFO", //机器信息表
"T_CONFIGURATION", //收银系统参数配置表
"T_AUDITTASKS" //智能稽核任务表【待优化】
});
try
{
//设置配置参数
ServerPartClientThread.setConfiguration($"{_MasterDataUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 100, 3);
//配置线程参数
ServerPartClientThread.setConfigThread(ServerPartConfigThread);
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "服务区数据下载配置失败:" + ex.Message);
}
return true;
}
#endregion
#region ->
/// <summary>
/// 多链路传输配置
/// </summary>
/// <returns></returns>
private bool MulLinkConfigThreadConfigure()
{
//定义多链路传输配置获取服务地址
string str_MulLinkTransConfigUrl;
try
{
//默认读取Config文件中设置的传输链路配置地址;
str_MulLinkTransConfigUrl = ConfigurationManager.AppSettings["MulLinkTransConfigUrl"];
}
catch
{
str_MulLinkTransConfigUrl = "";
}
if (string.IsNullOrWhiteSpace(str_MulLinkTransConfigUrl))
{
//未配置多链路传输配置服务地址时,使用默认地址
str_MulLinkTransConfigUrl = "http://user.eshangtech.com:7088";
//TransResultBeginInvoke(DateTime.Now, $"多链路传输配置失败。原因:参数[MulLinkTransConfigUrl]未配置。");
//return false;
}
if (TransLinkConfigList == null)
{
//当启动程序时,调用服务获取多链路传输配置
TransLinkConfigList = OnTransLinkConfig(ServerPartCode, $"{str_MulLinkTransConfigUrl}/Service.asmx");
}
if (TransLinkConfigList == null || TransLinkConfigList.Count == 0)
{
//当云端未配置当前服务区多链路传输时,不继续初始化线程配置
TransResultBeginInvoke(DateTime.Now, $"多链路传输配置失败。原因:当前服务区云端未配置多链路传输。");
return false;
}
//遍历循环多链路配置列表,初始化每个链路的传输线程配置
foreach (var tlcm_TransLinkConfig in TransLinkConfigList)
{
//初始化链路传输数据类型,每个链路初始化一次
if (!MulLinkConfigThreadList.ContainsKey(tlcm_TransLinkConfig.TransLinkID))
{
MulLinkConfigThread mulLinkConfig = new MulLinkConfigThread(tlcm_TransLinkConfig.TableConfig, ServerPartCode);
MulLinkConfigThreadList.AddOrUpdate(tlcm_TransLinkConfig.TransLinkID, mulLinkConfig, (TransLinkID, MulLinkConfig) => mulLinkConfig);
}
//检查当前传输链路是否实例化传输线程配置
if (!MulLinkCilentThreadList.ContainsKey(tlcm_TransLinkConfig.TransLinkID))
{
//添加当前线程配置至线程列表
MulLinkCilentThread mulLinkCilent = new MulLinkCilentThread();
//绑定多链路线程上传回调事件
mulLinkCilent.UploadStringEvent += new MulLinkCilentThread.OutputResultsUploadArg(ClientThread_UploadStringEvent);
//绑定多链路线程下载回调事件
mulLinkCilent.DownloadStringEvent += new MulLinkCilentThread.OutputResultsDownArg(ClientThread_DownloadStringEvent);
MulLinkCilentThreadList.AddOrUpdate(tlcm_TransLinkConfig.TransLinkID, mulLinkCilent, (TransLinkID, MulLinkCilent) => mulLinkCilent);
}
//根据云端链路配置,设置需要启动传输的数据类型
List<string> _TransTableList = new List<string>();
foreach (var tc_TableConfig in tlcm_TransLinkConfig.TableConfig)
{
string[] str_TableName = tc_TableConfig.TableName.Split('.');
if (str_TableName.Length > 1)
{
_TransTableList.Add(str_TableName[1]);
//如多链路传输的数据上次给类型为状态反馈【T_STATEFEEDBACK】时需加上区服数据版本上传表类型【T_SERVERPARTFEEDBACK】
if (str_TableName[1] == "T_STATEFEEDBACK")
{
_TransTableList.Add("T_SERVERPARTFEEDBACK");
}
}
else
{
_TransTableList.Add(str_TableName[0]);
//如多链路传输的数据上次给类型为状态反馈【T_STATEFEEDBACK】时需加上区服数据版本上传表类型【T_SERVERPARTFEEDBACK】
if (str_TableName[0] == "T_STATEFEEDBACK")
{
_TransTableList.Add("T_SERVERPARTFEEDBACK");
}
}
}
try
{
//设置上传启动的表
MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].IsUpload(true, _TransTableList);
//设置下发启动的表
MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].IsDownload(true, _TransTableList);
//设置数据传输的链路地址
MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].setConfiguration(tlcm_TransLinkConfig.TransLinkURL, "", ServerPartCode, "", "", "", "", 20, 1);
//设置数据传输线程参数
MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].setConfigThread(MulLinkConfigThreadList[tlcm_TransLinkConfig.TransLinkID]);
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, $"链路[{tlcm_TransLinkConfig.TransLinkURL}]传输配置失败:" + ex.Message);
}
}
return true;
}
#endregion
#region ->
/// <summary>
/// 获取服务区多链路传输配置信息
/// </summary>
/// <param name="serverpartCode">服务区编码,多个使用英文逗号【,】隔开888888,888889</param>
/// <param name="serviceUrl">多链路传输配置获取服务地址格式http://127.0.0.1:7080/service.asmx </param>
/// <returns></returns>
private List<TransLinkConfigModel> OnTransLinkConfig(string serverpartCode, string serviceUrl)
{
List<TransLinkConfigModel> tlcm_TransLinkConfigList = new List<TransLinkConfigModel>();
try
{
//调用云端多链路配置服务接口,获取当前服务区多链路配置信息
string str_MulLinkTransConfig = Transmission.SDK.SoapWSHelper.QuerySoapWebServiceString(
serviceUrl, "GetMulLinkTransConfig", new Hashtable() { { "serverpartCodes", serverpartCode } });
if (string.IsNullOrWhiteSpace(str_MulLinkTransConfig))
{
//云端接口无返回值时,返回空白配置信息
return tlcm_TransLinkConfigList;
}
//反序列化返回值为JSon对象
JObject jObject_MulLinkTransConfig = JObject.Parse(str_MulLinkTransConfig);
if (jObject_MulLinkTransConfig.Property("IsSuccess") == null ||
jObject_MulLinkTransConfig.Property("IsSuccess").Value.ToString() != "1")
{
//当接口返回值IsSuccess不等于1时代表接口不成功返回空白配置信息
return tlcm_TransLinkConfigList;
}
//解析多链路配置为List实体
List<Model.MulLinkConfigModel> mlcm_MulLinkConfigModelList = jObject_MulLinkTransConfig.Property("Obj").Value.ToObject<List<Model.MulLinkConfigModel>>();
//var tmp_MulLinkConfigList = mlcm_MulLinkConfigModelList.Select(p => new { p.MulLinkConfig_ID, p.InterfaceAddress, p.ServerPartCode }).Distinct().ToList();
//多链路传输地址去重
var tmp_MulLinkConfigList = mlcm_MulLinkConfigModelList.Select(p => new { p.MulLinkConfig_ID, p.InterfaceAddress }).Distinct().ToList();
//遍历循环获取到的多链路信息,转化为本地多链路配置实体属性
foreach (var _MulLinkConfig in tmp_MulLinkConfigList)
{
TransLinkConfigModel temp_TransLinkConfig = new TransLinkConfigModel();
//设置链路唯一标识,用于多链路线程配置识别
temp_TransLinkConfig.TransLinkID = (int)_MulLinkConfig.MulLinkConfig_ID;
//设置链路传输真实服务地址
temp_TransLinkConfig.TransLinkURL = $"{_MulLinkConfig.InterfaceAddress}/Service.asmx";
//temp_TransLinkConfig.ServerPartCode = _MulLinkConfig.ServerPartCode;
//设置链路传输服务区编码
temp_TransLinkConfig.ServerPartCode = serverpartCode;
//设置链路传输启动的表数据类型
temp_TransLinkConfig.TableConfig = new List<TransTableConfigModel>();
List<Model.MulLinkConfigModel> temp_TransTable = mlcm_MulLinkConfigModelList.FindAll(p =>
{
return p.MulLinkConfig_ID == _MulLinkConfig.MulLinkConfig_ID;//&& p.ServerPartCode == _MulLinkConfig.ServerPartCode;
});
//循环添加需要启动传输的数据表类型至配置列表
for (int i = 0; i < temp_TransTable.Count; i++)
{
TransTableConfigModel temp_TransTableConfig = new TransTableConfigModel();
if (temp_TransTable[i].TransFrequence != null)
{
temp_TransTableConfig.TransFrequence = (int)temp_TransTable[i].TransFrequence.Value;
}
temp_TransTableConfig.TableName = temp_TransTable[i].TableName;
temp_TransTableConfig.HistoryCallbackDate = temp_TransTable[i].HistoryCallBackDate;
temp_TransTableConfig.HistoryCallbackDays = (int)temp_TransTable[i].HistoryCallBackDays;
temp_TransTableConfig.StartTime = (int)temp_TransTable[i].StartTime;
temp_TransTableConfig.EndTime = (int)temp_TransTable[i].EndTime;
temp_TransLinkConfig.TableConfig.Add(temp_TransTableConfig);
}
tlcm_TransLinkConfigList.Add(temp_TransLinkConfig);
}
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, $"多链路传输配置获取异常。原因:{ex.Message}");
}
return tlcm_TransLinkConfigList;
}
#endregion
#region ->
/// <summary>
/// 上传回调事件
/// </summary>
/// <param name="uploadResultInfo"></param>
/// <param name="resultString"></param>
private void ClientThread_UploadStringEvent(UploadResultInfo uploadResultInfo, string resultString)
{
if (uploadResultInfo.StartToEnd)
{
TransResultBeginInvoke(DateTime.Now, resultString);
}
else
{
//于窗体中显示上传结果
TransResultBeginInvoke(DateTime.Now, string.Format("上传完成:[{0}]\n     总数{1};成功:{2};过滤:{3};失败:{5};耗时:{4}{6}",
uploadResultInfo.TableName, uploadResultInfo.TotalNumber, uploadResultInfo.SuccessNumber,
uploadResultInfo.FilterNumber, uploadResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒",
uploadResultInfo.TotalNumber - uploadResultInfo.SuccessNumber - uploadResultInfo.FilterNumber,
(string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError) ? "" : ("\n     接口错误" + uploadResultInfo.InterfaceError)) +
(string.IsNullOrWhiteSpace(uploadResultInfo.Error) ? "" : ("\n     本地错误" + uploadResultInfo.Error))));
//若上传出现异常,则记录日志文本文件
if (!string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError) || !string.IsNullOrWhiteSpace(uploadResultInfo.Error))
{
//接口报错,记录异常变量,延迟重试传输
if (!string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError))
{
CheckTransferErrorNotify(uploadResultInfo.TableName, uploadResultInfo.ServiceURL);
}
//记录接口错误信息到文本日志中,供后续排查
if (!string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError))
{
Transmission.SDK.LogHelper.WriteServiceLog("接口错误:" + uploadResultInfo.InterfaceError +
$"\n{uploadResultInfo.TableDesc}数据上传错误:[{uploadResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{uploadResultInfo.Elapsed.TotalSeconds.ToString("F2") + ""}");
}
//记录本地错误信息到文本日志中,供后续排查
if (!string.IsNullOrWhiteSpace(uploadResultInfo.Error))
{
Transmission.SDK.LogHelper.WriteServiceLog("本地错误:" + uploadResultInfo.Error +
$"\n{uploadResultInfo.TableDesc}数据上传错误:[{uploadResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{uploadResultInfo.Elapsed.TotalSeconds.ToString("F2") + ""}");
}
}
else
{
if (TransferErrorNotify != null)
{
TransferErrorNotify.RemoveAll(p => p.ServiceURL == uploadResultInfo.ServiceURL);
}
}
}
}
#endregion
#region ->
/// <summary>
/// 下载回调事件
/// </summary>
/// <param name="downResultInfo"></param>
/// <param name="resultString"></param>
private void ClientThread_DownloadStringEvent(DownResultInfo downResultInfo, string resultString)
{
if (downResultInfo.StartToEnd)
{
TransResultBeginInvoke(DateTime.Now, resultString);
}
else
{
//于窗体中显示下载结果
TransResultBeginInvoke(DateTime.Now, string.Format("下载完成:[{0}]\n     总数{1};新增:{2};更新:{3};过滤:{4};耗时:{5}{6}",
downResultInfo.TableName, downResultInfo.TotalNumber, downResultInfo.AddNumber, downResultInfo.UpNumber,
downResultInfo.FilterNumber, downResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒",
(string.IsNullOrWhiteSpace(downResultInfo.InterfaceError) ? "" : ("\n     接口错误" + downResultInfo.InterfaceError)) +
(string.IsNullOrWhiteSpace(downResultInfo.Error) ? "" : ("\n     本地错误" + downResultInfo.Error))));
//若下载出现异常,则记录日志文本文件
if (!string.IsNullOrWhiteSpace(downResultInfo.InterfaceError) || !string.IsNullOrWhiteSpace(downResultInfo.Error))
{
//接口报错,记录异常变量,延迟重试传输
if (!string.IsNullOrWhiteSpace(downResultInfo.InterfaceError))
{
CheckTransferErrorNotify(downResultInfo.TableName, downResultInfo.ServiceURL);
}
//记录接口错误信息到文本日志中,供后续排查
if (!string.IsNullOrWhiteSpace(downResultInfo.InterfaceError))
{
Transmission.SDK.LogHelper.WriteServiceLog("接口错误:" + downResultInfo.InterfaceError +
$"\n{downResultInfo.TableDesc}数据获取错误:[{downResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{downResultInfo.Elapsed.TotalSeconds.ToString("F2") + ""}");
}
//记录本地错误信息到文本日志中,供后续排查
if (!string.IsNullOrWhiteSpace(downResultInfo.Error))
{
Transmission.SDK.LogHelper.WriteServiceLog("本地错误:" + downResultInfo.Error +
$"\n{downResultInfo.TableDesc}数据获取错误:[{downResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{downResultInfo.Elapsed.TotalSeconds.ToString("F2") + ""}");
}
}
else
{
if (TransferErrorNotify != null)
{
TransferErrorNotify.RemoveAll(p => p.ServiceURL == downResultInfo.ServiceURL);
}
}
}
}
/// <summary>
/// 接口异常记录缓存
/// </summary>
/// <param name="tableName">传输表名</param>
/// <param name="serviceURL">传输接口地址</param>
private void CheckTransferErrorNotify(string tableName, string serviceURL)
{
//初始化缓存变量
if (TransferErrorNotify == null)
{
TransferErrorNotify = new List<TransferErrorNotifyModel>();
}
//读取缓存的对应数据表传输异常变量
TransferErrorNotifyModel tenm_TransferErrorNotify = TransferErrorNotify.Find(p => p.ServiceURL == serviceURL);
//
if (tenm_TransferErrorNotify == null)
{
tenm_TransferErrorNotify = new TransferErrorNotifyModel();
//tenm_TransferErrorNotify.TableName = tableName;
tenm_TransferErrorNotify.ServiceURL = serviceURL;
TransferErrorNotify.Add(tenm_TransferErrorNotify);
}
//记录接口报错重试次数
if (tenm_TransferErrorNotify.ErrorCount < 10)
{
tenm_TransferErrorNotify.ErrorCount += 1;
}
tenm_TransferErrorNotify.LastErrorTime = DateTime.Now;
if (tenm_TransferErrorNotify.ErrorCount >= 3)
{
tenm_TransferErrorNotify.RestartTime = DateTime.Now.AddMinutes(5);
}
}
#endregion
#region ->
private delegate void DelegateTransResult(DateTime triggerTime, string resultMessage);
private void TransResultBeginInvoke(DateTime triggerTime, string resultMessage)
{
Dispatcher.BeginInvoke(new DelegateTransResult(TransResult), new object[] { triggerTime, resultMessage });
}
/// <summary>
/// 运行日志呈现
/// </summary>
/// <param name="triggerTime">日志时间</param>
/// <param name="resultMessage">日志内容</param>
private void TransResult(DateTime triggerTime, string resultMessage)
{
if (TransResultTable == null)
{
TransResultTable = ResultTable();
}
foreach (DataRow _RowTemp in TransResultTable.Select(string.Format("TransDate < '{0}'", DateTime.Now.AddHours(-1))))
{
TransResultTable.Rows.Remove(_RowTemp);
}
TransResultTable.AcceptChanges();
DataRow _DataRow = TransResultTable.NewRow();
_DataRow["TransDate"] = triggerTime;
_DataRow["TransResult"] = resultMessage;
TransResultTable.Rows.InsertAt(_DataRow, 0);
DataTransResult.AutoGenerateColumns = false;
DataTransResult.SelectionMode = DataGridSelectionMode.Single;
DataTransResult.ItemsSource = TransResultTable.DefaultView;
}
/// <summary>
/// 运行日志记录表结构
/// </summary>
/// <returns></returns>
private DataTable ResultTable()
{
DataTable _DataTable = new DataTable();
_DataTable.Columns.Add("TransDate", typeof(DateTime));
_DataTable.Columns.Add("TransResult", typeof(string));
return _DataTable;
}
#endregion
#region ->
/// <summary>
/// 方法 -> 比较两集合值
/// </summary>
/// <param name="listOne">集合</param>
/// <param name="listTwo">集合</param>
/// <param name="isCase">是否区分大小写</param>
private bool IsListCompare(List<string> listOne, List<string> listTwo, bool isCase = false)
{
if (listOne == null && listTwo == null)
{
return true;
}
if (listOne != null && listTwo != null)
{
if (listOne.Count == listTwo.Count)
{
foreach (string tempOne in listOne)
{
foreach (string tempTwo in listTwo)
{
if (isCase)
{
if (!tempOne.Equals(tempTwo))
{
return false;
}
}
else
{
if (!tempOne.ToUpper().Equals(tempTwo.ToUpper()))
{
return false;
}
}
}
}
return true;
}
}
return false;
}
#endregion
}
}