AutoCatBackend/routes/vehicles.js

231 lines
7.1 KiB
JavaScript

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 = 10;
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) }
}
];
}
console.log('====== Query ======');
console.log(finalQuery);
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;