Add get transactions in RESTful service
MODIFY
src/assets/server/rest/v1/docs/e-mobility-oas.json
src/assets/server/rest/v1/docs/e-mobility-oas.json
}
}
},
+ "/api/transactions": {
+ "get": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "description": "Retrieve a list of Transactions",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/Issuer"
+ },
+ {
+ "$ref": "#/components/parameters/Search"
+ },
+ {
+ "$ref": "#/components/parameters/StartDateTime"
+ },
+ {
+ "$ref": "#/components/parameters/EndDateTime"
+ },
+ {
+ "$ref": "#/components/parameters/ChargingStationID"
+ },
+ {
+ "$ref": "#/components/parameters/ConnectorID"
+ },
+ {
+ "$ref": "#/components/parameters/UserID"
+ },
+ {
+ "$ref": "#/components/parameters/TagID"
+ },
+ {
+ "$ref": "#/components/parameters/SiteID"
+ },
+ {
+ "$ref": "#/components/parameters/SiteAreaID"
+ },
+ {
+ "$ref": "#/components/parameters/InactivityStatus"
+ },
+ {
+ "$ref": "#/components/parameters/TransactionStatistics"
+ },
+ {
+ "$ref": "#/components/parameters/Limit"
+ },
+ {
+ "$ref": "#/components/parameters/Skip"
+ },
+ {
+ "$ref": "#/components/parameters/SortFields"
+ },
+ {
+ "$ref": "#/components/parameters/OnlyRecordCount"
+ },
+ {
+ "$ref": "#/components/parameters/ProjectFields"
+ }
+ ],
+ "tags": [
+ "Transactions"
+ ],
+ "responses": {
+ "200": {
+ "description": "Return Transaction's list",
+ "content": {
+ "application/json": {
+ "example": {
+ "count": 1,
+ "result": [
+ {
+ "id": 1234567889,
+ "issuer": true,
+ "siteID": "####",
+ "siteAreaID": "####",
+ "connectorId": 2,
+ "tagID": "####",
+ "userID": "####",
+ "chargeBoxID": "####",
+ "meterStart": 1122030,
+ "timestamp": "2021-02-15T16:04:04.000Z",
+ "stateOfCharge": 0,
+ "timezone": "Europe/Paris",
+ "stop": {
+ "userID": "####",
+ "timestamp": "2021-02-15T16:05:38.000Z",
+ "tagID": "####",
+ "meterStop": 1122046,
+ "stateOfCharge": 0,
+ "totalConsumptionWh": 16,
+ "totalInactivitySecs": 0,
+ "inactivityStatus": "I",
+ "totalDurationSecs": 94,
+ "price": 0.002,
+ "priceUnit": "EUR",
+ "user": {
+ "email": "####",
+ "firstName": "####",
+ "name": "####",
+ "id": "####"
+ }
+ },
+ "ocpi": false,
+ "ocpiWithCdr": false,
+ "user": {
+ "email": "####",
+ "firstName": "####",
+ "name": "####",
+ "id": "####"
+ },
+ "car": {
+ "licensePlate": "####"
+ },
+ "carCatalog": {
+ "vehicleMake": "Tesla",
+ "vehicleModel": "Model 3",
+ "vehicleModelVersion": "Long Range Dual Motor"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/500BackendError"
+ }
+ }
+ }
+ },
"/api/chargingstations": {
"get": {
"security": [
}
},
{
- "in": "query",
- "name": "Statistics",
- "required": false,
- "description": "Refund or History statistics",
- "schema": {
- "type": "string",
- "example": "history",
- "enum": [
- "refund",
- "history"
- ]
- }
+ "$ref": "#/components/parameters/TransactionStatistics"
},
{
"in": "query",
]
}
},
+ "StartDateTime": {
+ "in": "query",
+ "name": "StartDateTime",
+ "description": "Start Date (ISO format)",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ "EndDateTime": {
+ "in": "query",
+ "name": "EndDateTime",
+ "description": "End Date (ISO format)",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ "TagID": {
+ "in": "query",
+ "name": "TagID",
+ "description": "Badge ID",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ "UserID": {
+ "in": "query",
+ "name": "UserID",
+ "description": "User ID",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
"ChargingStationID": {
"in": "query",
"name": "ChargingStationID",
"type": "number"
}
},
+ "InactivityStatus": {
+ "in": "query",
+ "name": "InactivityStatus",
+ "description": "Inactivity Status",
+ "required": false,
+ "schema": {
+ "type": "number",
+ "enum": [
+ "I", "W", "E"
+ ]
+ }
+ },
"chargingProfileID": {
"in": "path",
"name": "id",
"example": 1
}
},
+ "TransactionStatistics": {
+ "in": "query",
+ "name": "Statistics",
+ "description": "Refund or History statistics",
+ "schema": {
+ "type": "string",
+ "example": "history",
+ "enum": [
+ "refund",
+ "history"
+ ]
+ }
+ },
"SiteID": {
"in": "query",
"name": "SiteID",

MODIFY
src/server/rest/v1/router/GlobalRouter.ts
src/server/rest/v1/router/GlobalRouter.ts
@@ -6,6 +6,7 @@ import ChargingStationRouter from './api/ChargingStationRouter';
import { StatusCodes } from 'http-status-codes';
import SwaggerRouter from './doc/SwaggerRouter';
import TenantRouter from './api/TenantRouter';
+import TransactionRouter from './api/TransactionRouter';
import UtilRouter from './util/UtilRouter';
export default class GlobalRouter {
@@ -31,7 +32,8 @@ export default class GlobalRouter {
protected buildRouteAPI(): void {
this.router.use('/api', AuthService.authenticate(), [
new TenantRouter().buildRoutes(),
- new ChargingStationRouter().buildRoutes()
+ new ChargingStationRouter().buildRoutes(),
+ new TransactionRouter().buildRoutes(),
]);
}

MODIFY
src/server/rest/v1/router/api/ChargingStationRouter.ts
src/server/rest/v1/router/api/ChargingStationRouter.ts
+/* eslint-disable @typescript-eslint/no-misused-promises */
import { ServerAction, ServerRoute } from '../../../../../types/Server';
import express, { NextFunction, Request, Response } from 'express';
@@ -143,20 +144,23 @@ export default class ChargingStationRouter {
protected buildRouteChargingStationGetOCPPParameters(): void {
this.router.get(`/${ServerRoute.REST_CHARGING_STATION_GET_OCPP_PARAMETERS}`, async (req: Request, res: Response, next: NextFunction) => {
req.query.ChargeBoxID = req.params.id;
- await RouterUtils.handleServerAction(ChargingStationService.handleGetChargingStationOcppParameters.bind(this), ServerAction.CHARGING_STATIONS_OCPP_PARAMETERS, req, res, next);
+ await RouterUtils.handleServerAction(ChargingStationService.handleGetChargingStationOcppParameters.bind(this),
+ ServerAction.CHARGING_STATIONS_OCPP_PARAMETERS, req, res, next);
});
}
protected buildRouteChargingStationRequestOCPPParameters(): void {
this.router.post(`/${ServerRoute.REST_CHARGING_STATIONS_REQUEST_OCPP_PARAMETERS}`, async (req: Request, res: Response, next: NextFunction) => {
- await RouterUtils.handleServerAction(ChargingStationService.handleRequestChargingStationOcppParameters.bind(this), ServerAction.CHARGING_STATION_REQUEST_OCPP_PARAMETERS, req, res, next);
+ await RouterUtils.handleServerAction(ChargingStationService.handleRequestChargingStationOcppParameters.bind(this),
+ ServerAction.CHARGING_STATION_REQUEST_OCPP_PARAMETERS, req, res, next);
});
}
protected buildRouteChargingStationExportOCPPParameters(): void {
this.router.get(`/${ServerRoute.REST_CHARGING_STATIONS_EXPORT_OCPP_PARAMETERS}`, async (req: Request, res: Response, next: NextFunction) => {
req.query.ChargingStationID = req.params.id;
- await RouterUtils.handleServerAction(ChargingStationService.handleExportChargingStationsOCPPParams.bind(this), ServerAction.CHARGING_STATIONS_OCPP_PARAMS_EXPORT, req, res, next);
+ await RouterUtils.handleServerAction(ChargingStationService.handleExportChargingStationsOCPPParams.bind(this),
+ ServerAction.CHARGING_STATIONS_OCPP_PARAMS_EXPORT, req, res, next);
});
}

MODIFY
src/server/rest/v1/router/api/TenantRouter.ts
src/server/rest/v1/router/api/TenantRouter.ts
+/* eslint-disable @typescript-eslint/no-misused-promises */
import { ServerAction, ServerRoute } from '../../../../../types/Server';
import express, { NextFunction, Request, Response } from 'express';

ADD
src/server/rest/v1/router/api/TransactionRouter.ts
+/* eslint-disable @typescript-eslint/no-misused-promises */
+import { ServerAction, ServerRoute } from '../../../../../types/Server';
+import express, { NextFunction, Request, Response } from 'express';
+
+import RouterUtils from '../RouterUtils';
+import TransactionService from '../../service/TransactionService';
+
+export default class TransactionRouter {
+ private router: express.Router;
+
+ public constructor() {
+ this.router = express.Router();
+ }
+
+ public buildRoutes(): express.Router {
+ this.buildRouteCompletedTransactions();
+ return this.router;
+ }
+
+ protected buildRouteCompletedTransactions(): void {
+ this.router.get(`/${ServerRoute.REST_TRANSACTIONS}`, async (req: Request, res: Response, next: NextFunction) => {
+ await RouterUtils.handleServerAction(TransactionService.handleGetTransactionsCompleted.bind(this), ServerAction.CHARGING_STATIONS, req, res, next);
+ });
+ }
+}

MODIFY
src/server/rest/v1/service/TransactionService.ts
src/server/rest/v1/service/TransactionService.ts
@@ -61,7 +61,7 @@ export default class TransactionService {
res.json(response);
next();
} catch (error) {
- Logging.logActionExceptionMessageAndSendResponse(action, error, req, res, next);
+ await Logging.logActionExceptionMessageAndSendResponse(action, error, req, res, next);
}
}
@@ -86,7 +86,7 @@ export default class TransactionService {
for (const transactionId of filteredRequest.transactionIds) {
const transaction = await TransactionStorage.getTransaction(req.user.tenantID, transactionId);
if (!transaction) {
- Logging.logError({
+ await Logging.logError({
tenantID: req.user.tenantID,
user: req.user, actionOnUser: (transaction.user ? transaction.user : null),
module: MODULE_NAME, method: 'handleRefundTransactions',
@@ -97,7 +97,7 @@ export default class TransactionService {
continue;
}
if (transaction.refundData && !!transaction.refundData.refundId && transaction.refundData.status !== RefundStatus.CANCELLED) {
- Logging.logError({
+ await Logging.logError({
tenantID: req.user.tenantID,
user: req.user, actionOnUser: (transaction.user ? transaction.user : null),
module: MODULE_NAME, method: 'handleRefundTransactions',
@@ -222,7 +222,7 @@ export default class TransactionService {
// Save
await TransactionStorage.saveTransaction(req.user.tenantID, transaction);
// Ok
- Logging.logInfo({
+ await Logging.logInfo({
tenantID: req.user.tenantID,
action: action,
user: req.user, actionOnUser: (transaction.user ? transaction.user : null),
@@ -447,7 +447,7 @@ export default class TransactionService {
true
);
// Log
- Logging.logSecurityInfo({
+ await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
source: chargingStation.id,
user: req.user, actionOnUser: user,
@@ -869,7 +869,7 @@ export default class TransactionService {
// Not Found
if (!transaction) {
result.inError++;
- Logging.logError({
+ await Logging.logError({
tenantID: loggedUser.tenantID,
user: loggedUser,
module: MODULE_NAME, method: 'handleDeleteTransactions',
@@ -880,7 +880,7 @@ export default class TransactionService {
// Already Refunded
} else if (refundConnector && !refundConnector.canBeDeleted(transaction)) {
result.inError++;
- Logging.logError({
+ await Logging.logError({
tenantID: loggedUser.tenantID,
user: loggedUser,
module: MODULE_NAME, method: 'handleDeleteTransactions',
@@ -891,7 +891,7 @@ export default class TransactionService {
// Billed
} else if (billingImpl && transaction.billingData && transaction.billingData.invoiceID) {
result.inError++;
- Logging.logError({
+ await Logging.logError({
tenantID: loggedUser.tenantID,
user: loggedUser,
module: MODULE_NAME, method: 'handleDeleteTransactions',
@@ -922,7 +922,7 @@ export default class TransactionService {
// Delete All Transactions
result.inSuccess = await TransactionStorage.deleteTransactions(loggedUser.tenantID, transactionsIDsToDelete);
// Log
- Logging.logActionsResponse(loggedUser.tenantID,
+ await Logging.logActionsResponse(loggedUser.tenantID,
ServerAction.TRANSACTIONS_DELETE,
MODULE_NAME, 'deleteTransactions', result,
'{{inSuccess}} transaction(s) were successfully deleted',

MODIFY
src/server/rest/v1/service/security/TransactionSecurity.ts
src/server/rest/v1/service/security/TransactionSecurity.ts
@@ -51,7 +51,6 @@ export default class TransactionSecurity {
public static filterTransactionsRequest(request: any): HttpTransactionsRequest {
const filteredRequest = {} as HttpTransactionsRequest;
- // Handle picture
if (Utils.objectHasProperty(request, 'Issuer')) {
filteredRequest.Issuer = UtilsSecurity.filterBoolean(request.Issuer);
}

MODIFY
src/types/Server.ts
src/types/Server.ts
@@ -437,6 +437,8 @@ export enum ServerRoute {
REST_CHARGING_PROFILES = 'chargingprofiles',
REST_CHARGING_PROFILE = 'chargingprofiles/:id',
+ REST_TRANSACTIONS = 'transactions',
+
REST_PING = 'ping',
REST_TENANTS = 'tenants'

MODIFY
src/types/requests/HttpTransactionRequest.ts
src/types/requests/HttpTransactionRequest.ts
import HttpDatabaseRequest from './HttpDatabaseRequest';
+import { InactivityStatus } from '../Transaction';
export interface HttpTransactionsRefundRequest {
transactionIds: number[];
@@ -34,7 +35,7 @@ export interface HttpTransactionsRequest extends HttpDatabaseRequest {
Search?: string;
ErrorType?: string;
RefundStatus?: string;
- InactivityStatus?: string;
+ InactivityStatus?: InactivityStatus;
MinimalPrice?: boolean;
Statistics?: 'refund' | 'history';
ReportIDs?: string;

Add get transactions in RESTful service