@golemio/parkings
Version:
Golemio Parkings Module
450 lines • 22.4 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParkingRepository = void 0;
const SourceEnum_1 = require("../../helpers/constants/SourceEnum");
const ParkingAverageOccupancyRepository_1 = require("./ParkingAverageOccupancyRepository");
const ParkingEntrancesRepository_1 = require("./ParkingEntrancesRepository");
const ParkingPaymentsRepository_1 = require("./ParkingPaymentsRepository");
const ParkingProhibitionsRepository_1 = require("./ParkingProhibitionsRepository");
const ParkingTariffRelationsRepository_1 = require("./ParkingTariffRelationsRepository");
const Di_1 = require("../ioc/Di");
const ModuleContainerToken_1 = require("../ioc/ModuleContainerToken");
const ParkingsLocationModel_1 = require("../models/ParkingsLocationModel");
const _sch_1 = require("../../schema-definitions");
const output_gateway_1 = require("@golemio/core/dist/output-gateway");
const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
const sequelize_1 = require("@golemio/core/dist/shared/sequelize");
const tsyringe_1 = require("@golemio/core/dist/shared/tsyringe");
const ParkingOpeningHoursRepository_1 = require("./ParkingOpeningHoursRepository");
let ParkingRepository = exports.ParkingRepository = class ParkingRepository extends output_gateway_1.SequelizeModel {
constructor(setup, locationModel, averageOccupancyRepository, parkingOpeningHoursRepository, entrancesRepository, paymentsRepository, parkingProhibitionsRepository, parkingTariffRelationsRepository) {
super(setup.name, setup.tableName, setup.attributes, setup.options);
this.locationModel = locationModel;
this.averageOccupancyRepository = averageOccupancyRepository;
this.parkingOpeningHoursRepository = parkingOpeningHoursRepository;
this.entrancesRepository = entrancesRepository;
this.paymentsRepository = paymentsRepository;
this.parkingProhibitionsRepository = parkingProhibitionsRepository;
this.parkingTariffRelationsRepository = parkingTariffRelationsRepository;
this.shouldHideSecondarySourcesFromPrimaryData = true;
this.groupBy = (array, key) => {
if (!array || !Array.isArray(array)) {
throw new Error("The input array must be a valid array.");
}
if (!key || typeof key !== "string") {
throw new Error("The key must be a valid string.");
}
return array.reduce((map, item) => {
if (!item || !item.hasOwnProperty(key)) {
console.warn(`Item is missing the key "${key}":`, item);
return map;
}
const groupKey = item[key];
if (!map.has(groupKey)) {
map.set(groupKey, []);
}
map.get(groupKey).push(item);
return map;
}, new Map());
};
this.geoConfigHelper = Di_1.ParkingsContainer.resolve(ModuleContainerToken_1.ModuleContainerToken.GeoConfigHelper);
this.associate();
}
associate() {
this.sequelizeModel.hasMany(this.locationModel.sequelizeModel, {
as: "parking_locations",
foreignKey: "source_id",
sourceKey: "source_id",
});
this.sequelizeModel.hasMany(this.entrancesRepository.sequelizeModel, {
as: "parking_entrances",
foreignKey: "parking_id",
sourceKey: "id",
});
this.sequelizeModel.hasOne(this.averageOccupancyRepository.sequelizeModel, {
as: "parking_average_occupancy",
foreignKey: "source_id",
sourceKey: "source_id",
});
this.sequelizeModel.hasMany(this.parkingOpeningHoursRepository.sequelizeModel, {
as: "parking_hours",
foreignKey: "parking_id",
sourceKey: "id",
});
this.sequelizeModel.hasOne(this.paymentsRepository.sequelizeModel, {
as: "parking_payments",
foreignKey: "parking_id",
sourceKey: "id",
});
this.sequelizeModel.hasOne(this.parkingProhibitionsRepository.sequelizeModel, {
as: "parking_prohibitions",
foreignKey: "parking_id",
sourceKey: "id",
});
this.sequelizeModel.hasOne(this.parkingTariffRelationsRepository.sequelizeModel, {
as: "parking_tariffs_relation",
foreignKey: "parking_id",
sourceKey: "id",
});
}
async GetAll(params) {
try {
const { whereLocation, where, whereOpeningHours } = await this.prepareWhereConditions(params);
const parkings = await this.sequelizeModel.findAll({
attributes: [
"id",
"source",
"source_id",
"name",
"valid_from",
"centroid",
"updated_at",
"date_modified",
"security",
"max_vehicle_dimensions",
"covered",
"total_spot_number",
"parking_policy",
"contact",
"category",
"parking_type",
"area",
"address",
"location",
],
where,
order: [["id", "ASC"]],
limit: params.limit || 100,
offset: params.offset || 0,
bind: params.boundingBox && {
lonMin: params.boundingBox[1],
latMin: params.boundingBox[2],
lonMax: params.boundingBox[3],
latMax: params.boundingBox[0],
},
raw: true,
nest: true,
});
if (parkings.length === 0) {
return [];
}
const { parkingIds, sourceIds } = this.getUniqueParkingIds(parkings);
const [parkingTariffsRelations, locations, openingHours, averageOccupancy, entrances, payments, prohibitions] = await Promise.all([
this.parkingTariffRelationsRepository.sequelizeModel.findAll({
attributes: ["parking_id", "tariff_id"],
where: {
parking_id: { [sequelize_1.Op.in]: Array.from(parkingIds) },
},
order: [["parking_id", "ASC"]],
raw: true,
}),
this.locationModel.sequelizeModel.findAll({
attributes: ["id", "location", "address", "total_spot_number", "special_access", "source_id"],
where: {
source_id: { [sequelize_1.Op.in]: Array.from(sourceIds) },
...whereLocation,
},
order: [["id", "ASC"]],
raw: true,
}),
this.parkingOpeningHoursRepository.sequelizeModel.findAll({
attributes: ["parking_id", "valid_from", "valid_to", "periods_of_time"],
where: {
parking_id: { [sequelize_1.Op.in]: Array.from(parkingIds) },
...whereOpeningHours,
},
order: [["valid_from", "ASC"]],
raw: true,
}),
this.averageOccupancyRepository.sequelizeModel.findAll({
attributes: ["source_id", "day_of_week", "hour"],
where: {
source_id: { [sequelize_1.Op.in]: Array.from(sourceIds) },
},
order: [
["day_of_week", "ASC"],
["hour", "ASC"],
],
raw: true,
}),
this.entrancesRepository.sequelizeModel.findAll({
attributes: [
"parking_id",
"entry",
"exit",
"entrance_type",
"level",
"max_height",
"max_width",
"max_length",
"max_weight",
"location",
],
where: {
parking_id: { [sequelize_1.Op.in]: Array.from(parkingIds) },
},
order: [["entrance_id", "ASC"]],
raw: true,
}),
this.paymentsRepository.sequelizeModel.findAll({
attributes: [
"parking_id",
"payment_web_url",
"payment_android_url",
"payment_ios_url",
"payment_discovery_url",
],
where: {
parking_id: { [sequelize_1.Op.in]: Array.from(parkingIds) },
},
order: [["parking_id", "ASC"]],
raw: true,
}),
this.parkingProhibitionsRepository.sequelizeModel.findAll({
attributes: ["parking_id", "lpg", "bus", "truck", "motorcycle", "bicycle", "trailer"],
where: {
parking_id: { [sequelize_1.Op.in]: Array.from(parkingIds) },
},
order: [["parking_id", "ASC"]],
raw: true,
}),
]);
const averageOccupancyMap = new Map(averageOccupancy.map((ao) => [ao.source_id, ao]));
const paymentsMap = new Map(payments.map((p) => [p.parking_id, p]));
const parkingTariffsRelationsMap = new Map(parkingTariffsRelations.map((p) => [p.parking_id, p.tariff_id]));
const prohibitionsMap = new Map(prohibitions.map((pr) => [pr.parking_id, pr]));
const locationsMap = this.groupBy(locations, "source_id");
const openingHoursMap = this.groupBy(openingHours, "parking_id");
const entrancesMap = this.groupBy(entrances, "parking_id");
const filteredParkings = [];
for (const parking of parkings) {
if (!locationsMap.has(parking.source_id)) {
continue;
}
parking.parking_locations = locationsMap.get(parking.source_id) || [];
parking.parking_hours = openingHoursMap.get(parking.id) || [];
parking.parking_entrances = entrancesMap.get(parking.id) || [];
parking.parking_average_occupancy = averageOccupancyMap.get(parking.source_id) !== undefined;
parking.parking_payments = paymentsMap.get(parking.id) || {};
parking.parking_prohibitions = prohibitionsMap.get(parking.id) || {};
parking.tariff_id = parkingTariffsRelationsMap.get(parking.id) || null;
filteredParkings.push(parking);
}
return filteredParkings;
}
catch (err) {
throw new golemio_errors_1.GeneralError("Database error ~ GetAll " + err.message, this.name, err, 500);
}
}
async GetOne(id, sources) {
try {
if (!sources) {
throw new golemio_errors_1.GeneralError("List of sources must be provided!", this.name, undefined, 500);
}
const result = await this.sequelizeModel.findOne({
attributes: { include: ["updated_at"] },
include: [
{
model: this.parkingTariffRelationsRepository.sequelizeModel,
as: "parking_tariffs_relation",
attributes: ["tariff_id"],
required: false,
subQuery: false,
},
{
model: this.locationModel.sequelizeModel,
as: "parking_locations",
on: {
source: {
[sequelize_1.Op.eq]: sequelize_1.Sequelize.col(`"${this.sequelizeModel.tableName}".source`),
},
source_id: {
[sequelize_1.Op.eq]: sequelize_1.Sequelize.col(`"${this.sequelizeModel.tableName}".source_id`),
},
},
required: true,
subQuery: false,
},
{
model: this.parkingOpeningHoursRepository.sequelizeModel,
as: "parking_hours",
on: {
parking_id: {
[sequelize_1.Op.eq]: sequelize_1.Sequelize.col(`"${this.sequelizeModel.tableName}".id`),
},
},
required: false,
subQuery: false,
},
{
model: this.averageOccupancyRepository.sequelizeModel,
as: "parking_average_occupancy",
attributes: ["source_id"],
on: {
source: {
[sequelize_1.Op.eq]: sequelize_1.Sequelize.col(`"${this.sequelizeModel.tableName}".source`),
},
source_id: {
[sequelize_1.Op.eq]: sequelize_1.Sequelize.col(`"${this.sequelizeModel.tableName}".source_id`),
},
},
required: false,
subQuery: false,
},
{
model: this.entrancesRepository.sequelizeModel,
as: "parking_entrances",
on: {
parking_id: {
[sequelize_1.Op.eq]: sequelize_1.Sequelize.col(`"${this.sequelizeModel.tableName}".id`),
},
},
required: false,
subQuery: false,
},
{
model: this.paymentsRepository.sequelizeModel,
as: "parking_payments",
required: false,
subQuery: false,
},
{
model: this.parkingProhibitionsRepository.sequelizeModel,
as: "parking_prohibitions",
attributes: ["lpg", "bus", "truck", "motorcycle", "bicycle", "trailer"],
required: false,
subQuery: false,
},
],
where: {
id,
source: {
[sequelize_1.Op.in]: sources,
},
},
order: [
[{ model: this.locationModel.sequelizeModel, as: "parking_locations" }, "id", "ASC"],
[{ model: this.parkingOpeningHoursRepository.sequelizeModel, as: "parking_hours" }, "valid_from", "ASC"],
[
{ model: this.averageOccupancyRepository.sequelizeModel, as: "parking_average_occupancy" },
"day_of_week",
"ASC",
],
[{ model: this.averageOccupancyRepository.sequelizeModel, as: "parking_average_occupancy" }, "hour", "ASC"],
[{ model: this.entrancesRepository.sequelizeModel, as: "parking_entrances" }, "entrance_id", "ASC"],
],
});
if (result === null) {
return null;
}
const resultData = result.dataValues;
resultData.parking_locations = resultData.parking_locations.map((location) => location.dataValues);
resultData.parking_hours = resultData.parking_hours.map((item) => item.dataValues);
resultData.parking_average_occupancy = !!resultData.parking_average_occupancy;
return resultData;
}
catch (err) {
throw new golemio_errors_1.GeneralError("Database error ~ GetOne " + err.message, this.name, err, 500);
}
}
async prepareWhereConditions(params) {
let where = {};
let whereLocation = {};
let whereOpeningHours = {};
let primarySources = [];
const areaLimit = sequelize_1.Sequelize.fn("ST_BuildArea", sequelize_1.Sequelize.fn("ST_GeomFromGeoJSON", JSON.stringify(this.geoConfigHelper.returnGeoCoordinates())));
if (params.primarySource) {
primarySources = params.primarySource;
}
else {
throw new golemio_errors_1.GeneralError("List of sources must be provided! ", this.name, undefined, 500);
}
// DO NOT SHOW OSM PARKINGS IF THERE ARE OTHER SOURCES
if (this.shouldHideSecondarySourcesFromPrimaryData && primarySources.length > 1) {
primarySources = primarySources.filter((source) => source !== SourceEnum_1.SourceEnum.OSM);
}
where.source = { [sequelize_1.Op.in]: primarySources };
where.location = sequelize_1.Sequelize.where(sequelize_1.Sequelize.fn("ST_Within", sequelize_1.Sequelize.col("sanitized_location"), areaLimit), "true");
if (params.validFrom) {
where.valid_from = { [sequelize_1.Op.gte]: params.validFrom };
}
if (params.minutesBefore) {
where.updated_at = { [sequelize_1.Op.gte]: sequelize_1.Sequelize.literal(`NOW() - INTERVAL '${params.minutesBefore} minutes'`) };
}
if (params.updatedSince) {
where.updated_at = { [sequelize_1.Op.gte]: params.updatedSince };
}
if (params.parkingPolicy) {
where.parking_policy = { [sequelize_1.Op.in]: params.parkingPolicy };
}
if (params.activeOnly === true) {
where.active = true;
}
if (params.boundingBox) {
where = {
...where,
[sequelize_1.Op.and]: (0, sequelize_1.literal)(`ST_Contains(ST_MakeEnvelope($lonMin, $latMin, $lonMax, $latMax, 4326), location)`),
};
}
if (params.accessDedicatedTo) {
whereLocation.special_access = { [sequelize_1.Op.overlap]: params.accessDedicatedTo };
}
if (params.openTo) {
whereOpeningHours.valid_from = { [sequelize_1.Op.lte]: params.openTo };
}
if (params.openFrom) {
whereOpeningHours.valid_to = {
[sequelize_1.Op.or]: [{ [sequelize_1.Op.gte]: params.openFrom }, { [sequelize_1.Op.eq]: null }],
};
}
return { whereLocation, where, whereOpeningHours };
}
getUniqueParkingIds(parkings) {
const parkingIds = new Set();
const sourceIds = new Set();
for (const parking of parkings) {
if (parking.id)
parkingIds.add(parking.id);
if (parking.source_id)
sourceIds.add(parking.source_id);
}
return { parkingIds, sourceIds };
}
};
ParkingRepository.defaultSetup = {
name: "OGParkingRepository",
tableName: _sch_1.Parkings.parkings.pgTableName,
attributes: _sch_1.Parkings.parkings.outputSequelizeAttributes,
options: { schema: _sch_1.Parkings.pgSchema },
};
exports.ParkingRepository = ParkingRepository = __decorate([
(0, tsyringe_1.injectable)(),
__param(0, (0, tsyringe_1.inject)(ModuleContainerToken_1.ModuleContainerToken.ParkingRepositorySetup)),
__param(1, (0, tsyringe_1.inject)(ModuleContainerToken_1.ModuleContainerToken.ParkingsLocationModel)),
__param(2, (0, tsyringe_1.inject)(ModuleContainerToken_1.ModuleContainerToken.ParkingAverageOccupancyRepository)),
__param(3, (0, tsyringe_1.inject)(ModuleContainerToken_1.ModuleContainerToken.ParkingOpeningHoursRepository)),
__param(4, (0, tsyringe_1.inject)(ModuleContainerToken_1.ModuleContainerToken.ParkingEntrancesRepository)),
__param(5, (0, tsyringe_1.inject)(ModuleContainerToken_1.ModuleContainerToken.ParkingPaymentsRepository)),
__param(6, (0, tsyringe_1.inject)(ModuleContainerToken_1.ModuleContainerToken.ParkingProhibitionsRepository)),
__param(7, (0, tsyringe_1.inject)(ModuleContainerToken_1.ModuleContainerToken.ParkingTariffRelationsRepository)),
__metadata("design:paramtypes", [Object, ParkingsLocationModel_1.ParkingsLocationModel,
ParkingAverageOccupancyRepository_1.ParkingAverageOccupancyRepository,
ParkingOpeningHoursRepository_1.ParkingOpeningHoursRepository,
ParkingEntrancesRepository_1.ParkingEntrancesRepository,
ParkingPaymentsRepository_1.ParkingPaymentsRepository,
ParkingProhibitionsRepository_1.ParkingProhibitionsRepository,
ParkingTariffRelationsRepository_1.ParkingTariffRelationsRepository])
], ParkingRepository);
//# sourceMappingURL=ParkingRepository.js.map