377 lines
14 KiB
C#
377 lines
14 KiB
C#
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<trade_contract_group, bool> 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<Dictionary<string, string>> 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<Dictionary<string, string>> AppendDictionary()
|
|
{
|
|
return Return.Success(new Dictionary<string, string>());
|
|
}
|
|
|
|
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<string, string>()
|
|
};
|
|
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<string, object> 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<string> 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<string>(confirmDoc.RelativePath.Replace(".docx", ".pdf"));
|
|
}
|
|
|
|
return Return.Success<string>(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<string>(dicReturnInfo.Msg);
|
|
}
|
|
|
|
dicReturnInfo = AppendDictionary();
|
|
if (!dicReturnInfo.Success)
|
|
{
|
|
return Return.Fail<string>(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<string>(returnInfo.Msg);
|
|
}
|
|
|
|
//更新操作时间
|
|
var now = DateTime.Now;
|
|
File.SetLastAccessTime(outPutFilePath, now);
|
|
|
|
if (needAddData)
|
|
{
|
|
confirmDoc = SaveData(contractGroup, outPutFileName, contractNo);
|
|
}
|
|
FuncAfterGenerated?.Invoke(contractGroup);
|
|
|
|
return Return.Success<string>(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<trade_contract_r>();
|
|
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;
|
|
}
|
|
}
|
|
}
|