using YLErp.BLL;
using YLErp.Helpers;
using YLErp.Model;
using YLErp.Model.Enum;
namespace YLErp.Modules.TradeModule.DealModule
{
///
/// 交易行权操作
///
public class TradeExerciseService : TradeCashService
{
public TradeExerciseService(YLBaseService baseService) : base(baseService)
{
}
public TradeExerciseService(OptUserInfo userInfo) : base(userInfo)
{
}
///
/// 行权待复核提交
///
public TradeCashResult ApplyExerciseRecheck(TradeCashReq req)
{
var tradeDalService = new TradeDalModule.TradeDalService(this.OptUser);
//这个对象只提供收盘前数据,用于创建TradeCash记录
var td = tradeDalService.GetTradeOrEodTrade(new[] { req.TradeId }, req.ValueDate ?? SystemValueDate).FirstOrDefault();
if (td == null)
{
throw new ServiceException("交易信息不存在,id:" + req.TradeId);
}
var unwindNotional = td.IsUsePremiumRate == true ? req.UnwindPercentRate / 100 * td.OriginalNotional : req.UnwindNotional;
if (unwindNotional >= Math.Floor(td.Notional * Math.Pow(10, 8)) / Math.Pow(10, 8))
{
req.UnwindType = "全部行权";
td.UnWindNotional = td.Notional;
}
else
{
td.UnWindNotional = unwindNotional;
}
//部分行权和部分平仓业务处理保持一致
if (req.UnwindType == "部分行权")
{
return new TradeCloseService(this).CloseReCheck(req, true);
}
else
{
if (td == null)
{
throw new ServiceException("行权失败,该交易不存在,不能提交行权审核!");
}
if (PS.Config.TradeElement.ExecuteAfterGeneratedConfirmDoc && !td.HasGeneratedConfirmBook() && td.TradeType != "自定义交易")
{
throw new ServiceException("请先去生成交易确认书");
}
if (td.TradeStatus != ConsTrade.确认成交 && td.TradeStatus != ConsTrade.提前终止拒绝)
{
throw new ServiceException("行权失败,该交易处于待" + td.TradeStatus + "状态,不能提交行权审核!");
}
//保存tradecash
//增加现金交割交易记录
req.ValidState = ConsGlobal.InValid;
if (req.UnwindType != null && req.UnwindType.Contains("全部") && td.OriginalStockEqvNotional > 0)
{
req.UnwindPercentRate = td.StockEqvNotional / td.OriginalStockEqvNotional.Value * 100;
}
var valueDate = td.ExerciseDate != null && td.ExerciseDate < valuedateBLL.ValueDate ? td.ExerciseDate.Value : valuedateBLL.ValueDate;
var tc = ExerciseTrade_TradeCashSave(td, req, valueDate);
//检查是否有交易审批流程
var hasTradeProcess = HasTradeProcess();
ExerciseReCheck_SetTrade(req.TradeId, hasTradeProcess);
//配对 行权待复核提交
if (req.IsUnwindPairTrade)
{
//执行匹配交易
if (!string.IsNullOrEmpty(td.PairTrade))
{
int pairTradeId = Convert.ToInt32(td.PairTrade);
//这个对象只提供收盘前数据,用于创建TradeCash记录
var pairTrade = tradeDalService.GetTradeOrEodTrade(new[] { pairTradeId }, req.ValueDate.Value).FirstOrDefault();
req.ExtraAmount = Math.Abs(pairTrade.StockEqvNotional * (valuedateBLL.SystemDate.ExerciseCostRatioReal ?? 0)) * ("卖出".Equals(pairTrade.BuySell) ? 1 : 0);
req.Amount = CalcAmountOnly(pairTradeId, req.FinalPrice ?? 0) + req.ExtraAmount;
ExerciseTrade_TradeCashSave(pairTrade, req, valueDate);
ExerciseReCheck_SetTrade(pairTradeId, hasTradeProcess);
AddTradeOperationHistoryAndSetParentTradeInfo(false, pairTrade, "行权审核提交");
}
}
AddTradeOperationHistoryAndSetParentTradeInfo(false, td, "行权审核提交");
DbContext.SaveChanges();
return new TradeCashResult(td, tc);
}
}
private void ExerciseReCheck_SetTrade(int tradeId, bool hasTradeProcess)
{
var td = DbContext.trade.Find(tradeId);
td.OptDate = DateTime.Now;
td.CheckStatus = Convert.ToInt32(TradeCheckEnum.StatusOfOld);
// 先设状态,使流程类别能正确推断为 CloseProcess
td.TradeStatus = ConsTrade.行权待复核;
// 需求②:行权按交易状态查对应流程
var needApproval = valuedateBLL.SystemDate.CloseReApprove == 1 && TradeProcessCountByCategory(td) > 0;
if (needApproval)
{
// 需求①:进入审批前先判断触发条件——若所有节点都不满足触发条件,跳过审批。
needApproval = NeedApprovalByTrigger(td);
}
if (needApproval)
{
// 需要审批:保持"行权待复核",进入审批流程等待人工审批
InitTradeProcessOrder(td, UserId);
}
else
{
// 不需要审批:设 ProcessOrderId=审批通过,再调 UpdateTradeProcessLog(pass) 执行审批通过流程
td.ProcessOrderId = ProcessTradeLog.审批通过;
DbContext.SaveChanges();
new TradeOpenService(this).UpdateTradeProcessLog(new TradeOpenReqModel
{
tradeId = td.id,
status = "pass",
comments = "触发条件未满足,自动跳过审批",
notNeedOperationHistory = false
});
return;
}
DbContext.SaveChanges();
}
//仅计算金额(业务未知,请知晓后重新注释)
private double? CalcAmountOnly(int enid, double tradePrice)
{
var td = DbContext.trade.Find(enid);
if (td != null)
{
tradeBLL.SetFieldsByTradeType(td);
var tc = new trade_cash
{
IsPossibleExec = true
};
BLL.EodSettlement.SettlementCalcCommons.SetPossibleExec(tc, td, tradePrice);
return tc.Amount;
}
return 0;
}
}
}