const express = require('express'); const router = express.Router(); const jwt = require('jsonwebtoken'); const cors = require('cors'); const AvtocodProvider = require('../data_providers/avtocod'); const Vin01Provider = require('../data_providers/vin01'); const { regions } = require('../data_providers/constants'); const makeError = error => ({ success: false, error }); function makeNumberQuery(number, regions) { let regionsQuery = null; if(regions.length > 0) { regionsQuery = { $or: regions.map(r => { return { number: { $regex: `\\D${r}$` } }; }) }; } if(number && regionsQuery) { return { $and: [ { number: { $regex: number } }, regionsQuery ] }; } else if(number) { return { number: { $regex: number } }; } else if(regionsQuery) { return regionsQuery; } else { return {}; } } router.post('/check', async (req, res) => { const number = req.body.number.replace(/ /g, '').toUpperCase(); const googleIdToken = req.body.googleIdToken; const forceUpdate = req.body.forceUpdate.toLowerCase() == 'true'; const { login } = req.user; console.log(`=== checking number: ${number} ====================================`); let collection = req.db.collection('vehicles'); let vehicles = await collection.find({ number }).toArray(); if(vehicles.length > 0 && !forceUpdate) { console.log('vehicle found in database'); res.send({ success: true, data: vehicles[0] }); } else { try { let autocodPromise = AvtocodProvider.getReport(number); let all = [autocodPromise]; if(googleIdToken) { let vin01Promise = Vin01Provider.getReport(number, googleIdToken); all.push(vin01Promise); } let [autocod, vin01] = await Promise.allSettled(all); if(autocod.status == 'fulfilled') { let vehicle = autocod.value; console.log('autocod found vehicle: ', vehicle?.brand?.name?.original); vehicle.addedBy = login; if(vin01?.status == 'fulfilled') { vehicle.vin1 = vin01.value.vin1; if(vin01.value?.brand?.name?.original == vehicle?.brand?.name?.original) { vehicle.vin2 = vin01.value.vin2; vehicle.color = vin01.value.color; vehicle.ownershipPeriods = vin01.value.ownershipPeriods; } } // In case of force update of existing vehicle, transfer all events to the new DB record if (vehicles.length > 0) { vehicle.events = vehicles[0].events; } await collection.replaceOne({ number }, vehicle, { upsert: true }); res.status(201).send({ success: true, data: vehicle }); } else { throw Error(autocod.reason); } } catch(ex) { res.send(makeError(ex.message)); console.error(ex); } } }); router.get('/', async (req, res) => { const { limit, query, brand, model, color, regions } = req.query; let numberQuery = makeNumberQuery(query, regions?.split(',') ?? []); let findQuery = { 'brand.name.normalized': brand, 'model.name.normalized': model, color }; let findQueryFiltered = Object.fromEntries(Object.entries(findQuery).filter(([,val]) => val )); let finalQuery = { ...findQueryFiltered, ...numberQuery }; try { let collection = req.db.collection('vehicles'); let vehicles = await collection.find(finalQuery).sort({ addedDate: -1 }).limit(parseInt(limit ?? 0)).toArray(); res.send({ success: true, data: vehicles }); } catch(ex) { res.send(makeError('Error reading vehicles from DB')); console.error(ex); } }); router.get('/brands', async (req, res) => { try { let collection = req.db.collection('vehicles'); let brands = await collection.distinct('brand.name.normalized'); res.send({ success: true, data: brands.filter(Boolean) }); } catch(ex) { res.send(makeError('Error reading vehicle brands from DB')); console.error(ex); } }); router.get('/models', async (req, res) => { try { const { brand } = req.query; let collection = req.db.collection('vehicles'); let models = await collection.distinct('model.name.normalized', { 'brand.name.normalized': brand }); res.send({ success: true, data: models.filter(Boolean) }); } catch(ex) { res.send(makeError('Error reading vehicle models from DB')); console.error(ex); } }); router.get('/colors', async (req, res) => { try { let collection = req.db.collection('vehicles'); let colors = await collection.distinct('color'); res.send({ success: true, data: colors.filter(Boolean) }); } catch(ex) { res.send(makeError('Error reading vehicle colors from DB')); console.error(ex); } }); router.get('/regions', (req, res) => { res.send({ success: true, data: regions }); }); router.get('/shared_report', cors({ origin: 'https://auto.aliencat.pro' }), async (req, res) => { try { let { plateNumber } = jwt.verify(req.query.token, '#TheTruthIsOutThere'); let collection = req.db.collection('vehicles'); let vehicles = await collection.find({ number: plateNumber }).toArray(); if(vehicles.length > 0) { res.send({ success: true, data: vehicles[0] }); } else { res.send(makeError('Vehicle not found')); } } catch(ex) { res.send(makeError(ex.message)); console.error(ex); } }); module.exports = router;