using YLErp.BLL;
using YLErp.Model;
using YLErp.Model.Enum;
using YLErp.Modules.TradeDalModule;
namespace YLErp.Modules.TradeModule.DealModule
{
///
/// 交易平仓操作
///
public class TradeCloseService : TradeCashService
{
public TradeCloseService(YLBaseService baseService) : base(baseService)
{
}
public TradeCloseService(OptUserInfo userInfo) : base(userInfo)
{
}
///
/// 平仓待复核提交
///
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;
if (isFromExercise)
{
td.TradeStatus = ConsTrade.行权待复核;
}
else
{
td.TradeStatus = ConsTrade.平仓待复核;
}
td.CheckStatus = Convert.ToInt32(TradeCheckEnum.StatusOfOld);
//检查是否有交易审批流程
if (valuedateBLL.SystemDate.CloseReApprove == 1 && hasTradeProcess)
{
// 如果有审批组
InitTradeProcessOrder(td, UserId);
}
AddTradeOperationHistoryAndSetParentTradeInfo(false, td, isFromExercise ? "部分行权审核提交" : "平仓审核提交");
}
}
///
///
///
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; }
}
}