410 lines
11 KiB
JavaScript
410 lines
11 KiB
JavaScript
import { Router } from 'express';
|
|
import Jwt from 'jsonwebtoken';
|
|
import cors from 'cors';
|
|
import AvtocodProvider from '../data_providers/avtocod.js';
|
|
import Vin01Provider from '../data_providers/vin01.js';
|
|
import Constants from '../data_providers/constants.js';
|
|
import RsaProvider from '../data_providers/rsa.js';
|
|
import NomerogramProvider from '../data_providers/nomerogram.js';
|
|
import Utils from '../utils/utils.js';
|
|
import { ObjectId } from 'mongodb';
|
|
import DebugInfo from '../models/DebugInfo.js';
|
|
import Vehicle from '../models/vehicle.js';
|
|
import { TGProvider } from '../data_providers/tgprovider.js';
|
|
|
|
const router = Router();
|
|
|
|
const makeError = (error) => ({ success: false, error });
|
|
|
|
router.post('/check', async (req, res) => {
|
|
const number = req.body.number.replace(/ /g, '').toUpperCase();
|
|
const type = req.body.type;
|
|
const { googleIdToken, forceUpdate, notes, events } = req.body;
|
|
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');
|
|
let updatedDate = Date.now();
|
|
|
|
if (notes) {
|
|
Vehicle.mergeNotes(vehicles[0], notes);
|
|
}
|
|
|
|
if (events) {
|
|
Vehicle.mergeEvents(vehicles[0], events);
|
|
}
|
|
|
|
await collection.updateOne(
|
|
{ number },
|
|
{
|
|
$set: {
|
|
updatedDate,
|
|
events: vehicles[0].events,
|
|
notes: vehicles[0].notes,
|
|
},
|
|
},
|
|
);
|
|
vehicles[0].updatedDate = updatedDate;
|
|
res.send({ success: true, data: vehicles[0] });
|
|
} else {
|
|
try {
|
|
let autocodPromise = AvtocodProvider.getReport(number, type);
|
|
let all = [autocodPromise];
|
|
|
|
if (googleIdToken) {
|
|
let vin01Promise = Vin01Provider.getReport(number, googleIdToken, type);
|
|
all.push(vin01Promise);
|
|
} else {
|
|
all.push(
|
|
Promise.reject({
|
|
debugInfo: {
|
|
vin01vin: DebugInfo.fromError('No auth token'),
|
|
vin01history: DebugInfo.fromError('No auth token'),
|
|
vin01base: DebugInfo.fromError('No auth token'),
|
|
},
|
|
}),
|
|
);
|
|
}
|
|
|
|
if(type == 'GRZ') {
|
|
all.push(NomerogramProvider.getGroups(number));
|
|
} else {
|
|
let error = Error();
|
|
error.debugInfo = DebugInfo.fromError('not relevant');
|
|
all.push(Promise.reject(error));
|
|
}
|
|
|
|
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;
|
|
let vinMatch = false;
|
|
if (vin01.value.vin1 && vehicle.vin1) {
|
|
vinMatch = vin01.value.vin1.match(
|
|
RegExp(vehicle.vin1.replace(/\*/g, '.')),
|
|
);
|
|
}
|
|
|
|
if (vehicle.vin1 && vinMatch) {
|
|
vehicle.vin1 = vin01.value.vin1;
|
|
vehicle.vin2 = vin01.value.vin2;
|
|
vehicle.color = vin01.value.color;
|
|
vehicle.ownershipPeriods = vin01.value.ownershipPeriods;
|
|
} else if (!vinMatch) {
|
|
let vin01data = `${vin01.value.vin1} - ${vin01.value?.brand?.name?.original}`;
|
|
let autocodData = `${autocod.value.vin1} - ${autocod.value.brand.name.original}`;
|
|
let warning = `Vin01 VIN (${vin01data}) doesn't match with avtocod's one (${autocodData})`;
|
|
vin01.value.debugInfo.vin01vin.setWarning(warning);
|
|
//vin01.value.debugInfo.vin01history.setWarning(warning);
|
|
//vin01.value.debugInfo.vin01base.setWarning(warning);
|
|
}
|
|
Object.assign(vehicle.debugInfo, vin01.value.debugInfo);
|
|
}
|
|
|
|
if (nomerogram.status == 'fulfilled') {
|
|
let photos = nomerogram.value;
|
|
vehicle.photos = vehicle.photos?.concat(photos) ?? photos;
|
|
Object.assign(vehicle.debugInfo, {
|
|
nomerogram: new DebugInfo(),
|
|
});
|
|
} else {
|
|
Object.assign(vehicle.debugInfo, nomerogram.reason.debugInfo);
|
|
}
|
|
|
|
vehicle.addedBy = email;
|
|
|
|
// In case of force update of existing vehicle, transfer all events to the new DB record
|
|
if (vehicles.length > 0) {
|
|
vehicle.addedBy = vehicles[0].addedBy;
|
|
vehicle.addedDate = vehicles[0].addedDate;
|
|
vehicle.events = vehicles[0].events;
|
|
vehicle.osagoContracts = vehicles[0].osagoContracts;
|
|
vehicle.notes = vehicles[0].notes;
|
|
}
|
|
|
|
// Merge new notes/events with old ones
|
|
if (notes) {
|
|
vehicle.mergeNotes(notes);
|
|
}
|
|
|
|
if (events) {
|
|
vehicle.mergeEvents(events);
|
|
}
|
|
|
|
if(type == 'GRZ') {
|
|
await collection.replaceOne({ number }, vehicle, { upsert: true });
|
|
}
|
|
|
|
await Utils.vehicleRemoveEventEmails(vehicle, req);
|
|
|
|
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, sortBy, sortOrder } = req.query;
|
|
|
|
let pageSize = parseInt(req.query.pageSize);
|
|
if (isNaN(pageSize)) {
|
|
pageSize = 50;
|
|
}
|
|
|
|
try {
|
|
let finalQuery = Utils.makeVehiclesSearchQuery(req.query, email);
|
|
let collection = req.db.collection('vehicles');
|
|
|
|
let isAscending = sortOrder == 'ascending';
|
|
let response = {};
|
|
if (!pageToken) {
|
|
response.count = await collection.countDocuments(finalQuery);
|
|
} else {
|
|
let compareOperator = isAscending ? '$gt' : '$lt';
|
|
let lastVehicle = await collection.findOne({
|
|
_id: new ObjectId(pageToken),
|
|
});
|
|
finalQuery.$or = [
|
|
{ [sortBy]: { [compareOperator]: lastVehicle[sortBy] } },
|
|
{
|
|
[sortBy]: lastVehicle[sortBy],
|
|
_id: { [compareOperator]: new ObjectId(pageToken) },
|
|
},
|
|
];
|
|
}
|
|
|
|
let vehicles = await collection
|
|
.find(finalQuery)
|
|
.sort({ [sortBy]: isAscending ? 1 : -1 })
|
|
.limit(pageSize)
|
|
.toArray();
|
|
|
|
if (vehicles.length == pageSize) {
|
|
response.pageToken = vehicles[vehicles.length - 1]._id;
|
|
}
|
|
|
|
response.items = await Utils.vehiclesRemoveEventEmails(vehicles, req);
|
|
|
|
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) {
|
|
await Utils.vehicleRemoveEventEmails(vehicle, req);
|
|
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: Constants.regions });
|
|
});
|
|
|
|
router.get('/years', async (req, res) => {
|
|
try {
|
|
let collection = req.db.collection('vehicles');
|
|
let colors = await collection.distinct('year');
|
|
res.send({ success: true, data: colors.filter(Boolean) });
|
|
} catch (ex) {
|
|
res.send(makeError('Error reading vehicle years from DB'));
|
|
console.error(ex);
|
|
}
|
|
});
|
|
|
|
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) {
|
|
let vehicle = await Utils.vehicleRemoveEventEmails(vehicles[0], req);
|
|
res.send({ success: true, data: vehicle });
|
|
} 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) {
|
|
await Utils.vehicleRemoveEventEmails(vehicle, req);
|
|
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);
|
|
}
|
|
});
|
|
|
|
router.post('/checkGbTg', async (req, res) => {
|
|
let tgProvider = null;
|
|
|
|
try {
|
|
const number = req.body.number.replace(/ /g, '').toUpperCase();
|
|
const token = req.body.token;
|
|
|
|
tgProvider = new TGProvider();
|
|
await tgProvider.init();
|
|
let report = await tgProvider.getReport(number, token);
|
|
await tgProvider.close();
|
|
|
|
if (!report?.generalInfo && !report?.insurance) {
|
|
res.send(makeError('No data found'));
|
|
return;
|
|
}
|
|
|
|
let collection = req.db.collection('vehicles');
|
|
let vehicle = await collection.findOne({ number });
|
|
|
|
if (vehicle) {
|
|
let vinRegex = RegExp(vehicle.vin1.replace(/\*/g, '.'));
|
|
|
|
if (report?.generalInfo?.vin?.match(vinRegex)) {
|
|
let updatedFields = {
|
|
vin1: report.generalInfo.vin,
|
|
updatedDate: Date.now(),
|
|
};
|
|
|
|
if(report.generalInfo.color) {
|
|
updatedFields.color = report.generalInfo.color;
|
|
}
|
|
|
|
if(report.generalInfo.sts) {
|
|
updatedFields.sts = report.generalInfo.sts;
|
|
}
|
|
|
|
if (report.insurance) {
|
|
let osagoFound =
|
|
vehicle.osagoContracts?.some((elem) => {
|
|
return (elem.number = report.insurance.number);
|
|
}) ?? false;
|
|
if (!osagoFound) {
|
|
await collection.updateOne(
|
|
{ number },
|
|
{ $push: { osagoContracts: report.insurance } },
|
|
);
|
|
}
|
|
}
|
|
|
|
if (report.ownershipPeriods) {
|
|
updatedFields.ownershipPeriods = report.ownershipPeriods;
|
|
}
|
|
|
|
await collection.updateOne({ number }, { $set: updatedFields });
|
|
vehicle = await collection.findOne({ number });
|
|
await Utils.vehicleRemoveEventEmails(vehicle, req);
|
|
res.send({
|
|
success: true,
|
|
data: Object.assign(vehicle, updatedFields),
|
|
});
|
|
} else {
|
|
res.send(makeError('Vehicle doesn\'t match'));
|
|
}
|
|
} else {
|
|
res.send(makeError('Vehicle not found'));
|
|
}
|
|
} catch (ex) {
|
|
res.send(makeError(ex.message));
|
|
console.error(ex);
|
|
await tgProvider.close();
|
|
}
|
|
});
|
|
|
|
export default router;
|