diff --git a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【债券ETF】-清洁版.docx b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【债券ETF】-清洁版.docx index 3233881e..e99377d3 100644 Binary files a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【债券ETF】-清洁版.docx and b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【债券ETF】-清洁版.docx differ diff --git a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【债券ETF】-清洁版.docx b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【债券ETF】-清洁版.docx index e6ad31f5..423071ed 100644 Binary files a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【债券ETF】-清洁版.docx and b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【债券ETF】-清洁版.docx differ diff --git a/Plugins/YLErp.Plugins.GuoLian/DocumentGenerator/TradeConfirmationGenerator.cs b/Plugins/YLErp.Plugins.GuoLian/DocumentGenerator/TradeConfirmationGenerator.cs index c0cd3c47..6276da48 100644 --- a/Plugins/YLErp.Plugins.GuoLian/DocumentGenerator/TradeConfirmationGenerator.cs +++ b/Plugins/YLErp.Plugins.GuoLian/DocumentGenerator/TradeConfirmationGenerator.cs @@ -326,6 +326,8 @@ namespace YLErp.Plugins.GuoLian.DocumentGenerator dic["IsFixed"] = "□"; dic["IsFloat"] = "□"; + dic["期初观察日"] = trade.StartDate?.ToString("yyyy年M月d日") ?? ""; + dic["期末观察日"] = trade.ExerciseDate?.ToString("yyyy年M月d日") ?? ""; if (interestMargin != null) { if (string.IsNullOrEmpty(interestMargin.FloatRateUnderlyingCode)) @@ -343,6 +345,13 @@ namespace YLErp.Plugins.GuoLian.DocumentGenerator dic["利差"] = ((double)interestMargin.InterestRateDefault * 10000).ToString("N0"); dic["重置频率"] = (interestMargin.interest_rest_days ?? 0) + "天"; } + if (interestMargin.SwapIntervalList.Count()>0) + { + var firstInterval = interestMargin.SwapIntervalList.OrderBy(o=>o.Date).First(); + var lastInterval = interestMargin.SwapIntervalList.OrderBy(o => o.Date).Last(); + dic["期初观察日"] = firstInterval.Date.ToString("yyyy年M月d日") ?? ""; + dic["期末观察日"] = lastInterval.Date.ToString("yyyy年M月d日") ?? ""; + } } else { diff --git a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs index 332873f5..a62a6c4f 100644 --- a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs @@ -771,10 +771,6 @@ namespace YLErp.Modules.SwapModule { var client = PrepareBaseTradeClient(req); - if (req.StructureType != ClientMarginTypeEnum.多空组合.ToString() && _underlying.CalcTypeIsStock() && ((client.TradingInstType & TradingInstTypeEnum.Equity) != TradingInstTypeEnum.Equity)) - { - throw new ServiceException($"客户'{client.Name}'的'交易资产'属性不包括'权益',不能进行收益互换交易"); - } if (client.EvaluateExpireDate < req.TradeDate) { throw new ServiceException("适当性评估已经过期,只有在适当性有效期内才可以新开仓"); diff --git a/YLErpDAL/Modules/SystemModule/ClientEditConfigService.cs b/YLErpDAL/Modules/SystemModule/ClientEditConfigService.cs index a2868852..0cb6db5f 100644 --- a/YLErpDAL/Modules/SystemModule/ClientEditConfigService.cs +++ b/YLErpDAL/Modules/SystemModule/ClientEditConfigService.cs @@ -612,6 +612,8 @@ namespace YLErp.Modules.SystemModule /// public string dictionaryKey { get; set; } + public int? maxLength { get; set; } + public override string ToString() { return $"{name}-{label}-{type}"; diff --git a/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs b/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs index bac3c424..82428458 100644 --- a/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs +++ b/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs @@ -273,7 +273,10 @@ namespace YLErp.Modules.TradeModule.DealModule logger.Info($"[groupGenerateHandle_Date] 未找到客户信息 - ClientId: {firstTrade.ClientId}"); return; } - + if (string.IsNullOrEmpty(client.Code)) + { + throw new ServiceException($"对手方代码缩写缺失,请联系运营组同事维护: {firstTrade.ClientName}"); + } var supProtocolDate = client.SupProtocolDate; logger.Info($"[groupGenerateHandle_Date] 客户补充协议日期: {supProtocolDate}"); diff --git a/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateContext.cs b/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateContext.cs index 7894e15b..050fa800 100644 --- a/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateContext.cs +++ b/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateContext.cs @@ -1347,6 +1347,9 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule return Trade.TradeNumber; } + /// + /// 生成国贸确认书编号 + /// private string GenerateGuolianContractNo() { if (_contractType != ContractTypeEnum.Trade) @@ -1355,13 +1358,11 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule } if (Trade.TradeType == "收益互换") { - var posi = GetSwapPositions(Trade.id, true).FirstOrDefault(p => p.PositionType > 0); - var isLong = posi?.PositionType == (int)PositionTypeFlag.Short ? false : true; - - return "GLMS-" + _client.Number + "-" + Trade.TradeNumber; + return GuolianContractNoGenerator.Generate(DbContext, (trade)Trade, _client.Code); } - return Trade.TradeNumber; + return Trade.TradeNumber; } + /// /// 生成国贸确认书编号 /// diff --git a/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateService.cs b/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateService.cs index c7a4e306..e2d4a4df 100644 --- a/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateService.cs +++ b/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateService.cs @@ -1,4 +1,4 @@ -using NPOI.Util; +using NPOI.Util; using Org.BouncyCastle.Asn1.Ocsp; using System.Text; using YLErp.BLL; @@ -842,105 +842,259 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule } } - public (bool, string, DateTime, string) UploadContractFileNew(string contractCode, bool isCounterpartyDoc, UploadFileModel uploadFileModel) + /// + /// 单笔交易上传确认书。 + /// 会将该 tradeId 对应的旧 trade_contract_r 置为无效,并新增一条有效记录;同时创建/更新 trade_contract_document 并保存上传文件。 + /// + public UploadContractFileNewResult UploadContractFileNew( + int tradeId, + bool useContractCode, + string contractCode, + bool isCounterpartyDoc, + UploadFileModel uploadFileModel) { + var nowDate = DateTime.Now; + if (tradeId <= 0) + { + return new UploadContractFileNewResult { Success = false, Message = "请传入参数", OptDate = nowDate, DocumentPath = string.Empty }; + } + + if (!TryValidateUploadContractFileNew(new[] { tradeId }, uploadFileModel, out _, out var errMsg)) + { + return new UploadContractFileNewResult { Success = false, Message = errMsg, OptDate = nowDate, DocumentPath = string.Empty }; + } try { - var msg = ""; - #region 验证 - if (string.IsNullOrWhiteSpace(contractCode)) - { - - return (false, "请传入参数", DateTime.Now, ""); - } - - var db = DbContextFactory.GetYLDbContext(); - 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 contractDocRF = contractDocRArr.FirstOrDefault(); - if (contractDoc == null || contractDocRF == null) + var trade = db.trade.AsNoTracking().FirstOrDefault(t => t.id == tradeId && t.ValidState != "InValid"); + if (trade == null) { - return (false, "没有相关的确认书文档", DateTime.Now, ""); + return new UploadContractFileNewResult { Success = false, Message = "未找到交易数据", OptDate = nowDate, DocumentPath = string.Empty }; } - #endregion - if (uploadFileModel?.Length > 0) + var oldR = db.trade_contract_r + .Where(r => r.TradeId == tradeId && r.Type == ContractTypeEnum.Trade && r.IsValid) + .OrderByDescending(r => r.id) + .FirstOrDefault(); + + var oldCode = (oldR?.ContractCode ?? "").Trim(); + + var activeCode = ""; + if (useContractCode) { - #region 验证 - if (PS.Config.ErpElement.SecuritiesEnvironment) + activeCode = (contractCode ?? "").Trim(); + if (string.IsNullOrWhiteSpace(activeCode)) { - if (System.IO.Path.GetExtension(uploadFileModel.FileName).ToLower() != ".xlsx" - && System.IO.Path.GetExtension(uploadFileModel.FileName).ToLower() != ".xls" - && System.IO.Path.GetExtension(uploadFileModel.FileName).ToLower() != ".pdf" - && System.IO.Path.GetExtension(uploadFileModel.FileName).ToLower() != ".docx" - && System.IO.Path.GetExtension(uploadFileModel.FileName).ToLower() != ".doc") + return new UploadContractFileNewResult { Success = false, Message = "合约编号必填", OptDate = nowDate, DocumentPath = string.Empty }; + } + + if (!string.Equals(oldCode, activeCode, StringComparison.OrdinalIgnoreCase)) + { + var isExists = new TradeContractGenerateService(OptUser).GetExistsContractCode(new[] { activeCode }).Any(); + if (isExists) { - return (false, "请上传PDF/Word/Excel格式的文件", DateTime.Now, ""); + return new UploadContractFileNewResult { Success = false, Message = "合约编号已存在", OptDate = nowDate, DocumentPath = string.Empty }; } } - if (PS.Config.ErpElement.SecuritiesEnvironment && uploadFileModel.Length > Modules.SuperviseReportModule.SAC.Model.ReportStatusModel.MaxAnnexLength)//小于30MB - { - return (false, "上传失败,单笔确认书文件大小不应超过30MB", DateTime.Now, ""); - } - #endregion - - var tradeNumber = "未知"; - if (contractDocRF != null) - { - tradeNumber = contractDocRF.TradeNumber; - } - var filePath = Path.Combine(OtcAppContext.AppDocsPath, "contractdoc", "output"); - - if (!Directory.Exists(filePath)) - { - Directory.CreateDirectory(filePath); - } - - var stampFileFullName = Path.Combine(filePath, uploadFileModel.FileName); - contractDoc.Paths = stampFileFullName.Replace(OtcAppContext.AppDocsPath, "/App_Docs").Replace("\\", "/"); - contractDoc.FileName = uploadFileModel.FileName; - if (File.Exists(stampFileFullName)) - { - File.Delete(stampFileFullName); - } - - using var fs = new FileStream(stampFileFullName, FileMode.Create, FileAccess.ReadWrite); - - using var sr = uploadFileModel.OpenReadStream(); - - sr.Seek(0, SeekOrigin.Begin); - var tempBytes = new byte[sr.Length]; - sr.Read(tempBytes, 0, tempBytes.Length); - fs.Write(tempBytes, 0, tempBytes.Length); - - sr.Close(); - - fs.Close(); - msg = msg.Length > 0 ? msg : "上传成功"; } - - #region 更新数据 - contractDoc.SourceType = isCounterpartyDoc ? 2 : 1; // 对方用印文件=人工上传,否则=系统生成 - var confrimService = new TradeConfirmService(OptUser, db); - foreach (var contractDocR in contractDocRArr) + else { - new TradeConfirmService(OptUser, db).EditReportStatus(contractDocR.TradeId, true); + if (!string.IsNullOrWhiteSpace(oldCode)) + { + activeCode = oldCode; + } + else + { + var client = DataCacheProvider.GetClientDataSource().GetData(trade.ClientId); + if (string.IsNullOrEmpty(client?.Code)) + { + return new UploadContractFileNewResult { Success = false, Message = "对手方代码缩写缺失,请联系运营组同事维护", OptDate = nowDate, DocumentPath = string.Empty }; + } + activeCode = GenerateContractCodeForTrade(db, trade, client?.Code); + } } - db.SaveChanges(); - #endregion + if (string.IsNullOrWhiteSpace(activeCode)) + { + return new UploadContractFileNewResult { Success = false, Message = "合约编号生成失败", OptDate = nowDate, DocumentPath = string.Empty }; + } - return (true, msg, contractDoc.OptDate.Value, contractDoc.StampDocumentFileName); + trade_contract_document oldDoc = null; + if (!string.IsNullOrWhiteSpace(oldCode)) + { + oldDoc = db.trade_contract_document.FirstOrDefault(d => d.Code == oldCode && d.Type == ContractTypeEnum.Trade); + } + + var oldValidRs = new List(); + if (oldR != null) + { + oldValidRs.Add(oldR); + oldR.IsValid = false; + oldR.OptDate = nowDate; + oldR.OptId = OptUser.UserId; + oldR.OptName = OptUser.UserName; + } + + var newDoc = new trade_contract_document(); + db.trade_contract_document.Add(newDoc); + + if (oldDoc != null) + { + newDoc.ValueDate = oldDoc.ValueDate; + newDoc.BuyerId = oldDoc.BuyerId; + newDoc.BuyerName = oldDoc.BuyerName; + newDoc.SellerId = oldDoc.SellerId; + newDoc.SellerName = oldDoc.SellerName; + newDoc.ContractVersion = oldDoc.ContractVersion; + newDoc.FileType = oldDoc.FileType; + newDoc.DayNumber = oldDoc.DayNumber; + newDoc.ClientId = oldDoc.ClientId; + newDoc.Comments = oldDoc.Comments; + db.trade_contract_document.Remove(oldDoc); + } + else + { + var isGJBuyer = trade.BuySell == "买入"; + newDoc.ValueDate = valuedateBLL.ValueDate; + newDoc.BuyerId = isGJBuyer ? 0 : trade.ClientId; + newDoc.BuyerName = isGJBuyer ? (PS.Config.CompanyName ?? "") : trade.ClientName; + newDoc.SellerId = isGJBuyer ? trade.ClientId : 0; + newDoc.SellerName = isGJBuyer ? trade.ClientName : (PS.Config.CompanyName ?? ""); + newDoc.ClientId = trade.ClientId; + } + + newDoc.Code = activeCode; + newDoc.Status = ContractStatusEnum.Draft; + newDoc.SourceType = isCounterpartyDoc ? 2 : 1; + newDoc.Type = ContractTypeEnum.Trade; + newDoc.OptId = OptUser.UserId; + newDoc.OptName = OptUser.UserName; + newDoc.OptDate = nowDate; + + SaveUploadFile(activeCode, uploadFileModel, out var outputRelativeDir); + newDoc.Paths = outputRelativeDir; + newDoc.FileName = uploadFileModel.FileName; + + var newR = new trade_contract_r(); + db.trade_contract_r.Add(newR); + newR.TradeId = tradeId; + newR.TradeNumber = trade.TradeNumber; + newR.ContractCode = activeCode; + newR.TradeClearCode = activeCode; + newR.Type = ContractTypeEnum.Trade; + newR.IsValid = true; + newR.OptId = OptUser.UserId; + newR.OptName = OptUser.UserName; + newR.OptDate = nowDate; + + new TradeConfirmService(OptUser, db).EditReportStatus(tradeId, true); + db.SaveChanges(); + + return new UploadContractFileNewResult + { + Success = true, + Message = "上传成功", + OptDate = newDoc.OptDate ?? nowDate, + DocumentPath = newDoc.RelativePath + }; } catch (Exception ex) { LogFactory.GetLogger("UploadContractFileNew").Error("UploadContractFileNew出错", ex); - return (false, "操作出错", DateTime.Now, ""); + return new UploadContractFileNewResult { Success = false, Message = "操作出错", OptDate = nowDate, DocumentPath = string.Empty }; } } + /// + /// 生成合约编号逻辑:如果是收益互换交易,使用国联的生成规则;否则默认使用 TradeNumber 作为合约编号。 + /// + /// + /// + /// + /// + private string GenerateContractCodeForTrade(YLContext db, trade trade,string clientCode) + { + if (trade.TradeType == "收益互换") + { + return GuolianContractNoGenerator.Generate(db, trade, clientCode ?? ""); + } + return trade.TradeNumber; + } + + private static bool TryValidateUploadContractFileNew( + IReadOnlyCollection tradeIds, + UploadFileModel uploadFileModel, + out HashSet tradeIdSet, + out string errMsg) + { + tradeIdSet = new HashSet(); + errMsg = null; + + if (tradeIds == null || tradeIds.Count == 0) + { + errMsg = "请传入参数"; + return false; + } + + if (uploadFileModel == null || uploadFileModel.Length <= 0) + { + errMsg = "请选择需上传的文件"; + return false; + } + + var fileExt = System.IO.Path.GetExtension(uploadFileModel.FileName)?.ToLowerInvariant(); + if (fileExt != ".xlsx" && fileExt != ".xls" && fileExt != ".pdf" && fileExt != ".docx" && fileExt != ".doc") + { + errMsg = "请上传PDF/Word/Excel格式的文件"; + return false; + } + + foreach (var tid in tradeIds) + { + if (tid > 0) + { + tradeIdSet.Add(tid); + } + } + if (tradeIdSet.Count == 0) + { + errMsg = "请传入参数"; + return false; + } + + return true; + } + /// + /// 保存上传的文件到服务器,并返回相对路径和文件名 + /// + /// + /// + /// + /// + private static void SaveUploadFile(string contractCode, UploadFileModel uploadFileModel, out string outputRelativeDir) + { + var outputDir = Path.Combine(OtcAppContext.AppDocsPath, "contractdoc", "output"); + if (!Directory.Exists(outputDir)) + { + Directory.CreateDirectory(outputDir); + } + var ext = Path.GetExtension(uploadFileModel.FileName) ?? ""; + + var outputFullPath = Path.Combine(outputDir, uploadFileModel.FileName); + if (File.Exists(outputFullPath)) + { + File.Delete(outputFullPath); + } + + using (var fs = new FileStream(outputFullPath, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var sr = uploadFileModel.OpenReadStream()) + { + sr.CopyTo(fs); + } + + outputRelativeDir = Path.Combine("App_Docs", "contractdoc", "output"); + } public string GetSealErrMsg(string code) diff --git a/YLErpDAL/Modules/TradeModule/DocGenerateModule/GuolianContractNoGenerator.cs b/YLErpDAL/Modules/TradeModule/DocGenerateModule/GuolianContractNoGenerator.cs new file mode 100644 index 00000000..18e0312b --- /dev/null +++ b/YLErpDAL/Modules/TradeModule/DocGenerateModule/GuolianContractNoGenerator.cs @@ -0,0 +1,174 @@ +using YLErp.BLL; +using YLErp.DBModels; +using YLErp.DBModels.Consts; +using YLErp.DBModels.Enums; + +namespace YLErp.Modules.TradeModule.DocGenerateModule +{ + /// + /// 国贸交易确认书编号生成器 + /// 规则: + /// - 对客交易(OpponentRole为"甲方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-{标的代码}-{当日第N笔对客交易(数字递增)},从001开始 + /// - 非对客交易(OpponentRole为"乙方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-{标的代码}-{当日第N笔非对客交易(字母递增)},从A开始 + /// + public class GuolianContractNoGenerator + { + private static readonly object _syncLock = new object(); + + /// + /// 生成国贸交易确认书编号 + /// + /// 数据库上下文 + /// 交易记录 + /// 客户代码 + /// 确认书编号 + public static string Generate( + YLContext dbContext, + trade trade, + string clientCode) + { + // 根据trade的OpponentRole判断是否为对客交易 + var isClientTrade = trade.OpponentRole == "甲方"; + var underlyingCode = trade.UnderlyingCode ?? ""; + var tradeDate = trade.TradeDate ?? DateTime.MinValue; + var tradeDateStr = tradeDate.ToString("yyyyMMdd"); + var prefix = $"GLMS-{clientCode}-{tradeDateStr}-{underlyingCode}-"; + + lock (_syncLock) + { + var existingForTrade = dbContext.trade_contract_r + .Where(r => r.TradeId == trade.id && r.Type == ContractTypeEnum.Trade && r.IsValid) + .Select(r => r.ContractCode) + .FirstOrDefault(); + + if (!string.IsNullOrWhiteSpace(existingForTrade)) + { + return existingForTrade; + } + + var existingCodes = dbContext.trade_contract_r + .Where(d => d.ContractCode.StartsWith(prefix) && d.Type == ContractTypeEnum.Trade && d.IsValid) + .Select(d => d.ContractCode) + .ToList(); + + var existingCodeSet = new HashSet(); + for (var i = 0; i < existingCodes.Count; i++) + { + var code = existingCodes[i]; + if (!string.IsNullOrWhiteSpace(code)) + { + existingCodeSet.Add(code); + } + } + + if (isClientTrade) + { + var maxNo = 0; + var prefixLen = prefix.Length; + for (var i = 0; i < existingCodes.Count; i++) + { + var code = existingCodes[i]; + if (string.IsNullOrEmpty(code) || code.Length <= prefixLen) + { + continue; + } + + var suffix = code.Substring(prefixLen); + if (int.TryParse(suffix, out var n) && n > maxNo) + { + maxNo = n; + } + } + + var nextNo = maxNo + 1; + var contractNo = $"{prefix}{nextNo:D3}"; + while (existingCodeSet.Contains(contractNo)) + { + nextNo++; + contractNo = $"{prefix}{nextNo:D3}"; + } + return contractNo; + } + else + { + var maxNo = 0; + var prefixLen = prefix.Length; + for (var i = 0; i < existingCodes.Count; i++) + { + var code = existingCodes[i]; + if (string.IsNullOrEmpty(code) || code.Length <= prefixLen) + { + continue; + } + + var suffix = code.Substring(prefixLen); + if (!TryParseLettersToNumber(suffix, out var n)) + { + continue; + } + + if (n > maxNo) + { + maxNo = n; + } + } + + var nextNo = maxNo + 1; + var contractNo = $"{prefix}{NumberToLetter(nextNo)}"; + while (existingCodeSet.Contains(contractNo)) + { + nextNo++; + contractNo = $"{prefix}{NumberToLetter(nextNo)}"; + } + return contractNo; + } + } + } + + private static bool TryParseLettersToNumber(string letters, out int number) + { + number = 0; + if (string.IsNullOrEmpty(letters)) + { + return false; + } + + for (var i = 0; i < letters.Length; i++) + { + var c = letters[i]; + if (c >= 'a' && c <= 'z') + { + c = (char)(c - 32); + } + else if (c < 'A' || c > 'Z') + { + number = 0; + return false; + } + + number = (number * 26) + (c - 'A' + 1); + } + return true; + } + + /// + /// 将数字转换为字母序列(1=A, 2=B, 26=Z, 27=AA, 28=AB...) + /// + private static string NumberToLetter(int number) + { + if (number <= 0) + { + return "A"; + } + + string result = ""; + while (number > 0) + { + number--; // 调整为从0开始 + result = (char)('A' + (number % 26)) + result; + number /= 26; + } + return result; + } + } +} diff --git a/YLErpDAL/Modules/TradeModule/DocGenerateModule/UploadContractFileNewResult.cs b/YLErpDAL/Modules/TradeModule/DocGenerateModule/UploadContractFileNewResult.cs new file mode 100644 index 00000000..95da9835 --- /dev/null +++ b/YLErpDAL/Modules/TradeModule/DocGenerateModule/UploadContractFileNewResult.cs @@ -0,0 +1,12 @@ +using System; + +namespace YLErp.Modules.TradeModule.DocGenerateModule +{ + public sealed class UploadContractFileNewResult + { + public bool Success { get; set; } + public string Message { get; set; } + public DateTime OptDate { get; set; } + public string DocumentPath { get; set; } + } +} diff --git a/YLErpDAL/Modules/TradeModule/TradeOAService.cs b/YLErpDAL/Modules/TradeModule/TradeOAService.cs index 88e081a4..79af5edc 100644 --- a/YLErpDAL/Modules/TradeModule/TradeOAService.cs +++ b/YLErpDAL/Modules/TradeModule/TradeOAService.cs @@ -296,7 +296,7 @@ namespace YLErp.Modules.TradeModule htmb = 0, //合同密级 0一般 1秘密 2绝密 qysdzz = "2809700652352016752", - yyr = "yangx,yinfeng", + yyr = "yangx," + applicantLoginName, hehj = 0, //合同缓急 0一般 1紧急 2特急 //去除后缀 diff --git a/YLErpDAL/Modules/UnderlyingModule/UnderlyingDalService.cs b/YLErpDAL/Modules/UnderlyingModule/UnderlyingDalService.cs index d9af5ba0..22011d3c 100644 --- a/YLErpDAL/Modules/UnderlyingModule/UnderlyingDalService.cs +++ b/YLErpDAL/Modules/UnderlyingModule/UnderlyingDalService.cs @@ -435,7 +435,7 @@ namespace YLErp.Modules.UnderlyingModule dbModel.MarketCode = string.IsNullOrWhiteSpace(dbModel.MarketName) ? "" : DataCacheProvider.GetMarketDataSource().AsQueryable().FirstOrDefault(n => n.MarketName == dbModel.MarketName)?.ExchangeNo; } - if (dbModel.ContractSize <= 1) + if (dbModel.ContractSize < 1) { dbModel.ContractSize = variety.TradeUnitValue > 0 ? variety.TradeUnitValue.Value : 1; } diff --git a/YLErpWeb/Controllers/TradeConfirmBookController.cs b/YLErpWeb/Controllers/TradeConfirmBookController.cs index eace6701..14c0470d 100644 --- a/YLErpWeb/Controllers/TradeConfirmBookController.cs +++ b/YLErpWeb/Controllers/TradeConfirmBookController.cs @@ -782,9 +782,9 @@ namespace YLErp.Web.Controllers /// /// 将上传确认书做成页面 /// - public ActionResult confirmBookUploadNew(string Id) + public ActionResult confirmBookUploadNew(int tradeId = 0) { - ViewBag.Id = Id; + ViewBag.TradeId = tradeId; return View(); } @@ -2631,4 +2631,4 @@ namespace YLErp.Web.Controllers } } } -} \ No newline at end of file +} diff --git a/YLErpWeb/Controllers/tradeController.cs b/YLErpWeb/Controllers/tradeController.cs index 990c31ee..0624d5ad 100644 --- a/YLErpWeb/Controllers/tradeController.cs +++ b/YLErpWeb/Controllers/tradeController.cs @@ -2032,22 +2032,16 @@ namespace YLErp.Web.Controllers } return JsonError(msg); } - public ActionResult UploadContractFileNew(string encryptId, bool isCounterpartyDoc = false) - { + public ActionResult UploadContractFileNew(int tradeId, bool isCounterpartyDoc = false, bool useContractCode = false, string contractCode = null) + { var uploadFileModel = Request.Form.Files.Count > 0 ? Request.Form.Files[0].ToUploadFileModel() : null; - var docId = DataProtectHelper.DecryptInt(encryptId); - var contractDoc = db.trade_contract_document.FirstOrDefault(o => o.id == docId); - if (contractDoc == null) - { - return JsonError("未找到确认书数据"); - } - var (flag, msg, optDate, stampPath) = new ConfirmationGenerateService(CurUser).UploadContractFileNew(contractDoc.Code, isCounterpartyDoc, uploadFileModel); - if (flag) + var result = new ConfirmationGenerateService(CurUser).UploadContractFileNew(tradeId, useContractCode, contractCode, isCounterpartyDoc, uploadFileModel); + if (result.Success) { - return JsonSuccess(msg); + return JsonSuccess(result.Message); } - return JsonError(msg); + return JsonError(result.Message); } public ActionResult tradeContractManagementQuery(string tradeNumber) @@ -8967,4 +8961,4 @@ namespace YLErp.Web.Controllers #endregion } -} \ No newline at end of file +} diff --git a/YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml b/YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml index 6a395497..4133bbc4 100644 --- a/YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml +++ b/YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml @@ -420,13 +420,13 @@ - + - + - + {{item.underlying!=null?item.underlying.QuoteUnitString:''}} @@ -503,7 +503,7 @@
起息日 - 扣除本金 + 扣除本金
观察日间隔 @@ -601,4 +601,4 @@
- \ No newline at end of file + diff --git a/YLErpWeb/Views/TradeConfirmBook/confirmBookUploadNew.cshtml b/YLErpWeb/Views/TradeConfirmBook/confirmBookUploadNew.cshtml index f30dd95e..5f022100 100644 --- a/YLErpWeb/Views/TradeConfirmBook/confirmBookUploadNew.cshtml +++ b/YLErpWeb/Views/TradeConfirmBook/confirmBookUploadNew.cshtml @@ -1,11 +1,10 @@ -@{ +@{ ViewBag.Title = "confirmBookUploadNew"; Layout = "~/Views/Shared/_InfoLayout.cshtml"; var pageObj = new { - Id = ViewBag.Id, - SendMailId = ViewBag.SendMailId + TradeId = ViewBag.TradeId }; } @@ -23,26 +22,34 @@ var page = @Json.Serialize(pageObj); function UploadFiles1() { - if (main.isEmpty(page.Id)) { - main.message("还未生成确认书,无法上传"); + var tradeId = page.TradeId; + + if (main.isEmpty(tradeId)) { + main.message("缺少交易参数,无法上传"); return; } - //alert(tradeNumber); - var encryptId = page.Id; var files = $("#openFile")[0].files; if (files.length <= 0) { main.message("请选择需上传的文件"); return; } - var description = $("#fileDescription").val(); + var useContractCode = $("#useContractCode").is(':checked'); + var contractCode = $("#contractCode").val(); + + if (useContractCode && main.isEmpty(contractCode)) { + main.message("合约编号必填"); + return; + } var data = new FormData(); for (var x = 0; x < files.length; x++) { data.append(files[x].name, files[x]); } - data.append("encryptId", encryptId); + data.append("tradeId", tradeId); data.append("isCounterpartyDoc", $("#isCounterpartyDoc").is(':checked')); + data.append("useContractCode", useContractCode); + data.append("contractCode", contractCode); $.ajax({ type: "Post", @@ -67,6 +74,19 @@ } }); } + + function toggleContractCode() { + var useContractCode = $("#useContractCode").is(':checked'); + $("#contractCode").prop("disabled", !useContractCode); + if (!useContractCode) { + $("#contractCode").val(""); + } + } + + $(function () { + $("#useContractCode").on("change", toggleContractCode); + toggleContractCode(); + }); }
@@ -74,6 +94,13 @@
+
+ +
+ + +
+
@@ -87,4 +114,4 @@ 取消
- \ No newline at end of file + diff --git a/YLErpWeb/Views/client/_ClientEditFields.cshtml b/YLErpWeb/Views/client/_ClientEditFields.cshtml index c8c5a4f2..f8065a25 100644 --- a/YLErpWeb/Views/client/_ClientEditFields.cshtml +++ b/YLErpWeb/Views/client/_ClientEditFields.cshtml @@ -95,11 +95,19 @@ - + } else { - + if (f.maxLength.HasValue) + { + + } + else + { + + } + } @if (f.required) { diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js index 9922fb2e..6a68a4b1 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js @@ -177,6 +177,16 @@ const vue = new Vue({ this.initSwapRateList(); }, methods: { + getPosiPriceFormat(item) { + return tradeHelper.IsBond(item && item.UnderlyingInstrumentType) + ? inputFormatMarginRateNoPercent + : inputFormatTradeSinglePrice; + }, + getPosiPriceFormatKey(item, field) { + const index = item && item.index != null ? item.index : ''; + const isBond = tradeHelper.IsBond(item && item.UnderlyingInstrumentType); + return `${index}-${field}-${isBond ? 'bond' : 'other'}`; + }, changeStructureType() { this.trade.StockEqvNotional = 0; //this.trade.trade_extend.ExtendObj.FlowBookMode = 0; @@ -529,7 +539,7 @@ const vue = new Vue({ .done(function (resp) { item.PosiNetNoFeePrice = otcformat.trading.umprice(resp.obj.netPrice); item.PosiGrossPrice = otcformat.trading.umprice(resp.obj.price); - thisObj.changeStockEqvNotional(); + thisObj.calcNotional(); }); }, //年化利率变更同步修改 同行观察日利率 @@ -587,7 +597,7 @@ const vue = new Vue({ thisObj.observation.ObservationSettlementRules = observation ? observation.ObservationSettlementRules : 0; } thisObj.observation.IsDeductPrincipal = observation ? observation.IsDeductPrincipal : true; - if (type == 0) { + if (type == 1) { thisObj.observation.IsDeductPrincipal = false; } var startTime = thisObj.trade.TradeDate; @@ -1544,4 +1554,4 @@ $(function () { $(this).datepicker("setDate", dateVal); }); -}); \ No newline at end of file +}); diff --git a/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBook.js b/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBook.js index 9d54a593..e0acfadb 100644 --- a/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBook.js +++ b/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBook.js @@ -1,4 +1,4 @@ -var valuedate = page.valuedate; +var valuedate = page.valuedate; var ContractTypeCtrl; var ReportId; @@ -354,8 +354,8 @@ const colModelGrid = (new function () { end: function () { SearchClick(true) } }); } - this.uploadNew = function (encryptId) { - var srcurl = "/TradeConfirmBook/confirmBookUploadNew/?Id=" + encryptId; + this.uploadNew = function (tradeId) { + var srcurl = "/TradeConfirmBook/confirmBookUploadNew/?tradeId=" + tradeId; main.open("上传确认书", srcurl, { area: ['500px', '420px'], end: function () { SearchClick(true) } @@ -935,8 +935,8 @@ function showToolName(cellValue, options, rowObject) { html += "" .template(rowObject.EncryptId, "发送Email"); } - var canUpload = page.canGenerate == true ? "" : "disabled"; - html += "".template(rowObject.MetaDic.ContractEncryptId, canUpload); + html += "" + .template(rowObject.id); html += "".template(rowObject.id); return html; } @@ -1321,4 +1321,4 @@ function submitOA(id) { }).fail(function (xhr, status, error) { SearchClick(true); }); -} \ No newline at end of file +} diff --git a/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBookListByClient.js b/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBookListByClient.js index 18035f3b..15a4e26b 100644 --- a/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBookListByClient.js +++ b/YLErpWeb/wwwroot/Scripts/app/trade/tradeConfirmBookListByClient.js @@ -56,8 +56,8 @@ const colModelGrid = (new function () { end: function () { SearchClick(true) } }); } - this.uploadNew = function (encryptId) { - var srcurl = "/TradeConfirmBook/confirmBookUploadNew/?Id=" + encryptId; + this.uploadNew = function (tradeId) { + var srcurl = "/TradeConfirmBook/confirmBookUploadNew/?tradeId=" + tradeId; main.open("上传确认书", srcurl, { area: ['500px', '420px'], end: function () { SearchClick(true) } @@ -256,7 +256,8 @@ function showToolName(cellValue, options, rowObject) { .template(rowObject.EncryptId, "发送Email"); } var canUpload = page.canGenerate == true && rowObject.ContractDocUrl ? "" : "disabled"; - html += "".template(rowObject.ContractCode, canUpload); + html += "" + .template(rowObject.tradeIds && rowObject.tradeIds.length > 0 ? rowObject.tradeIds[0] : 0, canUpload); return html; }