#EQD-5843 国联民生-交易确认书编号规则, 客户编号规则, 以及确认书相关的一些调整

This commit is contained in:
吴方海
2026-05-21 17:16:57 +08:00
parent 220ca7eba9
commit 2031b6f0ba
7 changed files with 298 additions and 110 deletions
@@ -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)
/// <summary>
/// 单笔交易上传确认书。
/// <para>会将该 tradeId 对应的旧 trade_contract_r 置为无效,并新增一条有效记录;同时创建/更新 trade_contract_document 并保存上传文件。</para>
/// </summary>
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<trade_contract_r>();
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 };
}
}
/// <summary>
/// 生成合约编号逻辑:如果是收益互换交易,使用国联的生成规则;否则默认使用 TradeNumber 作为合约编号。
/// </summary>
/// <param name="db"></param>
/// <param name="trade"></param>
/// <param name="clientCode"></param>
/// <returns></returns>
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<int> tradeIds,
UploadFileModel uploadFileModel,
out HashSet<int> tradeIdSet,
out string errMsg)
{
tradeIdSet = new HashSet<int>();
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;
}
/// <summary>
/// 保存上传的文件到服务器,并返回相对路径和文件名
/// </summary>
/// <param name="contractCode"></param>
/// <param name="uploadFileModel"></param>
/// <param name="outputRelativeDir"></param>
/// <param name="outputFileName"></param>
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)
@@ -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; }
}
}