Files
zszq-trs/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js
T
hjhan 905bd407e2 refactor(frontend): 清理已删除利息模式 7/8 的前端死分支
后端 InterestModeEnum 已删除 mode 7/8(无历史数据),前端对应分支恒不成立。
移除 swaptrade 下 6 个 JS 文件中的 ==7/==8 死分支,并精简仅校验 mode7/8
唯一性的 checkSwapRateList(保留 changeInterestMode 方法签名以对齐 cshtml 绑定)。
2026-08-13 09:05:58 +08:00

543 lines
30 KiB
JavaScript
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.
//otcformat禁止千分位分组
window.otcformat.options.disableGrouping = true;
const inputFormatSwapRate = Object.freeze({ precision: 4, append: '%', trimTailZeros: false });
const inputFormatTradePrice = Object.freeze({ precision: otcformat.trading.tradePrice.precision, append: '' });
const inputFormatEqvNotional = swapPricePrecision.getCommonInputFormat('amount', { append: '', negative: true });
const inputFormatCloseAmount = swapPricePrecision.getCommonInputFormat('amount', { append: '', negative: true });
const swapInstrumentType = (model.FlowEvents || []).find(item => item && item.UnderlyingInstrumentType)?.UnderlyingInstrumentType || model.UnderlyingInstrumentType || '';
const formatSwapAmount = value => swapPricePrecision.normalizeCommon('amount', value);
const formatSwapQuantity = value => swapPricePrecision.normalizeCommon('quantity', value, swapInstrumentType);
const inputFormatMarginRate = Object.freeze({ precision: otcformat.trading.marginRateP.precision, append: '%' });
const inputFormatMarginRateNoPercent = Object.freeze({ precision: otcformat.trading.umpriceP.precision, append: '', percent: true });
const inputFormatSwapDeliveryPrice = Object.freeze({ precision: 9, append: '', negative: true });
const consPosiFeeType = Object.freeze({ Percent: 0, Unit: 1 });
const swapPosiFeeCalc = {
normalizeFeeType(feeType) {
return Number(feeType) === consPosiFeeType.Unit ? consPosiFeeType.Unit : consPosiFeeType.Percent;
},
calcTradingFee(feeType, feeUnit, closeNotionalValue, closeQty) {
const normalizedFeeType = this.normalizeFeeType(feeType);
const normalizedFeeUnit = Number(feeUnit) || 0;
const normalizedCloseNotionalValue = Number(closeNotionalValue) || 0;
const normalizedCloseQty = Number(closeQty) || 0;
const tradingFee = normalizedFeeType === consPosiFeeType.Unit
? normalizedFeeUnit * normalizedCloseQty
: normalizedFeeUnit / 100 * normalizedCloseNotionalValue;
return formatSwapAmount(_.round(tradingFee, 2));
},
calcAllocatedTradingFee(totalFee, feeType, feeUnit, closeNotionalValue, closeQty, notionalValue, notionalQty) {
const normalizedFeeUnit = Number(feeUnit) || 0;
if (normalizedFeeUnit === 0) {
return null;
}
const normalizedFeeType = this.normalizeFeeType(feeType);
const closeBase = normalizedFeeType === consPosiFeeType.Unit ? Number(closeQty) || 0 : Number(closeNotionalValue) || 0;
const originalBase = normalizedFeeType === consPosiFeeType.Unit ? Number(notionalQty) || 0 : Number(notionalValue) || 0;
if (originalBase <= 0) {
return null;
}
return formatSwapAmount(_.round((Number(totalFee) || 0) * closeBase / originalBase, 2));
},
calcTradingFeePending(beforeCloseFee, feeType, feeUnit, closeNotionalValue, closeQty, notionalValue, notionalQty, closePercent) {
const allocatedFee = this.calcAllocatedTradingFee(
beforeCloseFee, feeType, feeUnit, closeNotionalValue, closeQty, notionalValue, notionalQty);
if (allocatedFee !== null) {
return allocatedFee;
}
return (Number(beforeCloseFee) || 0) * (Number(closePercent) || 0);
}
};
let ValueDate = model.ValueDate;
const vue = new Vue({
el: '#vueDiv',
data: {
deal: model,
floatPosition: null,
interestList: [],
marginList: [],
initPosiNetPrice: 0,
multiplier: 1,
// 平仓比例展示/输入均为"占期初(original)"语义(A):默认与每次重开都基于原始名义本金。
// oriClosePercent = 剩余名义本金/期初名义本金 = 最多可平比例(不能平超过剩余持仓)。
oriClosePercent: 1,
ratio: 1,
shortRatio: 1,
},
computed: {
maxUnwindDate() {
return ValueDate;
},
minStartDate() {
return this.deal.StartDate;
}
},
created() {
this.multiplier = this.deal.StructureType == '普通债券类收益互换' ? 100 : 1;
this.initDeal();
this.setValueDate(this.deal.ValueDate);
},
methods: {
formatAmount(value) {
return swapPricePrecision.formatCommon('amount', value);
},
formatQuantity(value) {
return swapPricePrecision.formatCommon('quantity', value, swapInstrumentType);
},
getQuantityInputFormat() {
return swapPricePrecision.getCommonInputFormat('quantity', { append: '' }, swapInstrumentType);
},
getDeliveryPriceInputFormat() {
return swapPricePrecision.getInputFormat(
this.floatPosition && this.floatPosition.UnderlyingInstrumentType,
'grossPrice',
inputFormatSwapDeliveryPrice);
},
getStorageDeliveryPrice() {
return swapPricePrecision.roundForSubmit(
swapPricePrecision.shiftDecimal(this.floatPosition.TradingAmountAvg, this.multiplier === 100 ? -2 : 0),
this.floatPosition && this.floatPosition.UnderlyingInstrumentType,
'grossPrice',
this.multiplier === 100 ? 2 : 0);
},
initDeal() {
var positions = model.FlowEvents.filter((item) => {
return item.UnderlyingCode;
});
this.floatPosition = positions[0];
this.initPosiNetPrice = this.floatPosition.PosiGrossPrice;
this.interestList = model.FlowEvents.filter((item) => {
return item.InterestMode == 1 || item.InterestMode == 2 || item.InterestMode == 9;
});
this.marginList = model.FlowEvents.filter((item) => {
return item.InterestMode == 5 || item.InterestMode == 6;
});
this.ratio = this.floatPosition.PayDirection == 1 ? -1 : 1;
this.shortRatio = this.floatPosition.PositionType == 1 ? 1 : -1;
this.TradeStartDate = model.TradeStartDate;
// 最多可平比例(占期初口径) = 剩余名义本金 / 期初名义本金;分母为 0 时兜底为 1
this.oriClosePercent = (this.deal.NotionalValue && this.deal.PosiNotionalValue)
? this.deal.PosiNotionalValue / this.deal.NotionalValue : 1;
// 转换期末标的价格为百分比形式
if (this.floatPosition.TradingAmountAvg) {
this.floatPosition.TradingAmountAvg = swapPricePrecision.shiftDecimal(this.floatPosition.TradingAmountAvg, this.multiplier === 100 ? 2 : 0);
}
},
IsBond(instType) {
return tradeHelper.IsBond(instType);
},
priceFormat(price) {
price = swapPricePrecision.shiftDecimal(price, this.multiplier === 100 ? 2 : 0);
var pricef = swapPricePrecision.format(price, this.floatPosition && this.floatPosition.UnderlyingInstrumentType, 'grossPrice');
return pricef;
},
dataFormat() {
this.deal.NotionalValue = formatSwapAmount(this.deal.NotionalValue);
this.deal.PosiNotionalValue = formatSwapAmount(this.deal.PosiNotionalValue);
this.deal.CloseNotionalValue = formatSwapAmount(this.deal.CloseNotionalValue);
this.deal.NotionalQty = formatSwapQuantity(this.deal.NotionalQty);
this.deal.PositionQty2 = formatSwapQuantity(this.deal.PositionQty);
this.floatPosition.Quantity = formatSwapQuantity(this.floatPosition.Quantity);
this.floatPosition.PositionQty = formatSwapQuantity(this.floatPosition.PositionQty);
this.deal.CloseQty = formatSwapQuantity(this.deal.CloseQty);
this.deal.ClosePercent = otcformat.fixed6(this.deal.ClosePercent);
this.deal.SwapCloseAmount = formatSwapAmount(this.deal.SwapCloseAmount);
//this.floatPosition.PosiNetPrice = otcformat.trading.tradeSinglePrice(this.floatPosition.PosiNetPrice);
//this.floatPosition.PosiGrossPrice = otcformat.trading.tradeSinglePrice(this.floatPosition.PosiGrossPrice);
this.floatPosition.TradingAmountAvg = swapPricePrecision.roundForSubmit(
this.floatPosition.TradingAmountAvg,
this.floatPosition.UnderlyingInstrumentType,
'grossPrice');
this.floatPosition.TradingFee = formatSwapAmount(this.floatPosition.TradingFee);
this.floatPosition.TradingFeePending = formatSwapAmount(this.floatPosition.TradingFeePending);
this.floatPosition.DividendIn = formatSwapAmount(this.floatPosition.DividendIn);
this.floatPosition.MarkClosePnl = formatSwapAmount(this.floatPosition.MarkClosePnl);
this.interestList.forEach(x => {
//x.Principal = formatSwapAmount(x.Principal);
//x.Rate = otcformat.fixed6(x.Rate);
x.InterestAmount = formatSwapAmount(x.InterestAmount);
x.InterestClosePnL = formatSwapAmount(x.InterestClosePnL);
//x.InterestStartDate = x.InterestStartDate ? x.InterestStartDate.substr(0, 10) : "";
//x.InterestEndDate = x.InterestEndDate ? x.InterestEndDate.substr(0, 10) : "";
});
this.marginList.forEach(x => {
x.InterestAmount = formatSwapAmount(x.InterestAmount);
x.InterestClosePnL = formatSwapAmount(x.InterestClosePnL);
});
},
setValueDate(e) {//修改事件日期,并同步平仓日期
if (e) {
this.deal.ValueDate = e;
this.deal.UnwindDate = e;
this.floatPosition.UnwindDate = e;
}
if (!isUseApproval) {
this.getInterestList();
//this.refreshUnderlyingPrice();
} else {
this.dataFormat();
}
},
setUnwindDate(e) {//修改平仓日期,并同步事件日期
this.setValueDate(e);
},
changeCloseMethod() {//修改平仓类型
if (this.deal.CloseMethod == 1) {
this.deal.ClosePercent = this.oriClosePercent;
this.deal.CloseNotionalValue = formatSwapAmount(parseFloat(this.deal.PosiNotionalValue));
this.deal.CloseQty = this.deal.PositionQty;
} else {
// ClosePercent 是占期初口径(A),需除以 oriClosePercent 转占剩余(B) 再乘剩余数量
this.deal.CloseQty = this.calcCloseQtyByPercent(this.deal.ClosePercent);
}
this.calcTradingFeePending();
this.refreshTradingFeeByUnit();
this.getInterestList();
this.calcFloatClosePnl();
},
// 按"占期初口径(A)"的 ClosePercent 反算平仓数量:CloseQty = PositionQty × (ClosePercent / oriClosePercent)
// 多次部分平仓后必须这样转换,否则全部↔部分切换时 ClosePercent 没变但 CloseQty 会变(不自洽)
// 使用 swapCalc.calcCloseQtyByOriginalPercent 的 roundHalfAwayFromZero 避免 JS 浮点精度偏差
// (如 32500000*(0.5/0.65)=24999999.999999996 而非 25000000
calcCloseQtyByPercent(closePercent) {
return SwapCalc.calcCloseQtyByOriginalPercent(closePercent, this.oriClosePercent, this.deal.PositionQty);
},
calcTradingFeePending() {
this.floatPosition.TradingFeePending = swapPosiFeeCalc.calcTradingFeePending(
this.floatPosition.BeforeCloseFee,
this.floatPosition.PosiFeeType,
this.floatPosition.PosiTradingFeeUnit,
this.deal.CloseNotionalValue,
this.deal.CloseQty,
this.deal.NotionalValue,
this.deal.NotionalQty,
this.deal.ClosePercent);
},
refreshTradingFeeByUnit() {
this.floatPosition.TradingFee = swapPosiFeeCalc.calcTradingFee(
this.floatPosition.PosiFeeType,
this.floatPosition.PosiTradingFeeUnit,
this.deal.CloseNotionalValue,
this.deal.CloseQty);
},
changeCloseQty() {//修改平仓数量
if (parseFloat(this.deal.CloseQty) > parseFloat(this.deal.PositionQty)) {
main.message("平仓数量不能超过持仓数量");
return;
}
// CloseQty/PositionQty 得占剩余(B),× oriClosePercent 转回占期初(A)
var ori = parseFloat(this.oriClosePercent) || 0;
this.deal.ClosePercent = otcformat.fixed6((parseFloat(this.deal.CloseQty) / parseFloat(this.deal.PositionQty)) * ori);
if (parseFloat(this.deal.CloseQty) == parseFloat(this.deal.PositionQty)) {
this.deal.CloseMethod = 1;
} else {
this.deal.CloseMethod = 2;
}
// 占期初口径:平仓名义本金 = 平仓比例 × 期初名义本金(NotionalValue)
this.deal.CloseNotionalValue = formatSwapAmount(parseFloat(this.deal.ClosePercent) * parseFloat(this.deal.NotionalValue));
this.calcTradingFeePending();
this.refreshTradingFeeByUnit();
this.getInterestList();
this.calcFloatClosePnl();
},
changeClosePercent() {//修改平仓比例
if (parseFloat(this.deal.ClosePercent) > this.oriClosePercent) {
main.message("平仓比例不能超过" + this.oriClosePercent * 100 + "%");
this.deal.ClosePercent = this.oriClosePercent;
return;
}
// 调试埋点(?otcdebug=1):记录用户改后的平仓比例,便于定位"改了比例利息腿却不动"的前端入口
if (window.otcDebug) window.otcDebug.log('[unwind] changeClosePercent → 平仓比例=', this.deal.ClosePercent,
' oriClosePercent=', this.oriClosePercent, ' 占期初口径');
this.deal.CloseQty = this.calcCloseQtyByPercent(this.deal.ClosePercent);
// 占期初口径:平仓名义本金 = 平仓比例 × 期初名义本金(NotionalValue)
this.deal.CloseNotionalValue = formatSwapAmount(parseFloat(this.deal.ClosePercent) * parseFloat(this.deal.NotionalValue));
if (parseFloat(this.deal.ClosePercent) == parseFloat(this.oriClosePercent)) {
this.deal.CloseMethod = 1;
} else {
this.deal.CloseMethod = 2;
}
this.calcTradingFeePending();
this.refreshTradingFeeByUnit();
this.getInterestList();
this.calcFloatClosePnl();
},
changeCloseNotionalValue() {//修改平仓名义本金
if (parseFloat(this.deal.CloseNotionalValue) > parseFloat(this.deal.PosiNotionalValue)) {
main.message("平仓名义本金不能超过持仓名义本金");
this.deal.CloseNotionalValue = this.deal.PosiNotionalValue;
return;
}
// 占期初口径:平仓比例 = 平仓名义本金 / 期初名义本金(NotionalValue)
this.deal.ClosePercent = otcformat.fixed6(parseFloat(this.deal.CloseNotionalValue) / parseFloat(this.deal.NotionalValue));
this.deal.CloseQty = this.calcCloseQtyByPercent(this.deal.ClosePercent);
if (parseFloat(this.deal.ClosePercent) == parseFloat(this.oriClosePercent)) {
this.deal.CloseMethod = 1;
} else {
this.deal.CloseMethod = 2;
}
this.calcTradingFeePending();
this.refreshTradingFeeByUnit();
this.getInterestList();
this.calcFloatClosePnl();
},
changeUnderlyingPrice() {//修改标的价格
this.calcFloatClosePnl();
},
refreshUnderlyingPrice() {//刷新标的价格
var thisObj = this;
main.post("/underlying_manager/GetUnderlyingPriceByCode",
{ code: thisObj.floatPosition.UnderlyingCode, valuedate: thisObj.deal.ValueDate })
.done(function (res) {
thisObj.floatPosition.TradingAmountAvg = swapPricePrecision.roundForSubmit(
swapPricePrecision.shiftDecimal(res.obj, thisObj.multiplier === 100 ? 2 : 0),
thisObj.floatPosition.UnderlyingInstrumentType,
'grossPrice');
thisObj.calcFloatClosePnl();
});
},
calcFloatClosePnl() {//计算浮动端平仓盈亏
var thisObj = this;
let floatRatio = thisObj.floatPosition.PayDirection == 1 ? 1 : -1;
let longRatio = thisObj.floatPosition.PositionType == 1 ? 1 : -1;
let TradingFee = thisObj.floatPosition.TradingFee == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFee);
let TradingFeePending = thisObj.floatPosition.TradingFeePending == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFeePending);
let deliveryPrice = thisObj.getStorageDeliveryPrice();
thisObj.floatPosition.MarkClosePnl = Math.round(thisObj.deal.CloseQty * (deliveryPrice - thisObj.initPosiNetPrice) * floatRatio * longRatio * 10000) / 10000;
thisObj.floatPosition.MarkClosePnl = Number(thisObj.floatPosition.MarkClosePnl.toFixed(2));//MarkClosePnl 纯盯市不要计算交易费用和分红
thisObj.floatPosition.MarkClosePnl = formatSwapAmount(thisObj.floatPosition.MarkClosePnl);
thisObj.floatPosition.FloatPnlSum = (parseFloat(thisObj.floatPosition.MarkClosePnl) + TradingFee + TradingFeePending + parseFloat(thisObj.floatPosition.DividendIn)).toFixed(2);
thisObj.calcCloseAmount();
},
changeTradingFee() {//修改交易费用
this.calcFloatClosePnl();
},
changeInterestAmount(item) {//修改利息金额
let interestRatio = item.InterestDirection == 1 ? 1 : -1;
item.InterestClosePnL = formatSwapAmount(parseFloat(item.InterestAmount) * interestRatio + parseFloat(item.InterestFee) * interestRatio);
this.calcCloseAmount();
},
//calcClosePnL() {//计算浮动端平仓盈亏
// let pnl = parseFloat(this.floatPosition.ClosePnL) - parseFloat(this.floatPosition.TradingFee);
// this.floatPosition.ClosePnL = formatSwapAmount(pnl);
// this.calcCloseAmount();
//},
calcCloseAmount() {//计算平仓总额=浮动收取+利息收取-浮动支付-利息支付
let floatRatio = this.floatPosition.PayDirection == 1 ? 1 : -1;
let ratio = this.floatPosition.PositionType == 1 ? 1 : -1;
let thisObj = this;
let pnl = parseFloat(this.floatPosition.FloatPnlSum);
let TradingFee = thisObj.floatPosition.TradingFee == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFee);
thisObj.deal.SwapCloseAmount = pnl;
thisObj.deal.SwapRealizedPnL = pnl;
thisObj.deal.SwapMarginRebatePnl = 0;
thisObj.deal.SwapMarginAmount = 0;
let deliveryPrice = thisObj.getStorageDeliveryPrice();
thisObj.floatPosition.TradingAmount = deliveryPrice * parseFloat(thisObj.deal.CloseQty);
thisObj.floatPosition.CloseFee = TradingFee;
if (thisObj.deal.CloseQty == 0) {
thisObj.floatPosition.TradingAmountFeeAvg = 0;
} else {
thisObj.floatPosition.TradingAmountFeeAvg = deliveryPrice + (TradingFee / thisObj.deal.CloseQty) * ratio;
}
this.interestList.forEach(x => {
/*let interestRatio = x.InterestDirection == 1 ? 1 : -1;*/
let interestAmount = parseFloat(x.InterestClosePnL);
thisObj.deal.SwapCloseAmount = parseFloat(thisObj.deal.SwapCloseAmount) + interestAmount;
thisObj.deal.SwapRealizedPnL = parseFloat(thisObj.deal.SwapRealizedPnL) + interestAmount;
});
this.marginList.forEach(x => {
let interestAmount = parseFloat(x.InterestClosePnL);
let interestRatio = x.InterestDirection == 1 ? -1 : 1;
thisObj.deal.SwapCloseAmount = parseFloat(thisObj.deal.SwapCloseAmount) + interestAmount;
thisObj.deal.SwapMarginRebatePnl = parseFloat(thisObj.deal.SwapMarginRebatePnl) + interestAmount;
thisObj.deal.SwapRealizedPnL = parseFloat(thisObj.deal.SwapRealizedPnL) + interestAmount;
thisObj.deal.SwapMarginAmount = parseFloat(thisObj.deal.SwapMarginAmount) + parseFloat(x.InterestPrincipal) * interestRatio;
});
thisObj.deal.SwapRealizedPnL = Number(thisObj.deal.SwapRealizedPnL.toFixed(2));
thisObj.deal.SwapCloseAmount = Number(thisObj.deal.SwapCloseAmount.toFixed(2));
thisObj.deal.SwapCloseAmount = formatSwapAmount(thisObj.deal.SwapCloseAmount);
thisObj.deal.SwapRealizedPnL = formatSwapAmount(thisObj.deal.SwapRealizedPnL);
thisObj.deal.SwapMarginRebatePnl = formatSwapAmount(thisObj.deal.SwapMarginRebatePnl);
thisObj.deal.SwapMarginAmount = formatSwapAmount(thisObj.deal.SwapMarginAmount);
},
getInterestList() {//根据平仓日期获取利息腿信息
var thisObj = this;
// closePercent 按"占期初(original)"语义(A)传给后端,由 GetUnwindInterestList 转为"占剩余(B)"计算
var postData = { valueDate: thisObj.deal.ValueDate, unwindDate: thisObj.deal.ValueDate, tradeId: thisObj.deal.SwapTradeId, closePercent: thisObj.deal.ClosePercent, eventType: 2, notionalValue: thisObj.deal.NotionalValue, posiNotionalValue: thisObj.deal.PosiNotionalValue }
// 调试埋点(?otcdebug=1):记录实际发给后端的平仓比例——未来若"改比例利息腿不动",
// 对比此处请求比例 与 下方返回各腿 principal/amount 是否随比例变化,即可定位是前端没传对还是后端没缩放。
if (window.otcDebug) window.otcDebug.log('[unwind] getInterestList → POST closePercent=', thisObj.deal.ClosePercent,
' closeNotionalValue=', thisObj.deal.CloseNotionalValue, ' posiNotionalValue=', thisObj.deal.PosiNotionalValue);
main.post("/swaptrade2/GetUnwindInterestList", postData, { async: true }).done(function (resp) {
thisObj.interestList = resp.obj.filter((item) => {
return item.InterestMode == 1 || item.InterestMode == 2 || item.InterestMode == 9;
});
thisObj.marginList = resp.obj.filter((item) => {
return item.InterestMode == 5 || item.InterestMode == 6;
});
// 调试埋点(?otcdebug=1):逐腿打印 mode/principal/amount/rate,定位哪条腿不随平仓比例缩放
// (如 mode=1 固定值腿在 GLMS 缺陷中曾恒为全量、不随比例变化)。
if (window.otcDebug) window.otcDebug.log('[unwind] getInterestList ← 返回利息腿=', thisObj.interestList.map(function (i) {
return { mode: i.InterestMode, principal: i.InterestPrincipal, amount: i.InterestAmount, rate: i.InterestRate };
}));
thisObj.calcCloseAmount();
thisObj.dataFormat();
thisObj.getDivindIn();
});
},
getDivindIn() {
var thisObj = this;
// 方案C:分红改由后端 InitUnwind 读 EOD PosiDividendSum 填入 floatPosition.DividendIn 与 DividendPending
// (单一可信源)。前端不再调用 GetBondPayMentInterest 自算——消除"期初持仓×totalInterest"对已平仓
// 部分的重复计入(GLMS-20260105-0004 平仓前部分平仓40%后,再平仓时分红误显 -36,160,应为 0)。
// ⚠ floatPosition.DividendIn / DividendPending 均保持后端返回值不动,前端不得覆盖:
// - DividendIn(本次落袋)、DividendPending(待结算存量=PosiDividendSum 全量口径)。
// - 互换页 DividendPending 保持 0(互换=全量结清,结清后待结算归0),见 incomeSwapTrade.js。
// - 历史:曾硬编码 DividendPending=0,对 PosiDividendSum≠0 的部分平仓会落库错误的 0(回归)。
thisObj.calcFloatClosePnl();
thisObj.dataFormat();
},
closeTrade() {//平仓
var thisObj = this;
if (main.isEmpty(thisObj.deal.ValueDate)) {
main.message("请输入平仓日期");
return;
}
if (thisObj.deal.CloseType == 1) {//数量平仓方式
if (parseFloat(thisObj.deal.CloseQty) > parseFloat(thisObj.deal.PositionQty)) {
main.message("平仓数量不能持仓数量");
return;
}
if (parseFloat(this.deal.CloseQty) <= 0) {
main.message("平仓数量不能小于或等于0");
return;
}
} else {
if (parseFloat(this.deal.ClosePercent) > 1) {
main.message("平仓比例不能超过100%");
return;
}
if (parseFloat(this.deal.CloseNotionalValue) > parseFloat(this.deal.PosiNotionalValue)) {
main.message("平仓名义本金不能超过持仓名义本金");
return;
}
}
thisObj.deal.UnwindDate = thisObj.deal.ValueDate;
let reqObj = _.cloneDeep(thisObj.deal);
let marginCloneList = _.cloneDeep(thisObj.marginList);
reqObj.FlowEvents = _.cloneDeep(thisObj.interestList);
marginCloneList.forEach((item) => {
reqObj.FlowEvents.push(item);
})
thisObj.floatPosition.EventDate = thisObj.deal.ValueDate;
let floatPosition = _.cloneDeep(thisObj.floatPosition);
floatPosition.Quantity = reqObj.CloseQty;
floatPosition.TradingAmountAvg = thisObj.getStorageDeliveryPrice();
reqObj.FlowEvents.push(floatPosition);
var postData = { unwindData: reqObj };
var msg = "确认提交平仓?";
var postUrl = "/swaptrade2/SwapUnwindJson";
if (g_isShowReCheckClose) {
msg = "确认提交平仓审核?";
postUrl = "/swaptrade2/ApplyUnwind";
postData.eventType = 2;//互换3,平仓2
}
main.confirm(msg,
function () {
//重新计算百分比
var thisObj2 = thisObj;
main.post(postUrl, postData).done(function (res) {
if (res.success) {
thisObj2.closetrade_cashWindow();
}
else {
try {
thisObj2.closetrade_cashWindow();
} catch (e) {
}
}
});
});
},
getSumbitText: function () {
return g_isShowReCheckClose ? "审核提交" : "保存";
},
submitApproval(status) {
var pop = '';
if (status === 'pass') {
pop = "确认通过审批?";
}
if (status === 'reject') {
pop = "确认拒绝?";
}
let thisObj = this;
var confirmFunc = function (additionalProcessing) {
var pData = { tradeId: thisObj.deal.SwapTradeId, status: status, text: "" };
if (!main.isEmpty(additionalProcessing)) {
pData.additionalProcessing = additionalProcessing;
}
var thisObj2 = thisObj;
main.post("/processtradelog/UpdateTradeProcessLog", pData).done(
function (data) {
if (data.obj && data.obj.proccessType == "AdditionalProcessing") {
if (data.obj.type == "LackOfMoney") {
var htmlContent = `<div style="padding:10px">${data.obj.message}</div>`;
var lackMoneyConfirmLayer = main.open2("提示",
htmlContent,
{
area: ["430px", "175px"],
btn: ['交易特批', '取消'],
yes: function (index, layero) {
var layerIndex = lackMoneyConfirmLayer;
main.confirm("客户资金或授信不足,强制成交会导致本机构产生风险!要继续审批通过?", function () {
layer.close(layerIndex);
confirmFunc("LackOfMoney");
});
},
cancel: function (index, layero) {
if (window.parent && window.parent.reloadtrade) {
thisObj2.closetrade_cashWindow();
}
(parent || window).layer.closeAll();
}
});
}
return;
}
(parent || window).main.message(data.msg);
try { thisObj2.closetrade_cashWindow(); }
catch (e) { }
if (parent) {
parent.layer.closeAll();
}
});
}
main.confirm(pop, confirmFunc);
},
closetrade_cashWindow: function () {
layer.closeMe('reloadData');
},
closeCurrentWindow: function () {
try {
if (window.parent && window.parent.reload) window.parent.reload();
} catch (e) {
}
try {
var layer = window.parent.layer;
layer.close(layer.getFrameIndex(window.name));
} catch (e) {
}
}
},
components: {
'vue-datepicker': FastVue.vueDatePicker(),
'vue-number-input': FastVue.vueNumberInput(),
'vue-swap-price-input': swapPricePrecision.createVueInputComponent(),
}
});