Files
zszq-trs/YLErpDAL/Modules/TradeModule/DealModule/TradeCloseService.cs
T

172 lines
6.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using YLErp.BLL;
using YLErp.Helpers;
using YLErp.Model;
using YLErp.Model.Enum;
using YLErp.Modules.TradeDalModule;
namespace YLErp.Modules.TradeModule.DealModule
{
/// <summary>
/// 交易平仓操作
/// </summary>
public class TradeCloseService : TradeCashService
{
public TradeCloseService(YLBaseService baseService) : base(baseService)
{
}
public TradeCloseService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 平仓待复核提交
/// </summary>
public TradeCashResult CloseReCheck(TradeCashReq req, bool isFromExercise = false)
{
var tradeDalService = new TradeDalService(OptUser);
//这个对象只提供收盘前数据,用于创建TradeCash记录
var td = tradeDalService.GetTradeOrEodTrade(new[] { req.TradeId }, req.ValueDate ?? SystemValueDate).FirstOrDefault();
if (td == null)
{
if (isFromExercise)
{
throw new ServiceException("行权失败,该交易不存在,不能提交行权审核");
}
else
{
throw new ServiceException("平仓失败,该交易不存在,不能提交平仓审核");
}
}
if (td.TradeType == "结构化交易")
{
throw new ServiceException("操作失败,结构化交易主交易不支持此操作");
}
if (td.TradeStatus != ConsTrade.确认成交 && td.TradeStatus != ConsTrade.提前终止拒绝)
{
if (isFromExercise)
{
throw new ServiceException("行权失败,该交易处于待" + td.TradeStatus + "状态,不能提交行权审核!");
}
else
{
throw new ServiceException("平仓失败,该交易处于待" + td.TradeStatus + "状态,不能提交平仓审核!");
}
}
if (PS.Config.TradeElement.ExecuteAfterGeneratedConfirmDoc && td.TradeType != "远期" && td.TradeType != "自定义交易" && td.TradeType != "现金流交易"
&& !DbContext.trade_contract_r.Any(n => n.TradeId == td.id && n.Type == "交易确认书" && n.IsValid))
{
throw new ServiceException("请先去生成交易确认书");
}
bool isPartialClose = false;
if (req != null)
{
unwindPreHandle(req, td, isFromExercise, out isPartialClose);
}
//保存tradecash
//增加现金交割交易记录
req.ValidState = ConsGlobal.InValid;
var tc = CloseTrade_TradeCashSave(td, req, false, !isFromExercise, !isPartialClose);
var hasTradeProcess = HasTradeProcess();
CloseReCheck_SetTrade(td.id, isFromExercise, hasTradeProcess);
//配对 平仓待复合提交
if (req.IsUnwindPairTrade && !string.IsNullOrEmpty(td.PairTrade))
{
int pairTradeId = Convert.ToInt32(td.PairTrade);
//这个对象只提供收盘前数据,用于创建TradeCash记录
var pairTrade = tradeDalService.GetTradeOrEodTrade(new[] { pairTradeId }, req.ValueDate.Value).FirstOrDefault();
//配对交易平仓总份额取各自剩余的总份额
req.Notional = pairTrade.Notional;
//UnwindNotional >= Notional代表全部品仓,配对交易的平仓份额为自己剩余的总份额
//UnwindNotional < td.Notional部分平仓,配对的两笔交易部分平仓份额相等,即req.UnwindNotional不变
if (req.UnwindNotional >= Math.Floor(pairTrade.Notional * Math.Pow(10, 8)) / Math.Pow(10, 8))
{
req.UnwindNotional = pairTrade.Notional;
}
if (isFromExercise)
{
req.UnwindFee = -req.UnwindFee;
}
CloseTrade_TradeCashSave(pairTrade, req, !isFromExercise, !isPartialClose);
CloseReCheck_SetTrade(pairTrade.id, isFromExercise, hasTradeProcess);
}
DbContext.SaveChanges();
return new TradeCashResult(td, tc);
}
//平仓待复核提交
public void CloseReCheck_SetTrade(int tradeId, bool isFromExercise, bool hasTradeProcess)
{
var td = DbContext.trade.Find(tradeId);
td.OptId = UserId;
td.OptName = UserName;
td.OptDate = OptDate;
td.CheckStatus = Convert.ToInt32(TradeCheckEnum.StatusOfOld);
// 先设状态,使流程类别能正确推断为 CloseProcess(需求②按交易状态推断开仓/了结)
td.TradeStatus = isFromExercise ? ConsTrade.行权待复核 : ConsTrade.平仓待复核;
//检查是否有交易审批流程(需求②:平仓/行权按交易状态查对应流程,而非只查开仓流程)
var needApproval = valuedateBLL.SystemDate.CloseReApprove == 1 && TradeProcessCountByCategory(td) > 0;
if (needApproval)
{
// 需求①:进入审批前先判断触发条件——若所有节点都不满足触发条件,跳过审批。
needApproval = NeedApprovalByTrigger(td);
}
if (needApproval)
{
// 需要审批:保持"平仓待复核/行权待复核",进入审批流程等待人工审批
InitTradeProcessOrder(td, UserId);
AddTradeOperationHistoryAndSetParentTradeInfo(false, td, isFromExercise ? "部分行权审核提交" : "平仓审核提交");
}
else
{
// 不需要审批:设 ProcessOrderId=审批通过,再调 UpdateTradeProcessLog(pass) 执行审批通过流程
// SetTradeOpen 会完成平仓、改状态、写日志,与人工审批通过完全一致)
td.ProcessOrderId = ProcessTradeLog.审批通过;
DbContext.SaveChanges();
new TradeOpenService(this).UpdateTradeProcessLog(new TradeOpenReqModel
{
tradeId = td.id,
status = "pass",
comments = "触发条件未满足,自动跳过审批",
notNeedOperationHistory = false
});
}
}
}
/// <summary>
///
/// </summary>
public class TradeCashResult
{
public TradeCashResult(trade td, trade_cash tc)
{
Trade = td ?? throw new ArgumentNullException(nameof(td));
TradeCash = tc ?? throw new ArgumentNullException(nameof(tc));
}
public trade Trade { get; }
public trade_cash TradeCash { get; }
}
}