margins)
+ {
+ var marginList = margins.ToList();
+ var totalWeight = marginList.Sum(x => Math.Abs(x.InterestPrincipalFix));
+ return totalWeight == 0
+ ? 0
+ : marginList.Sum(x => x.InterestIncomeSum
+ * (x.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1)
+ * Math.Abs(x.InterestPrincipalFix)) / totalWeight;
+ }
+ ///
+ /// 将数据库中以公司/交易簿记方向保存的日终字段转换为客户视角。
+ /// 该转换必须在拆分浮动收益、费用和期间付息/分红之前完成,
+ /// 否则页面、Excel 和净额结算金额会出现相反符号。
///
///
private void SetClientEodPosition(eod_swap_position position)
@@ -2412,10 +2588,10 @@ namespace YLErp.Modules.SwapModule
position.SwapPositionValue = -position.SwapPositionValue;
position.PosiDividendSum = -position.PosiDividendSum;
}
- private void SetPosiPrice(eod_swap_position position)
+ private void SetPosiPrice(eod_swap_position position, bool? useBondPriceScale = null)
{
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(position.UnderlyingCode);
- if (um != null && um.IsBond())
+ if (useBondPriceScale ?? (um != null && um.IsBond()))
{
position.PosiNetPrice *= 100;
position.UnderlyingPrice *= 100;
diff --git a/YLErpWeb/App_Docs/导出模板/结算报告模板.xlsx b/YLErpWeb/App_Docs/导出模板/结算报告模板.xlsx
index ba6be62b..ae0f519f 100644
Binary files a/YLErpWeb/App_Docs/导出模板/结算报告模板.xlsx and b/YLErpWeb/App_Docs/导出模板/结算报告模板.xlsx differ
diff --git a/YLErpWeb/Views/SwapTrade2/TradeMarketReport_EodPosition.cshtml b/YLErpWeb/Views/SwapTrade2/TradeMarketReport_EodPosition.cshtml
index 1429aaec..3516c460 100644
--- a/YLErpWeb/Views/SwapTrade2/TradeMarketReport_EodPosition.cshtml
+++ b/YLErpWeb/Views/SwapTrade2/TradeMarketReport_EodPosition.cshtml
@@ -6,9 +6,8 @@
var pageObj = new
{
EndTime = ViewBag.EndTime?.ToString(),
- StartTime = ViewBag.StartTime?.ToString(),
valueDate = valuedateBLL.ValueDate.ToString("yyyy-MM-dd"),
- configcolumn = configcolumn_data.互换估值,
+ configcolumn = configcolumn_data.互换估值V1,
StructureType = ViewBag.StructureType
};
}
@@ -23,7 +22,7 @@
width: 250px !important;
}
- #ValueDateFrom, #ValueDate {
+ #ValueDate {
width: 152px !important;
font-size: 1rem !important;
}
@@ -51,9 +50,8 @@
@Html.MyAceDropdownInput("ClientId", "客户名称", ClientDataModel.GetAllClient(), false, true, null, false)
- @Html.MyAceDropdownInput("BookId", "簿记账户", AssetunitController.GetClientassetunit(), false, true, null, false)
@Html.CheckBox("ParentFlag", false) @Html.Label(null,"包含子级", new { @style = "font-size:12px;" })
- @Html.ShortInput("ValueDateFrom", "起始日期:")
+ @Html.MyAceDropdownInput("BookId", "簿记账户", AssetunitController.GetClientassetunit(), false, true, null, false)
@Html.ShortInput("ValueDate", "结束日期:")
@MyControls.SearchBtn()
@if (CurUser.结算管理_每日估值报告邮件发送)
@@ -61,7 +59,6 @@
@MyControls.Btn("配置报告", "PopDesc()")
@MyControls.Btn("发送报告", "SendReport()")
}
-
diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js
index a011f68f..045d5dc2 100644
--- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js
+++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js
@@ -456,10 +456,6 @@ function colModelGridEodPosition() {
return colModelGrid;
}
//框架合约table
-//TODO(估值模块V1-缺失字段): 以下需求字段本轮未实现,待后端确认数据来源后补充:
-// - 期间付息/分红(浮动端分组)
-// - 付息方式、合约估值(到期轧差口径/期间支付派息口径)(估值与实现收益分组)
-// - 标的类型(基本信息分组)
function colModelGridEodSwap() {
//按需求《估值模块V1》2.2 分组定义排列列顺序,确保组内列连续(setGroupHeaders 要求)
var colModelGrid = [{
@@ -526,6 +522,13 @@ function colModelGridEodSwap() {
width: 100,
align: 'center',
sortable: false
+ }, {
+ name: 'UnderlyingType',
+ label: '标的类型',
+ index: 'UnderlyingType',
+ width: 100,
+ align: 'center',
+ sortable: false
},
//=== 名义本金 ===
{
@@ -568,12 +571,22 @@ function colModelGridEodSwap() {
},
//=== 浮动端 ===
{
- name: 'position.FloatingPnL',
+ name: 'FloatingUnrealizedPnl',
label: '合约浮动端待实现收益',
- index: 'position.FloatingPnL',
+ index: 'FloatingUnrealizedPnl',
width: 150,
align: 'center',
formatter: StockEqvNotionalFormat,
+ }, {
+ name: 'PeriodAmount',
+ label: '期间付息/分红',
+ index: 'PeriodAmount',
+ width: 150,
+ align: 'center',
+ formatter: StockEqvNotionalFormat,
+ cellattr: function () {
+ return ' title="合约期间内的期间付息金额(无关乎派息支付日)"';
+ },
},
//=== 利息端 ===
{
@@ -613,30 +626,23 @@ function colModelGridEodSwap() {
width: 150,
align: 'center',
formatter: StockEqvNotionalFormat,
- },
- //=== 估值与实现收益 ===
- {
- name: 'position.PostionValue',
- label: '合约持仓价值',
- index: 'position.PostionValue',
- width: 150,
- align: 'center',
- formatter: StockEqvNotionalFormat
}, {
- name: 'position.TdRealizedPnL',
- label: '合约当日实现收益',
- index: 'position.TdRealizedPnL',
- width: 150,
- align: 'center',
- formatter: StockEqvNotionalFormat
- }, {
- name: 'position.RealizedPnL',
- label: '合约已实现收益',
- index: 'position.RealizedPnL',
- width: 150,
+ name: 'MarginInterestGain',
+ label: '收取对手方保证金利息',
+ index: 'MarginInterestGain',
+ width: 170,
align: 'center',
formatter: StockEqvNotionalFormat,
}, {
+ name: 'MarginInterestLoss',
+ label: '支付对手方保证金利息',
+ index: 'MarginInterestLoss',
+ width: 170,
+ align: 'center',
+ formatter: StockEqvNotionalFormat,
+ },
+ //=== 估值与实现收益 ===
+ {
name: 'position.dv01',
label: 'DV',
index: 'position.dv01',
@@ -648,6 +654,33 @@ function colModelGridEodSwap() {
if (abs < 0.0001) return "0";
return cellvalue.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 4 });
},
+ }, {
+ name: 'InterestPaymentMethod',
+ label: '付息方式',
+ index: 'InterestPaymentMethod',
+ width: 120,
+ align: 'center',
+ }, {
+ name: 'MaturityNettingValuation',
+ label: '合约估值(到期轧差口径)',
+ index: 'MaturityNettingValuation',
+ width: 190,
+ align: 'center',
+ formatter: NullableStockEqvNotionalFormat,
+ }, {
+ name: 'PeriodPaymentValuation',
+ label: '合约估值(期间支付派息口径)',
+ index: 'PeriodPaymentValuation',
+ width: 210,
+ align: 'center',
+ formatter: NullableStockEqvNotionalFormat,
+ }, {
+ name: 'position.RealizedPnL',
+ label: '合约已实现收益',
+ index: 'position.RealizedPnL',
+ width: 150,
+ align: 'center',
+ formatter: StockEqvNotionalFormat,
}
];
@@ -657,13 +690,13 @@ function colModelGridEodSwap() {
//框架合约分组配置(对应需求《估值模块V1》2.2 字段定义)
//columns 使用 colModel.name;组内列在 colModel 中必须连续
var eodSwapGroupConfig = [
- { title: '基本信息', columns: ['position.ValueDate', 'AssetBookName', 'ClientName', 'SwapTradeNo', 'StructureType', 'SwapTradeTypeStr'] },
+ { title: '基本信息', columns: ['position.ValueDate', 'AssetBookName', 'ClientName', 'SwapTradeNo', 'StructureType', 'SwapTradeTypeStr', 'UnderlyingType'] },
{ title: '名义本金', columns: ['position.NotionalValue', 'position.NotionalValueLong', 'position.NotionalValueShort'] },
{ title: '标的市值', columns: ['position.MarketValueLong', 'position.MarketValueShort'] },
- { title: '浮动端', columns: ['position.FloatingPnL'] },
+ { title: '浮动端', columns: ['FloatingUnrealizedPnl', 'PeriodAmount'] },
{ title: '利息端', columns: ['position.InterestPnL'] },
- { title: '保证金', columns: ['position.InitMarginGain', 'position.PostionMarginGain', 'position.InitMarginLoss', 'position.PostionMarginLoss'] },
- { title: '估值与实现收益', columns: ['position.PostionValue', 'position.TdRealizedPnL', 'position.RealizedPnL', 'position.dv01'] }
+ { title: '保证金', columns: ['position.InitMarginGain', 'position.PostionMarginGain', 'position.InitMarginLoss', 'position.PostionMarginLoss', 'MarginInterestGain', 'MarginInterestLoss'] },
+ { title: '估值与实现收益', columns: ['position.dv01', 'InterestPaymentMethod', 'MaturityNettingValuation', 'PeriodPaymentValuation', 'position.RealizedPnL'] }
];
@@ -677,7 +710,11 @@ function gridComplete() {
if (page.tabIndex == 2) {
var defer = main.setcolumnChooser(jgrid, page.configcolumn_data);
$.when(defer).done(function () {
+ normalizeEodSwapColumnsForGroupHeaders(jgrid, eodSwapGroupConfig);
main.initCollapsibleGroupHeaders(jgrid, eodSwapGroupConfig);
+ jgrid.jqGrid('setLabel', 'PeriodAmount', null, null, {
+ title: '合约期间内的期间付息金额(无关乎派息支付日)'
+ });
});
} else {
main.setcolumnChooser(jgrid, page.configcolumn_data);
@@ -704,7 +741,69 @@ function exportVisibleColumns() {
var dateStr = $("#DateValueDate").val() || '';
var tabName = page.tabIndex == 2 ? '框架合约' : '日终持仓';
var fileName = '日终持仓风险_互换_' + tabName + (dateStr ? '_' + dateStr : '');
- main.exportVisibleColumnsToExcel(jgrid, fileName);
+ var groupConfig = page.tabIndex == 2 ? eodSwapGroupConfig : null;
+ if (page.tabIndex != 2) {
+ main.exportVisibleColumnsToExcel(jgrid, fileName, groupConfig);
+ return;
+ }
+
+ var exportPostData = $.extend({}, GetPostData(), {
+ page: 1,
+ rows: 0,
+ sidx: jgrid.jqGrid('getGridParam', 'sortname'),
+ sord: jgrid.jqGrid('getGridParam', 'sortorder')
+ });
+ $.ajax({
+ url: queryurl,
+ type: 'POST',
+ dataType: 'json',
+ traditional: true,
+ data: exportPostData
+ }).done(function (result) {
+ main.exportVisibleColumnsToExcel(jgrid, fileName, groupConfig, result && result.rows ? result.rows : []);
+ }).fail(function () {
+ main.message && main.message('导出失败,无法获取筛选后的全部数据');
+ });
+}
+
+function normalizeEodSwapColumnsForGroupHeaders(jgrid, groupConfig) {
+ var colModel = jgrid.jqGrid('getGridParam', 'colModel') || [];
+ var currentNames = colModel.map(function (c) { return c.name; });
+ var groupedNames = [];
+ var groupedNameMap = {};
+ groupConfig.forEach(function (group) {
+ (group.columns || []).forEach(function (name) {
+ if (!groupedNameMap[name] && currentNames.indexOf(name) >= 0) {
+ groupedNameMap[name] = true;
+ groupedNames.push(name);
+ }
+ });
+ });
+
+ var firstGroupedIndex = currentNames.findIndex(function (name) { return groupedNameMap[name]; });
+ if (firstGroupedIndex < 0) {
+ return;
+ }
+
+ var prefixNames = currentNames.slice(0, firstGroupedIndex).filter(function (name) {
+ return !groupedNameMap[name];
+ });
+ var suffixNames = currentNames.slice(firstGroupedIndex).filter(function (name) {
+ return !groupedNameMap[name];
+ });
+ var desiredNames = prefixNames.concat(groupedNames).concat(suffixNames);
+ if (desiredNames.join('|') === currentNames.join('|')) {
+ return;
+ }
+
+ var perm = desiredNames.map(function (name) {
+ return currentNames.indexOf(name);
+ }).filter(function (idx) {
+ return idx >= 0;
+ });
+ if (perm.length === currentNames.length) {
+ jgrid.jqGrid("remapColumns", perm, true);
+ }
}
//---------------------------Formatter---------------------------------
@@ -719,6 +818,12 @@ function RealizedPnlFormat(cellValue, options, rowObject) {
function StockEqvNotionalFormat(cellValue, options, rowObject) {
return otcformat.trading.StockEqvNotional(cellValue);
}
+function NullableStockEqvNotionalFormat(cellValue, options, rowObject) {
+ if (cellValue === null || cellValue === undefined || cellValue === '') {
+ return '';
+ }
+ return StockEqvNotionalFormat(cellValue, options, rowObject);
+}
function PosiStatusFormat(cellValue, options, rowObject) {
return cellValue == 1 ? "已平" : "正常";
}
@@ -817,4 +922,4 @@ function SearchClick(isSearchclick) {
function showcolumnChooser() {
var jgrid = jQuery('#listGrid');
main.showcolumnChooser(jgrid, cloumnTargetName, page.configcolumn_data);
-}
\ No newline at end of file
+}
diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_EodPosition.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_EodPosition.js
index 9a6deb23..1642cdaf 100644
--- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_EodPosition.js
+++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_EodPosition.js
@@ -2,32 +2,16 @@
$(function () {
var PostData = {};
- //控件选择时的触发事件
- main.setTradeDatePicker("", "#ValueDate", page.calcDate, function (selectedDate) {
- if (selectedDate) {
- $("#ValueDateFrom").datepicker("option", "maxDate", selectedDate);
- }
- });
- main.setTradeDatePicker("", "#ValueDateFrom", page.calcDate, function (selectedDate) {
- if (selectedDate) {
- $("#ValueDate").datepicker("option", "minDate", selectedDate);
- }
- });
- //手动修改时的触发事件
- $("#ValueDate").change(function () {
- $("#ValueDateFrom").datepicker("option", "maxDate", $("#ValueDate").val());
- });
- $("#ValueDateFrom").change(function () {
- $("#ValueDate").datepicker("option", "minDate", $("#ValueDateFrom").val());
- });
+ main.setTradeDatePicker("", "#ValueDate", page.calcDate);
- //默认初始值赋值逻辑
+ // 互换估值页仅暴露一个估值日。当前后端按 ValueDate 单日查询,
+ // 因此 ValueDateFrom 传同日仅用于保持请求对象和报告参数的日期语义一致。
$("#ValueDate").val(page.EndTime || page.calcDate);
- $("#ValueDateFrom").val(page.StartTime && page.EndTime ? page.StartTime : '');
PostData.StructureType = page.StructureType;
- PostData.ValueDateFrom = $("#ValueDateFrom").val();
+ PostData.ValueDateFrom = $("#ValueDate").val();
PostData.ValueDate = $("#ValueDate").val();
PostData.ClientId = $("#ClientId").val();
+ PostData.BookId = $("#BookId").val();
var grid = jQuery('#listGrid').jqGrid({
url: '/swaptrade2/clientEodSwapPositionQuery',
@@ -50,8 +34,7 @@ $(function () {
pagerpos: 'left',
rowNum: 100,
rowList: [100, 1000],
- loadComplete: gridComplete,
- grouping: true
+ loadComplete: gridComplete
});
g_grid = jQuery('#listGrid');
@@ -110,11 +93,7 @@ function searchPositionDetials(isSearchclick) {
// main.message("结束日期不能大于当前系统日期!");
// return;
//}
- if ($("#ValueDate").val() < $("#ValueDateFrom").val()) {
- main.message("起始日期不能大于结束日期!");
- return;
- }
- listGrid.appendPostData({ ValueDateFrom: $("#ValueDateFrom").val() });
+ listGrid.appendPostData({ ValueDateFrom: $("#ValueDate").val() });
listGrid.appendPostData({ ValueDate: $("#ValueDate").val() });
listGrid.appendPostData({ StructureType: page.StructureType });
if (typeof (isSearchclick) != "undefined" && isSearchclick) {
@@ -134,7 +113,7 @@ function onSortCol(index, icol, sortorder) {
var i = 0;
var colModelGrid = [
- //隐藏列(不参与分组)
+ //隐藏列
{
name: 'position.EncryptId',
label: 'EncryptId',
@@ -156,14 +135,6 @@ var colModelGrid = [
index: 'UnwindDate',
hidden: true,
optionHide: true
- }, {
- name: 'TradeNumber',
- label: '交易编号',
- index: 'TradeNumber',
- sortIndex: i++,
- width: 180,
- align: 'center',
- sortable: false
}, {
name: 'ConfrimNo',
label: '确认书编号',
@@ -173,11 +144,11 @@ var colModelGrid = [
align: 'center',
sortable: false
}, {
- name: 'ClientName',
- label: '交易对手',
- index: 'ClientName',
+ name: 'TradeNumber',
+ label: '交易编号',
+ index: 'TradeNumber',
sortIndex: i++,
- width: 120,
+ width: 180,
align: 'center',
sortable: false
}, {
@@ -189,6 +160,15 @@ var colModelGrid = [
align: 'center',
sortable: false,
formatter:'date',
+ }, {
+ name: 'MaturitySettlementDate',
+ label: '到期结算日',
+ index: 'MaturitySettlementDate',
+ sortIndex: i++,
+ width: 100,
+ align: 'center',
+ sortable: false,
+ formatter: 'date',
}, {
name: 'position.ValueDate',
label: '估值日',
@@ -212,22 +192,7 @@ var colModelGrid = [
width: 120,
align: 'center',
sortable: false,
- formatter: RateFormat
- }, {
- name: 'position.FloatRateUnderlyingCode',
- label: '基准利率',
- index: 'position.FloatRateUnderlyingCode',
- width: 120,
- align: 'center',
- sortable: false
- }, {
- name: 'position.FloatRate',
- label: '当日适用基准利率',
- index: 'position.FloatRate',
- width: 120,
- align: 'center',
- sortable: false,
- formatter: RateFormat
+ formatter: SpreadRateFormat
}, {
name: 'position.PosiNotionalValue',
label: '标的名义金额',
@@ -235,7 +200,7 @@ var colModelGrid = [
width: 150,
align: 'center',
sortable: false,
- formatter: StockEqvNotionalFormat,
+ formatter: AmountFormat,
}, {
name: 'position.PosiQuantity',
label: '标的数量',
@@ -250,6 +215,15 @@ var colModelGrid = [
index: 'PeriodAmount',
width: 100,
align: 'center',
+ formatter: NullableAmountFormat,
+ sortable: false
+ }, {
+ name: 'DividendAmount',
+ label: '期间分红',
+ index: 'DividendAmount',
+ width: 100,
+ align: 'center',
+ formatter: NullableAmountFormat,
sortable: false
}, {
name: 'position.PosiGrossPrice',
@@ -266,12 +240,7 @@ var colModelGrid = [
width: 150,
align: 'center',
sortable: false,
- formatter: function (cellValue, options, rowObject) {
- if (cellValue == null) {
- return "";
- }
- return otcformat.trading.premiumRateP(cellValue);
- }
+ formatter: YieldRateFormat
},
{
name: 'position.UnderlyingPrice',
@@ -302,15 +271,7 @@ var colModelGrid = [
index: 'InterestAmount',
width: 120,
align: 'center',
- formatter: StockEqvNotionalFormat,
- sortable: false,
- }, {
- name: 'position.PosiFeePending',
- label: '开仓交易费用',
- index: 'position.PosiFeePending',
- width: 120,
- align: 'center',
- formatter: StockEqvNotionalFormat,
+ formatter: FixedAmountFormat,
sortable: false,
}, {
name: 'position.PosiProfitSum',
@@ -318,7 +279,47 @@ var colModelGrid = [
index: 'position.PosiProfitSum',
width: 120,
align: 'center',
- formatter: StockEqvNotionalFormat,
+ formatter: FixedAmountFormat,
+ sortable: false,
+ }, {
+ name: 'position.PosiFeePending',
+ label: '开平仓交易费用',
+ index: 'position.PosiFeePending',
+ width: 120,
+ align: 'center',
+ formatter: FixedAmountFormat,
+ sortable: false,
+ }, {
+ name: 'OpenMarginRate',
+ label: '预付金利率',
+ index: 'OpenMarginRate',
+ width: 120,
+ align: 'center',
+ formatter: TrimmedRateFormat,
+ sortable: false,
+ }, {
+ name: 'MarginInterestAmount',
+ label: '预付金利息',
+ index: 'MarginInterestAmount',
+ width: 120,
+ align: 'center',
+ formatter: FixedAmountFormat,
+ sortable: false,
+ }, {
+ name: 'OpenMarginAmount',
+ label: '期初预付金',
+ index: 'OpenMarginAmount',
+ width: 120,
+ align: 'center',
+ formatter: FixedAmountFormat,
+ sortable: false,
+ }, {
+ name: 'AdditionalMarginAmount',
+ label: '追加预付金',
+ index: 'AdditionalMarginAmount',
+ width: 120,
+ align: 'center',
+ formatter: FixedAmountFormat,
sortable: false,
}, {
name: 'NetSettmentAmount',
@@ -326,23 +327,23 @@ var colModelGrid = [
index: 'NetSettmentAmount',
width: 120,
align: 'center',
- formatter: StockEqvNotionalFormat,
+ formatter: FixedAmountFormat,
+ sortable: false,
+ }, {
+ name: 'TrsValue',
+ label: 'TRS估值',
+ index: 'TrsValue',
+ width: 120,
+ align: 'center',
+ formatter: FixedAmountFormat,
sortable: false,
}
- //TODO(估值模块V1-缺失字段): 以下需求字段本轮未实现,待后端确认数据来源后补充:
- // - 期间分红(ETF适用,利率与规模分组)
- // - 预付金利率、预付金利息、期初预付金、追加预付金(预付金分组)
- // - TRS估值(汇总分组)
-];
-
-//互换估值分组配置(对应需求《估值模块V1》3.2.2 字段定义)
-//columns 使用 colModel.name;现有列顺序已天然满足分组连续性,无需重排
-var eodSwapValuationGroupConfig = [
- { title: '基本信息', columns: ['TradeNumber', 'ConfrimNo', 'ClientName', 'position.PosiStartDate', 'position.ValueDate', 'position.UnderlyingCode'] },
- { title: '利率与规模', columns: ['InterestRate', 'position.FloatRateUnderlyingCode', 'position.FloatRate', 'position.PosiNotionalValue', 'position.PosiQuantity', 'PeriodAmount'] },
- { title: '价格', columns: ['position.PosiGrossPrice', 'InitYtm', 'position.UnderlyingPrice', 'DayCount'] },
- { title: '收益', columns: ['FloatRateAbs', 'InterestAmount', 'position.PosiFeePending', 'position.PosiProfitSum', 'NetSettmentAmount'] }
];
+// 页面字段顺序以《估值模块V1》第二部分为准;历史个人列配置只能控制显隐,不能打乱业务列顺序。
+var defaultVisibleColumnNames = colModelGrid
+ .filter(function (column) { return column.hidden !== true; })
+ .map(function (column) { return column.name; });
+var documentColumnOrder = colModelGrid.map(function (column) { return column.name; });
function formatter6(cellvalue, options, rowObject) {
return main.formatNumber(cellvalue, 6);
@@ -372,25 +373,37 @@ function gridComplete() {
}
}
//jgrid.sortGrid(g_sort.name, g_sort.order);
- //在列设置应用完成后初始化可折叠分组表头(setcolumnChooser 会 remapColumns,须在其 done 回调后建表头)
- var defer = main.setcolumnChooser(jgrid, page.configcolumn);
- $.when(defer).done(function () {
- main.initCollapsibleGroupHeaders(jgrid, eodSwapValuationGroupConfig);
+ $.when(main.setcolumnChooser(jgrid, page.configcolumn)).always(function () {
+ restoreDocumentColumnOrder(jgrid);
+ ensureBusinessColumnsVisible(jgrid);
});
$(".selftooltip").tooltip({ html: true, show: 50000, trigger: "hover" });
$(window).off('resize.jqGrid');
}
-//导出互换估值当前可见列(需求《估值模块V1》3.2 + 4.2)
-//与现有 DownLoadReport(整份PDF/Excel报告)独立,互不影响
-function exportSwapValuationVisibleColumns() {
- var jgrid = jQuery('#listGrid');
- var clientName = $("#ClientId :selected").text() || '';
- var dateStr = $("#ValueDate").val() || '';
- var fileName = (clientName ? clientName + '_' : '') + '每日估值报告_互换估值' + (dateStr ? '_' + dateStr : '');
- main.exportVisibleColumnsToExcel(jgrid, fileName);
+function restoreDocumentColumnOrder(jgrid) {
+ var colModel = jgrid.jqGrid('getGridParam', 'colModel') || [];
+ var currentNames = colModel.map(function (column) { return column.name; });
+ var targetNames = currentNames
+ .filter(function (name) { return documentColumnOrder.indexOf(name) < 0; })
+ .concat(documentColumnOrder);
+ var permutation = targetNames.map(function (name) { return currentNames.indexOf(name); });
+ if (permutation.length === currentNames.length
+ && permutation.every(function (index) { return index >= 0; })
+ && permutation.some(function (index, targetIndex) { return index !== targetIndex; })) {
+ jgrid.jqGrid('remapColumns', permutation, true);
+ }
}
+function ensureBusinessColumnsVisible(jgrid) {
+ var colModel = jgrid.jqGrid('getGridParam', 'colModel') || [];
+ var hasVisibleBusinessColumn = colModel.some(function (column) {
+ return defaultVisibleColumnNames.indexOf(column.name) >= 0 && column.hidden !== true;
+ });
+ if (!hasVisibleBusinessColumn) {
+ jgrid.jqGrid('showCol', defaultVisibleColumnNames);
+ }
+}
function reloadTradeMarketReport() {
//重新加载
@@ -430,10 +443,6 @@ function SendReport() {
main.message("结束日期不能大于当前系统日期!");
return;
}
- if ($("#ValueDate").val() < $("#ValueDateFrom").val()) {
- main.message("起始日期不能大于结束日期!");
- return;
- }
main.open("向{0}发送报告".template(clientName), "/clientbalance/TradeMarketClientSend?clientid=" + param.ClientId + "&ParentFlag=" + param.ParentFlag);
}
function DownLoadReport() {
@@ -454,18 +463,16 @@ function DownLoadReport() {
main.message("结束日期不能大于当前系统日期!");
return;
}
- if ($("#ValueDate").val() < $("#ValueDateFrom").val()) {
- main.message("起始日期不能大于结束日期!");
- return;
- }
-
main.post("/clientbalance/ViewTradeMarketFile", screenData()).done(function (res) {
window.open(res.obj);
});
}
function screenData() {
- var data = { From: $("#ValueDateFrom").val(), To: $("#ValueDate").val() };
+ // 已移除起始日期控件,预览报告按单个估值日生成,From/To 保持同日。
+ var data = { From: $("#ValueDate").val(), To: $("#ValueDate").val() };
data.ClientId = $("#ClientId").val();
+ // 报告下载和发送弹窗均从 screenData 取参数,必须保留当前簿记账户筛选。
+ data.BookId = $("#BookId").val();
if ($("#ParentFlag").prop("checked"))
data.ParentFlag = true;
else
@@ -477,12 +484,35 @@ function showChiCang() {
main.showcolumnChooser(jQuery('#listGrid'), page.configcolumn);
}
function PriceFormat(cellValue, options, rowObject) {
- return otcformat.trading.umprice(cellValue);
+ return main.formatNumber(cellValue, 9, { grouping: true });
}
function StockEqvNotionalFormat(cellValue, options, rowObject) {
return otcformat.trading.StockEqvNotional(cellValue);
}
+function AmountFormat(cellValue, options, rowObject) {
+ return main.formatNumber(cellValue, 2, { trimTailZeros: true });
+}
+function NullableAmountFormat(cellValue, options, rowObject) {
+ if (cellValue === null || cellValue === undefined || cellValue === '') {
+ return '';
+ }
+ return AmountFormat(cellValue, options, rowObject);
+}
+function FixedAmountFormat(cellValue, options, rowObject) {
+ return main.formatNumber(cellValue, 2);
+}
+function YieldRateFormat(cellValue, options, rowObject) {
+ if (cellValue === null || cellValue === undefined || cellValue === '') {
+ return '';
+ }
+ // percent 格式会在数字末尾添加 %,通用 trimTailZeros 无法识别其后的 0。
+ // 先将小数收益率转为百分比数值,再格式化并追加 %,确保最多保留四位小数且去尾零。
+ return main.formatNumber(cellValue * 100, 4, { trimTailZeros: true }) + '%';
+}
+function TrimmedRateFormat(cellValue, options, rowObject) {
+ return main.formatNumber(cellValue, 4, { percent: true, trimTailZeros: true });
+}
function RateFormat(cellValue, options, rowObject) {
if (cellValue) {
var num = new Number(cellValue) * 100;
@@ -491,19 +521,23 @@ function RateFormat(cellValue, options, rowObject) {
return "0.0000%";
}
}
+function SpreadRateFormat(cellValue, options, rowObject) {
+ if (cellValue) {
+ var num = new Number(cellValue) * 100;
+ return num.toFixed(2) + "%";
+ } else {
+ return "0.00%";
+ }
+}
function locationChange(tab) {
if ($("#ValueDate").val() > page.valueDate) {
main.message("结束日期不能大于当前系统日期!");
return;
}
- if ($("#ValueDate").val() < $("#ValueDateFrom").val()) {
- main.message("起始日期不能大于结束日期!");
- return;
- }
if ($("#ParentFlag").prop("checked"))
ParentFlag = true;
else
ParentFlag = false;
- window.location.href = tab + "?clientId=" + $("#ClientId").val() + "&startTime=" + $("#ValueDateFrom").val() + "&endTime=" + $("#ValueDate").val() + "&ParentFlag=" + ParentFlag;
+ window.location.href = tab + "?clientId=" + $("#ClientId").val() + "&startTime=" + $("#ValueDate").val() + "&endTime=" + $("#ValueDate").val() + "&ParentFlag=" + ParentFlag;
return;
}
diff --git a/YLErpWeb/wwwroot/Scripts/utils.js b/YLErpWeb/wwwroot/Scripts/utils.js
index 993ad26c..1114e8e7 100644
--- a/YLErpWeb/wwwroot/Scripts/utils.js
+++ b/YLErpWeb/wwwroot/Scripts/utils.js
@@ -1209,21 +1209,41 @@ main.refreshCollapsibleGroupHeaders = function (jgrid) {
*
* @param {jQuery} jgrid jqGrid 容器
* @param {string} fileName 导出文件名(不含扩展名)
+ * @param {Array} groupConfig 可选,分组表头配置,每项 { title: string, columns: string[] }
+ * @param {Array} exportRows 可选,后端返回的全部筛选结果;未传时导出当前页
*/
-main.exportVisibleColumnsToExcel = function (jgrid, fileName) {
+main.exportVisibleColumnsToExcel = function (jgrid, fileName, groupConfig, exportRows) {
var colModel = jgrid.jqGrid('getGridParam', 'colModel');
// 只导出可见列(hidden !== true),与折叠状态联动:收起的列自动不可见
var visibleCols = colModel.filter(function (c) { return c.hidden !== true && c.name !== 'cb' && c.name !== 'rn'; });
if (!visibleCols.length) { main.message && main.message("没有可导出的列"); return; }
- var rows = jgrid.jqGrid('getRowData'); // 获取当前页数据(已格式化)
+ var rows = exportRows || jgrid.jqGrid('getRowData');
+ if (exportRows) {
+ var gridElement = jgrid[0];
+ rows = exportRows.map(function (row, rowIndex) {
+ var formattedRow = {};
+ visibleCols.forEach(function (col) {
+ var colIndex = colModel.indexOf(col);
+ var rawValue = $.jgrid.getAccessor(row, col.name);
+ var formattedValue = gridElement && gridElement.formatter
+ ? gridElement.formatter(rowIndex + 1, rawValue, colIndex, row, 'add')
+ : rawValue;
+ formattedRow[col.name] = $('').html(formattedValue == null ? '' : String(formattedValue)).text().replace(/\u00a0/g, '');
+ });
+ return formattedRow;
+ });
+ }
var headerLabels = visibleCols.map(function (c) { return c.label || c.name; });
// 构建 HTML table,用 style 保持 mso-number-format 让金额不被科学计数法破坏
var html = '';
html += '
';
html += '
';
- //表头
+ //表头:有分组配置时导出两级表头(分类 + 字段),否则保持原单级表头。
+ if (groupConfig && groupConfig.length) {
+ html += buildGroupHeaderHtml(visibleCols, groupConfig);
+ }
html += '' + headerLabels.map(function (l) {
return '| ' + escapeXml(l) + ' | ';
}).join('') + '
';
@@ -1252,5 +1272,25 @@ main.exportVisibleColumnsToExcel = function (jgrid, fileName) {
function escapeXml(s) {
return s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
}
+
+ function buildGroupHeaderHtml(cols, config) {
+ var titleByColumn = {};
+ config.forEach(function (group) {
+ (group.columns || []).forEach(function (name) {
+ titleByColumn[name] = group.title || '';
+ });
+ });
+
+ var cells = [];
+ for (var i = 0; i < cols.length; i++) {
+ var title = titleByColumn[cols[i].name] || '';
+ var colspan = 1;
+ while (i + colspan < cols.length && (titleByColumn[cols[i + colspan].name] || '') === title) {
+ colspan++;
+ }
+ cells.push('' + escapeXml(title) + ' | ');
+ i += colspan - 1;
+ }
+ return '' + cells.join('') + '
';
+ }
};
-
\ No newline at end of file