const axios = require('axios'); const {DOMParser} = require('xmldom'); const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethod('exchangeRateUpdate', { description: 'Updates the exchange rates from an XML feed', accessType: 'WRITE', accepts: [], http: { path: '/exchangeRateUpdate', verb: 'post' }, returns: { arg: 'result', type: 'object', root: true } }); Self.exchangeRateUpdate = async() => { const response = await axios.get('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml'); const xmlData = response.data; const doc = new DOMParser().parseFromString(xmlData, 'text/xml'); const cubes = doc.getElementsByTagName('Cube'); const models = Self.app.models; const maxDateRecord = await models.ReferenceRate.findOne({order: 'dated DESC'}); const maxDate = maxDateRecord && maxDateRecord.dated ? new Date(maxDateRecord.dated) : null; for (let i = 0; i < cubes.length; i++) { const cube = cubes[i]; if (cube.nodeType === 1 && cube.attributes.getNamedItem('time')) { const xmlDate = new Date(cube.getAttribute('time')); const xmlDateWithoutTime = new Date(xmlDate.getFullYear(), xmlDate.getMonth(), xmlDate.getDate()); if (!maxDate || maxDate < xmlDateWithoutTime) { for (let j = 0; j < cube.childNodes.length; j++) { const rateCube = cube.childNodes[j]; if (rateCube.nodeType === doc.ELEMENT_NODE) { const currencyCode = rateCube.getAttribute('currency'); const rate = rateCube.getAttribute('rate'); if (['USD', 'CNY', 'GBP'].includes(currencyCode)) { const currency = await models.Currency.findOne({where: {code: currencyCode}}); if (!currency) throw new UserError(`Currency not found for code: ${currencyCode}`); const existingRate = await models.ReferenceRate.findOne({ where: {currencyFk: currency.id, dated: xmlDate} }); if (existingRate) { if (existingRate.value !== rate) await existingRate.updateAttributes({value: rate}); } else { await models.ReferenceRate.create({ currencyFk: currency.id, dated: xmlDate, value: rate }); } } } } } } } }; };