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 RsaProvider = require('../data_providers/rsa'); const NomerogramProvider = require('../data_providers/nomerogram'); const Utils = require('../utils'); const ObjectId = require('mongodb').ObjectID; const makeError = error => ({ success: false, error }); 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 { email } = 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); } else { all.push(Promise.reject({ debugInfo: { vin01vin: { fields: 0, error: 'No auth token' }, vin01history: { fields: 0, error: 'No auth token' }, vin01base: { fields: 0, error: 'No auth token' } } })); } all.push(NomerogramProvider.getGroups(number)); let [autocod, vin01, nomerogram] = await Promise.allSettled(all); let vehicle = null; if(autocod.status == 'rejected' && vin01.status == 'rejected') { throw autocod.reason; } else if(vin01.status == 'rejected') { vehicle = autocod.value; Object.assign(vehicle.debugInfo, vin01.reason.debugInfo); } else if(autocod.status == 'rejected') { vehicle = vin01.value; Object.assign(vehicle.debugInfo, autocod.reason.debugInfo); if(!vehicle.brand.name.normalized) { throw autocod.reason; } } else { vehicle = autocod.value; if(vehicle.vin1 && vin01.value.vin1.match(RegExp(vehicle.vin1.replace(/\*/g, '.')))) { vehicle.vin1 = vin01.value.vin1; vehicle.vin2 = vin01.value.vin2; vehicle.color = vin01.value.color; vehicle.ownershipPeriods = vin01.value.ownershipPeriods; } Object.assign(vehicle.debugInfo, vin01.value.debugInfo); } if(nomerogram.status == 'fulfilled') { vehicle.ads = nomerogram.value; Object.assign(vehicle.debugInfo, { nomerogram: { fields: 0, error: null } }); } else { Object.assign(vehicle.debugInfo, nomerogram.reason.debugInfo); console.error('nomerogram error: ', nomerogram.reason); } vehicle.addedBy = email; // In case of force update of existing vehicle, transfer all events to the new DB record if (vehicles.length > 0) { vehicle.addedDate = vehicles[0].addedDate; vehicle.events = vehicles[0].events; vehicle.osagoContracts = vehicles[0].osagoContracts; } await collection.replaceOne({ number }, vehicle, { upsert: true }); res.status(201).send({ success: true, data: vehicle }); } catch(ex) { res.send(makeError(ex.message)); console.error(ex); } } }); router.get('/', async (req, res) => { const { email } = req.user; const { pageToken } = req.query; const pageSize = 50; try { let finalQuery = Utils.makeVehiclesSearchQuery(req.query, email); let collection = req.db.collection('vehicles'); let response = {}; if(!pageToken) { response.count = await collection.countDocuments(finalQuery); } else { let lastVehicle = await collection.findOne({ _id: ObjectId(pageToken) }); finalQuery.$or = [ { updatedDate: { $lt: lastVehicle.updatedDate } }, { updatedDate: lastVehicle.updatedDate, _id: { $lt: ObjectId(pageToken) } } ]; } let vehicles = await collection.find(finalQuery).sort({ updatedDate: -1 }).limit(pageSize).toArray(); if(vehicles.length == pageSize) { response.pageToken = vehicles[vehicles.length - 1]._id; } response.items = vehicles; res.send({ success: true, data: response }); } catch(ex) { res.send(makeError('Error reading vehicles from DB')); console.error(ex); } }); router.get('/report', async (req, res) => { const { number } = req.query; try { let collection = req.db.collection('vehicles'); let vehicle = await collection.findOne({ number }); if(vehicle) { res.send({ success: true, data: vehicle }); } else { res.send(makeError('Vehicle not found')); } } catch(ex) { res.send(makeError(ex.message)); 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, process.env.JWT_SECRET_SHARED_REPORT); 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); } }); router.post('/checkOsago', async (req, res) => { try { const { number, vin, date, token } = req.body; let result = await RsaProvider.checkOsago(number, vin, date, token); let collection = req.db.collection('vehicles'); let filter = number ? { number } : { vin1: vin }; await collection.updateOne(filter, { $push: { osagoContracts: result } }); let vehicle = await collection.findOne(filter); if(vehicle) { res.send({ success: true, data: vehicle }); } else { res.status(204).send(makeError('There is no vehicle with such plate number or VIN')); } } catch(ex) { res.send(makeError(ex.message)); console.error(ex); } }); module.exports = router;