using YLErp.BLL; using YLErp.DBModels; using YLErp.Modules.SwapModule; namespace YLErp.Modules.SwapModule { /// /// BUG-01 方向守护(2026-08-24):授信出入表金额口径 占用记正/释放记负—— /// 已使用授信 = SUM(amount) 随占用上升、随释放回落;可用授信 = 有效授信 − 已使用授信 随占用收缩。 /// 连 dev 库闭环验证 Occupy/Release/GetUsedCredit(哨兵 client_id 自建自清,不触碰真实客户)。 /// [TestClass] public class ClientCreditInoutSignTest { private const int SentinelClientId = 99064001; //哨兵客户号(不存在的客户,仅授信出入表按 client_id 记账) private YLContext db; private ClientCreditInoutService service; [TestInitialize] public void Init() { db = new YLContext(); Cleanup(); service = new ClientCreditInoutService(OptUserInfo.SystemUser); } [TestCleanup] public void Teardown() { Cleanup(); db.Dispose(); } private void Cleanup() { var olds = db.client_credit_inout.Where(x => x.client_id == SentinelClientId).ToList(); if (olds.Count > 0) { db.client_credit_inout.RemoveRange(olds); db.SaveChanges(); } } /// 占用记正数:占用越多已使用授信越大(修复前为负——"越占越多"BUG-01) [TestMethod] public void CR_001_占用记正_已使用授信上升() { service.Occupy(SentinelClientId, 900001L, 800001, 10000, DateTime.Today, "方向守护-占用1"); Assert.AreEqual(10000, ClientCreditInoutService.GetUsedCredit(SentinelClientId, db), 1e-6); service.Occupy(SentinelClientId, 900002L, 800002, 5000, DateTime.Today, "方向守护-占用2"); Assert.AreEqual(15000, ClientCreditInoutService.GetUsedCredit(SentinelClientId, db), 1e-6); } /// 释放记负数:已使用授信回落,快照 used_after 同口径 [TestMethod] public void CR_002_释放记负_已使用授信回落() { service.Occupy(SentinelClientId, 900001L, 800001, 10000, DateTime.Today, "方向守护-占用"); service.Release(SentinelClientId, 900001L, 800001, 4000, DateTime.Today, "方向守护-释放"); var used = ClientCreditInoutService.GetUsedCredit(SentinelClientId, db); Assert.AreEqual(6000, used, 1e-6); //快照列与求和口径一致(最后一次写完后的已使用授信) var last = db.client_credit_inout.Where(x => x.client_id == SentinelClientId).OrderByDescending(x => x.id).First(); Assert.AreEqual(6000, last.used_after, 1e-6); Assert.AreEqual(-4000, last.amount, 1e-6, "释放行 amount 记负数"); } /// 方向传导:可用授信 = 有效授信 − 已使用授信,占用使其收缩(BUG-01 修复后的业务语义) [TestMethod] public void CR_003_可用授信随占用收缩() { service.Occupy(SentinelClientId, null, 800003, 10000, DateTime.Today, "方向守护-占用"); var used = ClientCreditInoutService.GetUsedCredit(SentinelClientId, db); var effective = 30000d; //有效授信给定量 Assert.AreEqual(20000, effective - used, 1e-6, "占用 10000 后可用授信应从 30000 收缩到 20000"); } /// Occupy/Release 入口对传入符号容错(一律按数量取绝对值定方向),防调用方残留旧负号 [TestMethod] public void CR_004_语义入口符号容错() { //即使调用方按旧习惯传负数,Occupy 也记正(数量口径),防止新代码库中残留旧符号调用点 var rec = service.Occupy(SentinelClientId, null, 800004, -7000, DateTime.Today, "方向守护-负号容错"); Assert.AreEqual(7000, rec.amount, 1e-6); var rel = service.Release(SentinelClientId, null, 800004, -3000, DateTime.Today, "方向守护-负号容错"); Assert.AreEqual(-3000, rel.amount, 1e-6); } } }