Files
zszq-trs/UnitTestProject/Modules/TradeModule/DocGenerateModule/GuolianContractNoGeneratorTest.cs
tengyufan 864a29d6a8 #EQD-6605 国联民生-确认书编号规则调整(不基于甲方乙方判定)
feat: 国联民生收益互换按簿记分类生成交易编号

簿记账户新增“簿记分类”字段,支持代客、融券,新增账户默认代客,历史账户统一初始化为代客
簿记账户分类设为必填,列表、编辑及详情页面同步展示
修改已被交易引用的簿记账户分类时增加二次确认,并提示关联交易数量
国联民生收益互换交易编号不再根据甲乙方判断,改为根据簿记账户分类生成
代客使用数字序号,融券使用字母序号,分别从已有同客户同日编号的最大序号继续递增
保留手工交易编号优先逻辑,标准格式的手工编号参与后续最大序号计算
生成候选编号后检查完整交易编号是否已存在,存在则继续递增
新增簿记分类编号格式、最大序号计算及数字字母序列隔离专项单测
2026-08-05 15:55:01 +08:00

179 lines
6.6 KiB
C#

using YLErp.Configuration;
using YLErp.DBModels;
using YLErp.Modules.TradeModule.DocGenerateModule;
namespace YLErp.UnitTestProject.Modules.TradeModule.DocGenerateModule
{
[TestClass]
public class GuolianContractNoGeneratorTest
{
[TestMethod]
public void IsGuolianSwapTrade_OnlyMatchesGuolianSwap()
{
var swapTrade = CreateSwapTrade();
Assert.IsTrue(GuolianContractNoGenerator.IsGuolianSwapTrade(swapTrade, CompanyEnum.国联));
Assert.IsFalse(GuolianContractNoGenerator.IsGuolianSwapTrade(
new trade { TradeType = "香草期权" }, CompanyEnum.国联));
Assert.IsFalse(GuolianContractNoGenerator.IsGuolianSwapTrade(swapTrade, CompanyEnum.国泰君安));
}
[TestMethod]
public void ShouldGenerateTradeNumberAfterSave_OnlyGeneratesForBlankTradeNumber()
{
var blankTrade = CreateSwapTrade();
var manualTrade = CreateSwapTrade();
manualTrade.TradeNumber = "MANUAL-001";
Assert.IsTrue(GuolianContractNoGenerator.ShouldGenerateTradeNumberAfterSave(
blankTrade, CompanyEnum.国联));
Assert.IsFalse(GuolianContractNoGenerator.ShouldGenerateTradeNumberAfterSave(
manualTrade, CompanyEnum.国联));
Assert.IsFalse(GuolianContractNoGenerator.ShouldGenerateTradeNumberAfterSave(
blankTrade, CompanyEnum.国泰君安));
}
[DataTestMethod]
[DataRow("GLMS-st0728-20260729-FICC-Q-210210IB", true, "GLMS-ST0728-20260729-FICC-Q-210210IB")]
[DataRow("GLMS-st0728-20260729-FICC-Q-210210IB", false, "GLMS-st0728-20260729-FICC-Q-210210IB")]
public void NormalizeTradeNumberCase_AppliesUpperTradeNumberConfiguration(
string tradeNumber,
bool upperTradeNumber,
string expected)
{
var actual = GuolianContractNoGenerator.NormalizeTradeNumberCase(tradeNumber, upperTradeNumber);
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void BuildTradeNumber_AgencyTrade_UsesNumericSequenceAndSanitizesUnderlyingCode()
{
var trade = CreateSwapTrade();
trade.OpponentRole = "乙方";
trade.TradeDate = new DateTime(2026, 7, 24);
trade.UnderlyingCode = "250210.IB";
var number = GuolianContractNoGenerator.BuildTradeNumber(trade, "IS", AssetUnit.BookCategoryAgency, 3);
Assert.AreEqual("GLMS-IS-20260724-FICC-03-250210IB", number);
}
[DataTestMethod]
[DataRow(1, "A")]
[DataRow(26, "Z")]
[DataRow(27, "AA")]
public void BuildTradeNumber_SecuritiesLendingTrade_UsesLetterSequence(int sequenceNo, string sequenceCode)
{
var trade = CreateSwapTrade();
trade.OpponentRole = "甲方";
trade.TradeDate = new DateTime(2026, 7, 24);
trade.UnderlyingCode = "180205.IB";
var number = GuolianContractNoGenerator.BuildTradeNumber(trade, "glmscounter", AssetUnit.BookCategorySecuritiesLending, sequenceNo);
Assert.AreEqual($"GLMS-glmscounter-20260724-FICC-{sequenceCode}-180205IB", number);
}
[TestMethod]
public void GetNextSequenceNo_AgencyTrade_UsesMaximumNumericSequence()
{
var tradeNumbers = new[]
{
"GLMS-1TT-20260804-FICC-01-180205IB",
"GLMS-1TT-20260804-FICC-02-180205IB",
"GLMS-1TT-20260804-FICC-03-180205IB",
"GLMS-1TT-20260804-FICC-A-180205IB",
"GLMS-1TT-20260804-FICC-CUSTOM-180205IB"
};
var sequenceNo = GuolianContractNoGenerator.GetNextSequenceNo(
tradeNumbers,
"1TT",
new DateTime(2026, 8, 4),
AssetUnit.BookCategoryAgency);
Assert.AreEqual(4, sequenceNo);
}
[TestMethod]
public void GetNextSequenceNo_AgencyTrade_StandardManualNumberReservesSequence()
{
var tradeNumbers = new[]
{
"GLMS-1TT-20260804-FICC-01-180205IB",
"GLMS-1TT-20260804-FICC-02-180205IB",
"GLMS-1TT-20260804-FICC-99-180205IB"
};
var sequenceNo = GuolianContractNoGenerator.GetNextSequenceNo(
tradeNumbers,
"1tt",
new DateTime(2026, 8, 4),
AssetUnit.BookCategoryAgency);
Assert.AreEqual(100, sequenceNo);
}
[TestMethod]
public void GetNextSequenceNo_SecuritiesLendingTrade_ExtendsLetterSequence()
{
var tradeNumbers = new[]
{
"GLMS-1TT-20260804-FICC-Z-180205IB",
"GLMS-1TT-20260804-FICC-AA-180205IB",
"GLMS-1TT-20260804-FICC-ZZ-180205IB",
"GLMS-1TT-20260804-FICC-99-180205IB"
};
var sequenceNo = GuolianContractNoGenerator.GetNextSequenceNo(
tradeNumbers,
"1TT",
new DateTime(2026, 8, 4),
AssetUnit.BookCategorySecuritiesLending);
var trade = CreateSwapTrade();
trade.TradeDate = new DateTime(2026, 8, 4);
trade.UnderlyingCode = "180205.IB";
var number = GuolianContractNoGenerator.BuildTradeNumber(
trade,
"1TT",
AssetUnit.BookCategorySecuritiesLending,
sequenceNo);
Assert.AreEqual("GLMS-1TT-20260804-FICC-AAA-180205IB", number);
}
[TestMethod]
public void GetNextSequenceNo_SeparatesNumericAndLetterSequences()
{
var tradeNumbers = new[]
{
"GLMS-1TT-20260804-FICC-01-180205IB",
"GLMS-1TT-20260804-FICC-02-180205IB",
"GLMS-1TT-20260804-FICC-A-180205IB",
"GLMS-1TT-20260804-FICC-B-180205IB"
};
var agencySequenceNo = GuolianContractNoGenerator.GetNextSequenceNo(
tradeNumbers,
"1TT",
new DateTime(2026, 8, 4),
AssetUnit.BookCategoryAgency);
var securitiesLendingSequenceNo = GuolianContractNoGenerator.GetNextSequenceNo(
tradeNumbers,
"1TT",
new DateTime(2026, 8, 4),
AssetUnit.BookCategorySecuritiesLending);
Assert.AreEqual(3, agencySequenceNo);
Assert.AreEqual(3, securitiesLendingSequenceNo);
}
private static trade CreateSwapTrade()
{
return new trade { TradeType = "收益互换" };
}
}
}