@ -3,7 +3,7 @@ const initModels = require('./../models/init-models');
const { AvailableAccommodationIds , AccommodationsDetails , Availability } = require ( '../vendor/heytrip' ) ;
const { isEmpty } = require ( '../utils/commons' ) ;
const { resolveDetails , resolveRatePlans } = require ( '../helper/heytripDataHelper' ) ;
const { DEFAULT _LGC , LGC _MAPPED } = require ( '../config/constants' ) ;
const { DEFAULT _LGC , LGC _MAPPED , HEYTRIP _API _PROD } = require ( '../config/constants' ) ;
const { sequelize : Sequelize , Op } = db ;
@ -24,6 +24,9 @@ const ReviewsSummaries = models.reviewsSummariesModel;
const Locations = models . locationsModel ;
// const CacheAvailability = models.cacheAvailabilityModel;
const Logs = models . requestLogsModel ;
// HeytripIds.hasMany(Hotelinfo, {
// foreignKey: 'hotel_id',
// onDelete: 'NO ACTION',
@ -32,7 +35,8 @@ const Locations = models.locationsModel;
// Hotelinfo.belongsTo(HeytripIds, { as: 'aid', foreignKey: 'hotel_id', onDelete: 'NO ACTION', onUpdate: 'NO ACTION' });
// Hotelinfo.hasMany(Rooms, { sourceKey: 'hotel_id', foreignKey: 'hotel_id', onDelete: 'NO ACTION', onUpdate: 'NO ACTION' });
// Rooms.belongsTo(Hotelinfo, { targetKey: 'hotel_id', foreignKey: 'hotel_id', onDelete: 'NO ACTION', onUpdate: 'NO ACTION', });
Hotelinfo . hasMany ( Hotelinfo2 , { as : 'lgc_info' , sourceKey : 'hotel_id' , foreignKey : 'hotel_id' , onDelete : 'NO ACTION' , onUpdate : 'NO ACTION' } ) ;
Hotelinfo . belongsTo ( HeytripIds , { as : 'aid' , foreignKey : 'hotel_id' , onDelete : 'NO ACTION' , onUpdate : 'NO ACTION' } ) ;
Hotelinfo . hasMany ( Hotelinfo2 , { as : 'locale_info' , sourceKey : 'hotel_id' , foreignKey : 'hotel_id' , onDelete : 'NO ACTION' , onUpdate : 'NO ACTION' } ) ;
Hotelinfo . hasMany ( City , { as : 'city' , sourceKey : 'city_id' , foreignKey : 'id' , onDelete : 'NO ACTION' , onUpdate : 'NO ACTION' , } ) ; // 多语种, 所以实际是 hasMany , 用 hasOne 要指定 lgc= 1 或者2
Hotelinfo . hasMany ( Country , { as : 'country' , sourceKey : 'country_code' , foreignKey : 'id' , onDelete : 'NO ACTION' , onUpdate : 'NO ACTION' , } ) ; // 多语种, 所以实际是 hasMany , 用 hasOne 要指定 lgc= 1 或者2
// Hotelinfo2.belongsTo(Hotelinfo, { targetKey: 'hotel_id', foreignKey: 'hotel_id', onDelete: 'NO ACTION', onUpdate: 'NO ACTION', });
@ -45,8 +49,8 @@ class Heytrip {
const keywordSplit = keyword . split ( ' ' ) ;
const keywordWhere = ( field ) => keywordSplit . map ( ( word ) => Sequelize . where ( Sequelize . fn ( 'instr' , Sequelize . col ( field ) , word ) , { [ Op . gt ] : 0 } ) ) ;
// 'hotelinfo.address'
const keywordSearch = [ 'hotelinfo.hotel_name' , ]. map ( ( field ) => ( { [ Op . and ] : keywordWhere ( field ) } ) ) ;
const keywordOrder = [ 'hotelinfo.hotel_name' , ]. reduce ( ( ro , field ) => ro . concat ( keywordSplit . map ( ( word ) => Sequelize . fn ( 'instr' , Sequelize . col ( field ) , word ) ) ) , [ ] ) ;
const keywordSearch = [ 'hotelinfo.hotel_name' ]. map ( ( field ) => ( { [ Op . and ] : keywordWhere ( field ) } ) ) ;
const keywordOrder = [ 'hotelinfo.hotel_name' ]. reduce ( ( ro , field ) => ro . concat ( keywordSplit . map ( ( word ) => Sequelize . fn ( 'instr' , Sequelize . col ( field ) , word ) ) ) , [ ] ) ;
// const keywordSearchCount = ['hi2_hotel_name', 'hi2_address'].map((field) => ({ [Op.and]: keywordWhere(field) }));
// const countRows = await Hotelinfo2.count({
@ -62,9 +66,10 @@ class Heytrip {
const { count , rows } = await Hotelinfo . findAndCountAll ( {
// const [ rows ] = await Hotelinfo.findAll({
include : [
{ model : HeytripIds , as : 'aid' , attributes : [ 'hotel_id' , 'update_flag' ] , where : { update _flag : { [ Op . ne ] : 99 } } } ,
{
model : Hotelinfo2 ,
as : 'l gc _info',
as : 'l ocale _info',
attributes : [
[ 'hi2_sn' , 'sn' ] ,
'hotel_id' ,
@ -79,8 +84,8 @@ class Heytrip {
required : false ,
separate : true ,
} ,
{ model : City , as : 'city' , attributes : [ 'id' , 'name' ] , where : { lgc : 2 } , required : false , separate : true , } ,
{ model : Country , as : 'country' , attributes : [ 'id' , 'name' ] , where : { lgc : 2 } , required : false , separate : true , } ,
{ model : City , as : 'city' , attributes : [ 'id' , 'name' ] , where : { lgc : 2 } , required : false , separate : true } ,
{ model : Country , as : 'country' , attributes : [ 'id' , 'name' ] , where : { lgc : 2 } , required : false , separate : true } ,
] ,
// include: [{ model: Hotelinfo2, as: 'h2', required: true }],
where : {
@ -97,8 +102,12 @@ class Heytrip {
// return { count, rows };
} ;
getLastPageIndex = async ( ) => {
const ret = await HeytripIds . max ( 'page_index' ) ;
getLastPageIndex = async ( where = { } ) => {
const ret = await HeytripIds . max ( 'page_index' , { where } ) ;
return ret ;
} ;
getFirstPageIndex = async ( where = { } ) => {
const ret = await HeytripIds . min ( 'page_index' , { where } ) ;
return ret ;
} ;
@ -123,6 +132,76 @@ class Heytrip {
} ;
} ;
syncAidState = async ( ) => {
const today = new Date ( ) ;
today . setHours ( 0 , 0 , 0 , 0 ) ; // set the time to 00:00:00.000
let lastPageIndex ; let pageIndex ;
lastPageIndex = await this . getFirstPageIndex ( { last _modify _time : { [ Op . lt ] : today } } ) ;
pageIndex = lastPageIndex ;
if ( isEmpty ( lastPageIndex ) ) {
lastPageIndex = await this . getLastPageIndex ( { last _modify _time : { [ Op . gt ] : today } , page _index : { [ Op . lt ] : 9999 } } ) ;
pageIndex = lastPageIndex + 1 ;
}
console . log ( 'syncAidState' , lastPageIndex , pageIndex ) ;
const validIds = ( await AvailableAccommodationIds ( pageIndex ) ) . map ( ( id ) => String ( id ) ) ;
if ( isEmpty ( validIds ) ) {
// await HeytripIds.update({ update_flag: 99, priority: 99 }, { where: { pageIndex: [Op.gt]: pageIndex } });
// 同步结束; 本次没有的ID: 更新: 99=失效
const stateOff = await HeytripIds . findAll ( {
raw : true ,
where : {
update _flag : { [ Op . notIn ] : [ 0 , 1 ] } ,
last _modify _time : { [ Op . gt ] : today } ,
} ,
attributes : [ 'hotel_id' ] ,
} ) ;
const stateOffIds = stateOff . map ( ( item ) => item . hotel _id ) ;
if ( ! isEmpty ( stateOffIds ) ) {
await HeytripIds . update ( { update _flag : 99 , priority : 99 } , { where : { hotel _id : stateOffIds } } ) ;
console . log ( 'updated stateOff' , stateOffIds . length ) ;
}
return {
nextPage : false ,
} ;
}
const savedIds = await HeytripIds . findAll ( {
raw : true ,
where : { hotel _id : validIds } ,
attributes : [ 'hotel_id' ] ,
logging : false ,
} ) ; // savedIds <= validIds
const savedPageIds = await HeytripIds . findAll ( {
raw : true ,
where : { page _index : pageIndex , } ,
attributes : [ 'hotel_id' ] ,
// logging: false,
} ) ;
// 已存在ID: 更新: 状态, 页码, 时间
const stateNormal = savedIds . filter ( ( item ) => validIds . includes ( ( item . hotel _id ) ) ) . map ( ( item ) => item . hotel _id ) ;
if ( ! isEmpty ( stateNormal ) ) {
await HeytripIds . update ( { update _flag : 0 , page _index : pageIndex , last _modify _time : Sequelize . fn ( 'NOW' ) } , { where : { hotel _id : stateNormal } } ) ;
}
const newIds = validIds . filter ( ( id ) => ! savedIds . map ( ( item ) => item . hotel _id ) . includes ( id ) ) ;
if ( ! isEmpty ( newIds ) ) {
const insertRows = newIds . map ( ( id ) => ( { hotel _id : id , page _index : pageIndex , update _flag : 1 } ) ) ;
await HeytripIds . bulkCreate ( insertRows ) ;
}
const oldToNext = savedPageIds . filter ( ( item ) => ! validIds . includes ( ( item . hotel _id ) ) ) . map ( ( item ) => item . hotel _id ) ;
if ( ! isEmpty ( oldToNext ) ) {
await HeytripIds . update ( { page _index : Number ( pageIndex ) + 9999 , update _flag : 99 } , { where : { hotel _id : oldToNext } } ) ;
}
return {
nextPage : true ,
pageIndex ,
} ;
}
newHotels = async ( ) => {
const [ rows ] = await Sequelize . query (
'SELECT i.hotel_id, IFNULL(h.hi_sn ,0) info_exists FROM heytrip_ids as i LEFT JOIN hotelinfo AS h ON h.hotel_id = i.hotel_id WHERE h.hi_sn IS NULL AND update_flag != 0 ORDER BY info_exists LIMIT 10'
@ -131,13 +210,6 @@ class Heytrip {
} ;
newHotelsLgc = async ( lgc ) => {
// const [rows] = await Sequelize.query(
// `SELECT h.hotel_id
// FROM hotelinfo AS h
// LEFT JOIN hotelinfo2 AS h2 ON h.hotel_id =h2.hotel_id
// AND h2.lgc = ${lgc}
// WHERE h2.hi2_sn IS NULL LIMIT 10`
// );
const [ rows ] = await Sequelize . query (
` SELECT i.hotel_id ,IFNULL(h.hi2_sn, 0) info_exists
FROM heytrip _ids AS i
@ -146,6 +218,7 @@ class Heytrip {
WHERE h . hi2 _sn IS NULL
AND update _flag != 99
ORDER BY info _exists LIMIT 10 `
, { logging : false }
) ;
const res = await this . syncInitHotelLgcDetailsAction ( rows , LGC _MAPPED [ lgc ] ) ;
return res ;
@ -182,10 +255,12 @@ class Heytrip {
return res ;
} ;
/ * *
* @ deprecated
* /
syncInitHotelDetailsAction = async ( rows , lgcObj = LGC _MAPPED [ DEFAULT _LGC ] ) => {
let allIds = [ ] ;
try {
allIds = rows . map ( ( item ) => item . hotel _id ) ;
const updateIds = rows . filter ( ( item ) => item . info _exists !== 0 ) . map ( ( item ) => item . hotel _id ) ;
const newIds = rows . filter ( ( item ) => item . info _exists === 0 ) . map ( ( item ) => item . hotel _id ) ;
@ -204,8 +279,8 @@ class Heytrip {
// return insertData; // debug: 0
/** 开始Database */
const sequelizeOptions = { logging : false } ;
const result = await Sequelize . transaction ( async t => {
const result = await Sequelize . transaction ( async ( transaction ) => {
const sequelizeOptions = { logging : false , transaction } ;
let Info ;
if ( ! isEmpty ( insertData . info ) ) Info = await Hotelinfo . bulkCreate ( insertData . info , sequelizeOptions ) ;
if ( ! isEmpty ( insertData . info2 ) ) await Hotelinfo2 . bulkCreate ( insertData . info2 , sequelizeOptions ) ;
@ -221,26 +296,23 @@ class Heytrip {
} ) ;
return { next : ! isEmpty ( allIds ) , data : allIds } ;
} catch ( error ) {
console . log ( error ) ;
return { next : false , data : allIds } ;
}
}
} ;
syncInitHotelLgcDetailsAction = async ( rows , lgcObj = LGC _MAPPED [ DEFAULT _LGC ] ) => {
let allIds = [ ] ;
try {
allIds = rows . map ( ( item ) => item . hotel _id ) ;
if ( isEmpty ( rows ) ) {
return { next : ! isEmpty ( allIds ) , data : allIds } ;
}
const _BaseInfoExists = await Hotelinfo . findAll ( { where : { hotel _id : allIds } } ) ;
const _BaseInfoExists = await Hotelinfo . findAll ( { where : { hotel _id : allIds } , logging : false } ) ;
const updateIds = _BaseInfoExists . map ( ( item ) => ` ${ item . hotel _id } ` ) ;
console . log ( 'updateIds' , updateIds ) ;
// console.log('updateIds', updateIds);
const res = await AccommodationsDetails ( {
Language : lgcObj . locale ,
@ -253,12 +325,20 @@ class Heytrip {
// return insertData; // debug: 0
/** 开始Database */
const result = await Sequelize . transaction ( async transaction => {
const result = await Sequelize . transaction ( async ( transaction ) => {
const sequelizeOptions = { logging : false , transaction } ;
let Info ;
const newInfo = insertData . info . filter ( iitem => ! updateIds . includes ( ` ${ iitem . hotel _id } ` ) ) ;
console . log ( 'newInfo' , newInfo . map ( xx => xx . hotel _id ) ) ;
const offInfo = allIds . filter ( ( iitem ) => ! resIds . includes ( ` ${ iitem } ` ) ) ;
if ( ! isEmpty ( offInfo ) ) {
await HeytripIds . update ( { update _flag : 99 } , { where : { hotel _id : offInfo } , ... sequelizeOptions } ) ;
}
const newInfo = insertData . info . filter ( ( iitem ) => ! updateIds . includes ( ` ${ iitem . hotel _id } ` ) ) ;
// console.log(
// 'newInfo',
// newInfo.map((xx) => xx.hotel_id)
// );
if ( ! isEmpty ( newInfo ) ) Info = await Hotelinfo . bulkCreate ( newInfo , sequelizeOptions ) ;
if ( ! isEmpty ( insertData . info2 ) ) await Hotelinfo2 . bulkCreate ( insertData . info2 , sequelizeOptions ) ;
@ -270,13 +350,12 @@ class Heytrip {
if ( ! isEmpty ( insertData . reviews _summaries ) ) await ReviewsSummaries . bulkCreate ( insertData . reviews _summaries , sequelizeOptions ) ;
if ( ! isEmpty ( insertData . locations ) ) await Locations . bulkCreate ( insertData . locations , sequelizeOptions ) ;
if ( ! isEmpty ( newInfo ) ) await HeytripIds . update ( { update _flag : 0 } , { where : { hotel _id : newInfo . map ( x => x . hotel _id ) } } ) ;
if ( ! isEmpty ( newInfo ) ) await HeytripIds . update ( { update _flag : 0 } , { where : { hotel _id : newInfo . map ( ( x ) => x . hotel _id ) } , ... sequelizeOptions } ) ;
return Info ;
} ) ;
return { next : ! isEmpty ( allIds ) , data : allIds } ;
} catch ( error ) {
console . log ( error ) ;
@ -303,5 +382,21 @@ class Heytrip {
const quoteRes = resolveRatePlans ( _quoteRes ) ;
return quoteRes ;
} ;
writeHeytripRequestLog = async ( { action , body } ) => {
const actionMapped = {
'getHotelAvailability' : '/Accommodation/Availability' ,
'getHotelInfo' : '/Accommodation/AccommodationsDetails' ,
'getHotelIds' : '/Accommodation/AvailableAccommodationIds' ,
} ;
const data = {
action : action ,
// method: ctx.method,
path : actionMapped [ action ] ,
request _data : body ,
// ip: ctx.ip,
} ;
return await Logs . create ( data , { logging : false } ) ;
} ;
}
module . exports = new Heytrip ( ) ;