diff --git a/Framework/YLErp.Core/Plugins/TradeDocGenerator/BaseDocumentGenerator_Batch.cs b/Framework/YLErp.Core/Plugins/TradeDocGenerator/BaseDocumentGenerator_Batch.cs index e2a6c753..913af16d 100644 --- a/Framework/YLErp.Core/Plugins/TradeDocGenerator/BaseDocumentGenerator_Batch.cs +++ b/Framework/YLErp.Core/Plugins/TradeDocGenerator/BaseDocumentGenerator_Batch.cs @@ -227,12 +227,12 @@ namespace YLErp.Plugins.TradeDocGenerator protected void FormatToDict(string key, DateTime? value, JObject dict) { dict[key] = value?.ToString("yyyy年MM月dd日"); - dict[key.Insert(key.Length - 2, "N")] = value?.ToString("yyyyMMdd"); - dict[key.Insert(key.Length - 2, "/")] = value?.ToString("yyyy/MM/dd"); - dict[key.Insert(key.Length - 2, "-")] = value?.ToString("yyyy-MM-dd"); - dict[key.Insert(key.Length - 2, "年")] = value?.ToString("yyyy"); - dict[key.Insert(key.Length - 2, "月")] = value?.ToString("MM"); - dict[key.Insert(key.Length - 2, "日")] = value?.ToString("dd"); + dict[key.Insert(key.Length, "N")] = value?.ToString("yyyyMMdd"); + dict[key.Insert(key.Length, "/")] = value?.ToString("yyyy/MM/dd"); + dict[key.Insert(key.Length, "-")] = value?.ToString("yyyy-MM-dd"); + dict[key.Insert(key.Length, "年")] = value?.ToString("yyyy"); + dict[key.Insert(key.Length, "月")] = value?.ToString("MM"); + dict[key.Insert(key.Length, "日")] = value?.ToString("dd"); } /// @@ -244,12 +244,12 @@ namespace YLErp.Plugins.TradeDocGenerator protected void FormatToDict(string key, DateTime value, Dictionary dict) { dict[key] = value.ToString("yyyy年MM月dd日"); - dict[key.Insert(key.Length - 2, "N")] = value.ToString("yyyyMMdd"); - dict[key.Insert(key.Length - 2, "/")] = value.ToString("yyyy/MM/dd"); - dict[key.Insert(key.Length - 2, "-")] = value.ToString("yyyy-MM-dd"); - dict[key.Insert(key.Length - 2, "年")] = value.ToString("yyyy"); - dict[key.Insert(key.Length - 2, "月")] = value.ToString("MM"); - dict[key.Insert(key.Length - 2, "日")] = value.ToString("dd"); + dict[key.Insert(key.Length, "N")] = value.ToString("yyyyMMdd"); + dict[key.Insert(key.Length, "/")] = value.ToString("yyyy/MM/dd"); + dict[key.Insert(key.Length, "-")] = value.ToString("yyyy-MM-dd"); + dict[key.Insert(key.Length, "年")] = value.ToString("yyyy"); + dict[key.Insert(key.Length, "月")] = value.ToString("MM"); + dict[key.Insert(key.Length, "日")] = value.ToString("dd"); } /// @@ -261,8 +261,8 @@ namespace YLErp.Plugins.TradeDocGenerator protected void FormatToDict(string key, int value, JObject dict) { dict[key] = value.ToString("0"); - dict[key.Insert(key.Length - 2, "A")] = Math.Abs(value).ToString("0"); - dict[key.Insert(key.Length - 2, "大写")] = Context.CmycurD(Math.Abs(value)); + dict[key.Insert(key.Length, "A")] = Math.Abs(value).ToString("0"); + dict[key.Insert(key.Length, "大写")] = Context.CmycurD(Math.Abs(value)); } /// @@ -275,28 +275,28 @@ namespace YLErp.Plugins.TradeDocGenerator { value = value == -0 ? 0 : value; dict[key] = value?.ToString("0.00"); - dict[key.Insert(key.Length - 2, "2")] = value?.ToString("0.00"); - dict[key.Insert(key.Length - 2, "3")] = value?.ToString("0.000"); - dict[key.Insert(key.Length - 2, "4")] = value?.ToString("0.0000"); - dict[key.Insert(key.Length - 2, "5")] = value?.ToString("0.00000"); - dict[key.Insert(key.Length - 2, "6")] = value?.ToString("0.000000"); - dict[key.Insert(key.Length - 2, "A")] = value != null ? Math.Abs(value.Value).ToString("0") : ""; - dict[key.Insert(key.Length - 2, "A2")] = value != null ? Math.Abs(value.Value).ToString("0.00") : ""; - dict[key.Insert(key.Length - 2, "A3")] = value != null ? Math.Abs(value.Value).ToString("0.000") : ""; - dict[key.Insert(key.Length - 2, "A4")] = value != null ? Math.Abs(value.Value).ToString("0.0000") : ""; - dict[key.Insert(key.Length - 2, "A5")] = value != null ? Math.Abs(value.Value).ToString("0.00000") : ""; - dict[key.Insert(key.Length - 2, "A6")] = value != null ? Math.Abs(value.Value).ToString("0.000000") : ""; - dict[key.Insert(key.Length - 2, "2?")] = value?.ToString("0.##"); - dict[key.Insert(key.Length - 2, "3?")] = value?.ToString("0.###"); - dict[key.Insert(key.Length - 2, "4?")] = value?.ToString("0.####"); - dict[key.Insert(key.Length - 2, "5?")] = value?.ToString("0.#####"); - dict[key.Insert(key.Length - 2, "6?")] = value?.ToString("0.######"); - dict[key.Insert(key.Length - 2, "A2?")] = value != null ? Math.Abs(value.Value).ToString("0.##") : ""; - dict[key.Insert(key.Length - 2, "A3?")] = value != null ? Math.Abs(value.Value).ToString("0.###") : ""; - dict[key.Insert(key.Length - 2, "A4?")] = value != null ? Math.Abs(value.Value).ToString("0.####") : ""; - dict[key.Insert(key.Length - 2, "A5?")] = value != null ? Math.Abs(value.Value).ToString("0.#####") : ""; - dict[key.Insert(key.Length - 2, "A6?")] = value != null ? Math.Abs(value.Value).ToString("0.######") : ""; - dict[key.Insert(key.Length - 2, "大写")] = value != null ? Context.CmycurD(Math.Abs(value.Value)) : ""; + dict[key.Insert(key.Length, "2")] = value?.ToString("0.00"); + dict[key.Insert(key.Length, "3")] = value?.ToString("0.000"); + dict[key.Insert(key.Length, "4")] = value?.ToString("0.0000"); + dict[key.Insert(key.Length, "5")] = value?.ToString("0.00000"); + dict[key.Insert(key.Length, "6")] = value?.ToString("0.000000"); + dict[key.Insert(key.Length, "A")] = value != null ? Math.Abs(value.Value).ToString("0") : ""; + dict[key.Insert(key.Length, "A2")] = value != null ? Math.Abs(value.Value).ToString("0.00") : ""; + dict[key.Insert(key.Length, "A3")] = value != null ? Math.Abs(value.Value).ToString("0.000") : ""; + dict[key.Insert(key.Length, "A4")] = value != null ? Math.Abs(value.Value).ToString("0.0000") : ""; + dict[key.Insert(key.Length, "A5")] = value != null ? Math.Abs(value.Value).ToString("0.00000") : ""; + dict[key.Insert(key.Length, "A6")] = value != null ? Math.Abs(value.Value).ToString("0.000000") : ""; + dict[key.Insert(key.Length, "2?")] = value?.ToString("0.##"); + dict[key.Insert(key.Length, "3?")] = value?.ToString("0.###"); + dict[key.Insert(key.Length, "4?")] = value?.ToString("0.####"); + dict[key.Insert(key.Length, "5?")] = value?.ToString("0.#####"); + dict[key.Insert(key.Length, "6?")] = value?.ToString("0.######"); + dict[key.Insert(key.Length, "A2?")] = value != null ? Math.Abs(value.Value).ToString("0.##") : ""; + dict[key.Insert(key.Length, "A3?")] = value != null ? Math.Abs(value.Value).ToString("0.###") : ""; + dict[key.Insert(key.Length, "A4?")] = value != null ? Math.Abs(value.Value).ToString("0.####") : ""; + dict[key.Insert(key.Length, "A5?")] = value != null ? Math.Abs(value.Value).ToString("0.#####") : ""; + dict[key.Insert(key.Length, "A6?")] = value != null ? Math.Abs(value.Value).ToString("0.######") : ""; + dict[key.Insert(key.Length, "大写")] = value != null ? Context.CmycurD(Math.Abs(value.Value)) : ""; } /// @@ -309,28 +309,28 @@ namespace YLErp.Plugins.TradeDocGenerator { value = value == -0 ? 0 : value; dict[key] = value.ToString("0.00"); - dict[key.Insert(key.Length - 2, "2")] = value.ToString("0.00"); - dict[key.Insert(key.Length - 2, "3")] = value.ToString("0.000"); - dict[key.Insert(key.Length - 2, "4")] = value.ToString("0.0000"); - dict[key.Insert(key.Length - 2, "5")] = value.ToString("0.00000"); - dict[key.Insert(key.Length - 2, "6")] = value.ToString("0.000000"); - dict[key.Insert(key.Length - 2, "A")] = Math.Abs(value).ToString("0"); - dict[key.Insert(key.Length - 2, "A2")] = Math.Abs(value).ToString("0.00"); - dict[key.Insert(key.Length - 2, "A3")] = Math.Abs(value).ToString("0.000"); - dict[key.Insert(key.Length - 2, "A4")] = Math.Abs(value).ToString("0.0000"); - dict[key.Insert(key.Length - 2, "A5")] = Math.Abs(value).ToString("0.00000"); - dict[key.Insert(key.Length - 2, "A6")] = Math.Abs(value).ToString("0.000000"); - dict[key.Insert(key.Length - 2, "2?")] = value.ToString("0.##"); - dict[key.Insert(key.Length - 2, "3?")] = value.ToString("0.###"); - dict[key.Insert(key.Length - 2, "4?")] = value.ToString("0.####"); - dict[key.Insert(key.Length - 2, "5?")] = value.ToString("0.#####"); - dict[key.Insert(key.Length - 2, "6?")] = value.ToString("0.######"); - dict[key.Insert(key.Length - 2, "A2?")] = Math.Abs(value).ToString("0.##"); - dict[key.Insert(key.Length - 2, "A3?")] = Math.Abs(value).ToString("0.###"); - dict[key.Insert(key.Length - 2, "A4?")] = Math.Abs(value).ToString("0.####"); - dict[key.Insert(key.Length - 2, "A5?")] = Math.Abs(value).ToString("0.#####"); - dict[key.Insert(key.Length - 2, "A6?")] = Math.Abs(value).ToString("0.######"); - dict[key.Insert(key.Length - 2, "大写")] = Context.CmycurD(Math.Abs(value)); + dict[key.Insert(key.Length, "2")] = value.ToString("0.00"); + dict[key.Insert(key.Length, "3")] = value.ToString("0.000"); + dict[key.Insert(key.Length, "4")] = value.ToString("0.0000"); + dict[key.Insert(key.Length, "5")] = value.ToString("0.00000"); + dict[key.Insert(key.Length, "6")] = value.ToString("0.000000"); + dict[key.Insert(key.Length, "A")] = Math.Abs(value).ToString("0"); + dict[key.Insert(key.Length, "A2")] = Math.Abs(value).ToString("0.00"); + dict[key.Insert(key.Length, "A3")] = Math.Abs(value).ToString("0.000"); + dict[key.Insert(key.Length, "A4")] = Math.Abs(value).ToString("0.0000"); + dict[key.Insert(key.Length, "A5")] = Math.Abs(value).ToString("0.00000"); + dict[key.Insert(key.Length, "A6")] = Math.Abs(value).ToString("0.000000"); + dict[key.Insert(key.Length, "2?")] = value.ToString("0.##"); + dict[key.Insert(key.Length, "3?")] = value.ToString("0.###"); + dict[key.Insert(key.Length, "4?")] = value.ToString("0.####"); + dict[key.Insert(key.Length, "5?")] = value.ToString("0.#####"); + dict[key.Insert(key.Length, "6?")] = value.ToString("0.######"); + dict[key.Insert(key.Length, "A2?")] = Math.Abs(value).ToString("0.##"); + dict[key.Insert(key.Length, "A3?")] = Math.Abs(value).ToString("0.###"); + dict[key.Insert(key.Length, "A4?")] = Math.Abs(value).ToString("0.####"); + dict[key.Insert(key.Length, "A5?")] = Math.Abs(value).ToString("0.#####"); + dict[key.Insert(key.Length, "A6?")] = Math.Abs(value).ToString("0.######"); + dict[key.Insert(key.Length, "大写")] = Context.CmycurD(Math.Abs(value)); } protected void FormatToDict(string v, string Date, Dictionary dic) diff --git a/Plugins/YLErp.Plugins.ZheShang/App_Docs/交易确认书/客户多头交易确认书模板.docx b/Plugins/YLErp.Plugins.ZheShang/App_Docs/交易确认书/客户多头交易确认书模板.docx deleted file mode 100644 index fdbc6b94..00000000 Binary files a/Plugins/YLErp.Plugins.ZheShang/App_Docs/交易确认书/客户多头交易确认书模板.docx and /dev/null differ diff --git a/Plugins/YLErp.Plugins.ZheShang/App_Docs/交易确认书/客户空头交易确认书模板.docx b/Plugins/YLErp.Plugins.ZheShang/App_Docs/交易确认书/客户空头交易确认书模板.docx deleted file mode 100644 index 39b90170..00000000 Binary files a/Plugins/YLErp.Plugins.ZheShang/App_Docs/交易确认书/客户空头交易确认书模板.docx and /dev/null differ diff --git a/Plugins/YLErp.Plugins.ZheShang/App_Docs/交易确认书/浙商证券利率债收益互换合约交易确认书模版.docx b/Plugins/YLErp.Plugins.ZheShang/App_Docs/交易确认书/浙商证券利率债收益互换合约交易确认书模版.docx new file mode 100644 index 00000000..dfec74d0 Binary files /dev/null and b/Plugins/YLErp.Plugins.ZheShang/App_Docs/交易确认书/浙商证券利率债收益互换合约交易确认书模版.docx differ diff --git a/Plugins/YLErp.Plugins.ZheShang/DocumentGenerator/TradeConfirmationGenerator.cs b/Plugins/YLErp.Plugins.ZheShang/DocumentGenerator/TradeConfirmationGenerator.cs index 8d6ead78..db5e1d1b 100644 --- a/Plugins/YLErp.Plugins.ZheShang/DocumentGenerator/TradeConfirmationGenerator.cs +++ b/Plugins/YLErp.Plugins.ZheShang/DocumentGenerator/TradeConfirmationGenerator.cs @@ -1,15 +1,18 @@ -using Newtonsoft.Json.Linq; +using Microsoft.VisualBasic; +using Newtonsoft.Json.Linq; +using NPOI.SS.Formula.Functions; using System.Text.RegularExpressions; using YLErp.Core.Helpers; using YLErp.DBModels; using YLErp.DBModels.Consts; +using YLErp.DBModels.Enums; using YLErp.Enums; using YLErp.Plugins.TradeDocGenerator; using YLErp.Plugins.TradeDocGenerator.Abstracts; namespace YLErp.Plugins.ShanXi.DocumentGenerator { - internal class TradeConfirmationGenerator : BaseConfirmationGenerator, ITradeConfirmationGenerator + internal class TradeConfirmationGenerator : BaseConfirmationGenerator_Batch, ITradeConfirmationGenerator { public TradeConfirmationGenerator() : base(ContractTypeEnum.Trade) @@ -21,23 +24,29 @@ namespace YLErp.Plugins.ShanXi.DocumentGenerator { string templatePath = null; var trade = Context.Trade; - if (trade.TradeType == "收益互换" && trade.StructureType != null) + if (trade.TradeType == "收益互换") //&& trade.StructureType != null) { - var swapPosition = Context.GetSwapPositions(trade.id, true).Where(x => x.PositionType > 0).FirstOrDefault(); - - if (swapPosition != null) - { - switch (swapPosition.PositionType) - { - case 1: - templatePath = MosPathHelper.Combine(GlobalConfig.PluginFolder, "App_Docs\\交易确认书\\客户多头交易确认书模板.docx"); - break; - case 2: - templatePath = MosPathHelper.Combine(GlobalConfig.PluginFolder, "App_Docs\\交易确认书\\客户空头交易确认书模板.docx"); - break; - } - } + //if (trade.StructureType == "普通债券类收益互换" || trade.StructureType == "普通收益互换") + //{ + // var swapPosition = Context.GetSwapPositions(trade.id, true).Where(x => x.PositionType > 0).FirstOrDefault(); + // if (swapPosition != null) + // { + // switch (swapPosition.PositionType) + // { + // case 1: + // templatePath = MosPathHelper.Combine(GlobalConfig.PluginFolder, "App_Docs\\交易确认书\\客户多头交易确认书模板.docx"); + // break; + // case 2: + // templatePath = MosPathHelper.Combine(GlobalConfig.PluginFolder, "App_Docs\\交易确认书\\客户空头交易确认书模板.docx"); + // break; + // } + // } + //} + //else + //{ + templatePath = MosPathHelper.Combine(GlobalConfig.PluginFolder, "App_Docs\\交易确认书\\浙商证券利率债收益互换合约交易确认书模版.docx"); + //} } else { @@ -78,87 +87,159 @@ namespace YLErp.Plugins.ShanXi.DocumentGenerator /// public void SetSwapData(Dictionary dic) { - SetSingleSwap(dic); + var trade = Context.Trade; + SetSingleSwap(dic); } private void SetSingleSwap(Dictionary dic) { var client = Context.GetClient(); - var trade = Context.Trade; var bank = Context.GetClientBankCard(false); var clientduties = Context.GetClientDuties(); - var swapPositions = Context.GetSwapPositions(trade.id, true); - var swapPosition = swapPositions.Where(x => x.PositionType == 1 || x.PositionType == 2).FirstOrDefault(); - var interestMargin = swapPositions.Where(x => ConsTrade.InterestModels.Contains(x.InterestMode)).FirstOrDefault(); - var initialMarginQuery = swapPositions.Where(x => x.InterestMode == 5); - var additionMarginQuery = swapPositions.Where(x => x.InterestMode == 6); - var underlyingCode = swapPosition?.UnderlyingCode; var table1 = new JArray(); var table2 = new JArray(); var clientMarginRate = Context.GetClientMarginRate(client.id); - - dic["交易编号"] = trade.TradeNumber; + dic["交易编号"] = GetContractNo(out string contractIndex); dic["交易对手方全称"] = client.ClientType != "产品" ? client.Name : $"{client.Manager}作为管理人代表{client.Name}"; dic["主协议编号"] = client.MainProtocolCode; dic["定义文件编号"] = client.SettleFileNumber; - FormatToDict("名义本金", trade.StockEqvNotionalReal, dic); - dic["成交日期"] = trade.TradeDate?.ToString("【yyyy】年【M】月【d】日"); - dic["开始日期"] = trade.StartDate?.ToString("【yyyy】年【M】月【d】日"); - dic["到期日期"] = trade.ExerciseDate?.ToString("【yyyy】年【M】月【d】日"); - dic["成交日期2"] = trade.TradeDate?.ToString("【yyyy】年【M】月【d】日"); - dic["户名"] = bank?.ClientName; - dic["银行账号"] = bank?.Card; - dic["开户行"] = bank?.Bank; - dic["大额行号"] = bank?.Payment; + var count = 0; - FormatToDict("期初标的交割全价", (double)((swapPosition?.PosiGrossPrice) ?? 0) * 100, dic); - FormatToDict("期初标的交割净价", (double)((swapPosition?.PosiNetNoFeePrice) ?? 0) * 100, dic); - - if (string.IsNullOrWhiteSpace(interestMargin?.FloatRateUnderlyingCode)) + var trades = Context.Trades; + var totalPosiQuantity = 0.0; + foreach (var trade in trades) { - dic["利率类型"] = "固定利率"; - dic["利差"] = ""; - dic["固定利率"] = ((interestMargin?.InterestRateDefault) ?? 0) * 100; - dic["参考利率"] = ""; + var swapPositions = Context.GetSwapPositions(trade.id, true); + var swapPosition = swapPositions.Where(x => x.PositionType == 1 || x.PositionType == 2).FirstOrDefault(); + var interestMargin = swapPositions.Where(x => ConsTrade.InterestModels.Contains(x.InterestMode)).FirstOrDefault(); + var initialMarginQuery = swapPositions.Where(x => x.InterestMode == 5); + var additionMarginQuery = swapPositions.Where(x => x.InterestMode == 6); + var underlyingCode = swapPosition?.UnderlyingCode; + + if (count == 0) + { + dic["名义本金".Insert("名义本金".Length, "2?")] = trade.StockEqvNotionalReal.ToString("0.##"); + dic["成交日期"] = trade.TradeDate?.ToString("yyyy年M月d日"); + dic["开始日期"] = trade.StartDate?.ToString("yyyy年M月d日"); + dic["到期日期"] = trade.ExerciseDate?.ToString("yyyy年M月d日"); + bool posiLong = swapPosition?.PositionType == (int)PositionTypeFlag.Short ? false : true; + var interestRate = interestMargin?.InterestRateDefault * 100 ?? 0; + var basicFee = trade.StockEqvNotionalReal == 0 ? 0 : ((double)((swapPosition?.PosiTradingFeePending) ?? 0) / trade.StockEqvNotionalReal) * 100; + dic["基本费率"] = (basicFee * 2).ToString("f4"); + dic["交易费用"] = (double)((swapPosition?.PosiTradingFeePending * 2) ?? 0); + dic["多头约定利率"] = "不适用"; + dic["空头约定利率"] = "不适用"; + if (posiLong) + { + dic["支付方"] = "乙方支付"; + dic["接收方"] = "甲方收取"; + } + else + { + dic["支付方"] = "甲方支付"; + dic["接收方"] = "乙方收取"; + } + if (string.IsNullOrEmpty(interestMargin?.FloatRateUnderlyingCode)) + { + dic["利率类型"] = "固定利率"; + dic["利差"] = ""; + dic["固定利率"] = ((interestMargin?.InterestRateDefault) ?? 0) * 100; + dic["参考利率"] = ""; + dic["重置频率"] = ""; + if (posiLong) + { + dic["多头约定利率"] = ((double)interestRate).ToString("0.####") + "%"; + } + else + { + dic["空头约定利率"] = ((double)interestRate).ToString("0.####") + "%"; + } + } + else + { + dic["利率类型"] = "浮动利率"; + dic["利差"] = ((interestMargin?.InterestRateDefault) ?? 0) * 10000; + dic["利差%"] = ((interestMargin?.InterestRateDefault) ?? 0) * 100; + dic["参考利率"] = interestMargin?.FloatRateUnderlyingCode; + dic["固定利率"] = ""; + dic["重置频率"] = interestMargin?.interest_rest_days; + } + dic["初始预付金支付日"] = interestMargin?.HappenDate == null ? "" : interestMargin?.HappenDate?.ToString("【yyyy】年【M】月【d】日"); + + dic["管理人名称"] = client.Manager; + var calculationBasis = interestMargin?.FloatRateUnderlyingCode; + if (!string.IsNullOrEmpty(calculationBasis)) + { + calculationBasis += interestRate > 0 ? " + " + ((double)interestRate).ToString("0.####") + "%" : ((double)interestRate).ToString("0.####") + "%"; + } + else + { + calculationBasis = ((double)interestRate).ToString("0.####") + "%"; + } + + dic["计算基准"] = calculationBasis; + dic["初始保障金率"] = ((clientMarginRate?.InitMarginRate ?? 0) * 100).ToString("0.####") + "%"; + dic["维持保障金率"] = ((clientMarginRate?.MaintenanceRate ?? 0) * 100).ToString("0.####") + "%"; + } + + var row = new JObject(); + row["序号"] = ++count; + FormatToDict("名义本金", trade.StockEqvNotionalReal, row); + row["成交日期"] = trade.TradeDate?.ToString("【yyyy】年【M】月【d】日"); + row["开始日期"] = trade.StartDate?.ToString("【yyyy】年【M】月【d】日"); + row["到期日期"] = trade.ExerciseDate?.ToString("【yyyy】年【M】月【d】日"); + row["成交日期2"] = trade.TradeDate?.ToString("【yyyy】年【M】月【d】日"); + row["户名"] = bank?.ClientName; + row["银行账号"] = bank?.Card; + row["开户行"] = bank?.Bank; + row["大额行号"] = bank?.Payment; + + FormatToDict("期初标的交割全价", (double)((swapPosition?.PosiGrossPrice) ?? 0) * 100, row); + FormatToDict("期初标的交割净价", (double)((swapPosition?.PosiNetNoFeePrice) ?? 0) * 100, row); + //row["利差"] = ((interestMargin?.InterestRateDefault) ?? 0) * 100; + //var basicFee = trade.StockEqvNotionalReal == 0 ? 0 : ((double)((swapPosition?.PosiTradingFeePending) ?? 0) / trade.StockEqvNotionalReal) * 100; + //row["基本费率"] = (basicFee * 2).ToString("f4"); + var initialMarginSum = initialMarginQuery.Sum(x => + x.InterestDirection == 2 ? x.InterestPrincipalFix * -1 : x.InterestPrincipalFix); + FormatToDict("交易费用", (double)((swapPosition?.PosiTradingFeePending * 2) ?? 0), row); + row["交易费率"] = row["基本费率"]; + FormatToDict("期初预付金", (double)initialMarginSum, row); + row["期初预付金利率"] = ((initialMarginQuery.FirstOrDefault()?.InterestRateDefault) ?? 0) * 100; + row["追加预付金返息率"] = ((clientMarginRate?.AddToMarginRebateRate) ?? 0) * 100; + if (!string.IsNullOrEmpty(underlyingCode)) + { + var um = Context.GetTradeUnderlying(underlyingCode); + row["标的代码"] = um.UnderlyingCode; + row["标的名称"] = um.UnderlyingName; + var bond = JsonHelper.Deserialize(um.ExJson) ?? + new UnderlyingBond(); + row["标的发行人"] = bond.UnderlyingIssuer; + decimal multiplier = um.IsBond() ? 100 : 1; + FormatToDict("期初价格", (double)((swapPosition?.PosiGrossPrice * multiplier) ?? 0), row); + } + else + { + row["标的名称"] = ""; + row["标的代码"] = ""; + row["期初价格"] = ""; + } + FormatToDict("数量", (double)((swapPosition?.PosiQuantity) ?? 0), row); + totalPosiQuantity += (double)((swapPosition?.PosiQuantity) ?? 0); + FormatToDict("合约乘数", (double)((swapPosition?.ContractSize) ?? 0), row); + row["方向"] = swapPosition?.PositionType switch + { + 1 => "买入", + 2 => "卖出", + _ => "" + }; + table1.Add(row); } - else - { - dic["利率类型"] = "浮动利率"; - dic["利差"] = ((interestMargin?.InterestRateDefault) ?? 0) * 10000; - dic["参考利率"] = interestMargin?.FloatRateUnderlyingCode; - dic["固定利率"] = ""; - } - if (initialMarginQuery.Any()) - { - dic["初始预付金支付日"] = initialMarginQuery.FirstOrDefault().HappenDate?.ToString("【yyyy】年【M】月【d】日"); - } - else - { - dic["初始预付金支付日"] = ""; - } - FormatToDict("标的期初全价", trade.StockEqvNotionalReal * (double)((swapPosition?.PosiGrossPrice) ?? 0), dic); - var basicFee = trade.StockEqvNotionalReal == 0 ? 0 : ((double)((swapPosition?.PosiTradingFeePending) ?? 0) / trade.StockEqvNotionalReal) * 100; - dic["基本费率"] = (basicFee * 2).ToString("f4"); - var initialMarginSum = initialMarginQuery.Sum(x => - x.InterestDirection == 2 ? x.InterestPrincipalFix * -1 : x.InterestPrincipalFix); - FormatToDict("交易费用", (double)((swapPosition?.PosiTradingFeePending * 2) ?? 0), dic); - dic["交易费率"] = dic["基本费率"]; - FormatToDict("期初预付金", (double)initialMarginSum, dic); - dic["期初预付金利率"] = ((initialMarginQuery.FirstOrDefault()?.InterestRateDefault) ?? 0) * 100; - dic["追加预付金返息率"] = ((clientMarginRate?.AddToMarginRebateRate) ?? 0) * 100; - dic["标的代码"] = underlyingCode; - dic["标的名称"] = Context.GetTradeUnderlying(underlyingCode).UnderlyingName; - - var bond = JsonHelper.Deserialize(Context.GetTradeUnderlying(underlyingCode).ExJson) ?? - new UnderlyingBond(); - dic["标的发行人"] = bond.UnderlyingIssuer; - - clientduties = clientduties.Where(x=> x.ContactTypeId.Contains("3")).OrderBy(o=>o.id).ToList();//交易下达人 - if (clientduties.Count>0) + clientduties = clientduties.Where(x => x.ContactTypeId.Contains("3")).OrderBy(o => o.id).ToList();//交易确认书邮件接收人 + if (clientduties.Count > 0) { - var clientduty= clientduties.First(); + var clientduty = clientduties.First(); var row = new JObject(); row["姓名"] = clientduty.ContactName; row["身份证号"] = clientduty.IdCardNo; @@ -168,9 +249,9 @@ namespace YLErp.Plugins.ShanXi.DocumentGenerator table2.Add(row); } + dic["table1"] = table1; dic["table2"] = table2; } - } } \ No newline at end of file diff --git a/Plugins/YLErp.Plugins.ZheShang/YLErp.Plugins.ZheShang.csproj b/Plugins/YLErp.Plugins.ZheShang/YLErp.Plugins.ZheShang.csproj index e2125f46..5c668224 100644 --- a/Plugins/YLErp.Plugins.ZheShang/YLErp.Plugins.ZheShang.csproj +++ b/Plugins/YLErp.Plugins.ZheShang/YLErp.Plugins.ZheShang.csproj @@ -18,6 +18,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/YLErpDAL/Model/SwapTradeSendEmailReq.cs b/YLErpDAL/Model/SwapTradeSendEmailReq.cs index 8879f232..4d41f06c 100644 --- a/YLErpDAL/Model/SwapTradeSendEmailReq.cs +++ b/YLErpDAL/Model/SwapTradeSendEmailReq.cs @@ -8,9 +8,14 @@ namespace YLErp.Model { public class SwapTradeSendEmailReq { - public SwapTradeSendEmailReq() { - tradeIds = new List(); + //public SwapTradeSendEmailReq() { + // tradeIds = new List(); + //} + //public List tradeIds; + public SwapTradeSendEmailReq() + { + contractCodes = new List(); } - public List tradeIds; + public List contractCodes; } } diff --git a/YLErpDAL/Model/SwapTradeSendEmailResp.cs b/YLErpDAL/Model/SwapTradeSendEmailResp.cs index 26542925..b74aa4d5 100644 --- a/YLErpDAL/Model/SwapTradeSendEmailResp.cs +++ b/YLErpDAL/Model/SwapTradeSendEmailResp.cs @@ -8,7 +8,7 @@ namespace YLErp.Model { public class SwapTradeSendEmailResp { - public int tradeId { get; set; } + public string contractCode { get; set; } public string send_email_result { get; set; } } } diff --git a/YLErpDAL/Models/DownloadDocReq.cs b/YLErpDAL/Models/DownloadDocReq.cs index 6097b957..574b843a 100644 --- a/YLErpDAL/Models/DownloadDocReq.cs +++ b/YLErpDAL/Models/DownloadDocReq.cs @@ -26,6 +26,8 @@ /// 确认书编号 /// public string ContractCode { get; set; } + + public List ContractCodes { get; set; } = null; /// /// 交易资金Id /// diff --git a/YLErpDAL/Modules/SwapModule/SwapEndConfirmService.cs b/YLErpDAL/Modules/SwapModule/SwapEndConfirmService.cs index 151cf8da..11c1e0d3 100644 --- a/YLErpDAL/Modules/SwapModule/SwapEndConfirmService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapEndConfirmService.cs @@ -169,36 +169,46 @@ namespace YLErp.Modules.SwapModule /// /// /// - public string SendConfirmEamil(int tradeId) + public string SendConfirmEamil(string contractCode) { - var tradeContract = DbContext.trade_contract_r.Where(x => x.IsValid && x.TradeId == tradeId && x.Type == ContractTypeEnum.Trade).FirstOrDefault(); - if (tradeContract == null) + //var tradeContract = DbContext.trade_contract_r.Where(x => x.IsValid && x.TradeId == tradeId && x.Type == ContractTypeEnum.Trade).FirstOrDefault(); + //if (tradeContract == null) + //{ + // return ""; + //} + var contracts = DbContext.trade_contract_r.Where(o => o.ContractCode == contractCode && o.Type == ContractTypeEnum.Trade && o.IsValid).ToArray(); + foreach (var tradeContract in contracts) { - return ""; + tradeContract.send_email_result = "发送中"; + DbContext.SaveChanges(); } - tradeContract.send_email_result = "发送中"; + + var sendResult = SendEmail(contractCode); + foreach (var tradeContract in contracts) + { + if (string.IsNullOrEmpty(sendResult)) + { + tradeContract.send_email_result = "已发送"; + } + else + { + tradeContract.send_email_result = "发送失败:" + sendResult; + } + } + DbContext.SaveChanges(); - var sendResult = SendEmail(tradeId); - if (string.IsNullOrEmpty(sendResult)) - { - tradeContract.send_email_result = "已发送"; - } - else - { - tradeContract.send_email_result = "发送失败:" + sendResult; - } - DbContext.SaveChanges(); - return tradeContract.send_email_result; + return string.IsNullOrEmpty(sendResult) ? "已发送" : "发送失败:" + sendResult; } /// /// 发送邮件 /// /// - private string SendEmail(int tradeId) + private string SendEmail(string contractCode) { var baseUrl = Environment.GetEnvironmentVariable("BondOmsInterface_BaseUrl"); - var sendEmailPUrl = "/swap/email/confirm/send?tradeId=" + tradeId; + //换成contractCode + var sendEmailPUrl = "/swap/email/confirm/send?contractCode=" + contractCode; if (!string.IsNullOrEmpty(baseUrl)) { var httpHelper = new HttpHelper(baseUrl, null); @@ -209,7 +219,7 @@ namespace YLErp.Modules.SwapModule } else { - LogFactory.GetLogger().Error("发送邮件失败:tradeId=" + tradeId, new Exception(result?.message)); + LogFactory.GetLogger().Error("发送邮件失败:contractCode=" + contractCode, new Exception(result?.message)); return result?.message ?? "发送邮件失败"; } } diff --git a/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs b/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs index b9c4add8..64e5e57a 100644 --- a/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs +++ b/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs @@ -1,8 +1,10 @@ using BaseOUDAL; using System.Collections.Concurrent; +using System.Drawing.Printing; using YLErp.Configuration; using YLErp.DBModels.Consts; using YLErp.Model; +using YLErp.Model.Enum; using YLErp.Models; using YLErp.Modules.TradeDalModule; using YLErp.Modules.TradeModule.DocGenerateModule; @@ -207,187 +209,34 @@ namespace YLErp.Modules.TradeModule.DealModule List results = new List(); List error = new List(); List file = new List(); - if (PS.Config.Is国泰君安 || PS.Config.Is厦门象屿) - { - var Tradelist = new TradeDalService(this).GetTradeOrEodTradeOfTidAPid(tradeIds, SystemValueDate, false, false); - using (var basedb = new ErpBaseContext()) - { - if (Tradelist.Any(O => O.IsGroup > 0)) - { - int count = Tradelist.Where(O => O.IsGroup != 2).GroupBy(O => O.IsGroup).Count(); - if (count > 1) - { - throw new ServiceException("不应勾选多个非黑盒标的的交易"); - } - var list = Tradelist.Where(x => x.TradeType == "结构化交易"); - var group = list.GroupBy(O => new { O.ClientId, O.StructureType }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); - foreach (var item in group) - { - if (item.Key.StructureType == "折价") - { - var list2 = list.Where(x => item.Value.Contains(x.id) && x.TradeType == "结构化交易").ToList(); - list2.ForEach(x => - { - var options = x.Propertys?.Where(o => o.name == "看涨看跌").ToList(); - if (options != null && options.Any()) - { - x.ExtendOptionTypeInfo = JsonHelper.Serialize(options); - } - else - { - throw new ServiceException("看涨看跌不能为空:" + x.TradeNumber); - } - }); - var group2 = list2.GroupBy(O => O.ExtendOptionTypeInfo).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); - foreach (var item2 in group2) - { - groupGenerateHandle_Date(item2.Value, docType, startDate, endDate, results, error, file); - if (error.Any()) break; - } - } - else - { - groupGenerateHandle_Date(item.Value, docType, startDate, endDate, results, error, file); - if (error.Any()) break; - } - } - - var swapList = Tradelist.Where(x => x.TradeType == "收益互换" && x.ParentTradeId == 0); - foreach (var item in swapList) - { - groupGenerateHandle_Date(new List { item.id }, docType, startDate, endDate, results, error, file); - } - } - } - - if (results.Count == 0) - { - var structTradeQuery = new TradeDalService(this).GetTradeOrEodTradeOfTidASid(tradeIds, SystemValueDate).Where(c => c.TradeType != "结构化交易"); - List instrumentTypeArr = new List() { ConsGlobal.InstrumentType.Stock, ConsGlobal.InstrumentType.StockIndex, ConsGlobal.InstrumentType.StockIF }; - DataCacheProvider.GetUnderlyingDataSource().AsQueryable(); - if (structTradeQuery.Any(O => instrumentTypeArr.Contains(getUnderlyingInstrumentType(O.UnderlyingId)) || O.TradeType == "雪球期权")) - { - //暂时将所有子交易都作为判断依据,等拿到模板后再根据模板做调整更改; - //目前是否为权益类的判断条件只是是否是股票,没有考虑IC IF等品种; - int count = structTradeQuery.GroupBy(O => new { UnderlyingInstrumentType = (instrumentTypeArr.Contains(getUnderlyingInstrumentType(O.UnderlyingId)) || O.TradeType == "雪球期权") ? 1 : 0 }).Count(); - if (count > 1) - { - throw new ServiceException("不应勾选多个非股票(含股指期货)标的的交易"); - } - var group = structTradeQuery.GroupBy(O => new { O.ClientId, O.TradeType }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); - - foreach (var item in group) - { - if (item.Key.TradeType == "雪球期权") - { - if (structTradeQuery.Any(O => !instrumentTypeArr.Contains(getUnderlyingInstrumentType(O.UnderlyingId)))) - { - var group2 = DbContext.trade.Where(c => item.Value.Contains(c.id)).AsEnumerable().GroupBy(m => m.OptionType).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); - foreach (var item2 in group2) - { - groupGenerateHandle_Date(item2.Value, docType, startDate, endDate, results, error, file); - if (error.Any()) break; - } - } - else - { - var group2 = DbContext.trade_snowball.Where(c => item.Value.Contains(c.TradeId)).AsEnumerable().GroupBy(m => m.IsFixedCoupon).ToDictionary(K => K.Key, V => V.Select(O => O.TradeId).ToList()); - foreach (var item2 in group2) - { - if (item2.Key) - { - groupGenerateHandle_Date(item2.Value, docType, startDate, endDate, results, error, file); - if (error.Any()) break; - } - else - { - var group3 = DbContext.trade.Where(c => item2.Value.Contains(c.id)).AsEnumerable().GroupBy(m => m.OptionType).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); - foreach (var item3 in group3) - { - groupGenerateHandle_Date(item3.Value, docType, startDate, endDate, results, error, file); - if (error.Any()) break; - } - } - } - } - } - else - { - groupGenerateHandle_Date(item.Value, docType, startDate, endDate, results, error, file); - if (error.Any()) break; - } - } - } - } - } - else if (PS.Config.Is润和) + if (PS.Config.Company == CompanyEnum.浙商) { var TradeQuery = new TradeDalService(this).GetTradeOrEodTradeOfTidASid(tradeIds, SystemValueDate).Where(c => (c.TradeType != "结构化交易" || c.IsGroup == 1) && tradeIds.Contains(c.id)); if (TradeQuery.Any()) { - var group = TradeQuery.GroupBy(O => new { O.ClientId, O.TradeDate }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); - foreach (var item in group) + var Ids = TradeQuery.Select(o => o.id).Distinct().ToArray(); + var swapPositions = DbContext.swap_position.Where(s => Ids.Contains(s.SwapTradeId) && s.IsInitial && s.PositionType > 0 && !s.Invalid) + .Distinct().ToList(); + foreach (var item in TradeQuery) { - var group2 = DbContext.trade.Where(c => item.Value.Contains(c.id) && c.TradeType == "远期").Select(O => O.id).ToList(); - if (group2.Any()) - { - groupGenerateHandle(group2, docType, startDate, endDate, results, error, file); - if (error.Any()) break; - } - var group4 = DbContext.trade.Where(c => item.Value.Contains(c.id) && c.TradeType == "亚式期权").Select(O => O.id).ToList(); - if (group4.Any()) - { - groupGenerateHandle(group4, docType, startDate, endDate, results, error, file); - if (error.Any()) break; - } - var group3 = DbContext.trade.Where(c => item.Value.Contains(c.id) && c.TradeType != "远期" && c.TradeType != "亚式期权").Select(O => O.id).ToList(); - if (group3.Any()) - { - groupGenerateHandle(group3, docType, startDate, endDate, results, error, file); - if (error.Any()) break; - } + item.swap_positions.Add(swapPositions.FirstOrDefault(o => o.SwapTradeId == item.id)); } - } - } - else if (PS.Config.Is东吴) - { - var TradeQuery = new TradeDalService(this).GetTradeOrEodTradeOfTidASid(tradeIds, SystemValueDate).Where(c => (c.TradeType != "结构化交易" || c.IsGroup == 1) && tradeIds.Contains(c.id)); - if (TradeQuery.Any()) - { - var group = TradeQuery.GroupBy(O => new { O.ClientId, O.TradeDate }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); + // 按照客户ID、交易日期、多空头进行分组 + var group = TradeQuery.GroupBy(O => new { O.ClientId, O.TradeDate, O.swap_positions.FirstOrDefault().PositionType}) + .ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); + foreach (var item in group) { - var query = from t in DbContext.trade - join tc in DbContext.trade_cash on t.id equals tc.TradeId - where t.ClientId == item.Key.ClientId && - tc.ValueDate == item.Key.TradeDate && !tc.IsDeleted && tc.Action == ClientCashInCashOut.系统操作_期权费 - select new { t.id }; - if (query.Any()) - { - groupGenerateHandle(query.Select(l => l.id).ToList(), docType, startDate, endDate, results, error, file); - } - } - } - } - else if(PS.Config.Is物产中大) - { - var TradeQuery = new TradeDalService(this).GetTradeOrEodTradeOfTidASid(tradeIds, SystemValueDate).Where(c => (c.TradeType != "结构化交易" || c.IsGroup == 1) && tradeIds.Contains(c.id)); - if (TradeQuery.Any()) - { - var group = TradeQuery.GroupBy(O => new { O.ClientId, O.TradeDate,O.TradeType }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); - foreach (var item in group) - { - if (item.Value.Count > 10) - { - throw new ServiceException("同客户同日期同类型交易生成超过限制!"); - } + // 如果是结构化交易或特殊交易类型需要额外处理,这里简化处理 var query = from t in DbContext.trade join tc in DbContext.trade_cash on t.id equals tc.TradeId where item.Value.Contains(tc.TradeId) && !tc.IsDeleted select new { t.id }; + if (query.Any()) { - groupGenerateHandle(query.Select(l => l.id).ToList(), docType, startDate, endDate, results, error, file); + // 使用现有的 groupGenerateHandle 方法来处理每组交易 + groupGenerateHandle(query.Select(l => l.id).Distinct().ToList(), docType, startDate, endDate, results, error, file); } } } @@ -681,6 +530,97 @@ namespace YLErp.Modules.TradeModule.DealModule return query.ToArray(); } + + public SearchListResult GetConfirmBookListByClient(ClientConfirmBookListReq req) + { + var result = new SearchListResult(); + var contractList = new List(); + // Fix for the issue: CS1525, CS0746, CS1003 + // The problem lies in the incorrect syntax for defining an anonymous type. + // Anonymous type members must be declared using member assignment or simple names. + + var query = from t in DbContext.trade.AsNoTracking().Where(x => x.TradeType == "收益互换" && x.ValidState != "InValid") + join tcrs in DbContext.trade_contract_r + on t.id equals tcrs.TradeId into tcrsGroup + from tcr in tcrsGroup.Where(r => r.IsValid && r.Type == ContractTypeEnum.Trade).DefaultIfEmpty() + join tcds in DbContext.trade_contract_document + on tcr.ContractCode equals tcds.Code into tcdsGroup + from tcd in tcdsGroup.DefaultIfEmpty() + join sp in DbContext.swap_position.AsNoTracking().Where(s => s.IsInitial && s.PositionType > 0 && !s.Invalid) + on t.id equals sp.SwapTradeId + select new + { + t.id, + t.TradeDate, + tcr.ContractCode, + t.ClientId, + t.ClientNumber, + t.ClientName, + tcr.send_email_result, + tcd.Status, + tcd.RelativePath, + tcd.SealResult, + ContractId = tcr != null ? tcr.id : 0, + sp.PositionType, + t.SentMailCount + }; + + if (req.StartDate != null && req.StartDate != DateTime.MinValue) + { + query = query.Where(o => o.TradeDate >= req.StartDate); + } + + if (req.EndDate != null && req.EndDate != DateTime.MaxValue) + { + query = query.Where(o => o.TradeDate <= req.EndDate); + } + + if (req.ClientIds != null && req.ClientIds.Count > 0) + { + query = query.Where(o => req.ClientIds.Contains(o.ClientId)); + } + + if (!string.IsNullOrEmpty(req.ContractCode)) + { + query = query.Where(o => o.ContractCode.Contains(req.ContractCode)); + } + + if (req.PositionTypes!= null && req.PositionTypes.Count() > 0) + { + query = query.Where(o => req.PositionTypes.Contains(o.PositionType)); + } + + var contractGroups = query.AsEnumerable() + .GroupBy(x => new { x.TradeDate, x.ClientId, x.PositionType }) + .Select(group => group.ToList()) + .ToList(); + + // 构建返回结果 + foreach (var group in contractGroups) + { + var sealResult = group.FirstOrDefault().SealResult; + contractList.Add(new clientContractR + { + id = group.FirstOrDefault().id, + ContractCode = group.FirstOrDefault().ContractCode, + TradeDate = group.FirstOrDefault().TradeDate.Value, + ClientNumber = group.FirstOrDefault().ClientNumber, + ClientName = group.FirstOrDefault().ClientName, + StampStatus = group.FirstOrDefault().Status, + EmailResult = group.FirstOrDefault().send_email_result, + ContractDocUrl = group.FirstOrDefault().RelativePath, + tradeIds = group.Select(x => x.id).Distinct().ToList(), + SealResult = sealResult != null ? Enum.GetName(typeof(SealResultEnum), sealResult) : "", + HasGeneratedConfirmBook = group.FirstOrDefault().ContractId != 0, + ContractId = group.FirstOrDefault().ContractId, + tradeCount = group.Select(x => x.id).Distinct().Count(), + PositionType = group.FirstOrDefault().PositionType, + SentMailCount = group.FirstOrDefault().SentMailCount ?? 0, + }); + } + result = contractList.AsQueryable().ToSearchList(req); + return result; + } } /// @@ -696,4 +636,58 @@ namespace YLErp.Modules.TradeModule.DealModule public Exception Exception; } + + public class ClientConfirmBookListReq : BaseSearchReq + { + //合约编号 + public string ContractCode { get; set; } + + //开仓起始时间 + public DateTime? StartDate { get; set; } + + //开仓结束时间 + public DateTime? EndDate { get; set; } + + //客户 + public List? ClientIds { get; set; } + + public List? PositionTypes { get; set; } + + } + + public class clientContractR + { + public int id { get; set; } + public string ContractCode { get; set; } + + public DateTime TradeDate { get; set; } + + public string ClientNumber { get; set; } + + public string ClientName { get; set; } + + public string StampStatus { get; set; } + + public string EmailResult { get; set; } + + public List tradeIds { get; set;} + + public string ContractDocUrl { get; set; } + + public string SealResult { get; set; } + + + public string ContractEncryptId { get; set; } + + public bool HasGeneratedConfirmBook { get; set; } + + public int ContractId { get; set; } + + public int PositionType { get; set; } + + public int tradeCount { get; set; } + + public int SentMailCount { get; set; } + + } } diff --git a/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateContext.cs b/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateContext.cs index e166578f..acc3b1cc 100644 --- a/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateContext.cs +++ b/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateContext.cs @@ -21,6 +21,7 @@ using YLErp.Configuration; using YLErp.DBModels; using YLErp.DBModels.Abstract; using YLErp.DBModels.Consts; +using YLErp.DBModels.Enums; using YLErp.Helpers; using YLErp.Model; using YLErp.Models; @@ -1323,6 +1324,13 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule { return UniqueTimeId.GetStr(); } + if (Trade.TradeType == "收益互换") + { + var posi = GetSwapPositions(Trade.id, true).FirstOrDefault(); + var isLong = posi?.PositionType == (int)PositionTypeFlag.Short ? false : true; + + return "ZSZQ-" + _client.Number + "-" + Trade.TradeDate?.ToString("yyyyMMdd") + (isLong ? "-L" : "-S"); + } return Trade.TradeNumber; } /// diff --git a/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateService.cs b/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateService.cs index 6f5e1b10..21b88550 100644 --- a/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateService.cs +++ b/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateService.cs @@ -162,38 +162,48 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule var tradeContractGroupTradeIds = tradeDic.Values.Select(x => x.trade.id).ToList(); //var childs = DbContext.trade.Where(x => tradeContractGroupTradeIds.Contains(x.ParentTradeId ?? 0)); var childs = service.GetStructTradeFromTradeOrEodTrade(tradeContractGroupTradeIds, SystemValueDate, true); - foreach (var tradeContractGroup in tradeDic.Values) + if (PS.Config.Company == Configuration.CompanyEnum.浙商) { - if ((tradeContractGroup.trade.TradeType != "结构化交易" && tradeContractGroup.trade.TradeType != "收益互换" && tradeContractGroup.trade_cash == null) - || (tradeContractGroup.trade.TradeType == "结构化交易" && tradeContractGroup.trade.IsGroup == 0 && tradeContractGroup.trade.SubTrades.Any(O => O.trade_cash == null))) + if (generatorV2 != null) { - resultList.Add(new TradeDocGenerateResult(tradeContractGroup.trade) - { - ErrorMessage = "缺少现金交割记录" - }); - } - //插件版本 - else if (generatorV2 != null) - { - var result = GenerateSingleV2(generatorV2, tradeContractGroup, docType); + var result = GenerateSingleV2(generatorV2, null, docType , allTradeList); resultList.Add(result); } - else - { - var result = GenerateSingleV1(tradeContractGroup, docType); - resultList.Add(result); - //if (!string.IsNullOrWhiteSpace(result.OutputFilePath)) - //{ - // tradeContractGroup.trade.HasGeneratedConfirmBook = 1; - // var childTds = childs.Where(x => x.ParentTradeId == tradeContractGroup.trade.id); - // foreach (var child in childTds) - // { - // child.HasGeneratedConfirmBook = 1; - // } - //} - } } - + else + { + foreach (var tradeContractGroup in tradeDic.Values) + { + if ((tradeContractGroup.trade.TradeType != "结构化交易" && tradeContractGroup.trade.TradeType != "收益互换" && tradeContractGroup.trade_cash == null) + || (tradeContractGroup.trade.TradeType == "结构化交易" && tradeContractGroup.trade.IsGroup == 0 && tradeContractGroup.trade.SubTrades.Any(O => O.trade_cash == null))) + { + resultList.Add(new TradeDocGenerateResult(tradeContractGroup.trade) + { + ErrorMessage = "缺少现金交割记录" + }); + } + //插件版本 + else if (generatorV2 != null) + { + var result = GenerateSingleV2(generatorV2, tradeContractGroup, docType); + resultList.Add(result); + } + else + { + var result = GenerateSingleV1(tradeContractGroup, docType); + resultList.Add(result); + //if (!string.IsNullOrWhiteSpace(result.OutputFilePath)) + //{ + // tradeContractGroup.trade.HasGeneratedConfirmBook = 1; + // var childTds = childs.Where(x => x.ParentTradeId == tradeContractGroup.trade.id); + // foreach (var child in childTds) + // { + // child.HasGeneratedConfirmBook = 1; + // } + //} + } + } + } if (generatorV2 == null) { DbContext.SaveChanges(); @@ -205,14 +215,21 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule /// /// /// - private TradeDocGenerateResult GenerateSingleV2(ITradeConfirmationGenerator generator, trade_contract_group tradeContractGroup, string docType = "DOCX") + private TradeDocGenerateResult GenerateSingleV2(ITradeConfirmationGenerator generator, trade_contract_group tradeContractGroup, string docType = "DOCX", List allTrades = null) { try { //修改调用的构造方法 - List trades = new List() { tradeContractGroup.trade }; + List trades = new List(); + if (allTrades != null && allTrades.Count() > 0) + { + trades = allTrades; + }else + { + trades = new List() { tradeContractGroup.trade }; + } List ids = new List(); - if (tradeContractGroup.trade != null && tradeContractGroup.trade.trade_cash != null) + if (tradeContractGroup != null && tradeContractGroup.trade != null && tradeContractGroup.trade.trade_cash != null) { ids.Add(tradeContractGroup.trade.trade_cash.id); } @@ -759,27 +776,26 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule } } - public (bool, string, DateTime, string) UploadContractFileNew(string encryptId, UploadFileModel uploadFileModel) + public (bool, string, DateTime, string) UploadContractFileNew(string contractCode, UploadFileModel uploadFileModel) { try { var msg = ""; #region 验证 - if (string.IsNullOrWhiteSpace(encryptId)) + if (string.IsNullOrWhiteSpace(contractCode)) { - return (false, "请传入id", DateTime.Now, ""); + return (false, "请传入参数", DateTime.Now, ""); } - - var intid = DataProtectHelper.DecryptInt(encryptId); + var db = DbContextFactory.GetYLDbContext(); - var contractDoc = db.trade_contract_document.Find(intid); + var contractDoc = db.trade_contract_document.FirstOrDefault(d => d.Code == contractCode ); var contractDocRArr = db.trade_contract_r.Where(O => O.ContractCode == contractDoc.Code && O.Type == contractDoc.Type && O.IsValid).ToArray(); - var contractDocR = contractDocRArr.FirstOrDefault(); - if (contractDoc == null || contractDocR == null) + var contractDocRF = contractDocRArr.FirstOrDefault(); + if (contractDoc == null || contractDocRF == null) { return (false, "没有相关的确认书文档", DateTime.Now, ""); } @@ -806,9 +822,9 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule #endregion var tradeNumber = "未知"; - if (contractDocR != null) + if (contractDocRF != null) { - tradeNumber = contractDocR.TradeNumber; + tradeNumber = contractDocRF.TradeNumber; } var filePath = Path.Combine(OtcAppContext.AppDocsPath, "contractdoc", "output"); @@ -841,8 +857,12 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule } #region 更新数据 + var confrimService = new TradeConfirmService(OptUser, db); + foreach (var contractDocR in contractDocRArr) + { + new TradeConfirmService(OptUser, db).EditReportStatus(contractDocR.TradeId, true); + } - new TradeConfirmService(OptUser, db).EditReportStatus(contractDocR.TradeId, true); db.SaveChanges(); #endregion diff --git a/YLErpWeb/App_Data/Menus.txt b/YLErpWeb/App_Data/Menus.txt index dce08627..aad3ddce 100644 --- a/YLErpWeb/App_Data/Menus.txt +++ b/YLErpWeb/App_Data/Menus.txt @@ -21,7 +21,7 @@ {Name:"成交簿记",Rights:["结算管理-成交簿记"],Url:"swaptrade2/SwapflowList"}, {Name:"资金记录",Rights:["结算管理-出入金维护"],Url:"entryexit/entryexitList"}, {Name:"收盘操作",Rights:["结算管理-收盘操作"],Url:"eod_trade_value/eodExec"}, - {Name:"交易确认书",Rights:["结算管理-交易确认书"],Url:"TradeConfirmBook/Index"}, + {Name:"交易确认书",Rights:["结算管理-交易确认书"],Url:"TradeConfirmBook/ConfirmBookListByClient"}, {Name:"结算确认书",Rights:["结算管理-结算确认书"],Url:"swaptrade2/tradeEndConfirmList"}, {Name:"每日估值报告",Rights:["结算管理-每日估值报告"],Url:"clientbalance/TradeMarketReport"}, ] diff --git a/YLErpWeb/Controllers/SwapTrade2Controller.cs b/YLErpWeb/Controllers/SwapTrade2Controller.cs index 0fbe5358..ce01c9a2 100644 --- a/YLErpWeb/Controllers/SwapTrade2Controller.cs +++ b/YLErpWeb/Controllers/SwapTrade2Controller.cs @@ -1033,10 +1033,10 @@ namespace YLErp.Web.Controllers /// /// /// - public JsonResult SendConfimEmail(int tradeId) + public JsonResult SendConfimEmail(string contractCode) { SwapEndConfirmService service = new SwapEndConfirmService(CurUser); - var result = service.SendConfirmEamil(tradeId); + var result = service.SendConfirmEamil(contractCode); return JsonSuccess(result); } } diff --git a/YLErpWeb/Controllers/TradeConfirmBookController.cs b/YLErpWeb/Controllers/TradeConfirmBookController.cs index c615c8e7..4be41d79 100644 --- a/YLErpWeb/Controllers/TradeConfirmBookController.cs +++ b/YLErpWeb/Controllers/TradeConfirmBookController.cs @@ -6,6 +6,7 @@ using YLErp.CustomizedBizLogic; using YLErp.DBModels.Consts; using YLErp.Enums; using YLErp.Model; +using YLErp.Model.Enum; using YLErp.Modules.AppModule; using YLErp.Modules.ClientModule; using YLErp.Modules.ReportModule; @@ -75,6 +76,17 @@ namespace YLErp.Web.Controllers return JsonError("申万定制功能,当前已不支持"); } + public ActionResult ConfirmBookListByClient() + { + return View(); + } + + public JsonResult clientConfirmQuery(ClientConfirmBookListReq req) + { + var result = new TradeContractGenerateService(CurUser).GetConfirmBookListByClient(req); + return Json(result); + } + public async Task SentMail(string enid, List reciver) { var result = await DoSendMailSywg(enid, reciver); diff --git a/YLErpWeb/Controllers/tradeController.cs b/YLErpWeb/Controllers/tradeController.cs index bcbab546..f68cfb89 100644 --- a/YLErpWeb/Controllers/tradeController.cs +++ b/YLErpWeb/Controllers/tradeController.cs @@ -2031,10 +2031,10 @@ namespace YLErp.Web.Controllers } return JsonError(msg); } - public ActionResult UploadContractFileNew(string encryptId) + public ActionResult UploadContractFileNew(string contractCode) { var uploadFileModel = Request.Form.Files.Count > 0 ? Request.Form.Files[0].ToUploadFileModel() : null; - var (flag, msg, optDate, stampPath) = new ConfirmationGenerateService(CurUser).UploadContractFileNew(encryptId, uploadFileModel); + var (flag, msg, optDate, stampPath) = new ConfirmationGenerateService(CurUser).UploadContractFileNew(contractCode, uploadFileModel); if (flag) { @@ -6325,6 +6325,11 @@ namespace YLErp.Web.Controllers isSelect = true; query = query.Where(O => req.TradeCashIds.Contains(O.TradeCashId)); } + if (req.ContractCodes != null && req.ContractCodes.Any(O => !string.IsNullOrWhiteSpace(O))) + { + isSelect = true; + query = query.Where(O => req.ContractCodes.Contains(O.ContractCode)); + } if (req.DocType != null) { query = query.Where(O => O.Type == req.DocType); @@ -6353,13 +6358,15 @@ namespace YLErp.Web.Controllers } } - var datas = query.ToList(); + var datas = query.ToList(); if (datas.Count == 0) { return ShowError("未找到确认书文件,请确认筛选条件是否有效!"); } + datas = datas.DistinctBy(O => O.ContractCode).ToList(); + var filePathList = new List(datas.Count * req.docpdf.Count()); var contractBLL = new TradeContractBLL(CurUser); diff --git a/YLErpWeb/Hubs/SwapConfirmSendEmailHub.cs b/YLErpWeb/Hubs/SwapConfirmSendEmailHub.cs index 82f02bcd..90d4c3d5 100644 --- a/YLErpWeb/Hubs/SwapConfirmSendEmailHub.cs +++ b/YLErpWeb/Hubs/SwapConfirmSendEmailHub.cs @@ -12,7 +12,7 @@ namespace YLErp.Web.Hubs { private static bool isProcessing = false; static readonly Dictionary _dic = new Dictionary(StringComparer.OrdinalIgnoreCase); - static readonly Dictionary _clientProgressDic = new Dictionary(); + static readonly Dictionary _clientProgressDic = new Dictionary(); public async Task StartProcessing(string jsonString) { SwapTradeSendEmailReq req = JsonHelper.Deserialize(jsonString); @@ -33,11 +33,11 @@ namespace YLErp.Web.Hubs if (isProcessing) { await client.SendAsync("ExceptionMessage", "正在发送邮件,请稍后再试"); - foreach (var tradeId in req.tradeIds) { - var msg= GetProcess(tradeId,async (d) => { - await client.SendAsync("UpdateProgress", getUpdateProcess(tradeId, d)); + foreach (var contractCode in req.contractCodes) { + var msg= GetProcess(contractCode, async (d) => { + await client.SendAsync("UpdateProgress", getUpdateProcess(contractCode, d)); }); - await client.SendAsync("UpdateProgress", getUpdateProcess(tradeId, msg)); + await client.SendAsync("UpdateProgress", getUpdateProcess(contractCode, msg)); } await client.SendAsync("ProcessCompleted", ""); return; @@ -47,10 +47,11 @@ namespace YLErp.Web.Hubs isProcessing = true; _clientProgressDic.Clear(); _dic.Clear(); - foreach (var tradeId in req.tradeIds) + //根据tradeIds 获取contractCode + foreach (var contractCode in req.contractCodes) { - _clientProgressDic[tradeId] = "发送中"; - await client.SendAsync("UpdateProgress", getUpdateProcess(tradeId, "发送中")); + _clientProgressDic[contractCode] = "发送中"; + await client.SendAsync("UpdateProgress", getUpdateProcess(contractCode, "发送中")); if (PS.Config.ErpElement.MailMessageRateLimit > 0) { var milliSeconds = 60d * 1000 / PS.Config.ErpElement.MailMessageRateLimit; @@ -67,9 +68,9 @@ namespace YLErp.Web.Hubs _dic["sendEmail"] = DateTime.Now; } } - var result = service.SendConfirmEamil(tradeId); - _clientProgressDic[tradeId] = result; - await client.SendAsync("UpdateProgress", getUpdateProcess(tradeId, result)); + var result = service.SendConfirmEamil(contractCode); + _clientProgressDic[contractCode] = result; + await client.SendAsync("UpdateProgress", getUpdateProcess(contractCode, result)); } isProcessing = false; await client.SendAsync("ProcessCompleted", ""); @@ -80,26 +81,27 @@ namespace YLErp.Web.Hubs await client.SendAsync("ExceptionMessage", ex.Message); } } - private string GetProcess(int tradeId,Action action) + private string GetProcess(string contractCode, Action action) { - if (_clientProgressDic.ContainsKey(tradeId)) + if (_clientProgressDic.ContainsKey(contractCode)) { - string process= _clientProgressDic[tradeId]; + string process= _clientProgressDic[contractCode]; if (action != null&& process=="发送中") { action.Invoke(process); Thread.Sleep(1000); - return GetProcess(tradeId, action); + return GetProcess(contractCode, action); } return process; } return ""; } - private string getUpdateProcess(int tradeId,string msg) + + private string getUpdateProcess(string contractCode, string msg) { SwapTradeSendEmailResp resp = new SwapTradeSendEmailResp() { - tradeId = tradeId, + contractCode = contractCode, send_email_result = msg }; return JsonHelper.Serialize(resp); diff --git a/YLErpWeb/Views/TradeConfirmBook/ConfirmBookListByClient.cshtml b/YLErpWeb/Views/TradeConfirmBook/ConfirmBookListByClient.cshtml new file mode 100644 index 00000000..81f31b91 --- /dev/null +++ b/YLErpWeb/Views/TradeConfirmBook/ConfirmBookListByClient.cshtml @@ -0,0 +1,84 @@ +@{ + ViewBag.Title = "交易确认书"; // 设置页面标题 + Layout = "~/Views/Shared/_MainLayout.cshtml"; // 指定布局页面 + + // 定义页面JS对象,用于传递后端数据到前端JS + var pageObj = new + { + // 获取客户确认书列表数据的URL + clientConfirmQueryUrl = Url.Action("clientConfirmQuery", "TradeConfirmBook"), + // 获取所有客户数据的URL (假设存在一个获取客户列表的方法) + getAllClientsUrl = Url.Action("GetAllClient", "ClientData"), // 请确保ClientDataController中有GetAllClient方法或使用正确的获取客户数据方法 + ConfirmBookStampStatus = PS.Config.ErpElement.ConfirmBookStampStatus, + valuedate = valuedateBLL.ValueDate.ToString("yyyy-MM-dd"), + SettleDocModeMultiple = valuedate.SettleDocModeMultiple.Equals(valuedateBLL.SystemDate.SettleDocMode), + BrokerMode = YLErp.PS.Config.ComponentVersion == YLErp.Configuration.ComponentVersion.Broker, + MarketMaker = YLErp.PS.Config.ComponentVersion == YLErp.Configuration.ComponentVersion.MarketMaker, + reqTradeStatus = $"{ConsTrade.确认成交},{ConsTrade.已到期},{ConsTrade.已平仓},{ConsTrade.已执行}", + SelectConfirmationBookTemplate = GlobalConfig.SelectConfirmationBookTemplate == true, + templateNames = ViewBag.TemplateNames, + IsAutoSealAndUploadFiles = YLErp.PS.GetErpConfig().IsAutoSealAndUploadFiles, + IsZheQi = PS.Config.Is浙期, + IsAutoSealAfterGeneratedBook = PS.GetErpConfig().IsAutoSealAfterGeneratedBook, + canGenerate = CurUser.结算管理_交易确认书生成, + canSendEmail = CurUser.结算管理_交易确认书邮件发送 + }; +} + +@section CSS{ + +} + +@section JS{ + @* 引入必要的JS库 *@ + + + + @* 引入此页面对应的JS逻辑文件 *@ + +} + +@* 搜索区域 *@ +
+ @* 合约编号输入框 *@ + @Html.ShortInput("ContractCode", "合约编号") + @* 客户名称下拉框 (使用MyAceDropdownInput,假设ClientDataModel.GetAllClient()能获取所需数据格式) *@ + @Html.MyAceDropdownInput("ClientIds", "客户名称", ClientDataModel.GetAllClient(), true) @* true表示允许多选 *@ + @* 开仓日期范围选择 *@ + @Html.SearchDateRange("OpenDate", "开仓日期") + @* 多空头方向选择 *@ + @Html.MyAceDropdownInput("MultiHead", "多空头方向", new List + { + new SelectListItem { Text = "多头", Value = "1" }, + new SelectListItem { Text = "空头", Value = "2" }, + }) + + @MyControls.SearchBtn() + @if (pageObj.canGenerate) + { + @MyControls.Btn("批量生成交易确认书", "BatchCreateContracts()") + } + @MyControls.Btn("批量下载交易确认书", "BatchDownLoadDoc()") + + @if (PS.GetErpConfig().IsAutoSealAndUploadFiles && !PS.GetErpConfig().IsAutoSealAfterGeneratedBook) + { + @MyControls.Btn("批量确认书用印", "BatchSealContracts()") + } + +
+ +
+
+ +@Html.Raw(JqGridSimple.OutTable()) + +@* 可能需要的其他HTML元素,例如下载链接的占位符 *@ + diff --git a/YLErpWeb/Views/TradeConfirmBook/confirmBookUploadNew.cshtml b/YLErpWeb/Views/TradeConfirmBook/confirmBookUploadNew.cshtml index 15263f16..df9d2a90 100644 --- a/YLErpWeb/Views/TradeConfirmBook/confirmBookUploadNew.cshtml +++ b/YLErpWeb/Views/TradeConfirmBook/confirmBookUploadNew.cshtml @@ -41,7 +41,7 @@ for (var x = 0; x < files.length; x++) { data.append(files[x].name, files[x]); } - data.append("encryptId", encryptId); + data.append("contractCode", encryptId); $.ajax({ type: "Post", diff --git a/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBookListByClient.js b/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBookListByClient.js new file mode 100644 index 00000000..8fb443dd --- /dev/null +++ b/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBookListByClient.js @@ -0,0 +1,552 @@ +// tradeConfirmBookListByClient.js +const colModelGrid = (new function () { + // 定义列模型 + this.colModels = [ + { + name: '', + label: '操作', + width: 450, + align: 'left', + formatter: showToolName + }, { + name: 'ClientId', + hidden: true, + optionHide: true + }, + { + name:"id", + label: 'id', + width: 100, + hidden: true, + key: true, + },{ label: '合约编号', name: 'ContractCode', width: 150, }, + { label: '客户名称', name: 'ClientName', width: 150 }, + { label: '交易日期', name: 'TradeDate', width: 100, align: 'center' ,formatter: 'date' }, + { label: '多空头', name: 'PositionType', width: 80, align: 'center', + formatter: function (cellValue, options, rowObject) { + return cellValue == 1 ? "多头" : "空头"; + } + }, + { label: '用印状态', name: 'StampStatus', width: 80, align: 'center' }, // 根据实际需要调整宽度和对齐 + { label: '邮件发送结果', name: 'EmailResult', width: 100, align: 'center', + formatter: function (cellValue, options, rowObject) { + console.log(cellValue); + var html = ""; + html += "