import { MONDIAL_RELAY_OFFICE, MONDIAL_RELAY_SECRET } from '../lib/constants' import { forEachObjIndexed, trim, isNaN, isNil, merge, path, reduce, splitEvery } from 'ramda' import Model from '@oyst/utils/lib/model' import easysoap from 'easysoap' import { makeError } from '@oyst/utils' import md5 from 'md5' const handleError = (code: any): { code: number, msg: string } => { switch (true) { case code < 4: return { code: 500, msg: 'invalid-office' } case code < 9 || code === 97: return { code: 401, msg: 'invalid-auth' } case code < 36: return { code: 500, msg: 'bad-params' } case code === 36: return { code: 400, msg: 'bad-postalcode' } default: return { code: 500, msg: 'unhandled-error' } } } interface IHours { begin: string, end: string } const _trim = (str: string): string => isNil(str) ? '' : trim(str) const _path = (p: any[], o: Object): string => path(p, o) const removeUselessHours = (hours: IHours[]): IHours[] => { const reduced = reduce((acc, key) => { if (hours[key].begin !== '-' && hours[key].end !== '-') { acc[key] = hours[key] } return acc }, {}, [0, 1]) as IHours[] const result = [] forEachObjIndexed((value, key) => { result.push(value) }, reduced) return result } const formatHours = (value: string): string => value === '0000' ? '-' : splitEvery(2, _trim(value)as any).join(':') const handleResults = (results: any[]): Object[] => { const pickupStores = [] results.map(result => { const data = result.PointRelais_Details const pickupStore = { address: { city: _trim(_path([5, 'Ville'], data)), latitude: _path([8, 'Latitude'], data), longitude: _path([9, 'Longitude'], data), name: _trim(_path([2, 'LgAdr1'], data)), postalCode: _trim(_path([4, 'CP'], data)), street: _trim(_path([3, 'LgAdr3'], data)), }, distance: _trim(_path([20, 'Distance'], data)), id: _path([1, 'Num'], data), informations: [ _trim(_path([11, 'Information'], data)), _trim(_path([19, 'Informations_Dispo'], data)) ], openingHours: { friday: removeUselessHours([{ begin: formatHours(_path([16, 'Horaires_Vendredi', 0, 'string'], data)), end: formatHours(_path([16, 'Horaires_Vendredi', 1, 'string'], data)) }, { begin: formatHours(_path([16, 'Horaires_Vendredi', 2, 'string'], data)), end: formatHours(_path([16, 'Horaires_Vendredi', 3, 'string'], data)) }]), monday: removeUselessHours([{ begin: formatHours(_path([12, 'Horaires_Lundi', 0, 'string'], data)), end: formatHours(_path([12, 'Horaires_Lundi', 1, 'string'], data)) }, { begin: formatHours(_path([12, 'Horaires_Lundi', 2, 'string'], data)), end: formatHours(_path([12, 'Horaires_Lundi', 3, 'string'], data)) }]), saturday: removeUselessHours([{ begin: formatHours(_path([17, 'Horaires_Samedi', 0, 'string'], data)), end: formatHours(_path([17, 'Horaires_Samedi', 1, 'string'], data)) }, { begin: formatHours(_path([17, 'Horaires_Samedi', 2, 'string'], data)), end: formatHours(_path([17, 'Horaires_Samedi', 3, 'string'], data)) }]), sunday: removeUselessHours([{ begin: formatHours(_path([18, 'Horaires_Dimanche', 0, 'string'], data)), end: formatHours(_path([18, 'Horaires_Dimanche', 1, 'string'], data)) }, { begin: formatHours(_path([18, 'Horaires_Dimanche', 2, 'string'], data)), end: formatHours(_path([18, 'Horaires_Dimanche', 3, 'string'], data)) }]), thursday: removeUselessHours([{ begin: formatHours(_path([15, 'Horaires_Jeudi', 0, 'string'], data)), end: formatHours(_path([15, 'Horaires_Jeudi', 1, 'string'], data)) }, { begin: formatHours(_path([15, 'Horaires_Jeudi', 2, 'string'], data)), end: formatHours(_path([15, 'Horaires_Jeudi', 3, 'string'], data)) }]), tuesday: removeUselessHours([{ begin: formatHours(_path([13, 'Horaires_Mardi', 0, 'string'], data)), end: formatHours(_path([13, 'Horaires_Mardi', 1, 'string'], data)) }, { begin: formatHours(_path([13, 'Horaires_Mardi', 2, 'string'], data)), end: formatHours(_path([13, 'Horaires_Mardi', 3, 'string'], data)) }]), wednesday: removeUselessHours([{ begin: formatHours(_path([14, 'Horaires_Mercredi', 0, 'string'], data)), end: formatHours(_path([14, 'Horaires_Mercredi', 1, 'string'], data)) }, { begin: formatHours(_path([14, 'Horaires_Mercredi', 2, 'string'], data)), end: formatHours(_path([14, 'Horaires_Mercredi', 3, 'string'], data)) }]) } } pickupStores.push(pickupStore) }) return pickupStores } export default class MondialRelay extends Model { private client: any = null private office: string = MONDIAL_RELAY_OFFICE private privateKey: string = MONDIAL_RELAY_SECRET private language: string = 'FR' private countryCode: string = 'FR' constructor (o?: any) { super() this.init(o) const params = { host: 'http://api.mondialrelay.com', path: '/Web_Services.asmx', wsdl: '/Web_Services.asmx?WSDL' } this.client = easysoap.createClient(params) } private securityKey (params: string[]): string { return md5(`${params.join('')}${this.privateKey}`).toUpperCase() } private getParams (keys: string[], values: string[]): Object { if (keys.length !== values.length) { throw new Error('bad-params') } const params = {} keys.forEach((key, index) => { params[key] = values[index] }) const securityKey = this.securityKey(values) return merge(params, { Security: securityKey }) } private call (method: string, params: Object): Promise { return this.client.call({ method, params, attributes: { xmlns: 'http://www.mondialrelay.fr/webservice/' } }) } public async searchByPostalCode (postalCode: string): Promise { return new Promise(async (resolve, reject) => { try { const result = await this.call( 'WSI3_PointRelais_Recherche', this.getParams([ 'Enseigne', 'Pays', 'NumPointRelais', 'Ville', 'CP', 'Latitude', 'Longitude' ], [ this.office, this.countryCode, '', '', postalCode, '', '' ]) ) const code: string = _path([ 'WSI3_PointRelais_RechercheResponse', 'WSI3_PointRelais_RechercheResult', 'STAT' ], result.data) || _path([ 'WSI3_PointRelais_RechercheResponse', 'WSI3_PointRelais_RechercheResult', '0', 'STAT' ], result.data) if (!code || code !== '0') { const error = handleError(parseInt(code, 10)) return reject(makeError(`RELAY-${error.code}`, error.msg)) } resolve(handleResults(_path([ 'WSI3_PointRelais_RechercheResponse', 'WSI3_PointRelais_RechercheResult', '1', 'PointsRelais' ], result.data) as Object[])) } catch (err) { console.log(err) reject(err) } }) } }