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;
}
}
}