fix: 佣金按委托级合并计费(分笔成交只收一次佣金)
- calcOrderFees 委托层合并计费:同一委托分笔成交按总金额算一次佣金(最低5元一次) - mapTrade 保留原始成交字段,不再逐笔算费 - 前端聚合调用 calcOrderFees,展开明细只展示成交本身 - 验证:200股拆两笔佣金5元(非10元);两笔独立委托各5元
This commit is contained in:
@@ -48,6 +48,23 @@ function directionText(direction) {
|
||||
return '—';
|
||||
}
|
||||
|
||||
/** 费用计算:按整笔委托合并(同一委托分笔成交只收一次佣金,最低5元;2026-09-01 老师修正) */
|
||||
function calcOrderFeesLocal(trades, commissionRateWan) {
|
||||
const list = Array.isArray(trades) ? trades : [];
|
||||
const totalAmount = list.reduce((s, t) => s + Math.max(0, +(t.amount ?? 0)), 0);
|
||||
const direction = list[0]?.direction ?? '';
|
||||
let commission = totalAmount * (commissionRateWan / 10000);
|
||||
if (commission < 5 && commission > 0) commission = 5;
|
||||
const stampTax = direction === 'sell' ? totalAmount * 0.0005 : 0;
|
||||
const transferFee = totalAmount * 0.00001;
|
||||
return {
|
||||
commission: +commission.toFixed(4),
|
||||
stampTax: +stampTax.toFixed(4),
|
||||
transferFee: +transferFee.toFixed(4),
|
||||
total: +(commission + stampTax + transferFee).toFixed(4),
|
||||
};
|
||||
}
|
||||
|
||||
/** 合并逻辑:按 m_strOrderSysID 把成交聚合进委托 */
|
||||
function mergeOrdersAndTrades(orders, trades) {
|
||||
const tradeByOrder = new Map();
|
||||
@@ -59,24 +76,22 @@ function mergeOrdersAndTrades(orders, trades) {
|
||||
const ts = tradeByOrder.get(o.orderId) ?? [];
|
||||
const totalVol = ts.reduce((s, t) => s + t.volume, 0);
|
||||
const totalAmount = ts.reduce((s, t) => s + t.amount, 0);
|
||||
// 费用逐笔计算后聚合(每笔 commission/stampTax/transferFee 已是金额)
|
||||
const aggCommission = ts.reduce((s, t) => s + t.commission, 0);
|
||||
const aggStampTax = ts.reduce((s, t) => s + t.stampTax, 0);
|
||||
const aggTransferFee = ts.reduce((s, t) => s + t.transferFee, 0);
|
||||
const aggFeeTotal = ts.reduce((s, t) => s + t.feeTotal, 0);
|
||||
const weightedPrice = totalVol > 0
|
||||
? ts.reduce((s, t) => s + t.price * t.volume, 0) / totalVol
|
||||
: 0;
|
||||
// 费用:按整笔委托合并计算(同一委托分笔成交只收一次佣金,calcOrderFees)
|
||||
const rateWan = ts[0]?.commissionRateWan ?? 0; // 佣金费率(万分之,来自成交,账号级一致)
|
||||
const fees = calcOrderFeesLocal(ts, rateWan);
|
||||
return {
|
||||
...o,
|
||||
trades: ts,
|
||||
aggVolume: totalVol,
|
||||
aggPrice: weightedPrice,
|
||||
aggAmount: totalAmount,
|
||||
aggCommission,
|
||||
aggStampTax,
|
||||
aggTransferFee,
|
||||
aggFeeTotal,
|
||||
aggCommission: fees.commission,
|
||||
aggStampTax: fees.stampTax,
|
||||
aggTransferFee: fees.transferFee,
|
||||
aggFeeTotal: fees.total,
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -288,10 +303,6 @@ function OrderRows({ order, expanded, onToggle }) {
|
||||
<th style={{ ...tdStyle, textAlign: 'right' }}>成交价</th>
|
||||
<th style={{ ...tdStyle, textAlign: 'right' }}>成交量</th>
|
||||
<th style={{ ...tdStyle, textAlign: 'right' }}>成交额</th>
|
||||
<th style={{ ...tdStyle, textAlign: 'right' }}>总费用</th>
|
||||
<th style={{ ...tdStyle, textAlign: 'right' }}>佣金</th>
|
||||
<th style={{ ...tdStyle, textAlign: 'right' }}>印花税</th>
|
||||
<th style={{ ...tdStyle, textAlign: 'right' }}>过户费</th>
|
||||
<th style={{ ...tdStyle, textAlign: 'right' }}>成交号</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -302,10 +313,6 @@ function OrderRows({ order, expanded, onToggle }) {
|
||||
<td style={{ ...tdStyle, textAlign: 'right' }}>{fmtNum(t.price)}</td>
|
||||
<td style={{ ...tdStyle, textAlign: 'right' }}>{fmtNum(t.volume, 0)}</td>
|
||||
<td style={{ ...tdStyle, textAlign: 'right' }}>{fmtNum(t.amount)}</td>
|
||||
<td style={{ ...tdStyle, textAlign: 'right' }}>{fmtNum(t.feeTotal, 2)}</td>
|
||||
<td style={{ ...tdStyle, textAlign: 'right' }}>{fmtNum(t.commission, 2)}</td>
|
||||
<td style={{ ...tdStyle, textAlign: 'right' }}>{fmtNum(t.stampTax, 2)}</td>
|
||||
<td style={{ ...tdStyle, textAlign: 'right' }}>{fmtNum(t.transferFee, 2)}</td>
|
||||
<td style={{ ...tdStyle, textAlign: 'right', color: '#999' }}>{t.tradeId}</td>
|
||||
</tr>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user