UNPKG

hkopendata

Version:

Access different Opendata API and data in Hong Kong

321 lines (312 loc) 11.9 kB
const cmn = require("../common"); const moment = require("../moment"); const Coordinate = require("../_class").Coordinate; function PreprocessFields(data) { const FIELDS = { regex: { "([A-z]+)?AmountCurrencyCode": "$1CurrencyCode" }, text: { "URL": "website", "CurrencyCode": "currency", "BaseCurrencyName": "baseName", "BaseCurrencyCode": "baseCurrency", "CurrencyName": "name", "OpenDayDescription": "openDay", "ExchangeRateTypeName": "exchangeRateType", "CalculationFrequency": "calculateFrequency", "Identification": "type", "APR": "repAPR", "MinCreditLimit": "creditLimitMin", "MaxPurchaseInterestFreeLengthDays": "maxInterestFreeDay", }, number: { "MinimumAge": "min", "LatitudeDescription": "latitude", "LongitudeDescription": "longitude", }, others: { "Notes": "remarks", "LoanInterestTierBand": "tierBand", } } if (Array.isArray(data)) { return data.map(v => PreprocessFields(v)) } else if (typeof data === "object" && data !== null) { let temp = {}, common = { "Name": "name", "Amount": "amount", "CurrencyCode": "currency", }, keyJoin = Object.keys(common).join("|"), regex = new RegExp(keyJoin, "i"), group = {}; data = cmn.RenameFields(data, FIELDS); Object.keys(data).filter(v => regex.test(v) && !/PerAmount/.test(v)).map(v => { let r = new RegExp(`([A-z]+)?(${keyJoin})$`), m = v.match(r), n; if (m) { if (m[1]) { if (/Territory|District/.test(m[1])) { temp[m[1].toCamelCase()] = data[v]; delete data[v]; } else { for (let key in data) { if (n = key.match(`${m[1]}(.*)`)) { let ckey = m[1].toCamelCase(), citem = n[1] in common ? common[n[1]] : n[1].toCamelCase(); if (!(ckey in group)) group[ckey] = {} group[ckey][citem] = n[1] == "Amount" && /^[0-9-.]+$/.test(data[key]) ? parseFloat(data[key]) : data[key]; delete data[key]; } } } } else if (m[2]) { temp[common[m[2]]] = m[2] == "Amount" && /^[0-9-.]+$/.test(data[v]) ? parseFloat(data[v]) : data[v]; delete data[v]; } } }) for (let name in group) { if (/^(brand|atm|branch|loanCap|fee|repayment|minimumRepayment)$/.test(name)) { if (Object.keys(temp) == 0 || Object.keys(group[name]).filter(v => v in temp).length == 0) { for (let k in group[name]) { if (/minimumRepayment/.test(name) && k == "amount") temp.minRepay = group[name][k]; else temp[k.toCamelCase()] = group[name][k]; } } else { temp[name] = group[name]; } } else { let r = new RegExp(name); Object.keys(data).filter(v => r.test(v)).map(v => { group[name][v.replace(r, "").toCamelCase()] = data[v]; delete data[v]; }) temp[name] = group[name]; } } for (let key in temp) { temp[key] = PreprocessFields(temp[key]) } for (let key in data) { let k = key.toCamelCase(); if (typeof data[key] === "object") { if ("TierBand" in data[key]) { temp[k] = PreprocessFields(data[key].TierBand); } else { temp[k] = PreprocessFields(data[key]); } } else if (typeof data[key] === "string") { temp[k] = data[key].trim(); if (temp[k] == "") delete temp[k]; } else { temp[k] = data[key]; } } return temp } return data; } function ParseEligibility(data) { let eligibility = []; Object.keys(data).map(e => { let type = e.match(/^([a-z]+)Eligibility/)[1].toCamelCase(); if (Array.isArray(data[e])) { parseEligibility(data[e], type).map(v => eligibility.push(v)); } else { eligibility.push(parseEligibility(data[e], type)); } }) return eligibility; } function parseEligibility(data, type) { if (Array.isArray(data)) { return data.map(v => parseEligibility(v, type)) } else if (typeof data === "object" && data !== null) { let temp = { type: type, } return { ...temp, ...data } } return data; } function ParseItem(data) { if (typeof data !== "object" || data === null) return data; else if (Array.isArray(data)) return data.map(v => ParseItem(v)); const FIELDS = { "name": "name", "websiteAddress": "website", "hotlineNumber": "tel", "currency": "currency", }; let temp = {}; for (let key in FIELDS) { if (key in data) { temp[FIELDS[key]] = data[key]; delete data[key]; } } for (let key in data) { if (key == "address") { if ("territory" in data[key]) temp.region = data[key].territory; if ("district" in data[key]) temp.district = data[key].district; if ("addressLine" in data[key]) temp.address = data[key].addressLine; if ("latitude" in data[key] && "longitude" in data[key]) { temp.coordinate = new Coordinate({ latitude: parseFloat(data[key].latitude), longitude: parseFloat(data[key].longitude), }); } delete data[key]; } else if (key == "services") { temp.services = {}; for (let k in data[key]) { let m; if (m = k.match(/([A-z]+)((Operat|Open)ingHour|CutOffTime)/)) { if (!("operatingHour" in temp.services)) temp.services.operatingHour = {} temp.services.operatingHour[m[1].toCamelCase()] = data[key][k]; } else if (data[key][k]) { let rename = { "rMBandForeignCurrencyATM": "foreignCurrencyAvailable", "rMBATMwithoutForeignCurrency": "aTMwithRMB", }, k2 = k.replace("Indicator", "").toCamelCase(); temp.services[k2 in rename ? rename[k2] : k2] = data[key][k]; } } delete data[key]; } else if (key == "openingHours") { temp.opening = {}; data[key].map(v => { let str = "-"; if (v.openTime && v.closeTime) { str = `${moment(v.openTime, "HH:mm").format("HH:mm")}-${moment(v.closeTime, "HH:mm").format("HH:mm")}` } else if (v.openTime || v.closeTime) { str = v.openTime ? moment(v.openTime, "HH:mm").format("HH:mm") : moment(v.closeTime, "HH:mm").format("HH:mm") } temp.opening[v.openDay.toLowerCase().substr(0, 3)] = [str]; }) for (let k in temp.opening) { let filter = temp.opening[k].filter(v => v != "-"); temp.opening[k] = filter.length > 0 ? filter : false; } delete data[key]; } else if (key == "contactInformation") { if ("phoneNumber" in data[key]) { temp.tel = data[key].phoneNumber; } if ("faxNumber" in data[key]) { temp.fax = data[key].faxNumber; } delete data[key]; } } if ("coreProduct" in data) { let rename = { "productDescription": "description", "productURL": "website", "tcsAndCsURL": "termsAndConditions", "applicationFormURL": "applyForm", "applicationHotline": "telApply", "customerServiceHotline": "telCs", "hotlineNumber": "tel", "cardScheme": "scheme" } for (let k in data.coreProduct) { if (/AccessChannels/.test(k)) { if (!("accessChannel" in temp)) temp.accessChannel = []; temp.accessChannel = temp.accessChannel.concat(data.coreProduct[k]); } else if (/^(cardScheme|creditLimit|maxInterestFreeDay)$/.test(k)) { if (!("card" in temp)) temp.card = {} temp.card[k in rename ? rename[k] : k] = data.coreProduct[k]; } else if (k in rename) { temp[rename[k]] = data.coreProduct[k]; } else { temp[k] = data.coreProduct[k]; } } if ("accessChannel" in temp) { temp.accessChannel = temp.accessChannel.map(v => v.trim()); } delete data.coreProduct; } if ("repayment" in data) { temp.repayment = data.repayment.map(v => ParseItem(v)); delete data.repayment; } if ("eligibility" in data) { temp.eligibility = ParseEligibility(data.eligibility); delete data.eligibility; } if ("featuresAndBenefits" in data) { temp.featureBenefit = data.featuresAndBenefits.featureBenefitItem.map(v => ParseItem(v)); delete data.featuresAndBenefits; } if ("feesCharges" in data) { temp.feesCharge = data.feesCharges.feeChargeDetail.map(v => { let fee = ParseItem(v); if ("fee" in fee && Object.keys(fee.fee).filter(v => v in fee).length == 0) { for (let key in fee.fee) { fee[key] = fee.fee[key]; } delete fee.fee; } return fee; }); delete data.feesCharges; } if ("loanCap" in data) { temp.loanAmount = data.loanCap.map(v => { let t = ParseItem(v); if ("amount" in t) { t.max = t.amount; delete t.amount } return t; }) delete data.loanCap; } if ("bankBuyRate" in data) { temp.buyRate = parseFloat(data.bankBuyRate); delete data.bankBuyRate; } if ("bankSellRate" in data) { temp.sellRate = parseFloat(data.bankSellRate); delete data.bankSellRate; } if ("fixedVariableInterestRateType" in data) { temp.fixedInterestRate = data.fixedVariableInterestRateType == "Fixed"; delete data.fixedVariableInterestRateType; } if ("remarks" in data) { temp.remarks = data.remarks; delete data.remarks; } if ("lastUpdateDateTime" in data) { temp.lastUpdate = moment(data.lastUpdateDateTime).format("YYYY-MM-DD HH:mm:ss"); delete data.lastUpdateDateTime; } for (let key in data) { if (/CurrencyCode/.test(key)) { if ("currency" in data) { temp[key.replace("Code", "")] = data[key]; } else { temp.currency = data[key]; } } else { temp[key] = ParseItem(data[key]); } } return temp; } module.exports = { ParseEligibility, PreprocessFields, ParseItem }