Files
zszq-trs/YLErpDAL/Modules/TradeModule/DocGenerateModule/BatchConfirmationGenerateService.cs
T
2025-04-28 11:07:31 +08:00

483 lines
20 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
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 YLErp.BLL;
using YLErp.DBModels.Consts;
using YLErp.Model;
using YLErp.Models;
using YLErp.Modules.ClientModule;
using YLErp.Modules.TradeDalModule;
using YLErp.MsOffice;
using YLErp.Office.Converters;
using YLErp.Plugins.TradeDocGenerator.Abstracts;
namespace YLErp.Modules.TradeModule.DocGenerateModule
{
/// <summary>
/// 生成交易确认书
/// </summary>
public class BatchConfirmationGenerateService : YLBaseService
{
public BatchConfirmationGenerateService(OptUserInfo userInfo) : base(userInfo)
{
}
public BatchConfirmationGenerateService(YLBaseService baseService) : base(baseService)
{
}
/// <summary>
/// 生成交易确认书
/// </summary>
public IEnumerable<TradeDocGenerateResult> Generate(IEnumerable<int> tradeIds, string docType, DateTime? startDate = null, DateTime? endDate = null)
{
if (tradeIds == null)
{
throw new ArgumentNullException(nameof(tradeIds));
}
if (docType == null)
{
throw new ArgumentNullException(nameof(docType));
}
//----------------------------------
// 获取当日行权 平仓 到期的有效交易
//----------------------------------
var statusList = new List<string>() {
ConsTrade.确认成交
};
if (GlobalConfig.EnableGenerateOnTradeClosed)
{
statusList.Add(ConsTrade.已到期);
statusList.Add(ConsTrade.已平仓);
statusList.Add(ConsTrade.已执行);
statusList.Add(ConsTrade.审批中);
}
var service = new TradeDalService(this);
//var tradeQuery = service
// .GetTradeOrEodTrade(tradeIds, ValueDate, true)
// .Where(O =>
// statusList.Contains(O.TradeStatus)
// && (O.ParentTradeId == null || O.ParentTradeId < 1)
// && O.ClientId != null);
//var tradeQuery = from trad in DbContext.trade
// where tradeIds.Contains(trad.id)
// && statusList.Contains(trad.TradeStatus)
// && trad.ValidState != "InValid" && trad.ClientId != null
// && (trad.ParentTradeId == null || trad.ParentTradeId < 1)
// select trad;
//----------------------------------
// 交易现金交割记录
//----------------------------------
List<trade> allTrades = DbContext.trade.Where(x => tradeIds.Contains(x.id)).ToList();
if (allTrades.Count < 1)
{
throw new ServiceException("没有已确认的记录信息!");
}
var tradeDic = allTrades.Where(O =>
statusList.Contains(O.TradeStatus)
&& O.ClientId != 0
&& O.ParentTradeId == 0)
.ToDictionary(n => n.id, n => new trade_contract_group { trade = n });
tradeIds = allTrades.Select(O => O.id);
//----------------------------------
// 生成交易确认书
//----------------------------------
var resultList = new List<TradeDocGenerateResult>();
AppManager.TryResolve(out ITradeConfirmationGenerator generatorV2);
var tradeContractGroupTradeIds = tradeDic.Values.Select(x => x.trade.id).ToList();
if (generatorV2 != null)
{
var result = GenerateSingleV2(
generatorV2,
tradeDic.Values.Select(O => O.trade).ToList(),
tradeDic.Values.Select(O => (O.trade.trade_cash?.id) ?? 0).ToList(),
docType,
startDate,
endDate);
resultList.Add(result);
}
else
{
foreach (var item in tradeDic)
{
resultList.Add(GenerateSingleV1(item.Value, docType));
}
}
if (generatorV2 == null)
{
DbContext.SaveChanges();
}
return resultList;
}
/// <summary>
///
/// </summary>
private TradeDocGenerateResult GenerateSingleV2(ITradeConfirmationGenerator generator, List<trade> trades, List<int> tradeCashIds, string docType = "DOCX", DateTime? startDate = null, DateTime? endDate = null)
{
try
{
var context = new ConfirmationGenerateContext(tradeCashIds, trades, ContractTypeEnum.Trade, OptUser, startDate, endDate);
generator.Initialize(docType, context);
return generator.GenerateDocument();
}
catch (Exception ex)
{
LogFactory.GetLogger("GenerateSingleV2").Error(ex);
return new TradeDocGenerateResult(trades)
{
ErrorMessage = ex.Message
};
}
}
/// <summary>
///
/// </summary>
private TradeDocGenerateResult GenerateSingleV1(trade_contract_group contractGroup, string docType = "DOCX")
{
if (contractGroup == null)
{
throw new ArgumentNullException(nameof(contractGroup));
}
var contractBLL = new TradeContractBLL(this);
var trade = contractGroup.trade;
tradeBLL.SetFieldsByTradeType(trade);
var needAddData = true;
#region 如果之前交易确认书已经生成过,则直接返回
var confirmDoc = contractBLL.GetContractDoc(trade.id, ContractTypeEnum.Trade);
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 new TradeDocGenerateResult(trade)
{
//OutputFilePath = $"/App_Docs/GTJA/{confirmDoc.FileName.Replace(".doc", ".pdf")}"
OutputFilePath = YLErp.Helpers.PathHelper.PhysicalPathToWebPath(pdfPath, OtcAppContext.RootPath)
};
}
return new TradeDocGenerateResult(trade)
{
//OutputFilePath = $"/App_Docs/GTJA/{confirmDoc.FileName}"
OutputFilePath = YLErp.Helpers.PathHelper.PhysicalPathToWebPath(confirmDoc.AbsolutePath, OtcAppContext.RootPath)
};
}
else
{
needAddData = false;
}
}
#endregion
var isGJBuyer = trade.BuySell == "买入";
var underlying = underlying_managerBLL.GetByCode(trade.UnderlyingCode);
if (underlying == null)
{
return new TradeDocGenerateResult(trade)
{
ErrorMessage = $"标的资产{trade.UnderlyingCode}信息未找到"
};
}
var client = DataCacheProvider.GetClientDataSource().GetData(trade.ClientId);
if (client == null)
{
return new TradeDocGenerateResult(trade)
{
ErrorMessage = $"客户{trade.ClientId}信息未找到"
};
}
var dic = new Dictionary<string, object>
{
["{{乙方名称}}"] = client.Name
};
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["{{自动行权}}"] = "到期实值自动行权";
//商品标的
if (trade.TradeType == "合成价差期权")
{
dic["{{商品标的名称}}"] = synthetic_underlyingBLL.GetUnderlyingTipsInfo(trade.UnderlyingCode);
}
else
{
dic["{{商品标的名称}}"] = trade.UnderlyingCode;
}
var strUnit = underlying.TradeUnitString;
var notional = trade.Notional;
dic["{{报价单位}}"] = strUnit;
dic["{{商品标的数量}}"] = $"{notional}{strUnit}";
dic["{{商品标的交易所}}"] = underlying.MarketName;
//价格
if (trade.ActualStrike != null)
{
if (trade.IsMoneynessOption == "是")
{
dic["{{执行价格}}"] = (trade.Strike ?? 0).OtcFormatUmPrice(true);
}
else
{
dic["{{执行价格}}"] = $"{trade.ActualStrike?.OtcFormatUmPrice()}元/{strUnit}";
}
}
else
{
dic["{{执行价格}}"] = "不适用";
}
var tradeType = trade.TradeType == "香草期权" ? "普通" : (trade.TradeType == "结构化交易" ? trade.StructureType : trade.TradeType.Replace("期权", ""));
dic["{{期权类型}}"] = $"{trade.ExerciseModeCn}{tradeType}{trade.OptionType}期权";
dic["{{期权费}}"] = $"{(trade.TradePrice ?? 0).OtcFormatMoney(grouping: false)}元";
dic["{{协议编号}}"] = client.Remark;
dic["{{期权价格}}"] = $"{(trade.TradeSinglePrice ?? 0).OtcFormat(OtcFormatFlag.tradeSinglePrice)}元/{strUnit}";
dic["{{支付时间}}"] = trade.PremiumPayDate != null ? "提前终止/到期时支付" : "已支付";
dic["{{期权方向}}"] = $"甲方{trade.BuySell}";
dic["{{名义本金}}"] = trade.StockEqvNotional.OtcFormat(OtcFormatFlag.StockEqvNotional);
dic["{{期初价格}}"] = (trade.SpotPrice ?? 0).OtcFormatUmPrice();
dic["{{期权费率}}"] = ((trade.PremiumRate ?? ((trade.TradePrice ?? 0) / trade.OriginalStockEqvNotional.Value)) * 100).OtcFormatFlex(2);
var settlementType = "价格";
if (trade.SettlementType == SettlementTypeEnum.SettlePrice)
{
settlementType = "结算价";
}
else if (trade.SettlementType == SettlementTypeEnum.ClosePrice)
{
settlementType = "收盘价";
}
if (trade.ExerciseMode == "American")
{
dic["{{美式期权结算价}}"] = $"所属交易所公布的标的合约可成交的最新价";
dic["{{欧式期权结算价}}"] = $"美式期权不适用";
}
else
{
dic["{{美式期权结算价}}"] = $"欧式期权不适用";
dic["{{欧式期权结算价}}"] = $"所属交易所在到期日收盘后公布的标的合约{settlementType}";
}
if (trade.UnderlyingInstrumentType != "CommodityFutures")
{
dic["{{证券名称}}"] = underlying.UnderlyingName;
dic["{{证券代码}}"] = underlying.UnderlyingCode;
dic["{{账户信息乙方}}"] = client.Name;
dic["{{联系方式乙方}}"] = client.Name;
dic["{{联系方式乙方联系人}}"] = client.Name;
dic["{{联系方式乙方电话}}"] = client.Phone;
dic["{{联系方式乙方电子邮件}}"] = client.Email;
var bankcard = ClientDataQueryService.GetBankCard(trade.ClientId);
if (bankcard != null)
{
dic["{{账户信息乙方户名}}"] = bankcard.ClientName;
dic["{{账户信息乙方账号}}"] = bankcard.Card;
dic["{{账户信息乙方开户行}}"] = bankcard.Bank;
}
dic["{{期权方向}}"] = $"甲方{trade.BuySell}";
dic["{{名义本金}}"] = trade.StockEqvNotional.OtcFormat(OtcFormatFlag.StockEqvNotional);
}
if (trade.OptionType == "看涨")
{
if (trade.ExerciseMode == "American")
{
dic["{{美式期权结算金额}}"] =
$"(行权时{trade.UnderlyingCode}合约可成交最新价 - {trade.ActualStrike.OtcFormatUmPrice()})× {notional.OtcFormatNotional()}";
dic["{{欧式期权结算金额}}"] = $"美式期权不适用";
}
else
{
dic["{{美式期权结算金额}}"] = $"欧式期权不适用";
dic["{{欧式期权结算金额}}"] =
$"{trade.ExerciseDate?.ToString("yyyy年M月d日")}{trade.UnderlyingCode}合约{settlementType} - {trade.ActualStrike.OtcFormatUmPrice()})× {notional.OtcFormatNotional()}";
}
}
else if (trade.OptionType == "看跌")
{
if (trade.ExerciseMode == "American")
{
dic["{{美式期权结算金额}}"] =
$"{trade.ActualStrike.OtcFormatUmPrice()} - 行权时{trade.UnderlyingCode}合约可成交最新价)× {notional.OtcFormatNotional()}";
dic["{{欧式期权结算金额}}"] = $"美式期权不适用";
}
else
{
dic["{{美式期权结算金额}}"] = $"欧式期权不适用";
dic["{{欧式期权结算金额}}"] =
$"({trade.ActualStrike.OtcFormatUmPrice()} - {trade.ExerciseDate?.ToString("yyyy年M月d日")}{trade.UnderlyingCode}合约{settlementType})× {notional.OtcFormatNotional()}";
}
}
//合同编号
string contractNo;
string outPutFileName;
if (confirmDoc != null)
{
contractNo = confirmDoc.Code;
outPutFileName = confirmDoc.FileName;
}
else
{
var contractIndex = contractBLL.GetContractNo("GTJA");
if (PS.Config.CompanyID == "中财资本")
{
contractNo = $"{trade.TradeNumber}";
}
else
{
contractNo = $"{client.Number}C{contractIndex}";
}
outPutFileName = $"{client.Name}交易确认书C{contractIndex}.docx";
}
dic["{{合同编号}}"] = contractNo;
dic["{{结算方式}}"] = "人民币现金结算";
dic["{{补充}}"] = "补充";
try
{
var templateDir = OtcAppContext.MapPath("~/App_Docs/GTJA");
var templatePath = OtcAppContext.MapPath("~/App_Docs/导出模板/交易确认书模板.docx");
if (trade.TradeType == "亚式期权")
{
templatePath = OtcAppContext.MapPath("~/App_Docs/导出模板/交易确认书(亚式期权)模板.docx");
}
if (trade.IsUsePremiumRate != null && trade.IsUsePremiumRate.Value)
{
templatePath = OtcAppContext.MapPath("~/App_Docs/导出模板/交易确认书(名义本金)模板.docx");
}
LogFactory.GetLogger("交易确认书").Info("交易确认书:" + outPutFileName);
var outPutFilePath = Path.Combine(templateDir, outPutFileName);
MsWordTempalteHelper.GenerateFromTemplate(templatePath, dic, outPutFilePath);
if (docType == "PDF" && !outPutFilePath.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
{
OfficeFileConverter.ConvertDocxToPDF(outPutFilePath, outPutFilePath.Replace(".docx", ".pdf"));
}
//更新操作时间
var now = DateTime.Now;
File.SetLastAccessTime(outPutFilePath, now);
#region --- Add trade_contract_document and trade_contract_r records
if (needAddData)
{
contractBLL.DeleteConfirmBook(trade.id, null);
var nowDate = DateTime.Now;
var contractRecord = new trade_contract_document();
DbContext.trade_contract_document.Add(contractRecord);
contractRecord.Code = dic["{{合同编号}}"].ToString();
contractRecord.ValueDate = valuedateBLL.ValueDate;
contractRecord.BuyerId = isGJBuyer ? 0 : trade.ClientId;
contractRecord.BuyerName = isGJBuyer ? PS.Config.CompanyFullName : trade.ClientName;
contractRecord.SellerId = isGJBuyer ? trade.ClientId : 0;
contractRecord.SellerName = isGJBuyer ? trade.ClientName : PS.Config.CompanyFullName;
contractRecord.FileType = FileTypeEnum.Word;
contractRecord.Status = ContractStatusEnum.Draft;
contractRecord.Paths = $"App_Docs\\GTJA\\{outPutFileName}";
contractRecord.FileName = outPutFileName;
contractRecord.Type = ContractTypeEnum.Trade;
contractRecord.OptId = UserId;
contractRecord.OptName = UserName;
contractRecord.OptDate = nowDate;
var contractTradeRelation = new trade_contract_r();
DbContext.trade_contract_r.Add(contractTradeRelation);
contractTradeRelation.TradeId = trade.id;
contractTradeRelation.TradeNumber = trade.TradeNumber;
contractTradeRelation.ContractCode = contractRecord.Code;
contractTradeRelation.Type = ContractTypeEnum.Trade;
contractTradeRelation.OptId = UserId;
contractTradeRelation.OptName = UserName;
contractTradeRelation.OptDate = nowDate;
contractTradeRelation.TradeCashId = contractGroup.trade_cash == null ? 0 : contractGroup.trade_cash.id;
contractTradeRelation.IsValid = true;
DbContext.SaveChanges();
}
#endregion --- Add trade_contract_document and trade_contract_r records
return new TradeDocGenerateResult(trade)
{
OutputFilePath = $"/App_Docs/GTJA/{(docType == "PDF" ? outPutFileName.Replace(".docx", ".pdf") : outPutFileName)}"
};
}
catch (Exception e)
{
LogFactory.GetLogger<ConfirmationGenerateService>().Error("GenerateSingleConfirmBook出错", e);
return new TradeDocGenerateResult(trade) { ErrorMessage = e.Message };
}
}
}
}