diff --git a/src/views/biz/reports/TrainsUpsell.jsx b/src/views/biz/reports/TrainsUpsell.jsx
index 47d61a3..eb32443 100644
--- a/src/views/biz/reports/TrainsUpsell.jsx
+++ b/src/views/biz/reports/TrainsUpsell.jsx
@@ -51,12 +51,14 @@ const TrainsUpsell = observer(({ ...props }) => {
const { date_picker_store: searchFormStore } = useContext(stores_Context);
const [searchValues, setSearchValues] = useTrainsStore(useShallow((state) => [state.searchValues, state.setSearchValues]));
- const [loading] = useTrainsStore(useShallow((state) => [state.loading]));
+ const [loading, typeLoading] = useTrainsStore(useShallow((state) => [state.loading, state.typeLoading]));
const [trainsOrdersSummary, compareData] = useTrainsStore((state) => state.trainsOrdersSummary);
+ const trainsUpsellOrdersDetail = useTrainsStore((state) => state.trainsUpsellOrdersDetail);
// const showDiff = !comm.isEmpty(searchValuesToSub.DateDiff2);
const showDiff = !comm.isEmpty(compareData);
const getTrainsWithUpsell = useTrainsStore((state) => state.getTrainsWithUpsell);
+ const getTrainsOrderDetail = useTrainsStore((state) => state.getTrainsOrderDetail);
const data0 = buildFunnelData(trainsOrdersSummary, compareData);
const chartConfig = {
@@ -126,12 +128,13 @@ const TrainsUpsell = observer(({ ...props }) => {
const tableProps = {
title: () => `${trainsOrdersSummary?.dateRangeStr || ''}` + (showDiff ? ` vs ${compareData?.dateRangeStr}` : ''),
dataSource: trainsOrdersSummary?.data || [],
- columns: [
- {
- title: '#',
- fixed: 'left',
- dataIndex: 'OrderType',
- },
+ // columns: [],
+ size: 'small',
+ pagination: false,
+ scroll: { x: 100 * 7 },
+ loading,
+ };
+ const tableCols = [
{
title: '数量',
dataIndex: 'OrderCount',
@@ -163,12 +166,7 @@ const TrainsUpsell = observer(({ ...props }) => {
dataIndex: 'Ordervalue',
render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.Ordervalue_vs, r.Ordervalue_diff, r.Ordervalue, r.diff?.Ordervalue)),
},
- ],
- size: 'small',
- pagination: false,
- scroll: { x: 100 * 7 },
- loading,
- };
+ ];
return (
<>
@@ -190,12 +188,13 @@ const TrainsUpsell = observer(({ ...props }) => {
onSubmit={(_err, obj, form, str) => {
setSearchValues(obj, form);
getTrainsWithUpsell(obj);
+ getTrainsOrderDetail(obj);
}}
/>
-
+
@@ -230,6 +229,16 @@ const TrainsUpsell = observer(({ ...props }) => {
+
+ `火车票Upsell: 各站`}
+ />
>
diff --git a/src/zustand/Trains.js b/src/zustand/Trains.js
index 9c05fa1..6cbea43 100644
--- a/src/zustand/Trains.js
+++ b/src/zustand/Trains.js
@@ -5,7 +5,7 @@ import { groupsCTplus, groupsMappedByCode } from '../libs/ht';
import { fetchJSON } from '../utils/request';
import { HT_HOST } from '../config';
import { resultDataCb } from '../components/DateGroupRadio/date';
-import { groupBy, isEmpty } from '../utils/commons';
+import { fixTo2Decimals, fixTo4Decimals, groupBy, isEmpty } from '../utils/commons';
const SERVICETYPE_TRAINSBOOKING = '2'; // 火车票服务
const FORM_TRAINSBOOKING = 32024; // 火车票预定
@@ -63,6 +63,114 @@ export const fetchTrainsUpsellTSummaryByType = async (params, type = 'Form', typ
return ret;
};
+const calcSummary = (arr, keepKeys = []) => {
+ const s = arr.reduce(
+ (acc, cur) => {
+ acc.CJCount += cur.COLI_Success === 1 ? 1 : 0;
+ acc.CJPersonNum += cur.COLI_Success === 1 ? cur.COLI_PersonNum + cur.COLI_ChildNum + cur.COLI_BabyNum : 0;
+ acc.OrderCount += 1;
+ acc.YJLY += cur.CGI_YJLY;
+ keepKeys.forEach((key) => {
+ acc[key] = cur[key];
+ });
+ return acc;
+ },
+ { CJCount: 0, CJPersonNum: 0, CJrate: 0, OrderCount: 0, YJLY: 0 }
+ );
+ s.CJrate = s.OrderCount ? (fixTo2Decimals(s.CJCount / s.OrderCount * 100)) : 0;
+ s.YJLY = fixTo2Decimals(s.YJLY);
+ return s;
+};
+
+const _detailRes = { ordercount1: [], ordercount2: [] };
+export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVal = FORM_TRAINSUPSELL, orderContent = 'detail') => {
+ const { errcode, errmsg, ...result } = await fetchJSON(HT_HOST + '/service-web/QueryData/GetOrderCountByType_Sub', {
+ ...defaultParams,
+ SubOrderType: orderContent,
+ ...params,
+ COLI_ApplyDate1: params.Date1,
+ COLI_ApplyDate2: params.Date2,
+ COLI_ApplyDateOld1: params.DateDiff1 || '',
+ COLI_ApplyDateOld2: params.DateDiff2 || '',
+ OrderType: type,
+ OrderType_val: typeVal,
+ });
+ const res = errcode !== 0 ? _detailRes : (result || _detailRes);
+ const dateStr = [params.Date1, params.Date2].map((d) => d.substring(0, 10)).join('~');
+ const ret = [
+ { dateRangeStr: dateStr, data: res.ordercount1 },
+ // { dateRangeStr: dateDiffStr, data: res.ordercount2 },
+ ];
+ 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 });
+ }
+ const retS = ret.map(({ dateRangeStr, data }) => {
+ const byWebCode = (Object.values(groupBy(data, 'COLI_WebCode'))).map((group) => calcSummary(group, ['COLI_WebCode']));
+ const summary = calcSummary(data);
+ return { dateRangeStr, data , summary, byWebCode };
+ });
+ // diff
+ 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 || {};
+ 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;
+ row.YJLY_vs = row2.YJLY ? fixTo2Decimals(((row.YJLY - row2.YJLY) / row2.YJLY) * 100) : 0;
+ row.OrderCount_vs = row2.OrderCount ? fixTo2Decimals(((row.OrderCount - row2.OrderCount) / row2.OrderCount) * 100) : 0;
+ row.CJCount_diff = row2.CJCount ? row.CJCount - row2.CJCount : 0;
+ row.CJPersonNum_diff = row2.CJPersonNum ? row.CJPersonNum - row2.CJPersonNum : 0;
+ row.CJrate_diff = row2.CJrate ? fixTo2Decimals(row.CJrate - row2.CJrate) : 0;
+ row.YJLY_diff = row2.YJLY ? fixTo2Decimals(row.YJLY - row2.YJLY) : 0;
+ row.OrderCount_diff = row2.OrderCount ? row.OrderCount - row2.OrderCount : 0;
+ return row;
+ });
+ //
+ const rows1Map = byWebCode1.reduce((a, row1) => ({ ...a, [row1.COLI_WebCode]: row1 }), {});
+ const rows2Map = byWebCode2.reduce((a, row2) => ({ ...a, [row2.COLI_WebCode]: row2 }), {});
+ // Diff: elements in rows2 but not in rows1
+ const diffKey = [...new Set(Object.keys(rows2Map).filter((x) => !new Set(Object.keys(rows1Map)).has(x)))];
+ withDiff1.push(
+ ...diffKey.map((key) => ({
+ diff: rows2Map[key],
+ CJrate: 0,
+ COLI_WebCode: rows2Map[key].COLI_WebCode,
+ CJCount_vs: -100,
+ CJPersonNum_vs: -100,
+ CJrate_vs: -100,
+ YJLY_vs: -100,
+ OrderCount_vs: -100,
+ CJCount_diff: -rows2Map[key].CJCount,
+ CJPersonNum_diff: -rows2Map[key].CJPersonNum,
+ CJrate_diff: -rows2Map[key].CJrate,
+ YJLY_diff: -rows2Map[key].YJLY,
+ OrderCount_diff: -rows2Map[key].OrderCount,
+ }))
+ );
+ retS[0].byWebCode = withDiff1;
+ }
+ // %
+ retS.forEach(({ summary, byWebCode }, i) => {
+ summary.CJrate = `${summary.CJrate}%`;
+ if (i !== 0) {
+ } else {
+ byWebCode.forEach((row) => {
+ row.CJrate = `${row.CJrate}%`;
+ row.CJrate_vs = `${row.CJrate_vs}%`;
+ row.CJrate_diff = `${row.CJrate_diff}%`;
+ row.CJCount_vs = `${row.CJCount_vs}%`;
+ row.CJPersonNum_vs = `${row.CJPersonNum_vs}%`;
+ row.OrderCount_vs = `${row.OrderCount_vs}%`;
+ row.YJLY_vs = `${row.YJLY_vs}%`;
+ });
+ }
+ });
+ return retS;
+};
+
export const fetchTrainsWithUpsellSummary = async (params) => {
const [trains, upsell] = await Promise.all([
// fetchBizTrainsOrderSummaryByType(params, 'Form', FORM_TRAINSBOOKING), // todo: 换成servicetype=2
@@ -117,6 +225,7 @@ const initialState = {
},
trainsOrdersSummary: [],
+ trainsUpsellOrdersDetail: [],
activeTab: 'Form',
activeDateGroupRadio: 'day',
@@ -170,6 +279,19 @@ const useTrainsStore = create(
}
},
+ getTrainsOrderDetail: async (params) => {
+ const { setTypeLoading } = get();
+ setTypeLoading(true);
+ set({ trainsUpsellOrdersDetail: [] });
+ try {
+ const res = await fetchUpsellOrderDetailByType(params);
+ set({ trainsUpsellOrdersDetail: res });
+ } catch (error) {
+ } finally {
+ setTypeLoading(false);
+ }
+ }
+
// sub
})),
{ name: 'trains' }