perf: 商务数据: 火车票Upsell: 各站; 外联老客户营销; 图表

main
Lei OT 5 months ago
parent 14b9ca88ce
commit a89cef09a2

@ -254,8 +254,12 @@ class Orders extends Component {
const table_data = orders_store.orderCountData_Form ? this.format_data(orders_store.orderCountData_Form) : [];
const data_source = orders_store.orderCountData ? orders_store.orderCountData : [];
const avg_line_y = Math.round(orders_store.avgLine1);
const pie_data = comm.empty(orders_store.orderCountData_Form) ? [] : orders_store.orderCountData_Form.ordercount1.filter(ele => ele.OrderTypeSN); //
const pie_data2 = comm.empty(orders_store.orderCountData_Form) ? [] : orders_store.orderCountData_Form.ordercount2.filter(ele => ele.OrderTypeSN);
const pie_data = comm.empty(orders_store.orderCountData_Form)
? []
: orders_store.orderCountData_Form.ordercount1.map((ele) => ({ ...ele, YJLYx: comm.price_to_number(ele.YJLY) })); //
const pie_data2 = comm.empty(orders_store.orderCountData_Form)
? []
: orders_store.orderCountData_Form.ordercount2.map((ele) => ({ ...ele, YJLYx: comm.price_to_number(ele.YJLY) }));
const config = {
data: data_source,
@ -327,7 +331,7 @@ class Orders extends Component {
colorField: "OrderType",
radius: 0.8,
label: {
type: "spider",
type: "outer",
content: "{name} {value} \t {percentage}",
},
legend: false, //
@ -497,10 +501,12 @@ class Orders extends Component {
/>
<Row>
<Col sm={24} lg={12}>
<Pie {...pie_config} data={pie_data} />
<Pie {...pie_config} data={pie_data} innerRadius={0.6} statistic={{title: false,content:{content:'数量'}}} />
<Pie {...pie_config} data={pie_data} angleField='YJLYx' innerRadius={0.6} statistic={{title: false,content:{content:'预计毛利'}}} />
</Col>
<Col sm={24} lg={12}>
<Pie {...pie_config} data={pie_data2} />
<Pie {...pie_config} data={pie_data2} innerRadius={0.6} statistic={{title: false,content:{content:'数量'}}} />
<Pie {...pie_config} data={pie_data2} angleField='YJLYx' innerRadius={0.6} statistic={{title: false,content:{content:'预计毛利'}}} />
</Col>
</Row>
</Col>

@ -1,6 +1,6 @@
import { useContext } from 'react';
import { Row, Col, Tabs, Table, Divider, Spin, Checkbox, Space } from 'antd';
import { ContainerOutlined, BlockOutlined, SmileOutlined, MobileOutlined, CustomerServiceOutlined } from '@ant-design/icons';
import { ContainerOutlined, BlockOutlined, SmileOutlined, MobileOutlined, CustomerServiceOutlined, IeOutlined } from '@ant-design/icons';
import { Line, Pie } from '@ant-design/charts';
import { NavLink } from 'react-router-dom';
import * as comm from '../../utils/commons';
@ -19,7 +19,7 @@ const BizOrder = observer(() => {
const [searchValues, setSearchValues] = useBizOrderStore(useShallow((state) => [state.searchValues, state.setSearchValues]));
const [activeTab, setActiveTab] = useBizOrderStore(useShallow((state) => [state.activeTab, state.setActiveTab]));
const [loading, onTabChange] = useBizOrderStore(useShallow((state) => [state.loading, state.onTabChange]));
const [loading, typeLoading, onTabChange] = useBizOrderStore(useShallow((state) => [state.loading, state.typeLoading,state.onTabChange]));
const orderCountDataRaw = useBizOrderStore((state) => state.orderCountDataRaw);
const [orderCountDataLines, avgLineValue] = useBizOrderStore(useShallow((state) => [state.orderCountDataLines, state.avgLineValue]));
@ -104,7 +104,7 @@ const BizOrder = observer(() => {
radius: 0.8,
label: {
type: 'outer',
content: '{name} {value} \n {percentage}',
content: '{name} {value} \t {percentage}',
},
legend: false, //
interactions: [
@ -291,6 +291,15 @@ const BizOrder = observer(() => {
</span>
),
},
{
key: 'webcode',
label: (
<span>
<IeOutlined />
来源站点
</span>
),
},
// {
// key: 'Product',
// label: (
@ -404,7 +413,7 @@ const BizOrder = observer(() => {
...ele,
children: (
<>
<Table sticky key={`table_to_xlsx_${ele.key}`} {...tableProps} />
<Table sticky key={`table_to_xlsx_${ele.key}`} {...tableProps} loading={typeLoading} />
<Divider orientation="right" plain>
<TableExportBtn label={ele.key} {...{ columns: tableProps.columns, dataSource: tableProps.dataSource }} />
</Divider>
@ -425,14 +434,17 @@ const BizOrder = observer(() => {
包含空值
</Checkbox> */}
</div>
<Spin spinning={loading}>
<Spin spinning={typeLoading}>
<Row>
<Col sm={24} lg={12}>
<Pie {...pieConfig} data={result?.ordercount1 || []} />
</Col>
<Col sm={24} lg={12}>
<Pie {...pieConfig} data={result?.ordercount2 || []} />
<Pie {...pieConfig} data={result?.ordercount1 || []} innerRadius={0.6} statistic={{title: false,content:{content:'数量'}}} />
<Pie {...pieConfig} data={result?.ordercount1 || []} angleField='YJLYx' innerRadius={0.6} statistic={{title: false,content:{content:'预计毛利'}}} />
</Col>
{showDiff && <Col sm={24} lg={12}>
<Pie {...pieConfig} data={result?.ordercount2 || []} innerRadius={0.6} statistic={{title: false,content:{content:'数量'}}} />
<Pie {...pieConfig} data={result?.ordercount2 || []} angleField='YJLYx' innerRadius={0.6} statistic={{title: false,content:{content:'预计毛利'}}} />
</Col>}
</Row>
</Spin>
</div>

@ -1,6 +1,6 @@
import { useContext } from 'react';
import { Row, Col, Table, Spin, Space, Divider } from 'antd';
import { Funnel, Pie } from '@ant-design/charts';
import { Funnel, Pie, Sunburst } from '@ant-design/charts';
import * as comm from '../../../utils/commons';
import SearchForm from '../../../components/search/SearchForm';
@ -9,22 +9,37 @@ import { observer } from 'mobx-react';
import { toJS } from 'mobx';
import { stores_Context } from '../../../config';
import { useShallow } from 'zustand/shallow';
import useTrainsStore from '../../../zustand/Trains';
import useTrainsStore, { SERVICETYPE_TRAINSBOOKING, FORM_TRAINSUPSELL } from '../../../zustand/Trains';
const buildSunburstData = (data1) => {
const total1 = (data1?.total || []).map((item) => {
return { ...item, name: item.label, value: item.YJLYx, children: data1?.data?.filter((child) => child.label === item.label).map((c2) => ({ ...c2, value: c2.YJLYx, name: c2.OrderType })) };
});
const ret1 = {
name: '预计利润',
// OrderType: 'xUpsell',
children: total1, // .sort((a, b) => a.name.localeCompare(b.name)), // .reverse(),
};
// if(data1) console.log('🉑', ret1);
return ret1;
};
const _getTrainService = (arr = []) => arr.find((item) => item.OrderTypeSN === SERVICETYPE_TRAINSBOOKING) || {};
const _getTrainUpsell = (arr = []) => arr.find((item) => item.OrderTypeSN === FORM_TRAINSUPSELL) || {};
const buildFunnelData = (data1, data2) => {
// const key = 'OrderCount';
const data01 = [
{ stage: '火车票服务', number: data1?.data?.[0]?.OrderCount, dateRange: data1?.dateRangeStr },
{ stage: '成行出票', number: data1?.data?.[0]?.CJCount, dateRange: data1?.dateRangeStr },
{ stage: '火车票Upsell', number: (data1?.data?.[1]?.OrderCount || 0) + 0, dateRange: data1?.dateRangeStr },
{ stage: 'Upsell成行', number: data1?.data?.[1]?.CJCount, dateRange: data1?.dateRangeStr },
{ stage: '火车票服务', number: _getTrainService(data1?.data)?.OrderCount, dateRange: data1?.dateRangeStr },
{ stage: '成行出票', number: _getTrainService(data1?.data)?.CJCount, dateRange: data1?.dateRangeStr },
{ stage: '火车票Upsell', number: (_getTrainUpsell(data1?.data)?.OrderCount || 0) + 0, dateRange: data1?.dateRangeStr },
{ stage: 'Upsell成行', number: _getTrainUpsell(data1?.data)?.CJCount, dateRange: data1?.dateRangeStr },
];
const data02 = !comm.isEmpty(data2)
? [
{ stage: '火车票服务', number: data2?.data?.[0]?.OrderCount, dateRange: data2?.dateRangeStr },
{ stage: '成行出票', number: data2?.data?.[0]?.CJCount, dateRange: data2?.dateRangeStr },
{ stage: '火车票Upsell', number: data2?.data?.[1]?.OrderCount, dateRange: data2?.dateRangeStr },
{ stage: 'Upsell成行', number: data2?.data?.[1]?.CJCount, dateRange: data2?.dateRangeStr },
{ stage: '火车票服务', number: _getTrainService(data2?.data)?.OrderCount || 0, dateRange: data2?.dateRangeStr },
{ stage: '成行出票', number: _getTrainService(data2?.data)?.CJCount || 0, dateRange: data2?.dateRangeStr },
{ stage: '火车票Upsell', number: _getTrainUpsell(data2?.data)?.OrderCount || 0, dateRange: data2?.dateRangeStr },
{ stage: 'Upsell成行', number: _getTrainUpsell(data2?.data)?.CJCount || 0, dateRange: data2?.dateRangeStr },
]
: [];
return data01.concat(data02);
@ -96,42 +111,56 @@ const TrainsUpsell = observer(({ ...props }) => {
},
};
const pieData = buildPieData(trainsOrdersSummary);
const pieData2 = buildPieData(compareData);
// console.log('🟠', pieData, pieData2);
const pieConfig = {
appendPadding: 0,
// data: pieData,
angleField: 'number',
colorField: 'stage',
radius: 0.8,
innerRadius: 0.6,
// startAngle: Math.PI ,
// endAngle: Math.PI * 1.5,
label: {
type: 'spider',
// content: '{name} {value} \n {percentage}',
content: '{name}\n{percentage}',
},
statistic: false,
legend: false, //
interactions: [
{
type: 'element-selected',
const sunburstData = buildSunburstData(trainsOrdersSummary, compareData);
const sunburstData2 = buildSunburstData(compareData);
const sunburstConfig = {
innerRadius: 0.3,
radius: 1,
colorField: 'name',
hierarchyConfig: {
// field: 'YJLYx',
ignoreParentValue: false,
sort: (a, b) => (a.name || '').localeCompare(b.name),
},
{
type: 'element-active',
},
],
label: { layout: [{ type: 'limit-in-shape' }] },
interactions: [{ type: 'element-selected' }, { type: 'element-active' }],
};
// const pieData = buildPieData(trainsOrdersSummary);
// const pieData2 = buildPieData(compareData);
// console.log('🟠', pieData, pieData2);
// const pieConfig = {
// appendPadding: 0,
// // data: pieData,
// angleField: 'number',
// colorField: 'stage',
// radius: 0.8,
// innerRadius: 0.6,
// // startAngle: Math.PI ,
// // endAngle: Math.PI * 1.5,
// label: {
// type: 'spider',
// // content: '{name} {value} \n {percentage}',
// content: '{name}\n{percentage}',
// },
// statistic: false,
// legend: false, //
// interactions: [
// {
// type: 'element-selected',
// },
// {
// type: 'element-active',
// },
// ],
// };
const tableProps = {
title: () => `${trainsOrdersSummary?.dateRangeStr || ''}` + (showDiff ? ` vs ${compareData?.dateRangeStr}` : ''),
dataSource: trainsOrdersSummary?.data || [],
// columns: [],
size: 'small',
pagination: false,
scroll: { x: 100 * 7 },
// scroll: { x: 100 * 7 },
loading,
};
const tableCols = [
@ -194,8 +223,18 @@ const TrainsUpsell = observer(({ ...props }) => {
</Col>
</Row>
<Space direction={'vertical'}>
<Table sticky key={`table_1`} {...tableProps} columns={[{ title: '#', fixed: 'left', dataIndex: 'OrderType' }, ...tableCols]} />
<Table sticky key={`table_0`} {...tableProps} columns={[{ title: '#', fixed: 'left', dataIndex: 'label' }, ...tableCols]} dataSource={trainsOrdersSummary?.total || []} rowKey={'label'} />
<Table
sticky
key={`table_1`}
{...tableProps}
columns={[{ title: '#', fixed: 'left', dataIndex: 'OrderType' }, ...tableCols]}
dataSource={trainsOrdersSummary?.data || []}
rowKey={'OrderType'}
/>
<Divider orientation="left">火车票</Divider>
<Spin spinning={loading}>
<Row gutter={[16, { sm: 16, lg: 32 }]}>
<Col {...{ xs: 24, md: 12, lg: 12 }}>
@ -205,7 +244,22 @@ const TrainsUpsell = observer(({ ...props }) => {
<Col {...{ xs: 24, md: 12, lg: 12 }}>
<h3>预计利润</h3>
<div style={{ display: showDiff ? 'flex' : 'block' }}>
<Pie
<Sunburst
key={showDiff ? 'sunburst1' : 'sunburst0'}
style={{ display: showDiff ? 'inline' : 'block' }}
{...sunburstConfig}
data={sunburstData}
/>
{showDiff && (
<Sunburst
key={'sunburst2'}
style={{ display: 'inline' }}
{...sunburstConfig}
data={sunburstData2}
// pattern={{ type: 'line' }}
/>
)}
{/* <Pie
key={showDiff ? 'pie1' : 'pie0'}
style={{ display: showDiff ? 'inline' : 'block' }}
{...pieConfig}
@ -224,7 +278,7 @@ const TrainsUpsell = observer(({ ...props }) => {
color={['#61DDAA', '#5B8FF9']}
pattern={{ type: 'line' }}
/>
)}
)} */}
</div>
</Col>
</Row>
@ -238,7 +292,10 @@ const TrainsUpsell = observer(({ ...props }) => {
loading={typeLoading}
columns={[{ title: '#', fixed: 'left', dataIndex: 'COLI_WebCode' }, ...tableCols]}
title={() => `火车票Upsell: 各站`}
rowKey={'COLI_WebCode'}
/>
{/* <Divider orientation="left">外联营销</Divider> */}
</Space>
</div>
</>

@ -5,7 +5,7 @@ import { groupsMappedByCode } from '../libs/ht';
import { fetchJSON } from '../utils/request';
import { HT_HOST } from '../config';
import { resultDataCb } from '../components/DateGroupRadio/date';
import { isEmpty } from '../utils/commons';
import { isEmpty, price_to_number } from '../utils/commons';
const defaultParams = { WebCode: 'all', IncludeTickets: 1, IncludeInternal: 1 };
@ -50,15 +50,15 @@ export const fetchBizOrderCountByType = async (type, params) => {
OrderType: type,
});
const res = errcode !== 0 ? _typeRes : (result || _typeRes);
const rows1Map = res.ordercount1.reduce((a, row1) => ({ ...a, [row1.OrderTypeSN]: row1 }), {});
const rows2Map = res.ordercount2.reduce((a, row2) => ({ ...a, [row2.OrderTypeSN]: row2 }), {});
const rows1Map = res.ordercount1.reduce((a, row1) => ({ ...a, [row1.OrderTypeSN]: {...row1, YJLYx: price_to_number(row1.YJLY)} }), {});
const rows2Map = res.ordercount2.reduce((a, row2) => ({ ...a, [row2.OrderTypeSN]: {...row2, YJLYx: price_to_number(row2.YJLY)} }), {});
const mixRow1 = res.ordercount1.map((row1) => ({ ...row1, diff: rows2Map[row1.OrderTypeSN] || {} }));
const mixRow1 = res.ordercount1.map((row1) => ({ ...row1, YJLYx: price_to_number(row1.YJLY), diff: rows2Map[row1.OrderTypeSN] || {} }));
// Diff: elements in rows2 but not in rows1
const diff = [...new Set(Object.keys(rows2Map).filter((x) => !new Set(Object.keys(rows1Map)).has(x)))];
mixRow1.push(...diff.map((sn) => ({ diff: rows2Map[sn], OrderType: rows2Map[sn].OrderType, OrderTypeSN: rows2Map[sn].OrderTypeSN })));
return { ...res, ordercount1: mixRow1 };
return { ...res, ordercount1: mixRow1, ordercount2: res.ordercount2.map((row1) => ({ ...row1, YJLYx: price_to_number(row1.YJLY), })) };
};
const _detailRes = { ordercount1: [], ordercount2: [] };

@ -4,17 +4,21 @@ import { immer } from 'zustand/middleware/immer';
import { groupsCTplus, groupsMappedByCode } from '../libs/ht';
import { fetchJSON } from '../utils/request';
import { HT_HOST } from '../config';
import { resultDataCb } from '../components/DateGroupRadio/date';
import { fixTo2Decimals, fixTo4Decimals, groupBy, isEmpty } from '../utils/commons';
import { fixTo2Decimals, fixTo4Decimals, groupBy, isEmpty, price_to_number } from '../utils/commons';
const SERVICETYPE_TRAINSBOOKING = '2'; // 火车票服务
const FORM_TRAINSBOOKING = 32024; // 火车票预定
const FORM_TRAINSUPSELL = 32214; // 火车票Upsell
/** 火车票服务 */
export const SERVICETYPE_TRAINSBOOKING = '2';
/** 火车票预定 */
export const FORM_TRAINSBOOKING = 32024;
/** 火车票Upsell */
export const FORM_TRAINSUPSELL = 32214;
/** 外联老客户营销 */
export const FORM_SALESSUPSELL = 32213;
const defaultParams = { WebCode: 'all', IncludeTickets: 1, IncludeInternal: 1 };
const _res = { ordercount1: [], ordercount2: [] };
export const fetchBizTrainsOrderSummaryByType = async (params, type = 'Form', typeVal = '') => {
export const fetchBizTrainsOrderSummaryByType = async (params, type = 'Form', typeVals = []) => {
const { errcode, errmsg, ...result } = await fetchJSON(HT_HOST + '/service-web/QueryData/GetOrderCountByType_biz', {
...defaultParams,
...params,
@ -27,20 +31,36 @@ export const fetchBizTrainsOrderSummaryByType = async (params, type = 'Form', ty
const res = errcode !== 0 ? _res : result || _res;
const dateStr = [params.Date1, params.Date2].map((d) => d.substring(0, 10)).join('~');
const ret = [
{ dateRangeStr: dateStr, data: res.ordercount1.find((row) => row.OrderTypeSN === typeVal) },
{
dateRangeStr: dateStr,
data: res.ordercount1.filter((row) => typeVals.includes(row.OrderTypeSN)).map((row) => ({ ...row, YJLYx: price_to_number(row.YJLY), label: '商务' })),
total: { ...res.ordercountTotal1, YJLYx: price_to_number(res.ordercountTotal1.YJLY), label: '商务' },
type,
},
// { dateRangeStr: dateDiffStr, data: res.ordercount2.find((row) => row.OrderTypeSN === typeVal) },
];
const dateDiffStr = isEmpty(params.DateDiff1) ? '' : [params.DateDiff1, params.DateDiff2].map((d) => d.substring(0, 10)).join('~');
if (!isEmpty(dateDiffStr)) {
ret.push({ dateRangeStr: dateDiffStr, data: res.ordercount2.find((row) => row.OrderTypeSN === typeVal) });
ret[0].total.diff = { ...res.ordercountTotal2, YJLYx: price_to_number(res.ordercountTotal2.YJLY) };
ret[0].data.forEach((row) => {
const _find = res.ordercount2.find((row2) => row2.OrderTypeSN === row.OrderTypeSN) || {};
row.diff = { ..._find, YJLYx: price_to_number(_find.YJLY || 0) };
});
ret.push({
dateRangeStr: dateDiffStr,
data: res.ordercount2.filter((row) => typeVals.includes(row.OrderTypeSN)).map((row) => ({ ...row, YJLYx: price_to_number(row.YJLY), label: '商务' })),
total: { ...res.ordercountTotal2, YJLYx: price_to_number(res.ordercountTotal2.YJLY), label: '商务' },
type,
});
}
// console.log('😉', ret);
return ret;
};
/**
* 从传统订单中获取upsell数据
*/
export const fetchTrainsUpsellTSummaryByType = async (params, type = 'Form', typeVal = '') => {
export const fetchTrainsUpsellTSummaryByType = async (params, type = 'Form', typeVals = []) => {
const { errcode, errmsg, ...result } = await fetchJSON(HT_HOST + '/service-web/QueryData/GetOrderCountByType', {
...defaultParams,
...params,
@ -53,13 +73,29 @@ export const fetchTrainsUpsellTSummaryByType = async (params, type = 'Form', typ
const res = errcode !== 0 ? _res : result || _res;
const dateStr = [params.Date1, params.Date2].map((d) => d.substring(0, 10)).join('~');
const ret = [
{ dateRangeStr: dateStr, data: res.ordercount1.find((row) => row.OrderTypeSN === typeVal) },
{
dateRangeStr: dateStr,
data: res.ordercount1.filter((row) => typeVals.includes(row.OrderTypeSN)).map(row => ({...row, YJLYx: price_to_number(row.YJLY), label: '传统'})),
total: { ...res.ordercountTotal1, YJLYx: price_to_number(res.ordercountTotal1.YJLY), label: '传统' },
type,
},
// { dateRangeStr: dateDiffStr, data: res.ordercount2.find((row) => row.OrderTypeSN === typeVal) },
];
const dateDiffStr = isEmpty(params.DateDiff1) ? '' : [params.DateDiff1, params.DateDiff2].map((d) => d.substring(0, 10)).join('~');
if (!isEmpty(dateDiffStr)) {
ret.push({ dateRangeStr: dateDiffStr, data: res.ordercount2.find((row) => row.OrderTypeSN === typeVal) });
ret[0].total.diff = { ...res.ordercountTotal2, YJLYx: price_to_number(res.ordercountTotal2.YJLY) };
ret[0].data.forEach((row) => {
const _find = res.ordercount2.find((row2) => row2.OrderTypeSN === row.OrderTypeSN) || {};
row.diff = { ..._find, YJLYx: price_to_number(_find.YJLY || 0) };
});
ret.push({
dateRangeStr: dateDiffStr,
data: res.ordercount2.filter((row) => typeVals.includes(row.OrderTypeSN)).map(row => ({...row, YJLYx: price_to_number(row.YJLY), label: '传统'})),
total: { ...res.ordercountTotal2, YJLYx: price_to_number(res.ordercountTotal2.YJLY), label: '传统' },
type,
});
}
// console.log('😉😉', ret);
return ret;
};
@ -83,10 +119,10 @@ const calcSummary = (arr, keepKeys = []) => {
};
const _detailRes = { ordercount1: [], ordercount2: [] };
export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVal = FORM_TRAINSUPSELL, orderContent = 'detail') => {
export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVal = FORM_TRAINSUPSELL) => {
const { errcode, errmsg, ...result } = await fetchJSON(HT_HOST + '/service-web/QueryData/GetOrderCountByType_Sub', {
...defaultParams,
SubOrderType: orderContent,
SubOrderType: 'detail',
...params,
COLI_ApplyDate1: params.Date1,
COLI_ApplyDate2: params.Date2,
@ -114,8 +150,8 @@ export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVa
if (!isEmpty(dateDiffStr)) {
const [{ byWebCode: byWebCode1 }, { byWebCode: byWebCode2 }] = retS;
const withDiff1 = byWebCode1.map((row, i) => {
const row2 = byWebCode2.find((r2) => r2.COLI_WebCode === row.COLI_WebCode);
row.diff = row2 || {};
const row2 = (byWebCode2.find((r2) => r2.COLI_WebCode === row.COLI_WebCode)) || {};
row.diff = row2;
row.CJCount_vs = row2.CJCount ? fixTo2Decimals(((row.CJCount - row2.CJCount) / row2.CJCount) * 100) : 0;
row.CJPersonNum_vs = row2.CJPersonNum ? fixTo2Decimals(((row.CJPersonNum - row2.CJPersonNum) / row2.CJPersonNum) * 100) : 0;
row.CJrate_vs = row2.CJrate ? fixTo2Decimals(row.CJrate - row2.CJrate) : 0;
@ -156,6 +192,9 @@ export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVa
retS.forEach(({ summary, byWebCode }, i) => {
summary.CJrate = `${summary.CJrate}%`;
if (i !== 0) {
byWebCode.forEach((row) => {
row.CJrate = `${row.CJrate}%`;
});
} else {
byWebCode.forEach((row) => {
row.CJrate = `${row.CJrate}%`;
@ -172,37 +211,33 @@ export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVa
};
export const fetchTrainsWithUpsellSummary = async (params) => {
const [trains, upsell] = await Promise.all([
// fetchBizTrainsOrderSummaryByType(params, 'Form', FORM_TRAINSBOOKING), // todo: 换成servicetype=2
fetchBizTrainsOrderSummaryByType(params, 'servicetype', SERVICETYPE_TRAINSBOOKING),
fetchTrainsUpsellTSummaryByType(params, 'Form', FORM_TRAINSUPSELL),
const [bizForm, bizService, upsell] = await Promise.all([
fetchBizTrainsOrderSummaryByType(params, 'Form', [FORM_TRAINSBOOKING]),
fetchBizTrainsOrderSummaryByType(params, 'servicetype', [SERVICETYPE_TRAINSBOOKING]),
fetchTrainsUpsellTSummaryByType(params, 'Form', [FORM_TRAINSUPSELL, FORM_SALESSUPSELL]),
]);
if (!isEmpty(trains[1])) {
trains[0].data.diff = trains[1].data;
upsell[0].data.diff = upsell[1].data;
}
const mergedMap = [...trains, ...upsell].reduce((acc, currentItem, currentIndex) => {
const dateRange = currentItem.dateRangeStr;
if (acc[dateRange]) {
acc[dateRange].data.push(currentItem.data);
// console.log('🟠','\n', structuredClone(bizForm), '\n', structuredClone(bizService),'\n', structuredClone(upsell));
const bizTotalOnly = structuredClone(bizForm).map((item) => ({ ...item, data: [] }));
const bizServiceDataOnly = structuredClone(bizService).map((item) => ({ ...item, total: {} }));
// console.log('🟠',bizTotalOnly, '\n', '\n', bizServiceDataOnly,'\n', upsell);
const mapByDate = new Map();
for (const item of [...bizTotalOnly, ...bizServiceDataOnly, ...upsell]) {
const dateRange = item.dateRangeStr;
for (const key in currentItem) {
if (key !== 'dateRange' && key !== 'data') {
acc[dateRange][key] = currentItem[key];
}
}
if (mapByDate.has(dateRange)) {
const existingItem = mapByDate.get(dateRange);
if (!isEmpty(item.total)) existingItem.total.push(item.total);
existingItem.data.push(...item.data);
} else {
acc[dateRange] = {
...currentItem,
data: [currentItem.data],
};
mapByDate.set(dateRange, {
...item,
data: item.data,
total: [item.total],
});
}
return acc;
}, {});
return Object.values(mergedMap);
// return groupBy([...trains, ...upsell], 'dateRangeStr');
}
// console.log('🔰0', Array.from(mapByDate.values()));
return Array.from(mapByDate.values());
};
/**

Loading…
Cancel
Save