124 lines
5.8 KiB
C#
124 lines
5.8 KiB
C#
using YLErp.BLL;
|
|
using YLErp.DBModels;
|
|
|
|
namespace YLErp.Modules.SwapModule
|
|
{
|
|
/// <summary>
|
|
/// 客户授信出入服务(R4 授信/现金标签体系,决策④)。
|
|
/// 授信出入表的写入口集中在 标签赋值(占用)与 平仓/到期返还(释放)两个链路内,禁止散落调用。
|
|
/// 金额符号口径(2026-08-20 业务确认):与资金流水同号——入金为负、出金为正;
|
|
/// 已使用授信 = SUM(amount) 直接求和(入金使已使用授信下降、可用授信=有效授信−已使用授信 上升;出金反之)。
|
|
/// change_type(占用/释放/调整)仅作分类审计,不参与求和方向。
|
|
/// </summary>
|
|
public class ClientCreditInoutService : YLBaseService
|
|
{
|
|
public ClientCreditInoutService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
}
|
|
|
|
public ClientCreditInoutService(YLBaseService baseService) : base(baseService)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 客户已使用授信 = SUM(amount)(金额与资金流水同号:入金负、出金正)。
|
|
/// 可用授信 = 有效授信 − 本值;入金使可用授信增长、出金使其收缩。
|
|
/// 供交易确认校验(RealtimePnlCalc.TradeCanBeConfirm)等静态上下文直接调用。
|
|
/// </summary>
|
|
public static double GetUsedCredit(int clientId, YLContext db)
|
|
{
|
|
var records = db.client_credit_inout.Where(x => x.client_id == clientId).ToList();
|
|
return Math.Round(records.Sum(x => x.amount), 2, MidpointRounding.AwayFromZero);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 客户当前已使用授信(实例方法,走服务 DbContext)
|
|
/// </summary>
|
|
public double GetUsedCredit(int clientId)
|
|
{
|
|
return GetUsedCredit(clientId, DbContext);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 写入一条授信变化记录(占用/释放/调整统一入口),并冗余记录变更后已使用授信。
|
|
/// amount 带符号:入金(客户付)为负、出金(客户收)为正,与资金流水 Money 同号。
|
|
/// </summary>
|
|
public client_credit_inout Record(int clientId, long? positionId, int? tradeId, int changeType,
|
|
double amount, DateTime happenDate, string remark)
|
|
{
|
|
if (amount == 0)
|
|
{
|
|
return null;
|
|
}
|
|
var amountRounded = Math.Round(amount, 2, MidpointRounding.AwayFromZero);
|
|
//变更后已使用授信快照:直接求和口径(符号已含方向)
|
|
var usedAfter = Math.Round(GetUsedCredit(clientId) + amountRounded, 2, MidpointRounding.AwayFromZero);
|
|
var record = new client_credit_inout
|
|
{
|
|
client_id = clientId,
|
|
position_id = positionId,
|
|
trade_id = tradeId,
|
|
change_type = changeType,
|
|
amount = amountRounded,
|
|
used_after = usedAfter,
|
|
happen_date = happenDate,
|
|
remark = remark,
|
|
OptId = UserId,
|
|
OptName = UserName,
|
|
OptTime = DateTime.Now
|
|
};
|
|
DbContext.client_credit_inout.Add(record);
|
|
DbContext.SaveChanges();
|
|
return record;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 占用:预付金腿标 Credit 的簿记入金(含拆单的授信部分;交易级占用 positionId 为空)。
|
|
/// amount 传负数(入金方向,与资金流水同号)。
|
|
/// </summary>
|
|
public client_credit_inout Occupy(int clientId, long? positionId, int tradeId, double amount, DateTime happenDate, string remark)
|
|
{
|
|
return Record(clientId, positionId, tradeId, client_credit_inout.ChangeTypeOccupy, amount, happenDate, remark);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 释放:平仓/到期按原标签返还授信部分(按腿的 position_id 匹配原占用记录)。
|
|
/// amount 传正数(出金方向,与资金流水同号)。
|
|
/// </summary>
|
|
public client_credit_inout Release(int clientId, long? positionId, int tradeId, double amount, DateTime happenDate, string remark)
|
|
{
|
|
return Record(clientId, positionId, tradeId, client_credit_inout.ChangeTypeRelease, amount, happenDate, remark);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除某交易的全部授信出入记录:与资金记录同生命周期——
|
|
/// 交易回退到开仓(DeleteTradeCashInCashOut)、修改清除(ClearSwapPositions)、删除交易时同步清理,
|
|
/// 重新确认/重补时按最新标签重写,避免占用悬挂。
|
|
/// 注意:阶段四追加保证金占用落地后,此处需区分保留追加部分。
|
|
/// </summary>
|
|
public void RemoveByTrade(int tradeId)
|
|
{
|
|
var records = DbContext.client_credit_inout.Where(x => x.trade_id == tradeId).ToList();
|
|
DbContext.client_credit_inout.RemoveRange(records);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按客户批量查询已使用授信(客户列表/详情"已使用授信"展示,数据源即本表)。
|
|
/// </summary>
|
|
public static Dictionary<int, double> GetUsedCreditByClients(List<int> clientIds, YLContext db)
|
|
{
|
|
var result = new Dictionary<int, double>();
|
|
if (clientIds == null || clientIds.Count == 0)
|
|
{
|
|
return result;
|
|
}
|
|
var records = db.client_credit_inout.Where(x => clientIds.Contains(x.client_id)).ToList();
|
|
foreach (var group in records.GroupBy(x => x.client_id))
|
|
{
|
|
result[group.Key] = Math.Round(group.Sum(x => x.amount), 2, MidpointRounding.AwayFromZero);
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
}
|