Files
zszq-trs/YLErpDAL/Modules/SuperviseReportModule/SAC/Service/ReportService.cs
T

1841 lines
86 KiB
C#

using NPOI.SS.Formula.Functions;
using OfficeOpenXml.Drawing.Slicer.Style;
using System;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using YieldChain.Helpers;
using YLErp.BLL;
using YLErp.Commons;
using YLErp.DBModels.Enums;
using YLErp.Helpers;
using YLErp.Modules.ClientModule;
using YLErp.Modules.SuperviseReportModule.SAC.Common;
using YLErp.Modules.SuperviseReportModule.SAC.Model;
using YLErp.Office;
using YLErp.Office.ExcelModule;
using static YLErp.Commons.ExcelHelper;
using static YLErp.DBModels.Consts.ConsReport;
using ExcelHelper = YLErp.Commons.ExcelHelper;
namespace YLErp.Modules.SuperviseReportModule.SAC.Service
{
public class ReportService : YLBaseService
{
public ReportService(OptUserInfo optUser) : base(optUser)
{
}
/// <summary>
/// 生成报送文件锁
/// </summary>
private static readonly AutoResetEvent generateSuperviseLock = new(true);
/// <summary>
/// 操作报送文件锁
/// </summary>
private static readonly AutoResetEvent optionSuperviseLock = new(true);
#region 生成报送文件
/// <summary>
/// 生成报送文件
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public List<SuperviseReport> Execute(ReportInfo req)
{
if (req.ReportTypes == null || req.ReportTypes.Count == 0)
{
throw new ServiceException("请选择要报送的类型");
}
var reportList = new List<SuperviseReport>();
var useBreak = false;
try
{
generateSuperviseLock.WaitOne();
var reportStatus = new ReportStatusModel();
do
{
reportStatus.ResetCurrentLength();
//放开存在未报送报告时,阻塞其他报告生成的限制,可能引起的业务中先后顺序的问题(比如一定要先新增后修改的问题)需要客户自己判断;
//var report = DbContext.supervise_report.Where(O => O.ReportType == SuperviseReportTypeEnum.SAC && O.ReportReponseStatus <= ReportSentStatus.SENDING).FirstOrDefault();
//if (report != null)
//{
// throw new ServiceException($"{UserBLL.GetById((int)report.optUserId)?.Name} 名下存在未发送或发送中的记录,请稍后操作");
//}
var serviceDict = new Dictionary<int, ReportBaseService>();
req.ReportTypes.Sort();
foreach (var item in req.ReportTypes)
{
var type = (SuperviseReportTypeEnum)item;
var service = ReportBaseService.ReportFactory(OptUser, type);
if (!service.CheckRequestParamer(req, out var errMsg))
{
throw new ServiceException(errMsg);
}
serviceDict[item] = service;
}
ReportBaseService.MaxExceIndex = queryCurrentExceIndex();
var checkMsgArr = new List<SacInfo>();
var res = new ReportResponse
{
Infos = new List<ReportRootModel>(),
Index = queryCurrentFileIndex(req.ReportDate)
};
foreach (var service in serviceDict)
{
try
{
ReportRootModel model = null;
service.Value.WriteDb = DbContext;
service.Value.FileNumber = res.Index;
service.Value.ReportStatus = reportStatus;
if (service.Key == (int)SuperviseReportTypeEnum.SAC_EventReport)
{
model = service.Value.Execute(req, req.EventReportStatus);
res.Infos.Add(model);
checkMsgArr.Add(service.Value.CheckValue(model, out _));
}
else if (service.Key == (int)SuperviseReportTypeEnum.SAC_OtherReport)
{
model = service.Value.Execute(req, req.OtherReportStatus);
res.Infos.Add(model);
checkMsgArr.Add(service.Value.CheckValue(model, out _));
}
else if (service.Key == (int)SuperviseReportTypeEnum.SAC_PeriodicReportSAC)
{
model = service.Value.Execute(req, req.SACReportStatus);
res.Infos.Add(model);
checkMsgArr.Add(service.Value.CheckValue(model, out _));
}
else if (service.Key == (int)SuperviseReportTypeEnum.SAC_PeriodicReportNAFMII)
{
model = service.Value.Execute(req, req.NAFMIIReportStatus);
res.Infos.Add(model);
checkMsgArr.Add(service.Value.CheckValue(model, out _));
}
else if (service.Key == (int)SuperviseReportTypeEnum.SAC_PeriodicReportISDA)
{
model = service.Value.Execute(req, req.ISDAReportStatus);
res.Infos.Add(model);
checkMsgArr.Add(service.Value.CheckValue(model, out _));
}
else if (service.Key == (int)SuperviseReportTypeEnum.SAC_PeriodicReportQuarter)
{
model = service.Value.Execute(req, req.PeriodicReportQuarterStatus);
res.Infos.Add(model);
checkMsgArr.Add(service.Value.CheckValue(model, out _));
}
else
{
foreach (var item in service.Value.ValidOperationType)
{
model = service.Value.Execute(req, item);
res.Infos.Add(model);
checkMsgArr.Add(service.Value.CheckValue(model, out _));
}
}
}
catch (Exception ex)
{
LogFactory.GetLogger("Execute").Info($"Exception" + ex.ToString());
throw;
}
}
res.Infos = res.Infos.Where(O => O != null).ToList();
if (res.Infos.Count == 0)
{
if (useBreak)
{
break;
}
else
{
throw new ServiceException("不存在要报送的数据");
}
}
if (checkMsgArr.Any(O => O != null))
{
var Tag = new ExceptionExtensionInfo
{
Tag = checkMsgArr.Where(O => O != null).ToList(),
};
//生成文件会报错,暂时先不开放这个功能
var savePath = $"~/App_Docs/Download/Report/Output/{OptUser.UserId}/报送文件_{DateTime.Now.ToString("yyyyMMddHHmmss")}.zip";
GenerateUploadZipFile(res, savePath);
Tag.ErrFilePath = savePath;
var exception = new ServiceException("数据校验未通过")
{
Tag = Tag
};
throw exception;
}
var zipPath = "";
try
{
optionSuperviseLock.WaitOne();
zipPath = ReportBaseService.ZipFile(res);
}
finally
{
optionSuperviseLock.Set();
}
foreach (var item in serviceDict)
{
if (!item.Value.BeforeOfGenerated(out var errMsg))
{
throw new ServiceException(errMsg);
}
}
var reportInfo = new DBModels.SuperviseReport()
{
ReportType = SuperviseReportTypeEnum.SAC,
ReportDate = req.ReportDate,
DataDate = req.DataDate,
SenderCode = req.SenderCode,
ReceiverCode = req.ReceiverCode,
LastMonthCash = req.LastMonthCash,
LatestMonthCash = req.LatestMonthCash,
LatestNetAssets = req.LatestNetAssets,
SRCReportStatus = req.SACReportStatus,
NAFMIIReportStatus = req.NAFMIIReportStatus,
ISDAReportStatus = req.ISDAReportStatus,
EventReportStatus = req.EventReportStatus,
OtherReportStatus = req.OtherReportStatus,
PeriodicReportQuarterStatus = req.PeriodicReportQuarterStatus,
FileTag = res.FileTag,
FilePath = zipPath,
ReportReponseStatus = ReportSentStatus.NONE,
ReportReponseCode = "",
ReportReponseMessage = "未知",
ReportReponsePath = "",
optDate = DateTime.Now,
optUserId = OptUser.UserId,
};
reportList.Add(reportInfo);
DbContext.supervise_report.Add(reportInfo);
DbContext.SaveChanges();
useBreak = reportStatus.Continue;
} while (reportStatus.Continue);
return reportList;
}
finally
{
generateSuperviseLock.Set();
}
}
/// <summary>
/// 获取当前记录序号
/// </summary>
/// <returns></returns>
private int queryCurrentExceIndex()
{
var exceId = DbContext.sac_report_notes.OrderByDescending(O => O.ExceId).Select(O => O.ExceId).FirstOrDefault();
var index = 1;
if (!string.IsNullOrWhiteSpace(exceId))
{
exceId = Regex.Match(exceId, @"\d{8}$").Value;
index = int.Parse(exceId) + 1;
}
return index;
}
/// <summary>
/// 获取当前报送文件序号
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
private int queryCurrentFileIndex(DateTime date)
{
var fileId = DbContext.supervise_report.Where(O => O.ReportDate == date && O.ReportType == SuperviseReportTypeEnum.SAC).OrderByDescending(O => O.FileTag).Select(O => O.FileTag).FirstOrDefault();
var index = 1;
if (!string.IsNullOrWhiteSpace(fileId))
{
if (fileId.EndsWith("_checked"))
{
fileId = fileId.Replace("_checked", "");
}
fileId = Regex.Match(fileId, @"\d{4}$").Value;
index = int.Parse(fileId) + 1;
}
if (index <= PS.Config.ReportFileBeginNumber)
{
index += PS.Config.ReportFileBeginNumber;
}
return index;
}
#endregion
/// <summary>
/// 发送报送文件
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ReturnInfo SentReport(int id)
{
//if (DbContext.supervise_report.Where(O => O.ReportType == SuperviseReportTypeEnum.SAC && O.id < id && O.ReportReponseStatus <= ReportSentStatus.SENDING).Any())
//{
// return Return.Fail("请按照生成顺序发送报告,并等待收到结果后再操作");
//}
try
{
var fileInfo = DbContext.supervise_report.Where(O => O.id == id).FirstOrDefault();
if (fileInfo == null)
{
return Return.Fail("记录不存在,请刷新页面后重试");
}
var absPath = OtcAppContext.MapPath(fileInfo.FilePath);
if (!System.IO.File.Exists(absPath))
{
return Return.Fail("文件不存在");
}
var targetPath = PS.Config.ErpElement.SAC_FDEPOutboxPath ?? "";
if (string.IsNullOrWhiteSpace(targetPath) && string.IsNullOrWhiteSpace(PS.Config.ErpElement.SAC_RemotePath_Outbox))
{
return Return.Fail("发件箱地址不存在");
}
if (targetPath.ToLower().Contains("{yyyy}"))
{
targetPath = targetPath.ToLower().Replace("{yyyy}", DateTime.Now.ToString("yyyy"));
}
if (targetPath.ToLower().Contains("{mm}"))
{
targetPath = targetPath.ToLower().Replace("{mm}", DateTime.Now.ToString("MM"));
}
if (targetPath.ToLower().Contains("{dd}"))
{
targetPath = targetPath.ToLower().Replace("{dd}", DateTime.Now.ToString("dd"));
}
IdentityScope identityScope = null;
FtpHelper ftpHelper = null;
try
{
if (!string.IsNullOrWhiteSpace(PS.Config.ErpElement.SAC_RemotePath_Outbox) &&
!string.IsNullOrWhiteSpace(PS.Config.ErpElement.SAC_RemoteUser) &&
!string.IsNullOrWhiteSpace(PS.Config.ErpElement.SAC_RemotePassword))
{
if (PS.Config.ErpElement.SAC_RemotePath_Outbox.ToLower().StartsWith("ftp"))
{
ftpHelper = new FtpHelper(PS.Config.ErpElement.SAC_RemotePath_Outbox, PS.Config.ErpElement.SAC_RemoteUser, PS.Config.ErpElement.SAC_RemotePassword, PS.Config.ErpElement.SAC_FtpUsePassive, 30000, PS.Config.ErpElement.SAC_EnableSsl);
}
else
{
identityScope = new IdentityScope(PS.Config.ErpElement.SAC_RemoteUser, PS.Config.ErpElement.SAC_RemotePath_Outbox, PS.Config.ErpElement.SAC_RemotePassword);
}
}
if (ftpHelper == null)
{
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
targetPath = Path.Combine(targetPath, fileInfo.FileTag + ".zip");
// 先记录源 ZIP 文件的修改时间
DateTime sourceLastWriteTime = File.GetLastWriteTimeUtc(absPath);
LogFactory.GetLogger("SentReport-SaveDb").Info($"zip文件的最后修改时间:{sourceLastWriteTime.ToString("yyyy-mm-dd HH:mm:dd:fff")}");
LogFactory.GetLogger("SentReport-SaveDb").Info("准备复制zip文件");
// 复制文件
File.Copy(absPath, targetPath);
// 强制设置目标 ZIP 文件的修改时间与源文件一致
File.SetLastWriteTimeUtc(targetPath, sourceLastWriteTime);
LogFactory.GetLogger("SentReport-SaveDb").Info($"准备生成.ok文件");
Thread.Sleep(1000);
File.Create(absPath + ".ok").Close();
LogFactory.GetLogger("SentReport-SaveDb").Info($"准备复制.ok文件");
File.Copy(absPath + ".ok", targetPath + ".ok");
LogFactory.GetLogger("SentReport-SaveDb").Info($"复制.ok文件完成");
}
else
{
if (ftpHelper.UploadFile(absPath, targetPath, out var msg))
{
File.Create(absPath + ".ok").Close();
ftpHelper.UploadFile(absPath + ".ok", targetPath, out msg);
}
else
{
LogFactory.GetLogger("SentReport-SaveDb").Error(msg);
}
}
try
{
fileInfo.ReportReponseStatus = ReportSentStatus.SENDING;
fileInfo.optDate = DateTime.Now;
fileInfo.optUserId = UserId;
DbContext.SaveChanges();
}
catch (Exception ex)
{
LogFactory.GetLogger("SentReport-SaveDb").Error(ex);
}
return Return.Success("成功,结果将稍后更新,请至历史报送列表中查看");
}
catch (Exception ex)
{
LogFactory.GetLogger("SentReport-SaveDb").Error(ex);
}
finally
{
identityScope?.Dispose();
}
}
catch (Exception ex)
{
LogFactory.GetLogger("SentReport").Error(ex);
}
return Return.Success("报送失败,请检查日志");
}
/// <summary>
/// 删除报送文件
/// </summary>
/// <param name="fileTag"></param>
/// <returns></returns>
public bool DeleteReport(string fileTag)
{
try
{
var xmlFileTag = fileTag.Replace("YSP_", "");
var query = DbContext.supervise_report.Where(O => O.FileTag.StartsWith(fileTag) || O.FileTag.StartsWith(xmlFileTag));
var tags = query.Select(O => O.FileTag);
DbContext.supervise_report.RemoveRange(query);
var sacNotes = DbContext.sac_report_notes.Where(O => tags.Contains(O.FileTag)).ToList();
sacNotes.ForEach(O => { O.OptTime = DateTime.Now; O.FileTag = "xx" + O.FileTag; });
DbContext.SaveChanges();
return true;
}
catch (Exception ex)
{
LogFactory.GetLogger("DeleteReport").Error(ex);
return false;
}
}
/// <summary>
/// 修改了结报送记录的状态
/// </summary>
/// <param name="db"></param>
/// <param name="tradeId"></param>
/// <param name="reportStartDate"></param>
public static void ChangeSettleReportStatus(YLContext db, int tradeId, DateTime reportStartDate)
{
var codeList = db.trade_contract_r.Where(O => O.TradeId == tradeId && O.Type == "交易确认书").Select(O => O.ContractCode).ToList();
foreach (var code in codeList)
{
var notes = (from note in db.sac_report_notes
where
note.IsValid
&& note.InfoTag.Contains("_" + code.Replace("_", "-") + "_了结")
&& note.ReportDate >= reportStartDate
&& !note.changeStatus
select note);
foreach (var item in notes)
{
var dict = JsonHelper.Deserialize<Dictionary<string, string>>(item.InfoCache);
if (dict.TryGetValue("ValueDate", out var dateStr) &&
DateTime.TryParse(dateStr, out var date) && date < reportStartDate)
{
continue;
}
item.changeStatus = true;
}
}
}
#region 处理报送响应文件
private static readonly HashSet<string> _responseFileNames = new();
private static readonly HashSet<string> _errFileNames = new();
private const string responseDir = "/App_Docs/Download/ReportResponse/";
private const string tempDir = "/App_Docs/Download/ReportResponse/Temp/";
private static bool runStatus = false;
public static void ListensResponse()
{
if (runStatus) { return; }
runStatus = true;
IdentityScope identityScope = null;
FtpHelper ftpHelper = null;
try
{
if (!string.IsNullOrWhiteSpace(PS.Config.ErpElement.SAC_RemotePath) &&
!string.IsNullOrWhiteSpace(PS.Config.ErpElement.SAC_RemoteUser) &&
!string.IsNullOrWhiteSpace(PS.Config.ErpElement.SAC_RemotePassword))
{
if (PS.Config.ErpElement.SAC_RemotePath.ToLower().StartsWith("ftp"))
{
ftpHelper = new FtpHelper(PS.Config.ErpElement.SAC_RemotePath, PS.Config.ErpElement.SAC_RemoteUser, PS.Config.ErpElement.SAC_RemotePassword, PS.Config.ErpElement.SAC_FtpUsePassive, 30000, PS.Config.ErpElement.SAC_EnableSsl);
}
else
{
identityScope = new IdentityScope(PS.Config.ErpElement.SAC_RemoteUser, PS.Config.ErpElement.SAC_RemotePath, PS.Config.ErpElement.SAC_RemotePassword);
}
}
var path = PS.Config.ErpElement.SAC_FDEPInboxPath ?? "";
if (string.IsNullOrWhiteSpace(path) && string.IsNullOrWhiteSpace(PS.Config.ErpElement.SAC_RemotePath))
{ return; }
if (path.ToLower().Contains("{yyyy}"))
{
path = path.ToLower().Replace("{yyyy}", DateTime.Now.ToString("yyyy"));
}
if (path.ToLower().Contains("{mm}"))
{
path = path.ToLower().Replace("{mm}", DateTime.Now.ToString("MM"));
}
if (path.ToLower().Contains("{dd}"))
{
path = path.ToLower().Replace("{dd}", DateTime.Now.ToString("dd"));
}
if (ftpHelper == null ? !Directory.Exists(path) : !ftpHelper.ExistDirectorie(path))
{
if (ftpHelper != null)
{
try
{
ftpHelper.GetDirectories(path);
}
catch
{
return;
}
}
else
{
return;
}
}
var fileNames = ftpHelper == null ? Directory.GetFiles(path) : ftpHelper.GetDirectories(path);
var fileNameArr = fileNames.Except(_responseFileNames).Except(_errFileNames).ToArray();
var resDir = OtcAppContext.MapPath(responseDir);
if (!Directory.Exists(resDir))
{
Directory.CreateDirectory(resDir);
}
var tDir = OtcAppContext.MapPath(tempDir);
if (!Directory.Exists(tDir))
{
Directory.CreateDirectory(tDir);
}
var targetName = "";
var msg = "";
foreach (var item in fileNameArr)
{
targetName = Path.Combine(resDir, Path.GetFileName(item));
var extensionName = Path.GetExtension(targetName);
if (extensionName.ToLower() != ".zip" || !Regex.IsMatch(targetName, @"OTC_\w{6}_\w{6}_YSP_20\d{6}_\d{4}") || File.Exists(targetName))
{
_responseFileNames.Add(item);
continue;
}
LogFactory.GetLogger("ListensResponse").Info($"发现新文件:{targetName}");
if (ftpHelper == null)
{
try
{
File.Copy(item, targetName);
}
catch (IOException ex)
{
LogFactory.GetLogger("ListensResponse").Error(ex);
}
}
else
{
targetName = ftpHelper.DownloadFile($"{path}{item}", resDir, out msg);
}
LogFactory.GetLogger("ListensResponse").Info($"准备解压:{targetName} to {tDir}");
var outPath = ZipHelper.unZipFile(targetName, tDir, out msg);
if (msg.StartsWith("解压失败"))
{
LogFactory.GetLogger("ListensResponse").Info($"解压失败,跳过本次解析:{msg}");
File.Delete(targetName);
continue;
}
LogFactory.GetLogger("ListensResponse").Info($"解压操作:{msg}");
if (msg.StartsWith("解压成功"))
{
saveReportResponse(outPath, Regex.Replace(targetName, @"^.+(?=\\App_Docs\\Download)", "").Replace("\\", "/"));
}
else
{
LogFactory.GetLogger("ListensResponse").Error($"文件:{item}\r\n{msg}");
_errFileNames.Add(item);
}
_responseFileNames.Add(item);
}
setTimeOutReportResponse();
}
catch (Exception ex)
{
LogFactory.GetLogger("ListensResponse").Error(ex, ex.ToString());
}
finally
{
identityScope?.Dispose();
runStatus = false;
}
}
private static void setTimeOutReportResponse()
{
using var db = DbContextFactory.GetYLDbContext();
var time = DateTime.Now.AddMinutes(-10);
var timeOutQuery = db.supervise_report.Where(O => O.ReportReponseStatus == ReportSentStatus.SENDING && O.optDate < time);
foreach (var item in timeOutQuery)
{
item.ReportReponseStatus = ReportSentStatus.ERROR;
item.ReportReponseCode = "-000001";
item.ReportReponseMessage = "协会尚未返回结果,等待中...";
}
db.SaveChanges();
}
private static void saveReportResponse(string path, string zipPath)
{
var files = Directory.EnumerateFiles(path);
using var db = DbContextFactory.GetYLDbContext();
var status = new List<bool>();
var fileTagList = new List<string>();
foreach (var item in files)
{
LogFactory.GetLogger("ListensResponse").Info($"处理文件:{item}");
var tag = Path.GetFileNameWithoutExtension(item);
var arr = tag.Split('_').ToList();
if (arr.Count < 6)
{
continue;
}
if (arr.Count == 6)
{
arr.Insert(3, "YSP");
}
var temp = arr[1];
arr[1] = arr[2];
arr[2] = temp;
arr.RemoveAt(arr.Count - 1);
tag = string.Join("_", arr);
var tag2 = string.Join("_", arr) + "_checked";
fileTagList.Add(tag);
fileTagList.Add(tag2);
LogFactory.GetLogger("ListensResponse").Info($"生成tag:{tag}");
var reportInfo = db.supervise_report.Where(O => O.FileTag == tag || O.FileTag == tag2).FirstOrDefault();
if (reportInfo == null)
{
continue;
}
LogFactory.GetLogger("ListensResponse").Info($"找到文件记录:{reportInfo.id}");
var xml = File.ReadAllText(item);
var model = XmlHelper.Deserialize<ReportRootModel>(xml);
reportInfo.ReportReponseCode = model.Header.RetCode;
reportInfo.ReportReponseMessage = model.Header.RetMsg;
reportInfo.ReportReponseStatus = reportInfo.ReportReponseCode == "000000" && (reportInfo.ReportType != SuperviseReportTypeEnum.SAC || status.All(O => O)) ? ReportSentStatus.SUCCESS : ReportSentStatus.ERROR;
reportInfo.optDate = DateTime.Now;
status.Add(reportInfo.ReportReponseCode == "000000");
if (reportInfo.ReportType == SuperviseReportTypeEnum.SAC)
{
LogFactory.GetLogger("ListensResponse").Info($"修改压缩文件记录:{reportInfo.id}");
reportInfo.ReportReponsePath = zipPath;
}
else
{
if (model.Body == null)
{
continue;
}
var kingstarViewResponseSqlList = new List<string>();
switch (reportInfo.ReportType)
{
case SuperviseReportTypeEnum.SAC_MasterAgrmt:
setSacNotes(db, model.Body.MasterAgrmt, model.Header);
break;
case SuperviseReportTypeEnum.SAC_MasterAgrmtProduct:
setSacNotes(db, model.Body.MasterAgrmtProduct, model.Header);
break;
case SuperviseReportTypeEnum.SAC_SupAgrmt:
setSacNotes(db, model.Body.SupAgrmt, model.Header);
break;
case SuperviseReportTypeEnum.SAC_PerformanceGuaranteeAgrmt:
setSacNotes(db, model.Body.PerformanceGuaranteeAgrmt, model.Header);
break;
case SuperviseReportTypeEnum.SAC_OptionConfirmation:
setSacNotes(db, model.Body.OptionConfirmation, model.Header);
break;
case SuperviseReportTypeEnum.SAC_SwapConfirmation:
setSacNotes(db, model.Body.SwapConfirmation, model.Header);
break;
case SuperviseReportTypeEnum.SAC_OptionTermination:
model.Body.OptionTermination.ForEach(O => { ((ReportBaseModel)O).BizID = O.BizID; O.DurationEventNO = O.DurationEventNO; });
setSacNotes(db, model.Body.OptionTermination, model.Header);
break;
case SuperviseReportTypeEnum.SAC_SwapDurationManagement:
model.Body.SwapDurationManagement.ForEach(O => { O.BizID = O.BizID; ((ReportBaseModel)O).DurationEventNO = O.DurationEventNO; });
setSacNotes(db, model.Body.SwapDurationManagement, model.Header);
break;
case SuperviseReportTypeEnum.SAC_PeriodicReportSAC:
((ReportBaseModel)model.Body.PeriodicReportSAC).BizID = model.Body.PeriodicReportSAC.BizID;
model.Body.PeriodicReportSAC.DurationEventNO = model.Body.PeriodicReportSAC.DurationEventNO;
setSacNotes(db, model.Body.PeriodicReportSAC, model.Header);
break;
case SuperviseReportTypeEnum.SAC_PeriodicReportNAFMII:
((ReportBaseModel)model.Body.PeriodicReportNAFMII).BizID = model.Body.PeriodicReportNAFMII.BizID;
model.Body.PeriodicReportNAFMII.DurationEventNO = model.Body.PeriodicReportNAFMII.DurationEventNO;
setSacNotes(db, model.Body.PeriodicReportNAFMII, model.Header);
break;
case SuperviseReportTypeEnum.SAC_PeriodicReportISDA:
((ReportBaseModel)model.Body.PeriodicReportISDA).BizID = model.Body.PeriodicReportISDA.BizID;
model.Body.PeriodicReportISDA.DurationEventNO = model.Body.PeriodicReportISDA.DurationEventNO;
setSacNotes(db, model.Body.PeriodicReportISDA, model.Header);
break;
case SuperviseReportTypeEnum.SAC_EventReport:
((ReportBaseModel)model.Body.EventReport).BizID = model.Body.EventReport.BizID;
model.Body.EventReport.DurationEventNO = model.Body.EventReport.DurationEventNO;
setSacNotes(db, model.Body.EventReport, model.Header);
break;
case SuperviseReportTypeEnum.SAC_OtherReport:
((ReportBaseModel)model.Body.OtherReport).BizID = model.Body.OtherReport.BizID;
model.Body.OtherReport.DurationEventNO = model.Body.OtherReport.DurationEventNO;
setSacNotes(db, model.Body.OtherReport, model.Header);
break;
case SuperviseReportTypeEnum.SAC_PeriodicReportQuarter:
((ReportBaseModel)model.Body.PeriodicReportQuarter).BizID = model.Body.PeriodicReportQuarter.BizID;
model.Body.PeriodicReportQuarter.DurationEventNO = model.Body.PeriodicReportQuarter.DurationEventNO;
setSacNotes(db, model.Body.PeriodicReportQuarter, model.Header);
break;
case SuperviseReportTypeEnum.SAC_ContractNumberProcess:
if (model.Body.ContractNumberProcess == null && model.Body.MasterAgrmt != null)
{
model.Body.ContractNumberProcess = new ContractNumberProcessModel();
model.Body.ContractNumberProcess.BizID = model.Body.MasterAgrmt.First().BizID;
model.Body.ContractNumberProcess.RetMsg = model.Body.MasterAgrmt.First().RetMsg;
model.Body.ContractNumberProcess.RetCode = model.Body.MasterAgrmt.First().RetCode;
model.Body.ContractNumberProcess.ExceID = model.Body.MasterAgrmt.First().ExceID;
}
model.Body.ContractNumberProcess.BizID = model.Body.ContractNumberProcess.BizID;
setSacNotes(db, model.Body.ContractNumberProcess, model.Header);
break;
case SuperviseReportTypeEnum.SAC_SwapEquityPayment:
model.Body.SwapEquityPayment.ForEach(O => { O.BizID = O.BizID; ((ReportBaseModel)O).DurationEventNO = O.DurationEventNO; });
setSacNotes(db, model.Body.SwapEquityPayment, model.Header);
break;
case SuperviseReportTypeEnum.SAC_ConfirmationAtt:
case SuperviseReportTypeEnum.SAC_OptionConfirmationAtt:
model.Body.ConfirmationAtt.ForEach(O => { O.BizID = O.BizID; O.DurationEventNO = O.DurationEventNO; });
setSacNotes(db, model.Body.ConfirmationAtt, model.Header);
break;
case SuperviseReportTypeEnum.SAC_ValuationInformation:
model.Body.ValuationInformation.ForEach(O =>
{
((ReportBaseModel)O).BizID = O.BizID;
((ReportBaseModel)O).DurationEventNO = O.DurationEventNO;
});
setSacNotes(db, model.Body.ValuationInformation, model.Header);
break;
default:
break;
}
if (kingstarViewResponseSqlList.Count > 0)
{ KingstarViewResponse(kingstarViewResponseSqlList); }
}
db.SaveChanges();
}
var subSystemInboxPath = PS.Config.ClientElement.SAC_SubSystemInboxPath;
LogFactory.GetLogger("ListensResponse").Info($"开始subSystemInboxPath:{subSystemInboxPath}");
LogFactory.GetLogger("ListensResponse").Info($"Path:{path}");
if (!string.IsNullOrEmpty(subSystemInboxPath))
{
ResponseSubsystem(db, path, subSystemInboxPath, fileTagList);
}
}
private const string responseSubsystemDir = "/App_Docs/Download/ReportResponse/Subsystem/";
/// <summary>
/// 解析一个zip文件
/// </summary>
/// <param name="db"></param>
/// <param name="path">zip文件解压后的文件夹路径</param>
/// <param name="zipFileTag"></param>
/// <param name="subSystemInboxPath"></param>
private static void ResponseSubsystem(YLContext db, string path, string subSystemInboxPath, List<string> fileTagList)
{
LogFactory.GetLogger("ListensResponse").Info($"path:{path}");
LogFactory.GetLogger("ListensResponse").Info($"subSystemInboxPath:{subSystemInboxPath}");
LogFactory.GetLogger("ListensResponse").Info($"fileTagListCount:{fileTagList.Count()}");
LogFactory.GetLogger("ListensResponse").Info($"fileTagList:{string.Join(",", fileTagList)}");
var responseRootDir = OtcAppContext.MapPath(responseSubsystemDir);
if (!Directory.Exists(responseRootDir))
{
Directory.CreateDirectory(responseRootDir);
}
LogFactory.GetLogger("ListensResponse").Info($"responseRootDir:{responseRootDir}");
var noteList = db.sac_report_notes.Where(O => fileTagList.Contains(O.FileTag) && O.InfoCache.Contains("Subsystem")).Select(O => O.InfoCache).ToArray().Select(O => Regex.Match(O, @"(?<=SubFileTag)[^,]+(?=,)").Value).ToHashSet();
LogFactory.GetLogger("ListensResponse").Info($"noteListCount:{noteList.Count()}");
LogFactory.GetLogger("ListensResponse").Info($"noteList:{string.Join(",", noteList)}");
var fileNames = Directory.GetFiles(path);//zip对应文件夹下的xml文件列表
LogFactory.GetLogger("ListensResponse").Info($"fileNames:{fileNames.Count()}");
foreach (var item in noteList)
{
LogFactory.GetLogger("ListensResponse").Info($"item:{item}");
LogFactory.GetLogger("ListensResponse").Info($"itemLength:{item.Length}");
var filetag = item.Substring(3, item.Length - 4);
var resDir = Path.Combine(responseRootDir, filetag);
if (Directory.Exists(resDir))//存在先删除目录和下边文件,避免文件夹重名和文件重名,而出现错误
{
ClearResDirContent(resDir);
}
Directory.CreateDirectory(resDir);//重新创建
foreach (var fileName in fileNames)
{
var targetName = Path.Combine(resDir, Path.GetFileName(fileName));
LogFactory.GetLogger("ListensResponse").Info($"targetName:{targetName}");
LogFactory.GetLogger("ListensResponse").Info($"fileName:{fileName}");
File.Copy(fileName, targetName);
}
var tempFileNames = Directory.GetFiles(resDir);
var totalFilePath = "";
var groupFileDic = new Dictionary<string, List<string>>();
foreach (var fileItem in tempFileNames)
{
var tag = Path.GetFileNameWithoutExtension(fileItem);
if (tag.Length < 41)
{
totalFilePath = fileItem;
continue;
}
LogFactory.GetLogger("ListensResponse").Info("xxx");
HandleXmlFile(db, fileItem, filetag, resDir);
LogFactory.GetLogger("ListensResponse").Info("yyyy");
}
tempFileNames = Directory.GetFiles(resDir);
LogFactory.GetLogger("ListensResponse").Info(string.Join(",", tempFileNames));
var smallFileCount = 0;
LogFactory.GetLogger("ListensResponse").Info("zzz");
LogFactory.GetLogger("ListensResponse").Info("temFileNames:" + string.Join(",", tempFileNames));
LogFactory.GetLogger("ListensResponse").Info("temFileNamesCount:" + tempFileNames.Length);
foreach (var fileItem in tempFileNames)//解压文件夹下的xml文件
{
var tag = Path.GetFileNameWithoutExtension(fileItem);
LogFactory.GetLogger("ListensResponse").Info("fileItem:" + fileItem);
LogFactory.GetLogger("ListensResponse").Info("tag.Length" + tag.Length);
if (tag.Length >= 41)
{
smallFileCount++;
}
}
if (smallFileCount == 0)
{
LogFactory.GetLogger("ListensResponse").Info($"smallFileCount==0");
File.Delete(totalFilePath);
Directory.Delete(resDir);
}
else
{
LogFactory.GetLogger("ListensResponse").Info($"smallFileCount!=0");
var newFileName = RenameTotalXmlFileName(resDir, totalFilePath, filetag);
UpdateTotalXmlFileNumber(newFileName, filetag);
CreateSubsystemResponse(resDir, subSystemInboxPath, filetag);
}
}
}
private static string RenameTotalXmlFileName(string resDir, string totalFilePath, string filetag)
{
LogFactory.GetLogger("ListensResponse").Info($"resDir:{resDir}");
LogFactory.GetLogger("ListensResponse").Info($"totalFilePath:{totalFilePath}");
LogFactory.GetLogger("ListensResponse").Info($"filetag:{filetag}");
var totalTag = Path.GetFileNameWithoutExtension(totalFilePath);
var newFileName = Path.Combine(resDir, CovertResponseTag(filetag) + totalTag.Substring(31) + ".xml");
var fi = new FileInfo(totalFilePath);
fi.MoveTo(newFileName);
//File.Move(totalFilePath, newFileName);
//File.Delete(totalFilePath);
return newFileName;
}
private static void RenameXmlFileName(string resDir, string xmlFile, string filetag)
{
var oldFileTag = Path.GetFileNameWithoutExtension(xmlFile);//OTC_123654_000899_YSP_20220714_0007
var newFileName = Path.Combine(resDir, CovertResponseTag(filetag) + oldFileTag.Substring(31) + ".xml");
var fi = new FileInfo(xmlFile);
fi.MoveTo(newFileName);
if (xmlFile != newFileName)
{
File.Delete(xmlFile);
}
LogFactory.GetLogger("ListensResponse").Info($"move:{xmlFile} to {newFileName}");
//RenameFile(xmlFile, newFileName);
}
private static string CovertResponseTag(string filetag)
{
return CovertResponseTag(filetag, true);
}
private static string CovertResponseTag(string filetag, bool removeYsp)
{
var arr = filetag.Split('_').ToList();
var temp = arr[1];
arr[1] = arr[2];
arr[2] = temp;
var tag = string.Join("_", arr);
if (removeYsp)
{
tag = tag.Replace("_YSP", "");
}
return tag;
}
private static void ClearResDirContent(string resDir)
{
var fileList = Directory.GetFiles(resDir);
foreach (var file in fileList)
{
File.Delete(file);
}
Directory.Delete(resDir);
}
private static void UpdateTotalXmlFileNumber(string xmlFile, string fileTag)
{
var xmldoc = new XmlDocument();
xmldoc.Load(xmlFile);
UpdateXmlFileNumber(xmldoc, fileTag);
xmldoc.Save(xmlFile);
}
private static void UpdateXmlFileNumber(XmlDocument xmldoc, string fileTag)
{
var layerHeadName = "/Root/Header";
var headerNode = xmldoc.SelectSingleNode(layerHeadName);
var fileNumber = fileTag.Split("_".ToCharArray())[5];
headerNode.SelectSingleNode("FileNumber").InnerText = fileNumber;
}
/// <summary>
/// 压缩文件生成响应zip文件
/// </summary>
/// <param name="resDir"></param>
/// <param name="subSystemInboxPath"></param>
/// <param name="fileTag"></param>
private static void CreateSubsystemResponse(string resDir, string subSystemInboxPath, string fileTag)
{
LogFactory.GetLogger("CreateSubsystemResponse").Info($"reportNote:null,excefileTag=" + fileTag);
var marketZipFile = Path.Combine(subSystemInboxPath, CovertResponseTag(fileTag, false) + ".zip");
LogFactory.GetLogger("CreateSubsystemResponse").Info($"reportNote:null,marketZipFile=" + marketZipFile);
ZipHelper.zipFile(resDir, marketZipFile);
LogFactory.GetLogger("CreateSubsystemResponse").Info($"reportNote:null,zipFile成功");
ClearResDirContent(resDir);//删除临时文件夹,要不A和D操作会用同名文件夹,拷贝会出现文件已经存在问题
}
private static void HandleXmlFile(YLContext db, string xmlFile, string fileTag, string resDir)
{
var xmldoc = new XmlDocument();
xmldoc.Load(xmlFile);
UpdateXmlFileNumber(xmldoc, fileTag);
LogFactory.GetLogger("ListensResponse").Info($"xml= {xmldoc.ToString()}");
var layerName = "/Root/Body";
var bodyNode = xmldoc.SelectSingleNode(layerName);
var bodyChildlist = bodyNode.ChildNodes;
var totalCount = bodyChildlist.Count;
var tag = "";
for (var i = 0; i < totalCount; i++)
{
var bodyChildNode = bodyChildlist[i];
var excelId = bodyChildNode.FirstChild.InnerText;
var reportNote = db.sac_report_notes.FirstOrDefault(x => x.ExceId == excelId);
if (reportNote == null)
{
LogFactory.GetLogger("ListensResponse").Info($"reportNote:null,excelId=" + excelId);
bodyNode.RemoveChild(bodyChildNode);
i--;
totalCount--;
continue;
}
var infoCacheDict = JsonHelper.Deserialize<Dictionary<string, string>>(reportNote.InfoCache);
if (!infoCacheDict.TryGetValue("SubFileTag", out tag) || string.IsNullOrEmpty(tag))
{
LogFactory.GetLogger("ListensResponse").Info($"SubFileTag:null,SubFileTag=" + tag);
bodyNode.RemoveChild(bodyChildNode);
i--;
totalCount--;
continue;
}
if (tag != fileTag)
{
bodyNode.RemoveChild(bodyChildNode);
i--;
totalCount--;
continue;
}
if (!infoCacheDict.TryGetValue("Source", out var source) || string.IsNullOrEmpty(source) || source != "Subsystem")
{
bodyNode.RemoveChild(bodyChildNode);
i--;
totalCount--;
continue;
}
if (!infoCacheDict.TryGetValue("ExceID", out var oldExcelId) || string.IsNullOrEmpty(oldExcelId))
{
bodyNode.RemoveChild(bodyChildNode);
i--;
totalCount--;
continue;
}
bodyChildNode.FirstChild.InnerText = oldExcelId;
}
xmldoc.Save(xmlFile);
if (bodyNode.ChildNodes.Count == 0)
{
File.Delete(xmlFile);
return;
}
//修改文件名
LogFactory.GetLogger("ListensResponse").Info($"文件保留,xmlFile=" + xmlFile);
RenameXmlFileName(resDir, xmlFile, fileTag);
}
private static void setSacNotes(YLContext db, ReportBaseModel model, HeaderModel header)
{
if (model == null)
{
return;
}
setSacNotes(db, new[] { model }, header);
}
public static void CreateKingstarViewResponseSql(YLContext db, List<string> kingstarViewResponseList, IEnumerable<ReportBaseModel> model)
{
var schema = PS.Config.ErpElement.KingstarViewTableSchema.IsNullOrWhiteSpace() ? "" : $"\"{PS.Config.ErpElement.KingstarViewTableSchema}\".";
var exceIds = model.Select(O => O.ExceID);
LogFactory.GetLogger("kingstarViewResponse").Info($"exceIds:{string.Join(",", exceIds)}");
var dict = db.sac_report_notes.Where(O => exceIds.Contains(O.ExceId)).ToDictionary(K => K.ExceId, V => V);
LogFactory.GetLogger("kingstarViewResponse").Info($"dict count:{dict.Count}");
foreach (var item in model)
{
LogFactory.GetLogger("kingstarViewResponse").Info($"开始excelId:{item.ExceID}");
if (!dict.ContainsKey(item.ExceID))
{
continue;
}
var note = dict[item.ExceID];
var infoCacheDict = JsonHelper.Deserialize<Dictionary<string, string>>(note.InfoCache);
if (infoCacheDict["Source"] != "KingstarView")
{
continue;
}
var curDate = DateTime.Now.ToString("yyyy-MM-dd 00:00:00");
var batchDate = DateTime.Now.ToString("yyyyMMdd");
var curTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
var eventNo = item.DurationEventNO;
var bizzType = "";
switch (note.ReportType)
{
case SuperviseReportTypeEnum.SAC_SwapConfirmation:
bizzType = "SWAPID";
break;
case SuperviseReportTypeEnum.SAC_SwapDurationManagement:
bizzType = "SWAPDURATION";
break;
case SuperviseReportTypeEnum.SAC_SwapEquityPayment:
bizzType = "SWAPRIGHTPAY";
break;
case SuperviseReportTypeEnum.SAC_ConfirmationAtt:
bizzType = "CONFIRMATIONATTR";
break;
}
infoCacheDict.TryGetValue("Tag", out var bizzID);
var rptID = item.BizID;
var sqlMapping = $"INSERT INTO {schema}TRANS_RPT_MAPPING(BIZZ_ID,RPT_ID,BIZZ_TYPE,CREATED_DATETIME,PUSH_TIME,EVENT_DATE,EVENT_NO)VALUES('{bizzID}','{rptID}','{bizzType}',to_date('{curDate}', 'yyyy-mm-dd hh24:mi:ss'),to_date('{curTime}', 'yyyy-mm-dd hh24:mi:ss'),to_date('{curDate}', 'yyyy-mm-dd hh24:mi:ss'),'{eventNo}')";
LogFactory.GetLogger("kingstarViewResponse").Info($"sqlMapping:{sqlMapping}");
kingstarViewResponseList.Add(sqlMapping);
var guidKey = Guid.NewGuid().ToString("N");
const string taskName = "KS_SWAP_NEW_CONFIRMATION_ETL";
const string taskDecc = "监管新规报备视图跑批任务";
var resultFlag = note.RetCode == "000000" ? "SUCCESS" : "FAILED";
var sqlLog = $"INSERT INTO {schema}ADM_EODBATCH_LOG(LOG_ID,BATCH_DATE,TASK_NAME,TASK_DESC,LOG_DATETIME,RESULT_FLAG)VALUES('{guidKey}','{batchDate}','{taskName}','{taskDecc}',to_date('{curTime}', 'yyyy-mm-dd hh24:mi:ss'),'{resultFlag}')";
kingstarViewResponseList.Add(sqlLog);
LogFactory.GetLogger("kingstarViewResponse").Info($"sqlLog:{sqlLog}");
LogFactory.GetLogger("kingstarViewResponse").Info($"开始excelId:{item.ExceID}");
}
}
private static void KingstarViewResponse(List<string> sqlList)
{
var connection = PS.Config.ErpElement.KingstarViewConnectionString;
LogFactory.GetLogger("kingstarViewResponse").Info($"链接字符串:{connection}");
using (var db = new DbHelper(connection))
{
db.ExecuteNoSqlsQuery(sqlList);
}
LogFactory.GetLogger("kingstarViewResponse").Info($"Success!");
}
private static void setSacNotes(YLContext db, IEnumerable<ReportBaseModel> model, HeaderModel header)
{
var exceIds = model.Select(O => O.ExceID);
var dict = db.sac_report_notes.Where(O => exceIds.Contains(O.ExceId)).ToDictionary(K => K.ExceId, V => V);
var sendFileId = new List<int>();
foreach (var item in model)
{
if (!dict.ContainsKey(item.ExceID))
{
continue;
}
var note = dict[item.ExceID];
LogFactory.GetLogger("ListensResponse").Info($"找到文件明细:{note.id}");
note.RetCode = item.RetCode;
note.RetMsg = item.RetMsg;
note.ReportResponse = note.RetCode == "000000";
note.BizId = item.BizID ?? "";
note.OptTime = DateTime.Now;
LogFactory.GetLogger("ListensResponse").Info($"更新文件明细:{note.ToJson()}");
if (note.ReportResponse)
{
var infoCacheDict = JsonHelper.Deserialize<Dictionary<string, string>>(note.InfoCache);
if (infoCacheDict != null)
{
infoCacheDict["DurationEventNO"] = item.DurationEventNO ?? "";
note.InfoCache = infoCacheDict.ToJson();
}
if (note.ReportType == SuperviseReportTypeEnum.SAC_MasterAgrmt ||
note.ReportType == SuperviseReportTypeEnum.SAC_MasterAgrmtProduct ||
note.ReportType == SuperviseReportTypeEnum.SAC_SupAgrmt ||
note.ReportType == SuperviseReportTypeEnum.SAC_PerformanceGuaranteeAgrmt)
{
LogFactory.GetLogger("ListensResponse").Info($"客户协议相关明细:{note.DataId}");
if (int.TryParse(note.DataId, out var dataId))
{
sendFileId.Add(dataId);
}
}//展期报告成功后要修改交易报告记录中的到期日
else if (note.InfoTag.Contains("_展期_") &&
(note.ReportType == SuperviseReportTypeEnum.SAC_OptionTermination ||
note.ReportType == SuperviseReportTypeEnum.SAC_SwapDurationManagement))
{
EditTradeDueDate(db, note);
}
else if (note.ReportType == SuperviseReportTypeEnum.SAC_ContractNumberProcess)
{
var obj = JsonHelper.Deserialize<ContractNumberProcessModel>(note.BizId);
EditContractNumber(db, obj, out var protocolNumberDict);
EditProtocolNumberSentStatus(protocolNumberDict);
}
//如果是废止报告,要把该报告对应的所有新增和修改的报告状态修改为无效
if (note.InfoTag.EndsWith("_D"))
{
ValidSacNote(db, note);
}
}
}
if (sendFileId.Count > 0)
{
LogFactory.GetLogger("ListensResponse").Info($"修改客户文件报送状态:{sendFileId.ToJson()}");
new ClientFileService(OptUserInfo.SystemUser).ChangeFileSentStates(sendFileId);
}
}
/// <summary>
/// 修改协议文件报送状态
/// </summary>
/// <param name="protocolNumberDict"></param>
private static void EditProtocolNumberSentStatus(Dictionary<SuperviseReportTypeEnum, List<string>> protocolNumberDict)
{
if (protocolNumberDict.Count < 0)
{
var clientDb = DbContextFactory.GetClientDbContext(OptUserInfo.SystemUser);
if (protocolNumberDict.ContainsKey(SuperviseReportTypeEnum.SAC_MasterAgrmt))
{
var list = protocolNumberDict[SuperviseReportTypeEnum.SAC_MasterAgrmt];
var changeList = clientDb.client_file.Where(O => O.HasSent && O.FileTypeName == ConsGlobal.ClientFileType.MainProtocol && list.Contains(O.ProtocolNumber));
foreach (var changeObj in changeList)
{
changeObj.HasSent = false;
}
}
if (protocolNumberDict.ContainsKey(SuperviseReportTypeEnum.SAC_SupAgrmt))
{
var list = protocolNumberDict[SuperviseReportTypeEnum.SAC_SupAgrmt];
var changeList = clientDb.client_file.Where(O => O.HasSent && O.FileTypeName == ConsGlobal.ClientFileType.EnhanceProtocol && list.Contains(O.ProtocolNumber));
foreach (var changeObj in changeList)
{
changeObj.HasSent = false;
}
}
clientDb.SaveChanges();
}
}
/// <summary>
/// 修改双方约定编号
/// </summary>
/// <param name="db"></param>
/// <param name="note"></param>
/// <exception cref="NotImplementedException"></exception>
public static void EditContractNumber(YLContext db, ContractNumberProcessModel obj, out Dictionary<SuperviseReportTypeEnum, List<string>> protocolNumberDict)
{
var dict = new Dictionary<string, string>();
obj.OptionConfirmationTuple.ForEach(O =>
{
if (O.ConfirmationID.IsNullOrWhiteSpace() || O.ConfirmationNo.IsNullOrWhiteSpace())
{
return;
}
dict[O.ConfirmationID] = O.ConfirmationNo;
});
obj.SwapConfirmationTuple.ForEach(O =>
{
if (O.ConfirmationID.IsNullOrWhiteSpace() || O.ConfirmationNo.IsNullOrWhiteSpace())
{
return;
}
dict[O.ConfirmationID] = O.ConfirmationNo;
});
obj.MasterAgrmtTuple.ForEach(O =>
{
if (O.MasterAgrmtID.IsNullOrWhiteSpace() || O.MasterAgrmtNo.IsNullOrWhiteSpace())
{
return;
}
dict[O.MasterAgrmtID] = O.MasterAgrmtNo;
});
obj.SupAgrmtTuple.ForEach(O =>
{
if (O.SupAgrmtID.IsNullOrWhiteSpace() || O.SupAgrmtNo.IsNullOrWhiteSpace())
{
return;
}
dict[O.SupAgrmtID] = O.SupAgrmtNo;
});
EditContractNumber(db, dict, out protocolNumberDict);
}
private static void EditContractNumber(YLContext db, Dictionary<string, string> dict, out Dictionary<SuperviseReportTypeEnum, List<string>> protocolNumberDict)
{
protocolNumberDict = new Dictionary<SuperviseReportTypeEnum, List<string>>();
var infoTagList = new HashSet<string>();
var keys = dict.Keys;
var objs = db.sac_report_notes.Where(O => O.IsValid && keys.Contains(O.BizId));
var serviceDict = new Dictionary<SuperviseReportTypeEnum, ReportBaseService>();
foreach (var item in objs)
{
var reportType = item.ReportType;
if (!serviceDict.ContainsKey(reportType))
{
serviceDict[reportType] = ReportBaseService.ReportFactory(OptUserInfo.SystemUser, reportType);
}
var newCode = dict[item.BizId];
item.InfoTag = serviceDict[reportType].ChangeCodeOfInfoTag(item.InfoTag, newCode, out var originalCode);
if (reportType == SuperviseReportTypeEnum.SAC_MasterAgrmt
|| reportType == SuperviseReportTypeEnum.SAC_SupAgrmt)
{
if (!protocolNumberDict.ContainsKey(reportType))
{
protocolNumberDict[reportType] = new List<string>();
}
protocolNumberDict[reportType].Add(originalCode);
}
infoTagList.Add(item.InfoTag);
}
var tempList = DbContextFactory.GetYLDbContext().sac_report_notes.Where(O => infoTagList.Contains(O.InfoTag));
if (tempList.Any())
{
throw new ServiceException("修改后的InfoTag存在重复");
}
}
public static void EditContractNumber(Stream inputStream)
{
var serviceDict = new Dictionary<SuperviseReportTypeEnum, ReportBaseService>();
var colConfig = new DataColumnModel[3];
colConfig[0] = new DataColumnModel("数据类型", nameof(InnerContractNumberModel.NumberType));
colConfig[1] = new DataColumnModel("原双方约定", nameof(InnerContractNumberModel.OriginalCode));
colConfig[2] = new DataColumnModel("新双方约定", nameof(InnerContractNumberModel.NewCode));
var dict = new ExcelHelper().ExcelToListT<InnerContractNumberModel>(colConfig, inputStream);
if (!dict.ContainsKey("Sheet1"))
{
throw new ServiceException("模板错误");
}
var db = DbContextFactory.GetYLDbContext();
var temp_List = dict["Sheet1"];
checkContractNumber(temp_List);
var list = new List<InnerContractNumberModel>();
foreach (var item in temp_List)
{
if (item.NumberType.IsNullOrWhiteSpace()
|| item.OriginalCode.IsNullOrWhiteSpace()
|| item.NewCode.IsNullOrWhiteSpace())
{
break;
}
list.Add(item);
var reportType = SuperviseReportTypeEnum.SAC;
switch (item.NumberType)
{
case "主协议编号":
reportType = SuperviseReportTypeEnum.SAC_MasterAgrmt;
break;
case "补充协议编号":
reportType = SuperviseReportTypeEnum.SAC_SupAgrmt;
break;
case "代签产品名称":
reportType = SuperviseReportTypeEnum.SAC_MasterAgrmtProduct;
break;
case "期权交易确认书编号":
reportType = SuperviseReportTypeEnum.SAC_OptionConfirmation;
break;
case "互换交易确认书编号":
reportType = SuperviseReportTypeEnum.SAC_SwapConfirmation;
break;
default:
continue;
}
var originCode = $"_{item.OriginalCode.Replace("_", "-")}_";
var bizDict =
db.sac_report_notes
.Where(O =>
O.ReportType == reportType
&& O.IsValid
&& O.ReportResponse
&& O.InfoTag.Contains(originCode))
.ToArray().GroupBy(O => O.BizId)
.ToDictionary(K => K.Key, V => V.FirstOrDefault().InfoTag);
foreach (var bizId in bizDict)
{
if ((reportType == SuperviseReportTypeEnum.SAC_SupAgrmt
|| reportType == SuperviseReportTypeEnum.SAC_MasterAgrmtProduct)
&& !Regex.IsMatch(bizId.Value, originCode + @"\w$"))
{
continue;
}
item.BizId = bizId.Key;//同一个编号只会有一条记录,不应该存在多条;
break;
}
}
var errArr = list.Where(O => O.BizId.IsNullOrWhiteSpace()).Select(O => O.OriginalCode);
if (errArr.Any())
{
throw new ServiceException($"下列原编号未找到对应记录:\r\n{string.Join(",", errArr)}\r\n请确认后重新操作");
}
var bizIdList = list.ToDictionary(K => K.BizId, V => V.NewCode);
EditContractNumber(db, bizIdList, out var protocolNumberDict);
EditProtocolNumberSentStatus(protocolNumberDict);
db.SaveChanges();
}
/// <summary>
/// 检查传入的双方约定编号是否重复
/// </summary>
/// <param name="temp_List"></param>
/// <exception cref="ServiceException"></exception>
private static void checkContractNumber(List<InnerContractNumberModel> temp_List)
{
// 检查重复 数据类型 [0]原编号;[1]新编号;
var dict = new Dictionary<string, HashSet<string>[]>();
var originCode = new List<string>();
var targetCode = new List<string>();
foreach (var item in temp_List)
{
if (item.NumberType.IsNullOrWhiteSpace()
|| item.OriginalCode.IsNullOrWhiteSpace()
|| item.NewCode.IsNullOrWhiteSpace())
{
break;
}
var numberType = item.NumberType;
if (item.NumberType == "期权交易确认书编号")
{
numberType = "确认书编号";
}
else if (item.NumberType == "互换交易确认书编号")
{
numberType = "确认书编号";
}
if (!dict.ContainsKey(numberType))
{
dict[numberType] = new HashSet<string>[2];
dict[numberType][0] = new HashSet<string>();
dict[numberType][1] = new HashSet<string>();
}
if (!dict[numberType][0].Add(item.OriginalCode))
{
originCode.Add(item.OriginalCode);
}
if (!dict[numberType][1].Add(item.NewCode))
{
targetCode.Add(item.NewCode);
}
}
var sb = new StringBuilder();
if (originCode.Any())
{
sb.AppendLine($"原编号存在重复:\r\n{string.Join(",", originCode)}");
}
if (targetCode.Any())
{
sb.AppendLine($"新编号存在重复:\r\n{string.Join(",", targetCode)}");
}
if (sb.Length > 0)
{
throw new ServiceException(sb.ToString());
}
}
/// <summary>
/// 修改交易报告记录中的到期日
/// </summary>
/// <param name="db"></param>
/// <param name="note"></param>
private static void EditTradeDueDate(YLContext db, SACReportNotes note)
{
var code = note.InfoTag.Split('_')[1];
var dateStr = "";
if (note.InfoTag.EndsWith("_D"))
{//废止报告使用原到期日覆盖
dateStr = Regex.Match(note.InfoCache, "(?<=OldMaturityDate\":\")[^\"]+(?=\")").Value;
}
else
{//非废止报告使用新到期日覆盖
dateStr = Regex.Match(note.InfoCache, "(?<=NewMaturityDate\":\")[^\"]+(?=\")").Value;
}
if (!string.IsNullOrEmpty(dateStr))
{
var notes = db.sac_report_notes
.Where(O => O.ReportType == (note.ReportType - 2) && O.InfoTag.Contains(code) && O.IsValid == true && O.ReportResponse)
.OrderByDescending(O => O.OptTime).ToList();
foreach (var n in notes)
{//覆盖交易到期日
n.InfoCache = Regex.Replace(n.InfoCache, "(?<=DueDate\":\")[^\"]+(?=\")", dateStr);
}
}
}
/// <summary>
/// 把该报告对应的所有新增和修改的报告状态修改为无效
/// </summary>
/// <param name="db"></param>
/// <param name="note"></param>
private static void ValidSacNote(YLContext db, SACReportNotes note)
{
var infoCacheDict = JsonHelper.Deserialize<Dictionary<string, string>>(note.InfoCache);
if (!infoCacheDict.TryGetValue("Tag", out var tag))
{
tag = " ";
}
tag = $"\"Tag\":\"{tag}\"";
var infoTag = note.InfoTag.Remove(note.InfoTag.Length - 1);
//因为履约保证书的InfoCache字段值是附件名,允许被修改,所以不作为筛选条件;
var arr = db.sac_report_notes
.Where(O =>
O.IsValid &&
(O.ReportType == SuperviseReportTypeEnum.SAC_PerformanceGuaranteeAgrmt
|| O.ReportType == SuperviseReportTypeEnum.SAC_OptionConfirmation
|| O.ReportType == SuperviseReportTypeEnum.SAC_SwapConfirmation
|| O.ReportType == SuperviseReportTypeEnum.SAC_OptionTermination
|| O.ReportType == SuperviseReportTypeEnum.SAC_SwapDurationManagement
|| O.ReportType == SuperviseReportTypeEnum.SAC_SwapEquityPayment
|| O.InfoCache.Contains(tag)) &&
O.InfoTag.Contains(infoTag)).ToList();
if (note.ReportType == SuperviseReportTypeEnum.SAC_SwapDurationManagement)
{
if (!infoCacheDict.TryGetValue("DurationEventNO", out string durationeventno))
{
durationeventno = " ";
}
durationeventno = $"\"DurationEventNO\":\"{durationeventno}\"";
infoTag = $"A1016_{note.InfoTag.Split('_')[1]}_";
arr.AddRange(db.sac_report_notes
.Where(O =>
O.IsValid &&
O.ReportType == SuperviseReportTypeEnum.SAC_SwapEquityPayment &&
O.InfoTag.StartsWith(infoTag) &&
O.InfoCache.Contains(durationeventno)).ToList());
}
foreach (var item1 in arr)
{
if (!note.InfoTag.Contains("_展期_") &&
(item1.ReportType == SuperviseReportTypeEnum.SAC_OptionTermination ||
item1.ReportType == SuperviseReportTypeEnum.SAC_SwapDurationManagement))
{
var dict2 = JsonHelper.Deserialize<Dictionary<string, string>>(item1.InfoCache);
if (!infoCacheDict.ContainsKey("ValueDate") || !dict2.ContainsKey("ValueDate") ||
infoCacheDict["ValueDate"] != dict2["ValueDate"])
{
continue;
}
}
item1.IsValid = false;
}
}
public class InnerContractNumberModel
{
/// <summary>
/// 编号类型
/// </summary>
public string NumberType { get; set; }
/// <summary>
/// 原编号
/// </summary>
public string OriginalCode { get; set; }
/// <summary>
/// 新编号
/// </summary>
public string NewCode { get; set; }
/// <summary>
/// BizId
/// <para>协会唯一编号</para>
/// </summary>
public string BizId { get; set; }
}
#endregion
#region 查询报送信息
/// <summary>
/// 查询已报送的文件
/// </summary>
/// <param name="fileTypes"></param>
/// <param name="createDateStart"></param>
/// <param name="createDateEnd"></param>
/// <returns></returns>
public IQueryable<SuperviseReport> QueryReportHistoryFromDb()
{
var query = DbContext.supervise_report.AsQueryable();
return query;
}
/// <summary>
/// 查询报送文件
/// </summary>
/// <param name="reportDate"></param>
/// <returns></returns>
public ReturnInfo<ReportInfo> QueryReportInfo(DateTime reportDate)
{
var lastMonthEnd = reportDate.AddDays(-reportDate.Day);
var superviseReport =
DbContext.supervise_report
.Where(O => O.ReportDate <= reportDate)
.OrderByDescending(O => O.ReportDate)
.ThenByDescending(O => O.optDate)
.FirstOrDefault();
var info = new ReportInfo
{
ReportDate = reportDate
};
if (superviseReport != null)
{
info.SenderCode = superviseReport.SenderCode;
info.ReceiverCode = superviseReport.ReceiverCode;
if (reportDate.Year == superviseReport.ReportDate.Year && reportDate.Month == superviseReport.ReportDate.Month)
{
info.LastMonthCash = superviseReport.LastMonthCash;
info.LatestMonthCash = superviseReport.LatestMonthCash;
}
else if (reportDate.Year == superviseReport.ReportDate.Year && reportDate.Month == (superviseReport.ReportDate.Month - 1))
{
info.LastMonthCash = superviseReport.LatestMonthCash;
}
info.LatestNetAssets = superviseReport.LatestNetAssets;
}
return Return.Success(info);
}
/// <summary>
/// 查询报送详情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public List<Dictionary<string, string>> QueryDetails(int id)
{
var tag = DbContext.supervise_report.Where(O => O.id == id).Select(O => O.FileTag).FirstOrDefault();
tag = (tag ?? "").Replace("YSP_", "").Replace("_checked", "");
var reportList_temp = DbContext.supervise_report.Where(O => O.FileTag.StartsWith(tag)).ToList();
var fileTagList_temp = reportList_temp.Select(O => O.FileTag).ToList();
var noteList_temp = DbContext.sac_report_notes.Where(O => fileTagList_temp.Contains(O.FileTag)).ToList();
var reports = (from report in reportList_temp
join notes in noteList_temp on report.FileTag equals notes.FileTag
select new { report, notes }).ToArray().GroupBy(O => O.report.FileTag)
.ToDictionary(K => K.First().report, V => V.Select(O => O.notes).Distinct().ToList());
var result = new List<Dictionary<string, string>>();
foreach (var item in reports)
{
var dict = new Dictionary<string, string>
{
["FileTag"] = item.Key.FileTag,
["FileType"] = EnumHelper.GetDescriptionByName<SuperviseReportTypeEnum>(item.Key.ReportType),
["ExceId"] = "-",
["BizID"] = "-",
["RetCode"] = item.Key.ReportReponseCode,
["RetMsg"] = item.Key.ReportReponseMessage
};
result.Add(dict);
foreach (var note in item.Value)
{
dict = new Dictionary<string, string>
{
["FileTag"] = note.InfoCache,
["FileType"] = "-",
["ExceId"] = note.ExceId,
["BizID"] = note.BizId,
["RetCode"] = note.RetCode,
["RetMsg"] = note.RetMsg
};
result.Add(dict);
}
}
return result;
}
/// <summary>
/// 查询收益说明
/// </summary>
/// <param name="pGroups"><seealso cref="DBModels.Consts.ConsAppConfig"/></param>
/// <returns></returns>
public Dictionary<string, Dictionary<string, string>> QueryReportDesc(List<string>? pGroups = null)
{
pGroups ??= new List<string>();
if (pGroups.Count == 0)
{
pGroups.Add(DBModels.Consts.ConsAppConfig.ReportDescOption);
pGroups.Add(DBModels.Consts.ConsAppConfig.ReportDescSwap);
}
var query = DbContext.AppConfig
.Where(O => pGroups.Contains(O.PGroup))
.AsEnumerable()
.GroupBy(O => O.PGroup)
.Select(n => new { n.Key, List = n.Select(m => new { m.PName, m.PValue }) })
.AsEnumerable()
.ToDictionary(
K => K.Key,
V => V.List.ToDictionary(K => K.PName, V1 => V1.PValue));
return query;
}
/// <summary>
/// 保存收益说明
/// </summary>
/// <returns></returns>
public int SaveReportDesc(Dictionary<string, Dictionary<string, string>> obj)
{
var pGroups = new List<string> {
DBModels.Consts.ConsAppConfig.ReportDescOption,
DBModels.Consts.ConsAppConfig.ReportDescSwap
};
DbContext.BulkDelete<AppConfig>($"{nameof(AppConfig.PGroup)} in @pGroups", new { pGroups });
foreach (var group in obj)
{
foreach (var item in group.Value)
{
if (item.Value.IsNullOrWhiteSpace()) { continue; }
DbContext.AppConfig.Add(new AppConfig()
{
CreateTime = DateTime.Now,
OptDate = DateTime.Now,
PGroup = group.Key,
PName = item.Key,
PType = "string",
PValue = item.Value,
Remark = "证券业报送中的收益描述信息"
});
}
}
return DbContext.SaveChanges();
}
/// <summary>
/// 报送预览
/// </summary>
/// <param name="fileTag"></param>
/// <param name="fileType"></param>
/// <returns></returns>
public List<SacInfo> GetSupervisePreview(string fileTag, string fileType)
{
var result = new List<SacInfo>();
var arr = fileTag.Split('_');//OTC_151089_000899_20210104_0002_A1008_A
var rootPath = OtcAppContext.MapPath("/App_Docs/Download/");
var pathName = string.Empty;
var xmlPath = string.Empty;
var zipPath = string.Empty;
switch (fileType)
{
case "send"://OTC_151089_000899_20210104_0002
pathName = $"{arr[0]}_{arr[1]}_{arr[2]}_YSP_{arr[3]}_{arr[4]}";//目录名
rootPath = Path.Combine(rootPath, "Report");//zip文件目录
zipPath = Path.Combine(rootPath, pathName + ".zip");//zip文件路径
if (!File.Exists(zipPath))
{
pathName = $"{arr[0]}_{arr[1]}_{arr[2]}_YSP_{arr[3]}_{arr[4]}_checked"; //目录名
zipPath = Path.Combine(rootPath, pathName + ".zip"); //zip文件路径
}
if (!File.Exists(zipPath))
{
pathName = $"{arr[0]}_{arr[1]}_{arr[2]}_{arr[3]}_{arr[4]}";//目录名
zipPath = Path.Combine(rootPath, pathName + ".zip");//zip文件路径
}
rootPath = Path.Combine(rootPath, "Temp");//临时文件根目录
pathName = Path.Combine(rootPath, pathName);//解压目录
xmlPath = Path.Combine(pathName, fileTag + ".xml");//预览文件路径
break;
case "recv"://OTC_000899_151089_20210104_0002
pathName = $"{arr[0]}_{arr[2]}_{arr[1]}_YSP_{arr[3]}_{arr[4]}";//目录名
xmlPath = $"{arr[0]}_{arr[2]}_{arr[1]}_{arr[3]}_{arr[4]}_{arr[5]}_{arr[6]}_R.xml";//预览文件名
rootPath = Path.Combine(rootPath, "ReportResponse");//zip文件目录
zipPath = Path.Combine(rootPath, pathName + ".zip");//zip文件路径
if (!File.Exists(zipPath))
{
pathName = $"{arr[0]}_{arr[2]}_{arr[1]}_{arr[3]}_{arr[4]}";//目录名
zipPath = Path.Combine(rootPath, pathName + ".zip");//zip文件路径
}
rootPath = Path.Combine(rootPath, "Temp");//临时文件根目录
pathName = Path.Combine(rootPath, pathName);//解压目录
xmlPath = Path.Combine(pathName, xmlPath);//预览文件路径
break;
default:
throw new ServiceException("未知操作类型");
}
try
{
optionSuperviseLock.WaitOne();
if (!Directory.Exists(pathName))
{
Directory.CreateDirectory(pathName);
ZipHelper.unZipFile(zipPath, rootPath, out var msg);
if (msg.StartsWith("解压失败"))
{
Directory.Delete(pathName, true);
LogFactory.GetLogger("SupervisePreview").Info($"解压失败:{msg}");
throw new ServiceException(msg);
}
}
var doc = new XmlDocument();
doc.Load(xmlPath);
var node = doc.GetElementsByTagName("Root")[0];
var info = new SacInfo(node.Name, "");
ReadXmlNode(node, info);
info.formatFieldDescription();
result.Add(info);
}
catch (ServiceException ex)
{
throw new ServiceException("预览失败:报送文件不存在或其他原因,详情请查看系统日志.", ex);
}
catch (Exception ex)
{
LogFactory.GetLogger("SupervisePreview").Error(ex);
throw new ServiceException("预览失败");
}
finally
{
optionSuperviseLock.Set();
}
return result;
}
private void ReadXmlNode(XmlNode node, SacInfo sacInfo)
{
if (node.HasChildNodes && node.ChildNodes.Count == 1 && node.ChildNodes[0].NodeType == XmlNodeType.Text)
{
sacInfo.FieldValue = node.InnerText;
}
else
{
foreach (XmlNode item in node.ChildNodes)
{
var sItem = new SacInfo(item.Name, item.Value);
ReadXmlNode(item, sItem);
sacInfo.SubMaps.Add(sItem);
}
}
}
#endregion
#region 导出
/// <summary>
/// 导出
/// </summary>
/// <param name="id"></param>
/// <param name="fileTag"></param>
/// <returns></returns>
public string ExportDetailsV2(int id, string fileTag, string path)
{
var reportHelper = new ReportInfoHelper();
try
{
if (!reportHelper.Init(id, fileTag) || !reportHelper.SaveToZipFile(path))
{
throw new ServiceException(reportHelper.ErrorMsg);
}
}
catch (Exception ex)
{
LogFactory.GetLogger("ExportDetails").Error(ex);
throw new ServiceException(ex.Message);
}
return path;
}
#endregion
#region 生成待重新上传的报送文件压缩包
private string GenerateUploadZipFile(ReportResponse res, string savePath)
{
if (res is null)
{
throw new ArgumentNullException(nameof(res));
}
if (string.IsNullOrWhiteSpace(savePath))
{
throw new ArgumentException($"“{nameof(savePath)}”不能为 null 或空白。", nameof(savePath));
}
var reportHelper = new ReportInfoHelper();
if (!reportHelper.Init(res) || !reportHelper.SaveToZipFile(savePath))
{
throw new ServiceException(reportHelper.ErrorMsg);
}
return savePath;
}
#endregion
}
}