Refactoring QR-Code
MODIFY
package-lock.json
package-lock.json
"integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
"dev": true
},
+ "blob-stream": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/blob-stream/-/blob-stream-0.1.3.tgz",
+ "integrity": "sha1-mNZor2mW4PMu9mbQbiFczH13aGw=",
+ "requires": {
+ "blob": "0.0.4"
+ },
+ "dependencies": {
+ "blob": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
+ "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE="
+ }
+ }
+ },
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",

MODIFY
package.json
package.json
"axios-retry": "^3.1.9",
"basic-auth": "^2.0.1",
"bcryptjs": "^2.4.3",
+ "blob-stream": "^0.1.3",
"bluebird": "^3.7.2",
"body-parser": "^1.19.0",
"body-parser-xml": "^2.0.0",

MODIFY
src/server/rest/CentralRestServerService.ts
src/server/rest/CentralRestServerService.ts
@@ -126,7 +126,7 @@ class RequestMapper {
[ServerAction.CHARGING_PROFILES]: ChargingStationService.handleGetChargingProfiles.bind(this),
[ServerAction.TRIGGER_SMART_CHARGING]: ChargingStationService.handleTriggerSmartCharging.bind(this),
[ServerAction.GENERATE_QR_CODE_FOR_CONNECTOR]: ChargingStationService.handleGenerateQrCodeForConnector.bind(this),
- [ServerAction.CHARGING_STATION_DOWNLOAD_QR_CODE_PDF]: ChargingStationService.handleDownloadQrCodePdf.bind(this),
+ [ServerAction.CHARGING_STATION_DOWNLOAD_QR_CODE_PDF]: ChargingStationService.handleDownloadQrCodesPdf.bind(this),
[ServerAction.REGISTRATION_TOKENS]: RegistrationTokenService.handleGetRegistrationTokens.bind(this),
[ServerAction.STATUS_NOTIFICATIONS]: ChargingStationService.handleGetStatusNotifications.bind(this),
[ServerAction.BOOT_NOTIFICATION]: ChargingStationService.handleGetBootNotifications.bind(this),

MODIFY
src/server/rest/v1/service/ChargingStationService.ts
src/server/rest/v1/service/ChargingStationService.ts
@@ -33,6 +33,7 @@ import SiteAreaStorage from '../../../../storage/mongodb/SiteAreaStorage';
import SiteStorage from '../../../../storage/mongodb/SiteStorage';
import SmartChargingFactory from '../../../../integration/smart-charging/SmartChargingFactory';
import { StatusCodes } from 'http-status-codes';
+import Tenant from '../../../../types/Tenant';
import TenantComponents from '../../../../types/TenantComponents';
import TenantStorage from '../../../../storage/mongodb/TenantStorage';
import TransactionStorage from '../../../../storage/mongodb/TransactionStorage';
@@ -835,99 +836,27 @@ export default class ChargingStationService {
public static async handleExportChargingStations(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Export
await UtilsService.exportToCSV(req, res, 'exported-charging-stations.csv',
- ChargingStationService.getChargingStations.bind(this), ChargingStationService.convertToCSV.bind(this));
+ ChargingStationService.getChargingStations.bind(this),
+ ChargingStationService.convertToCSV.bind(this));
}
- public static async handleDownloadQrCodePdf(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
- if (!req.query.SiteID && !req.query.SiteAreaID) {
+ public static async handleDownloadQrCodesPdf(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
+ // Filter
+ const filteredRequest = ChargingStationSecurity.filterDownloadQrCodesPdfRequest(req.query);
+ // Check
+ if (!filteredRequest.SiteID && !filteredRequest.SiteAreaID && !filteredRequest.ChargeBoxID) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
errorCode: HTTPError.GENERAL_ERROR,
- message: 'SiteID or SiteAreaID must be provided',
- module: MODULE_NAME, method: 'handleDownloadQrCodePdf',
+ message: 'Site ID or Site Area ID or Charging Station ID must be provided',
+ module: MODULE_NAME, method: 'handleDownloadQrCodesPdf',
user: req.user
});
}
- req.query.Limit = Constants.EXPORT_PAGE_SIZE.toString();
- // Get the total number of Logs
- req.query.OnlyRecordCount = 'true';
- let chargingStations = await ChargingStationService.getChargingStations(req,
- ['connectors.user.id', 'connectors.user.name', 'connectors.user.firstName', 'connectors.user.email']);
- let count = chargingStations.count;
- delete req.query.OnlyRecordCount;
- let skip = 0;
- const fileName = 'output.pdf';
- const createdStream = fs.createWriteStream(fileName);
- // Limit the number of records
- if (count > Constants.EXPORT_RECORD_MAX_COUNT) {
- count = Constants.EXPORT_RECORD_MAX_COUNT;
- }
- // Handle closed socket
- let connectionClosed = false;
- req.connection.on('close', () => {
- connectionClosed = true;
- });
- const pdfDoc = new PDFDocument();
- do {
- // Check if the socket is closed and stop the process
- if (connectionClosed) {
- break;
- }
- console.log(skip);
- // Get the Logs
- req.query.Skip = skip.toString();
- chargingStations = await ChargingStationService.getChargingStations(req,
- ['connectors.user.id', 'connectors.user.name', 'connectors.user.firstName', 'connectors.user.email']);
- let chargingStationQRCode: ChargingStationQRCode = {}, generatedQR: string;
- const i18nManager = new I18nManager(req.user.locale);
- pdfDoc.pipe(createdStream);
- let firstPage = true;
- const encoding: BufferEncoding = 'base64';
- if (!Utils.isEmptyArray(chargingStations.result)) {
- for (const chargingStation of chargingStations.result) {
- if (!Utils.isEmptyArray(chargingStation.connectors)) {
- for (const connector of chargingStation.connectors) {
- chargingStationQRCode = {
- chargingStationID: chargingStation.id,
- connectorID: connector.connectorId,
- endpoint: Utils.getChargingStationEndpoint(),
- tenantName: req.user.tenantName,
- tenantSubDomain: (await TenantStorage.getTenant(req.user.tenantID, { withLogo: false }, ['subdomain'])).subdomain
- };
- generatedQR = await Utils.generateQrCode(Buffer.from(JSON.stringify(chargingStationQRCode)).toString(encoding));
- if (!firstPage) {
- pdfDoc.addPage();
- }
- pdfDoc.image(generatedQR, 50, 50, {
- width: 500, height: 500
- });
- pdfDoc.text(i18nManager.translate('siteArea') + ': ' + chargingStation.siteArea.name + ' - ' + chargingStation.id + ' ' + i18nManager.translate('chargers.connector') + ' ' + Utils.getConnectorLetterFromConnectorID(connector.connectorId), 20, pdfDoc.page.height - 50, {
- lineBreak: false
- });
- firstPage = false;
- }
- }
- }
- }
- // Next page
- skip += Constants.EXPORT_PAGE_SIZE;
- } while (skip < count);
- pdfDoc.end();
- // End of stream
- createdStream.on('finish', function() {
- res.download(fileName, (err2) => {
- if (err2) {
- console.log(err2);
- throw err2;
- }
- fs.unlink(fileName, (err3) => {
- if (err3) {
- console.log(err3);
- throw err3;
- }
- });
- });
- });
+ // Export
+ await UtilsService.exportToPDF(req, res, 'exported-charging-stations-qr-code.pdf',
+ ChargingStationService.getChargingStationsForQrCode.bind(this),
+ ChargingStationService.convertQrCodeToPDF.bind(this));
}
@@ -1350,6 +1279,11 @@ export default class ChargingStationService {
'connectors.currentTransactionID', 'connectors.currentTotalInactivitySecs', 'connectors.currentTagID', 'chargePoints',
...userProject
];
+ } else {
+ projectFields = [
+ ...projectFields,
+ ...userProject
+ ];
}
// Get Charging Stations
const chargingStations = await ChargingStationStorage.getChargingStations(req.user.tenantID,
@@ -1357,11 +1291,12 @@ export default class ChargingStationService {
search: filteredRequest.Search,
withNoSiteArea: filteredRequest.WithNoSiteArea,
withSite: filteredRequest.WithSite,
- connectorStatuses: (filteredRequest.ConnectorStatus ? filteredRequest.ConnectorStatus.split('|') : null),
- connectorTypes: (filteredRequest.ConnectorType ? filteredRequest.ConnectorType.split('|') : null),
+ chargingStationIDs: filteredRequest.ChargeBoxID ? filteredRequest.ChargeBoxID.split('|') : null,
+ connectorStatuses: filteredRequest.ConnectorStatus ? filteredRequest.ConnectorStatus.split('|') : null,
+ connectorTypes: filteredRequest.ConnectorType ? filteredRequest.ConnectorType.split('|') : null,
issuer: filteredRequest.Issuer,
siteIDs: Authorizations.getAuthorizedSiteIDs(req.user, filteredRequest.SiteID ? filteredRequest.SiteID.split('|') : null),
- siteAreaIDs: (filteredRequest.SiteAreaID ? filteredRequest.SiteAreaID.split('|') : null),
+ siteAreaIDs: filteredRequest.SiteAreaID ? filteredRequest.SiteAreaID.split('|') : null,
includeDeleted: filteredRequest.IncludeDeleted,
locCoordinates: filteredRequest.LocCoordinates,
locMaxDistanceMeters: filteredRequest.LocMaxDistanceMeters,
@@ -1394,9 +1329,9 @@ export default class ChargingStationService {
return csv;
}
- private static convertToCSV(loggedUser: UserToken, chargingStations: ChargingStation[], writeHeader = true): string {
+ private static convertToCSV(req: Request, chargingStations: ChargingStation[], writeHeader = true): string {
let csv = '';
- const i18nManager = new I18nManager(loggedUser.locale);
+ const i18nManager = new I18nManager(req.user.locale);
// Header
if (writeHeader) {
csv = `Name${Constants.CSV_SEPARATOR}Created On${Constants.CSV_SEPARATOR}Number of Connectors${Constants.CSV_SEPARATOR}Site Area${Constants.CSV_SEPARATOR}Latitude${Constants.CSV_SEPARATOR}Longitude${Constants.CSV_SEPARATOR}Charge Point S/N${Constants.CSV_SEPARATOR}Model${Constants.CSV_SEPARATOR}Charge Box S/N${Constants.CSV_SEPARATOR}Vendor${Constants.CSV_SEPARATOR}Firmware Version${Constants.CSV_SEPARATOR}OCPP Version${Constants.CSV_SEPARATOR}OCPP Protocol${Constants.CSV_SEPARATOR}Last Seen${Constants.CSV_SEPARATOR}Last Reboot${Constants.CSV_SEPARATOR}Maximum Power (Watt)${Constants.CSV_SEPARATOR}Power Limit Unit\r\n`;
@@ -1406,7 +1341,7 @@ export default class ChargingStationService {
csv += `${chargingStation.id}` + Constants.CSV_SEPARATOR;
csv += `${i18nManager.formatDateTime(chargingStation.createdOn, 'L')} ${i18nManager.formatDateTime(chargingStation.createdOn, 'LT')}` + Constants.CSV_SEPARATOR;
csv += `${chargingStation.connectors ? chargingStation.connectors.length : '0'}` + Constants.CSV_SEPARATOR;
- csv += `${chargingStation.siteArea.name}` + Constants.CSV_SEPARATOR;
+ csv += `${chargingStation?.siteArea?.name ? chargingStation.siteArea.name : ''}` + Constants.CSV_SEPARATOR;
if (chargingStation.coordinates && chargingStation.coordinates.length === 2) {
csv += `${chargingStation.coordinates[1]}` + Constants.CSV_SEPARATOR;
csv += `${chargingStation.coordinates[0]}` + Constants.CSV_SEPARATOR;
@@ -1428,6 +1363,77 @@ export default class ChargingStationService {
return csv;
}
+
+ private static async getChargingStationsForQrCode(req: Request): Promise<DataResult<ChargingStation>> {
+ return ChargingStationService.getChargingStations(req,
+ ['id', 'connectors.connectorId', 'siteArea.name']);
+ }
+
+ private static async convertQrCodeToPDF(req: Request, pdfDocument: PDFDocument, chargingStations: ChargingStation[]): Promise<void> {
+ const i18nManager = new I18nManager(req.user.locale);
+ // Check for Connector ID
+ let connectorID = null;
+ if (req.query.ConnectorID) {
+ connectorID = Utils.convertToInt(req.query.ConnectorID);
+ }
+ // Content
+ for (const chargingStation of chargingStations) {
+ if (!Utils.isEmptyArray(chargingStation.connectors)) {
+ for (const connector of chargingStation.connectors) {
+ // Filter on connector ID?
+ if (connectorID > 0 && connector.connectorId !== connectorID) {
+ continue;
+ }
+ // Create data
+ const chargingStationQRCode: ChargingStationQRCode = {
+ chargingStationID: chargingStation.id,
+ connectorID: connector.connectorId,
+ endpoint: Utils.getChargingStationEndpoint(),
+ tenantName: req.tenant.name,
+ tenantSubDomain: req.tenant.subdomain
+ };
+ // Generated QR-Code
+ const qrCodeImage = await Utils.generateQrCode(
+ Buffer.from(JSON.stringify(chargingStationQRCode)).toString('base64'));
+ // Build title
+ const qrCodeTitle = `${chargingStation.id} / ${i18nManager.translate('chargers.connector')} ${Utils.getConnectorLetterFromConnectorID(connector.connectorId)}`;
+ // Add the QR Codes
+ ChargingStationService.build3SizesPDFQrCode(pdfDocument, qrCodeImage, qrCodeTitle);
+ // Add page (expect the last one)
+ if (!connectorID && (chargingStations[chargingStations.length - 1] !== chargingStation ||
+ chargingStation.connectors[chargingStation.connectors.length - 1] !== connector)) {
+ pdfDocument.addPage();
+ }
+ }
+ }
+ }
+ }
+
+ private static build3SizesPDFQrCode(pdfDocument: PDFDocument, qrCodeImage: string, qrCodeTitle: string): void {
+ const bigSquareSide = 300;
+ const mediumSquareSide = 150;
+ const smallSquareSide = 75;
+ const marginHeight = 50;
+ // Add big QR-Code
+ pdfDocument.image(qrCodeImage, (pdfDocument.page.width / 2) - (bigSquareSide / 2), marginHeight, {
+ width: bigSquareSide, height: bigSquareSide,
+ });
+ pdfDocument.fontSize(18);
+ pdfDocument.text(qrCodeTitle, 65, bigSquareSide + marginHeight, { align: 'center' });
+ // Add medium QR-Code
+ pdfDocument.image(qrCodeImage, (pdfDocument.page.width / 2) - (mediumSquareSide / 2), (bigSquareSide + (marginHeight * 2)), {
+ width: mediumSquareSide, height: mediumSquareSide,
+ });
+ pdfDocument.fontSize(12);
+ pdfDocument.text(qrCodeTitle, 65, bigSquareSide + mediumSquareSide + (marginHeight * 2) + 10, { align: 'center' });
+ // Add small QR-Code
+ pdfDocument.image(qrCodeImage, (pdfDocument.page.width / 2) - (smallSquareSide / 2), (bigSquareSide + mediumSquareSide + (marginHeight * 3)), {
+ width: smallSquareSide, height: smallSquareSide,
+ });
+ pdfDocument.fontSize(8);
+ pdfDocument.text(qrCodeTitle, 65, bigSquareSide + mediumSquareSide + smallSquareSide + (marginHeight * 3) + 10, { align: 'center' });
+ }
+
private static async handleChargingStationCommand(tenantID: string, user: UserToken, chargingStation: ChargingStation,
action: ServerAction, command: Command, params: any): Promise<any> {
let result: any;

MODIFY
src/server/rest/v1/service/LoggingService.ts
src/server/rest/v1/service/LoggingService.ts
@@ -28,7 +28,8 @@ export default class LoggingService {
public static async handleExportLogs(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
await UtilsService.exportToCSV(req, res, 'exported-logs.csv',
- LoggingService.getLogs.bind(this), LoggingService.convertToCSV.bind(this));
+ LoggingService.getLogs.bind(this),
+ LoggingService.convertToCSV.bind(this));
}
public static async handleGetLog(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
@@ -53,7 +54,7 @@ export default class LoggingService {
next();
}
- private static convertToCSV(loggedUser: UserToken, loggings: Log[], writeHeader = true): string {
+ private static convertToCSV(req: Request, loggings: Log[], writeHeader = true): string {
let csv = '';
// Header
if (writeHeader) {

MODIFY
src/server/rest/v1/service/TransactionService.ts
src/server/rest/v1/service/TransactionService.ts
@@ -699,7 +699,8 @@ export default class TransactionService {
public static async handleExportTransactions(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Export
await UtilsService.exportToCSV(req, res, 'exported-sessions.csv',
- TransactionService.getCompletedTransactionsToExport.bind(this), TransactionService.convertToCSV.bind(this));
+ TransactionService.getCompletedTransactionsToExport.bind(this),
+ TransactionService.convertToCSV.bind(this));
}
public static async getCompletedTransactionsToExport(req: Request): Promise<DataResult<Transaction>> {
@@ -714,7 +715,8 @@ export default class TransactionService {
public static async handleExportTransactionsToRefund(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Export
await UtilsService.exportToCSV(req, res, 'exported-refund-sessions.csv',
- TransactionService.getRefundedTransactionsToExport.bind(this), TransactionService.convertToCSV.bind(this));
+ TransactionService.getRefundedTransactionsToExport.bind(this),
+ TransactionService.convertToCSV.bind(this));
}
public static async getRefundedTransactionsToExport(req: Request): Promise<DataResult<Transaction>> {
@@ -826,7 +828,7 @@ export default class TransactionService {
next();
}
- public static convertToCSV(loggedUser: UserToken, transactions: Transaction[], writeHeader = true): string {
+ public static convertToCSV(req: Request, transactions: Transaction[], writeHeader = true): string {
let csv = '';
// Header
if (writeHeader) {

MODIFY
src/server/rest/v1/service/UserService.ts
src/server/rest/v1/service/UserService.ts
@@ -724,7 +724,8 @@ export default class UserService {
// Export with tags
req.query['WithTag'] = 'true';
await UtilsService.exportToCSV(req, res, 'exported-users.csv',
- UserService.getUsers.bind(this), UserService.convertToCSV.bind(this));
+ UserService.getUsers.bind(this),
+ UserService.convertToCSV.bind(this));
}
public static async handleGetSites(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
@@ -1075,7 +1076,7 @@ export default class UserService {
}
}
- private static convertToCSV(loggedUser: UserToken, users: User[], writeHeader = true): string {
+ private static convertToCSV(req: Request, users: User[], writeHeader = true): string {
let csv = '';
// Header
if (writeHeader) {
@@ -1092,7 +1093,7 @@ export default class UserService {
csv += `${moment(user.eulaAcceptedOn).format('YYYY-MM-DD')}` + Constants.CSV_SEPARATOR;
csv += `${moment(user.createdOn).format('YYYY-MM-DD')}` + Constants.CSV_SEPARATOR;
csv += `${moment(user.lastChangedOn).format('YYYY-MM-DD')}` + Constants.CSV_SEPARATOR;
- csv += `${user.lastChangedBy ? user.lastChangedBy as string : ''}\r\n`;
+ csv += `${user.lastChangedBy ? Utils.buildUserFullName(user.lastChangedBy as User, false) : ''}\r\n`;
}
return csv;
}

MODIFY
src/server/rest/v1/service/UtilsService.ts
src/server/rest/v1/service/UtilsService.ts
@@ -16,6 +16,7 @@ import { DataResult } from '../../../../types/DataResult';
import { HttpEndUserReportErrorRequest } from '../../../../types/requests/HttpNotificationRequest';
import Logging from '../../../../utils/Logging';
import OCPIEndpoint from '../../../../types/ocpi/OCPIEndpoint';
+import PDFDocument from 'pdfkit';
import { ServerAction } from '../../../../types/Server';
import Site from '../../../../types/Site';
import SiteArea from '../../../../types/SiteArea';
@@ -23,6 +24,7 @@ import Tag from '../../../../types/Tag';
import TenantComponents from '../../../../types/TenantComponents';
import UserToken from '../../../../types/UserToken';
import Utils from '../../../../utils/Utils';
+import blobStream from 'blob-stream';
import countries from 'i18n-iso-countries';
import moment from 'moment';
@@ -187,7 +189,7 @@ export default class UtilsService {
public static async exportToCSV(req: Request, res: Response, attachementName: string,
handleGetData: (req: Request) => Promise<DataResult<any>>,
- handleConvertToCSV: (loggedUser: UserToken, data: any[], writeHeader: boolean) => string): Promise<void> {
+ handleConvertToCSV: (req: Request, data: any[], writeHeader: boolean) => string): Promise<void> {
// Override
req.query.Limit = Constants.EXPORT_PAGE_SIZE.toString();
// Set the attachment name
@@ -212,12 +214,13 @@ export default class UtilsService {
if (connectionClosed) {
break;
}
- console.log(skip);
- // Get the Logs
+ // Get the data
req.query.Skip = skip.toString();
data = await handleGetData(req);
+ // Get CSV data
+ const csvData = handleConvertToCSV(req, data.result, (skip === 0));
// Send Transactions
- res.write(handleConvertToCSV(req.user, data.result, (skip === 0)));
+ res.write(csvData);
// Next page
skip += Constants.EXPORT_PAGE_SIZE;
} while (skip < count);
@@ -225,6 +228,48 @@ export default class UtilsService {
res.end();
}
+ public static async exportToPDF(req: Request, res: Response, attachementName: string,
+ handleGetData: (req: Request) => Promise<DataResult<any>>,
+ handleConvertToPDF: (req: Request, pdfDocument: PDFDocument, data: any[]) => Promise<string>): Promise<void> {
+ // Override
+ req.query.Limit = Constants.EXPORT_PDF_PAGE_SIZE.toString();
+ // Set the attachment name
+ res.attachment(attachementName);
+ // Get the total number of Logs
+ req.query.OnlyRecordCount = 'true';
+ let data = await handleGetData(req);
+ let count = data.count;
+ delete req.query.OnlyRecordCount;
+ let skip = 0;
+ // Limit the number of records
+ if (count > Constants.EXPORT_PDF_PAGE_SIZE) {
+ count = Constants.EXPORT_PDF_PAGE_SIZE;
+ }
+ // Handle closed socket
+ let connectionClosed = false;
+ req.connection.on('close', () => {
+ connectionClosed = true;
+ });
+ // Create the PDF
+ const pdfDocument = new PDFDocument();
+ pdfDocument.pipe(res);
+ do {
+ // Check if the socket is closed and stop the process
+ if (connectionClosed) {
+ break;
+ }
+ // Get the data
+ req.query.Skip = skip.toString();
+ data = await handleGetData(req);
+ // Transform data
+ await handleConvertToPDF(req, pdfDocument, data.result);
+ // Next page
+ skip += Constants.EXPORT_PAGE_SIZE;
+ } while (skip < count);
+ // Finish
+ pdfDocument.end();
+ }
+
public static checkIfChargingProfileIsValid(chargingStation: ChargingStation, chargePoint: ChargePoint,
filteredRequest: ChargingProfile, req: Request): void {
if (!Utils.objectHasProperty(filteredRequest, 'chargingStationID')) {

MODIFY
src/server/rest/v1/service/security/ChargingStationSecurity.ts
src/server/rest/v1/service/security/ChargingStationSecurity.ts
import { ChargingProfile, ChargingSchedule, ChargingSchedulePeriod, Profile } from '../../../../../types/ChargingProfile';
-import { HttpChargingProfilesRequest, HttpChargingStationCommandRequest, HttpChargingStationConnectorRequest, HttpChargingStationGetFirmwareRequest, HttpChargingStationLimitPowerRequest, HttpChargingStationOcppParametersRequest, HttpChargingStationParamsUpdateRequest, HttpChargingStationRequest, HttpChargingStationSetMaxIntensitySocketRequest, HttpChargingStationsRequest, HttpIsAuthorizedRequest, HttpTriggerSmartChargingRequest } from '../../../../../types/requests/HttpChargingStationRequest';
+import { HttpChargingProfilesRequest, HttpChargingStationCommandRequest, HttpChargingStationConnectorRequest, HttpChargingStationGetFirmwareRequest, HttpChargingStationLimitPowerRequest, HttpChargingStationOcppParametersRequest, HttpChargingStationParamsUpdateRequest, HttpChargingStationRequest, HttpChargingStationSetMaxIntensitySocketRequest, HttpChargingStationsRequest, HttpDownloadQrCodeRequest, HttpIsAuthorizedRequest, HttpTriggerSmartChargingRequest } from '../../../../../types/requests/HttpChargingStationRequest';
import { Command } from '../../../../../types/ChargingStation';
import HttpByIDRequest from '../../../../../types/requests/HttpByIDRequest';
@@ -60,6 +60,15 @@ export default class ChargingStationSecurity {
return { ID: sanitize(request.ID) };
}
+ public static filterDownloadQrCodesPdfRequest(request: any): HttpDownloadQrCodeRequest {
+ return {
+ ChargeBoxID: request.ChargeBoxID ? sanitize(request.ChargeBoxID) : null,
+ ConnectorID: request.ConnectorID ? Utils.convertToInt(sanitize(request.ConnectorID)) : null,
+ SiteAreaID: request.SiteAreaID ? sanitize(request.SiteAreaID) : null,
+ SiteID: request.SiteID ? sanitize(request.SiteID) : null,
+ };
+ }
+
public static filterChargingStationRequestByID(request: any): string {
return sanitize(request.ID);
}
@@ -69,7 +78,7 @@ export default class ChargingStationSecurity {
}
public static filterChargingStationsRequest(request: any): HttpChargingStationsRequest {
- const filteredRequest: HttpChargingStationsRequest = {} as HttpChargingStationsRequest;
+ const filteredRequest = {} as HttpChargingStationsRequest;
if (request.Issuer) {
filteredRequest.Issuer = UtilsSecurity.filterBoolean(request.Issuer);
}
@@ -80,6 +89,7 @@ export default class ChargingStationSecurity {
filteredRequest.SiteAreaID = sanitize(request.SiteAreaID);
filteredRequest.ConnectorStatus = sanitize(request.ConnectorStatus);
filteredRequest.ConnectorType = sanitize(request.ConnectorType);
+ filteredRequest.ChargeBoxID = sanitize(request.ChargeBoxID);
filteredRequest.IncludeDeleted = UtilsSecurity.filterBoolean(request.IncludeDeleted);
filteredRequest.ErrorType = sanitize(request.ErrorType);
if (Utils.containsGPSCoordinates([request.LocLongitude, request.LocLatitude])) {

MODIFY
src/types/requests/HttpChargingStationRequest.ts
src/types/requests/HttpChargingStationRequest.ts
@@ -22,12 +22,20 @@ export interface HttpChargingProfilesRequest extends HttpDatabaseRequest {
SiteID?: string;
}
+export interface HttpDownloadQrCodeRequest {
+ ChargeBoxID?: string;
+ ConnectorID?: number;
+ SiteID?: string;
+ SiteAreaID?: string;
+}
+
export interface HttpChargingStationsRequest extends HttpDatabaseRequest {
Issuer?: boolean;
Search?: string;
WithNoSiteArea?: boolean;
ConnectorStatus?: string;
ConnectorType?: string;
+ ChargeBoxID?: string;
SiteID?: string;
WithSite?: boolean;
SiteAreaID?: string;

MODIFY
src/utils/Constants.ts
src/utils/Constants.ts
@@ -29,6 +29,7 @@ export default class Constants {
public static readonly DB_PARAMS_DEFAULT_RECORD: DbParams = Object.freeze({ limit: Constants.DB_RECORD_COUNT_DEFAULT, skip: 0, sort: null });
public static readonly DB_PARAMS_COUNT_ONLY: DbParams = Object.freeze({ limit: Constants.DB_RECORD_COUNT_NO_LIMIT, skip: 0, onlyRecordCount: true, sort: null });
+ public static readonly EXPORT_PDF_PAGE_SIZE = 100;
public static readonly EXPORT_PAGE_SIZE = 1000;
public static readonly EXPORT_RECORD_MAX_COUNT = 100000;

Refactoring QR-Code