using YLErp.Commons; using YLErp.DBModels.Consts; using YLErp.Model; using YLErp.Modules; using YLErp.Modules.TradeModule; using YLErp.MsOffice; using YLErp.Office.Converters; namespace YLErp.BLL.GenerateDocument { public abstract class BaseGenerate { protected YLContext db = new(); protected BaseGenerate() { } protected BaseGenerate(trade_contract_group tradeContractGroup, string docType, int optId, string optName) { InitContractDataSet(tradeContractGroup); DocType = docType; OptId = optId; OptName = optName; } public string DocType { get; set; } public int OptId { get; set; } public string OptName { get; set; } protected virtual string ContractType { get; } protected string ContractFileDirectory => Path.Combine(OtcAppContext.AppDocsPath, @"contractdoc\"); public virtual string TemplateDirectory => Path.Combine(ContractFileDirectory, @"template\"); public virtual string TemplateFile { get; } protected ContractDataSet CurrentContractDataSet; public virtual string OutputFileDirectory => Path.Combine(ContractFileDirectory, @"output\"); public virtual string ContractNOSeed => ""; protected virtual Func FuncAfterGenerated => null; protected OptUserInfo GetOptUser() { return new OptUserInfo(OptId, OptName, OptUserFrom.System); } private string GetClientBuySell(string BuySell) { if ("卖出".Equals(BuySell)) { BuySell = "买入"; } else { BuySell = "卖出"; } return BuySell; } public virtual ReturnInfo> GetDictionary() { var tradeContractGroup = CurrentContractDataSet.ContractGroup; var dic = CurrentContractDataSet.ModelDic; var trade = tradeContractGroup.trade; var isGJBuyer = trade.BuySell == "买入"; var client = CurrentContractDataSet.Client; var underlying = CurrentContractDataSet.Underlying; #region 客户信息 dic["{{乙方名称}}"] = client.Name; dic["{{客户名称}}"] = client.Name; #endregion dic["{{交易编号}}"] = trade.TradeNumber; dic["{{交易方向}}"] = $"贵司{GetClientBuySell(trade.BuySell)}"; if (isGJBuyer) { dic["{{甲方方向}}"] = "买方"; dic["{{乙方方向}}"] = "卖方"; } else { dic["{{甲方方向}}"] = "卖方"; dic["{{乙方方向}}"] = "买方"; } dic["{{交易日}}"] = trade.TradeDate?.ToString("yyyy年M月d日"); if (trade.TradeType == "香草期权" || trade.TradeType == "亚式期权") { dic["{{生效日}}"] = trade.TradeDate?.ToString("yyyy年M月d日"); } else { dic["{{生效日}}"] = trade.StartDate?.ToString("yyyy年M月d日"); } if (trade.TradeType == "亚式期权") { dic["{{均价起算日}}"] = trade.trade_asian_option.AveragingPeriodStartDate?.ToString("yyyy年M月d日"); dic["{{奇异结构}}"] = $"{trade.trade_asian_option.StrikeTypeCn}的{trade.trade_asian_option.PayoffTypeCn}亚式"; } dic["{{到期日}}"] = trade.ExerciseDate?.ToString("yyyy年M月d日"); dic["{{行权日}}"] = "到期日"; dic["{{自动行权}}"] = "到期实值自动行权"; var strUnit = underlying.TradeUnitString; var notional = trade.Notional; #region 标的信息 dic["{{报价单位}}"] = strUnit; dic["{{商品标的数量}}"] = $"{notional}{strUnit}"; dic["{{商品标的交易所}}"] = underlying.MarketName; if (trade.TradeType == "合成价差期权") { dic["{{商品标的名称}}"] = synthetic_underlyingBLL.GetUnderlyingTipsInfo(trade.UnderlyingCode); } else { dic["{{商品标的名称}}"] = trade.UnderlyingCode; } #endregion //价格 if (trade.ActualStrike != null) { dic["{{执行价格}}"] = $"{trade.ActualStrike:f2}元/{strUnit}"; } else { dic["{{执行价格}}"] = "不适用"; } if (trade.SpotPrice != null) { dic["{{期初价格}}"] = $"{trade.SpotPrice:f2}元/{strUnit}"; } var tradeType = trade.TradeType == "香草期权" ? "普通" : (trade.TradeType == "结构化交易" ? trade.StructureType : trade.TradeType.Replace("期权", "")); dic["{{期权类型}}"] = $"{trade.ExerciseModeCn}{tradeType}{trade.OptionType}期权"; dic["{{期权费}}"] = $"{trade.TradePrice ?? 0:f3}元"; dic["{{期权价格}}"] = $"{trade.TradeSinglePrice ?? 0:f3}元/{strUnit}"; dic["{{支付时间}}"] = trade.PremiumPayDate != null ? "提前终止/到期时支付" : "已支付"; dic["{{结算方式}}"] = "人民币现金结算"; dic["{{补充}}"] = "补充"; return Return.Success(dic); } public virtual ReturnInfo> AppendDictionary() { return Return.Success(new Dictionary()); } protected virtual string GetContractIndex(trade_contract_group tradeContractGroup) { return ""; } protected virtual string GetContractNO(trade_contract_group tradeContractGroup, string contractIndex) { return ""; } protected virtual string GetOutputFileName(trade_contract_group tradeContractGroup, string contractIndex) { return ""; } protected virtual ReturnInfo InitContractDataSet(trade_contract_group tradeContractGroup) { CurrentContractDataSet = new ContractDataSet { ContractGroup = tradeContractGroup, ModelDic = new Dictionary() }; var trade = tradeContractGroup.trade; tradeBLL.SetFieldsByTradeType(trade); #region 标的 var underlying = CurrentContractDataSet.Underlying; underlying ??= db.underlying_manager.AsNoTracking().FirstOrDefault(x => x.UnderlyingCode == trade.UnderlyingCode); if (underlying == null) { return Return.Fail($"标的资产{trade.UnderlyingCode}信息未找到"); } CurrentContractDataSet.Underlying = underlying; #endregion #region 客户 using (var db2 = DbContextFactory.GetClientDbContext(null)) { var client = CurrentContractDataSet.Client; client ??= db2.client.AsNoTracking().FirstOrDefault(c => c.id == trade.ClientId); if (client == null) { return Return.Fail($"客户{trade.ClientName}信息未找到"); } CurrentContractDataSet.Client = client; var clientContactDuty = db2.clientduty.AsNoTracking().OrderBy(x => x.id).FirstOrDefault(x => x.ApprovalOrder < 1 && x.ClientId == client.id && x.ContactTypeId.Contains("1")); clientContactDuty ??= db2.clientduty.AsNoTracking().OrderBy(x => x.id).FirstOrDefault(x => x.ApprovalOrder < 1 && x.ClientId == client.id && x.ContactTypeId.Contains("2")); CurrentContractDataSet.ClientDuty = clientContactDuty; } #endregion #region 标的品种 var variety = CurrentContractDataSet.Variety; variety ??= db.variety.AsNoTracking().FirstOrDefault(x => x.id == underlying.UnderlyingTypeId); if (variety == null) { return Return.Fail($"标的{underlying.UnderlyingCode}对应的品种信息未找到"); } CurrentContractDataSet.Variety = variety; #endregion return Return.Success(); } private ReturnInfo GenerateDoc(Dictionary dic, string outPutFileName) { var templateFullPath = Path.Combine(TemplateDirectory, TemplateFile); if (DocType != FileTypeEnum.Word && DocType != FileTypeEnum.Pdf) { return Return.Fail($"{DocType}文档类型暂时不支持"); } MsWordTempalteHelper.GenerateFromTemplate(templateFullPath, dic, outPutFileName); return Return.Success(); } public virtual ReturnInfo GenerateBook() { var contractGroup = CurrentContractDataSet.ContractGroup; var trade = contractGroup.trade; var needAddData = true; #region 如果之前确认书已经生成过,则直接返回 var contractBLL = new TradeContractBLL(OptId, OptName); var confirmDoc = contractBLL.GetContractDoc(trade.id, ContractType); if (confirmDoc != null) { if (File.Exists(confirmDoc.AbsolutePath)) { if (DocType == "PDF") { var pdfPath = confirmDoc.AbsolutePath.Replace(".docx", ".pdf"); if (!File.Exists(pdfPath)) { OfficeFileConverter.ConvertDocxToPDF(confirmDoc.AbsolutePath, pdfPath); } return Return.Success(confirmDoc.RelativePath.Replace(".docx", ".pdf")); } return Return.Success(confirmDoc.RelativePath); } else { needAddData = false; } } #endregion //合同编号 string contractNo; string outPutFileName; if (confirmDoc != null) { contractNo = confirmDoc.Code; outPutFileName = confirmDoc.FileName.Replace(".docx", $".{DocType.ToLower()}"); } else { var contractIndex = GetContractIndex(contractGroup); contractNo = GetContractNO(contractGroup, contractIndex); outPutFileName = GetOutputFileName(contractGroup, contractIndex); } var dicReturnInfo = GetDictionary(); if (!dicReturnInfo.Success) { return Return.Fail(dicReturnInfo.Msg); } dicReturnInfo = AppendDictionary(); if (!dicReturnInfo.Success) { return Return.Fail(dicReturnInfo.Msg); } var dic = dicReturnInfo.Content.ToDictionary(K => K.Key, V => (object)V.Value); dic["{{合同编号}}"] = contractNo; var outPutFilePath = Path.Combine(OutputFileDirectory, outPutFileName); var returnInfo = GenerateDoc(dic, outPutFilePath); if (!returnInfo.Success) { return Return.Fail(returnInfo.Msg); } //更新操作时间 var now = DateTime.Now; File.SetLastAccessTime(outPutFilePath, now); if (needAddData) { confirmDoc = SaveData(contractGroup, outPutFileName, contractNo); } FuncAfterGenerated?.Invoke(contractGroup); return Return.Success(confirmDoc.RelativePath.Replace(".docx", $".{DocType.ToLower()}")); } public trade_contract_document SaveData(trade_contract_group contractGroup, string outPutFileName, string contractCode) { var trade = contractGroup.trade; var isGJBuyer = trade.BuySell == "买入"; var savedOutputFileName = outPutFileName.Replace(".pdf", ".docx"); var nowDate = DateTime.Now; var cd = new trade_contract_document(); db.trade_contract_document.Add(cd); cd.Code = contractCode; cd.ValueDate = valuedateBLL.ValueDate; cd.BuyerId = isGJBuyer ? 0 : trade.ClientId; cd.BuyerName = isGJBuyer ? (PS.Config.CompanyName ?? "") : trade.ClientName; cd.SellerId = isGJBuyer ? trade.ClientId : 0; cd.SellerName = isGJBuyer ? trade.ClientName : (PS.Config.CompanyName ?? ""); cd.FileType = FileTypeEnum.Word; cd.Status = ContractStatusEnum.Draft; cd.SourceType = 1; // 系统生成 cd.Paths = $"App_Docs\\contractdoc\\output\\{savedOutputFileName}"; cd.FileName = savedOutputFileName; cd.Type = ContractType; cd.OptId = OptId; cd.OptName = OptName; cd.OptDate = nowDate; var cr = new trade_contract_r(); db.trade_contract_r.Add(cr); cr.TradeId = trade.id; cr.TradeNumber = trade.TradeNumber; cr.ContractCode = cd.Code; cr.Type = ContractType; cr.OptId = OptId; cr.OptName = OptName; cr.OptDate = nowDate; cr.TradeCashId = contractGroup.trade_cash.id; cr.IsValid = true; var table = db.GetTableName(); var sql = $@"update {table} set {nameof(cr.TradeId)}=-{nameof(cr.TradeId)} where {nameof(cr.TradeId)}={cr.TradeId} and {nameof(cr.Type)}='{cr.Type}'"; db.Database.ExecuteSqlRaw(sql); db.SaveChanges(); return cd; } } }