You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

358 lines
12 KiB
JavaScript

const { objectMapper: _objectMapper, isNotEmpty, isEmpty } = require('../utils/commons');
10 months ago
const { DEFAULT_LGC, LGC_MAPPED } = require('../config/constants');
const objectMapper = (input, keyMap) => _objectMapper(input || {}, keyMap, false);
const infoDataMapper = (row) => {
const item = objectMapper(row, {
HotelId: 'hotel_id',
// HotelName: 'hotel_name',
LocaleName: 'hotel_name',
10 months ago
CountryCode: 'country_code',
CityId: 'city_id',
// Address: 'address',
AddressLocale: 'address',
10 months ago
Phone: 'phone',
Latitude: 'latitude',
Longitude: 'longitude',
Rating: 'rating',
HotelType: 'hotel_type',
Brand: 'brand',
PostalCode: 'postal_code',
HeroImg: 'hero_img',
SupplierType: 'supplier_type',
});
// item.hotel_name = isEmpty(item.hotel_name) ? row.LocaleName : item.hotel_name;
10 months ago
const review = objectMapper(row.Review, {
Score: 'review_score',
ReviewCount: 'review_count',
Desc: 'review_desc',
});
const location = objectMapper(row.Location, {
PoiScore: 'location_poi_score',
AirportScore: 'location_airport_score',
TransportationScore: 'location_transportation_score',
});
return {...item, ...review, ...location};
}
const info2DataMapper = (row, lgcObj) => {
const item = objectMapper(row, {
HotelId: 'hotel_id',
LocaleName: 'hi2_hotel_name',
Description: 'hi2_description',
AddressLocale: 'hi2_address',
});
const instruction = objectMapper(row.Instruction, {
Desc: 'h2_instruction_desc',
Special: 'h2_instruction_special',
FeesDesc: 'h2_instruction_fees_desc',
});
const location = objectMapper((row.Location?.WalkablePlaces), {
Title: 'h2_location_walkable_places_title',
Desc: 'h2_location_walkable_places_desc',
});
const highlight = objectMapper(row.Highlight, {
LocationHighlightDesc: 'h2_location_highlight_desc',
});
const review = objectMapper(row.Review, {
Desc: 'h2_review_desc',
});
return { ...item, ...instruction, ...location, ...highlight, ...lgcObj, ...review };
};
const roomsMapper = (row, lgcObj) => {
const rooms = (row.Rooms || []).map((rowRoom) => ({
hotel_id: row.HotelId,
...lgcObj,
...(objectMapper(rowRoom, {
RoomId: 'room_id',
RoomName: 'room_name',
LocaleName: 'locale_name',
BedTypeDesc: 'bed_type_desc',
Area: 'area',
Views: 'views',
Window: 'window',
Floor: 'floor',
WirelessWideband: 'wireless_wideband',
WiredBroadband: 'wired_broadband',
Smoking: 'smoking',
BathRoomType: 'bathroom_type',
// Images: 'images',
})),
max_occupancy: rowRoom.MaxOccupancy ? JSON.stringify(rowRoom.MaxOccupancy) : null,
bedrooms: rowRoom.BedRooms ? JSON.stringify(rowRoom.BedRooms) : null,
}));
return rooms;
};
const imagesDaraMapper = (row, lgcObj) => {
const images = (row.Rooms || []).reduce(
(r, rowRoom) =>
r.concat(
(rowRoom.Images || []).map((imgItem) => ({
hotel_id: row.HotelId,
...lgcObj,
info_source: 'rooms',
info_source_id: rowRoom.RoomId,
type: null,
url: imgItem.Url,
caption: null,
category: imgItem.Category,
}))
),
[]
);
const urls = (row.Urls || []).reduce(
(r, rowUrl) =>
r.concat(
rowUrl.Urls.map((imgItem) => ({
hotel_id: row.HotelId,
...lgcObj,
info_source: 'hotelinfo',
info_source_id: row.HotelId,
type: imgItem.Type,
url: imgItem.Url,
caption: rowUrl.Caption,
category: rowUrl.Category,
}))
),
[]
);
return [].concat(images, urls);
};
const mainhighlightsMapper = (row, lgcObj) => {
return (row.Highlight?.MainHighlights || []).map((mhl) => ({
hotel_id: row.HotelId, // hotel_id:
...lgcObj,
type: 'MainHighlights', // type:
category: mhl.Category, // category:
category_name: '', // category_name:
id: null, // id:
name: mhl.Name, // name:
symbol: null, // symbol:
tooltip: mhl.Tooltip, // tooltip:
}));
};
const facilityCMapper = (row, lgcObj) => {
return (row.Facility?.Categories || []).reduce(
(r, fc) =>
r.concat(
fc.Items.map((fcItem) => ({
hotel_id: row.HotelId, // hotel_id:
...lgcObj,
type: 'Facility', // type:
category: fc.Category, // category:
category_name: fc.Name, // category_name:
id: fcItem.Id, // id:
name: fcItem.Name, // name:
symbol: fcItem.Symbol, // symbol:
tooltip: null, // tooltip:
}))
),
[]
);
};
const facilityHLMapper = (row, lgcObj) =>
(row.Facility?.Highlights || []).map((fl) => ({
hotel_id: row.HotelId, // hotel_id:
...lgcObj,
type: 'Highlights', // type:
category: '', // category:
category_name: '', // category_name:
id: fl.Id, // id:
name: fl.Name, // name:
symbol: fl.Symbol, // symbol:
tooltip: null, // tooltip:
}));
const informationsMapper = (row, lgcObj) =>
(row.Informations || []).reduce(
(r, fc) =>
r.concat(
fc.Items.map((fcItem) => ({
hotel_id: row.HotelId, // hotel_id:
...lgcObj,
category: fc.Category, // category:
category_name: fc.CategoryName, // category_name:
id: fcItem.Id, // id:
name: fcItem.Name, // name:
value: fcItem.Value, // value:
}))
),
[]
);
const locationPlacesMapper = (sourceName, hotelId, places, lgcObj) =>
places.map((item) => ({
hotel_id: hotelId, // hotel_id:
...lgcObj,
location_type: sourceName, // location_type:
category: null, // category:
category_name: null, // category_name:
id: item.Id || null, // id:
name: item.Name, // name:
distance: item.Distance, // distance:
latitude: item.Latitude || null, // latitude:
longitude: item.Longitude || null, // longitude:
type_name: item.TypeName || null, // type_name:
type_id: item.TypeId || null, // type_id:
min_distance: null, // min_distance:
}));
const scoresMapper = (sourceName, hotelId, scores, lgcObj) => scores.map((item) => ({
hotel_id: hotelId, // hotel_id:
...lgcObj,
type: sourceName, // type:
name: sourceName==='ScoreDetails' ? item.Name : null, // name:
category: item.Category || null, // category:
score: item.Score || null, // score:
city_average: item.CityAverage || null, // city_average:
mention_name: sourceName==='PositiveMentions' ? item.Name : null, // mention_name:
mention_count: sourceName==='PositiveMentions' ? item.Count : null, // mention_count:
}));
/**
* 解析Details数据
* todo: BedRoom MaxOccupancy
*/
const resolveDetails = (res, lgcObj) => {
return res.reduce(
(rd, c) => {
if (isEmpty(c.HotelName) && isEmpty(c.LocaleName)) {
return rd;
}
10 months ago
rd.info.push(infoDataMapper(c));
rd.info2.push(info2DataMapper(c, lgcObj));
rd.rooms = rd.rooms.concat(roomsMapper(c, lgcObj));
rd.images = rd.images.concat(imagesDaraMapper(c, lgcObj));
// rd.images = rd.images.concat(urls);
// rd.test = rd.test.concat([c.Highlight.LocationHighlightDesc]); // test:
const MainHighlights = mainhighlightsMapper(c, lgcObj);
const facilityC = facilityCMapper(c, lgcObj);
const facilityHL = facilityHLMapper(c, lgcObj);
rd.facility = rd.facility.concat(MainHighlights, facilityC, facilityHL);
const infos = informationsMapper(c, lgcObj);
rd.infos = rd.infos.concat(infos);
const reviewScores = scoresMapper('ScoreDetails', c.HotelId, c.Review?.ScoreDetails || [], lgcObj);
const mentions = scoresMapper('PositiveMentions', c.HotelId, c.Review?.PositiveMentions || [], lgcObj);
rd.reviews = rd.reviews.concat(reviewScores, mentions);
const reviewSummaries = (c.Review?.Summaries || []).map((item) => ({
hotel_id: c.HotelId, // hotel_id:
...lgcObj,
country: item.Country, // country:
reviewer: item.Reviewer, // reviewer:
review_rating: item.ReviewRating, // review_rating:
desc: item.Desc, // desc:
review_date: item.ReviewDate, // review_date:
}));
rd.review_summaries = rd.review_summaries.concat(reviewSummaries);
const TopPlaces = locationPlacesMapper('TopPlaces', c.HotelId, c.Location?.TopPlaces || [], lgcObj);
const Shops = locationPlacesMapper('Shops', c.HotelId, c.Location?.Shops || [], lgcObj);
const Places = locationPlacesMapper('Places', c.HotelId, c.Location?.Places || [], lgcObj);
const NearbyCategories = (c.Location?.NearbyCategories || []).reduce(
(r, nc) =>
r.concat(
locationPlacesMapper('NearbyCategories', c.HotelId, nc.Places || [], lgcObj).map((item) => ({
...item,
category: nc.Category,
category_name: nc.Name,
min_distance: nc.MinDistance,
}))
),
[]
);
const WalkablePlaces = (c.Location?.WalkablePlaces?.Categories || []).reduce(
(r, nc) =>
r.concat(
locationPlacesMapper('WalkablePlaces', c.HotelId, nc.Places || [], lgcObj).map((item) => ({
...item,
category: nc.Name,
category_name: nc.Name,
}))
),
[]
);
rd.locations = rd.locations.concat(TopPlaces, Shops, Places, NearbyCategories, WalkablePlaces);
return rd;
},
{ info: [], info2: [], rooms: [], images: [], facility: [], infos: [], reviews: [], review_summaries: [], locations: [], test: [] }
);
}
/**
* 解析Availability数据
*/
/**
* 餐食类型 1明确数量(早中晚餐食看Breakfast Lunch Dinner 数量)2半包3全包4/晚二选一5+ /晚二选一
*/
const MealTypeMapped = {
'1': { value: 1, label: ({ Breakfast, Lunch, Dinner }) => `${Breakfast}份早餐` },
'2': { value: 2, label: ({ Breakfast, Lunch, Dinner }) => '半包' },
'3': { value: 3, label: ({ Breakfast, Lunch, Dinner }) => '全包' },
'4': { value: 4, label: ({ Breakfast, Lunch, Dinner }) => '午/晚二选一' },
'5': { value: 5, label: ({ Breakfast, Lunch, Dinner }) => '早+ 午/晚二选一' },
};
/**
* 付款方式 1现付 2预付
*/
const PayTypeMapped = {
'1': { value: 1, label: () => '现付' },
'2': { value: 2, label: () => '预付' },
};
/**
* 开票方式0 Unknown 1 提供方开票 2 酒店开票3 供应商开票
*/
const InvoiceTypeMapped = {
'0': { value: 0, label: () => '未知' },
'1': { value: 1, label: () => '提供方开票' },
'2': { value: 2, label: () => '酒店开票' },
'3': { value: 3, label: () => '供应商开票' },
};
/**
* 取消手续费类型0 未知 1扣首日 2扣全额 3按价格多少百分比扣 4免费取消 5扣几晚 6扣多少钱
*/
const cancelDeductTypeMapped = {
'0': { value: 0, label: () => '未知' },
'1': { value: 1, label: () => '扣首日' },
'2': { value: 2, label: () => '扣全额' },
'3': { value: 3, label: (value) => `扣款${value * 100}%` },
'4': { value: 4, label: () => '免费取消' },
'5': { value: 5, label: (value) => `${value}` },
'6': { value: 6, label: (value) => `扣款${value}` },
};
/**
* 解析报价数据
*/
const resolveRatePlans = (plans) => {
const res = plans.map((room) => ({
...room,
RatePlans: room.RatePlans.map((rp) => {
const PriceUnit = rp.Dailys[0].Price;
const CancelableText = rp.Cancelable === true ? '限时取消' : '不可取消';
const CancelRulesMapped = (rp.CancelRules || []).map((citem) => {
let OutputText = isNotEmpty(citem.StartTime) ? `北京时间: ${citem.StartTime}${citem.EndTime}, ` : '';
OutputText += cancelDeductTypeMapped[citem.DeductType].label(citem.DeductValue);
OutputText += citem.Desc;
return OutputText;
}); // 限时取消
rp.Cancelable === true ? CancelRulesMapped.push('其他时间不可取消') : false;
return { ...rp,
PriceUnit, PriceTotal: rp.Price,
CancelRulesText: CancelRulesMapped, CancelableText,
PayTypeText: PayTypeMapped[rp.PayType]?.label(),
};
10 months ago
}),
}));
return res;
};
module.exports = { resolveDetails, resolveRatePlans };