|
|
import { makeAutoObservable, runInAction, toJS } from 'mobx';
|
|
|
import { fetchJSON } from '../utils/request';
|
|
|
import { isEmpty, sortDescBy, objectMapper, groupBy, pick, unique, cloneDeep, omit, fixTo2Decimals } from '../utils/commons';
|
|
|
import { groupsMappedByCode, dataFieldAlias } from './../libs/ht';
|
|
|
import { DATE_FORMAT, SMALL_DATETIME_FORMAT } from './../config';
|
|
|
import moment from 'moment';
|
|
|
|
|
|
const fetchHotelData = async (param) => {
|
|
|
const defaultParam = {
|
|
|
DEI_SN: '',
|
|
|
City: '',
|
|
|
OrderState: '',
|
|
|
BookingType: '-1',
|
|
|
RecommendedLevel: '-1',
|
|
|
Star: '-1',
|
|
|
ArriveDateCheck: '0',
|
|
|
ArriveDateStart: '',
|
|
|
ArriveDateEnd: '',
|
|
|
ConfirmDateCheck: '0',
|
|
|
ConfirmDateStart: '',
|
|
|
ConfirmDateEnd: '',
|
|
|
Compare: '0',
|
|
|
CompareDateStart: '',
|
|
|
CompareDateEnd: '',
|
|
|
Area: '-1',
|
|
|
};
|
|
|
const json = await fetchJSON('/service-Analyse2/HotelReservation', { ...defaultParam, ...param });
|
|
|
return json.errcode === 0 ? json.result || [] : [];
|
|
|
};
|
|
|
|
|
|
const fetchCruiseData = async (param) => {
|
|
|
const defaultParam = {
|
|
|
DEI_SN: '',
|
|
|
OrderState: '', // 0: 不成行 1: 成行
|
|
|
ArriveDateStart: '',
|
|
|
ArriveDateEnd: '',
|
|
|
Compare: '',
|
|
|
CompareDateStart: '',
|
|
|
CompareDateEnd: '',
|
|
|
BookingType: '', // 0: 非单订三峡,1: 单订三峡
|
|
|
ProductName: '',
|
|
|
Direction: '', // 1: 上水 2: 下水
|
|
|
VEI_SN: '-1', // 只要列出常用游船供应商选择
|
|
|
RoomNumStart: '0',
|
|
|
RoomNumEnd: '',
|
|
|
PersonNumStart: '0',
|
|
|
PersonNumEnd: '',
|
|
|
Country: '-1',
|
|
|
};
|
|
|
const json = await fetchJSON('/service-Analyse2/CruiseReservation', { ...defaultParam, ...param });
|
|
|
return json.errcode === 0 ? json.result || [] : [];
|
|
|
};
|
|
|
|
|
|
const paramKeyMapped = {
|
|
|
'DateType': [
|
|
|
{ key: 'ArriveDateCheck', transform: (val) => (val === 'startDate' ? '1' : '0') },
|
|
|
{ key: 'ConfirmDateCheck', transform: (val) => (val === 'confirmDate' ? '1' : '0') },
|
|
|
// { key: 'ApplyDateCheck', transform: (val) => (val === 'applyDate' ? '1' : '0') },
|
|
|
],
|
|
|
'DepartmentList': { key: 'DEI_SN' },
|
|
|
'orderStatus': { key: 'OrderState' },
|
|
|
'Date1': [{ key: 'ArriveDateStart' }, { key: 'ConfirmDateStart' }],
|
|
|
'Date2': [{ key: 'ArriveDateEnd' }, { key: 'ConfirmDateEnd' }],
|
|
|
'DateDiff1': { key: 'CompareDateStart' },
|
|
|
'DateDiff2': { key: 'CompareDateEnd' },
|
|
|
'keyword': { key: 'ProductName' },
|
|
|
'agency': { key: 'VEI_SN' },
|
|
|
'cruiseDirection': { key: 'Direction' },
|
|
|
'cruiseBookType': { key: 'BookingType' },
|
|
|
'hotelStar': { key: 'Star' },
|
|
|
'hotelRecommandRate': { key: 'RecommendedLevel' },
|
|
|
'hotelBookType': { key: 'BookingType' },
|
|
|
'country': { key: 'Country' },
|
|
|
'countryArea': { key: 'Area', transform: (val) => (val === 'china' ? '1' : val === 'foreign' ? '0' : '-1') },
|
|
|
};
|
|
|
|
|
|
class HotelCruise {
|
|
|
constructor(appStore) {
|
|
|
this.appStore = appStore;
|
|
|
makeAutoObservable(this);
|
|
|
}
|
|
|
|
|
|
async getCruiseData(param = {}) {
|
|
|
this.cruise.loading = true;
|
|
|
this.cruise.dataSource = [];
|
|
|
const _queryParam = objectMapper(param, paramKeyMapped);
|
|
|
const queryParam = omit({ ...this.searchValuesToSub, ..._queryParam }, Object.keys(paramKeyMapped));
|
|
|
queryParam.Compare = isEmpty(param.DateDiff1) ? '' : '1';
|
|
|
const res = await fetchCruiseData(queryParam);
|
|
|
const resCP =
|
|
|
queryParam.Compare === ''
|
|
|
? res
|
|
|
: (res || []).map((ele) => ({
|
|
|
...ele,
|
|
|
// 计算 增长率 = (当前值 - 上次值) / 上次值 * 100
|
|
|
TotalNumPercent: ele.CPTotalNum ? fixTo2Decimals(((ele.TotalNum - ele.CPTotalNum) / ele.CPTotalNum) * 100) : '-',
|
|
|
TotalPersonNumPercent: ele.CPTotalPersonNum ? fixTo2Decimals(((ele.TotalPersonNum - ele.CPTotalPersonNum) / ele.CPTotalPersonNum) * 100) : '-',
|
|
|
TotalProfitPercent: ele.CPTotalProfit ? fixTo2Decimals(((ele.TotalProfit - ele.CPTotalProfit) / ele.CPTotalProfit) * 100) : '-',
|
|
|
}));
|
|
|
const summaryRow = ['TotalNum', 'TotalPersonNum', 'TotalProfit', 'CPTotalNum', 'CPTotalPersonNum', 'CPTotalProfit'].reduce(
|
|
|
(r, skey) => ({
|
|
|
...r,
|
|
|
[skey]: resCP.reduce((a, c) => a + c[skey], 0),
|
|
|
}),
|
|
|
{ ProductName: '合计' }
|
|
|
);
|
|
|
const summaryDelta = ['TotalNum', 'TotalPersonNum', 'TotalProfit'].reduce(
|
|
|
(r, skey) => ({
|
|
|
...r,
|
|
|
[`${skey}Percent`]: queryParam.Compare === '' ? null : fixTo2Decimals(((summaryRow[skey] - summaryRow[`CP${skey}`]) / summaryRow[`CP${skey}`]) * 100),
|
|
|
}),
|
|
|
{}
|
|
|
);
|
|
|
runInAction(() => {
|
|
|
this.cruise.loading = false;
|
|
|
this.cruise.dataSource = resCP;
|
|
|
this.cruise.summaryRow = { ...summaryRow, ...summaryDelta };
|
|
|
});
|
|
|
return this.cruise;
|
|
|
}
|
|
|
|
|
|
async getHotelData(param = {}) {
|
|
|
this.hotel.loading = true;
|
|
|
this.hotel.dataSource = [];
|
|
|
const _queryParam = objectMapper(param, paramKeyMapped);
|
|
|
const queryParam = omit({ ...this.searchValuesToSub, ..._queryParam }, Object.keys(paramKeyMapped));
|
|
|
queryParam.Compare = isEmpty(param.DateDiff1) ? '0' : '1';
|
|
|
const _res = await fetchHotelData(queryParam);
|
|
|
const res = (_res || []).map((ele) => ({ ...ele, RecommendRate_100: fixTo2Decimals(ele.RecommendRate * 100) + '%' }));
|
|
|
const resCP =
|
|
|
queryParam.Compare === '0'
|
|
|
? res
|
|
|
: (res || []).map((ele) => ({
|
|
|
...ele,
|
|
|
TotalNumPercent: ele.CPTotalNum ? fixTo2Decimals(((ele.TotalNum - ele.CPTotalNum) / ele.CPTotalNum) * 100) : '-',
|
|
|
RecomendNumPercent: ele.CPRecomendNum ? fixTo2Decimals(((ele.RecomendNum - ele.CPRecomendNum) / ele.CPRecomendNum) * 100) : '-',
|
|
|
RecommendRateDelta: fixTo2Decimals((ele.RecommendRate - (ele.CPRecommendRate || 0)) * 100),
|
|
|
CPRecommendRate_100: fixTo2Decimals(ele.CPRecommendRate * 100) + '%',
|
|
|
}));
|
|
|
const summaryRow = ['TotalNum', 'RecomendNum', ].reduce(
|
|
|
(r, skey) => ({
|
|
|
...r,
|
|
|
[skey]: resCP.reduce((a, c) => a + c[skey], 0),
|
|
|
[`CP${skey}`]: resCP.reduce((a, c) => a + c[`CP${skey}`], 0),
|
|
|
}),
|
|
|
{ CityName: '合计' }
|
|
|
);
|
|
|
summaryRow.RecommendRate = fixTo2Decimals(summaryRow.RecomendNum/summaryRow.TotalNum);
|
|
|
summaryRow.RecommendRate_100 = fixTo2Decimals(summaryRow.RecommendRate * 100) + '%';
|
|
|
summaryRow.CPRecommendRate = fixTo2Decimals(summaryRow.CPRecomendNum/summaryRow.CPTotalNum);
|
|
|
summaryRow.CPRecommendRate_100 = fixTo2Decimals(summaryRow.CPRecommendRate * 100) + '%';
|
|
|
const summaryDelta = ['TotalNum', 'RecomendNum', ].reduce(
|
|
|
(r, skey) => ({
|
|
|
...r,
|
|
|
[`${skey}Percent`]: queryParam.Compare === '0' ? null : fixTo2Decimals(((summaryRow[skey] - summaryRow[`CP${skey}`]) / summaryRow[`CP${skey}`]) * 100),
|
|
|
}),
|
|
|
{}
|
|
|
);
|
|
|
summaryDelta.RecommendRateDelta = queryParam.Compare === '0' ? undefined : fixTo2Decimals((summaryRow.RecommendRate - (summaryRow.CPRecommendRate || 0)) * 100);
|
|
|
runInAction(() => {
|
|
|
this.hotel.loading = false;
|
|
|
this.hotel.dataSource = resCP;
|
|
|
this.hotel.summaryRow = { ...summaryRow, ...summaryDelta };
|
|
|
});
|
|
|
}
|
|
|
|
|
|
searchValues = {
|
|
|
date: moment(),
|
|
|
DateType: { key: 'confirmDate', label: '确认日期' },
|
|
|
WebCode: { key: '', label: '所有来源' },
|
|
|
// IncludeTickets: { key: '1', label: '含门票'},
|
|
|
DepartmentList: [{ key: '', label: '所有小组' }],
|
|
|
operator: '-1',
|
|
|
opisn: '-1',
|
|
|
};
|
|
|
|
|
|
searchValuesToSub = {};
|
|
|
|
|
|
setSearchValues(obj, values) {
|
|
|
this.searchValues = { ...this.searchValues, ...values };
|
|
|
this.searchValuesToSub = obj;
|
|
|
}
|
|
|
|
|
|
cruise = { loading: false, dataSource: [], summaryRow: {} };
|
|
|
hotel = { loading: false, dataSource: [], summaryRow: {} };
|
|
|
resetData = () => {
|
|
|
this.results.loading = false;
|
|
|
for (const key of Object.keys(this.results)) {
|
|
|
if (key !== 'loading') {
|
|
|
this.results[key] = [];
|
|
|
}
|
|
|
}
|
|
|
for (const key of Object.keys(this.hotel)) {
|
|
|
if (key !== 'loading') {
|
|
|
this.hotel[key] = [];
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
}
|
|
|
export default HotelCruise;
|