Handle WithUser in get Transaction
MODIFY
src/assets/server/rest/v1/docs/e-mobility-oas.json
src/assets/server/rest/v1/docs/e-mobility-oas.json
"parameters": [
{
"$ref": "#/components/parameters/transactionID"
+ },
+ {
+ "$ref": "#/components/parameters/WithCar"
+ },
+ {
+ "$ref": "#/components/parameters/WithUser"
+ },
+ {
+ "$ref": "#/components/parameters/WithTag"
}
],
"tags": [
"schema": {
"type": "boolean"
}
+ },
+ {
+ "$ref": "#/components/parameters/WithCar"
+ },
+ {
+ "$ref": "#/components/parameters/WithUser"
+ },
+ {
+ "$ref": "#/components/parameters/WithTag"
}
],
"tags": [

MODIFY
src/client/ocpi/EmspOCPIClient.ts
src/client/ocpi/EmspOCPIClient.ts
@@ -512,10 +512,10 @@ export default class EmspOCPIClient extends OCPIClient {
if (!transaction || !transaction.ocpiData || !transaction.ocpiData.session || transaction.issuer) {
throw new BackendError({
action: ServerAction.OCPI_START_SESSION,
- source: transaction ? transaction.chargeBoxID : null,
+ source: transaction?.chargeBoxID,
message: `OCPI Remote Stop Session is not available for the Session ID '${transactionId}'`,
module: MODULE_NAME, method: 'remoteStopSession',
- detailedMessages: { transaction: transaction }
+ detailedMessages: { transaction }
});
}
const payload: OCPIStopSession = {

MODIFY
src/scheduler/tasks/ocpi/OCPIPushCdrsTask.ts
src/scheduler/tasks/ocpi/OCPIPushCdrsTask.ts
@@ -52,7 +52,7 @@ export default class OCPIPushCdrsTask extends SchedulerTask {
if (ocpiTransactionLock) {
try {
// Get Transaction
- const transaction = await TransactionStorage.getTransaction(tenant.id, transactionMDB._id);
+ const transaction = await TransactionStorage.getTransaction(tenant.id, transactionMDB._id, { withUser: true });
if (!transaction) {
await Logging.logError({
tenantID: tenant.id,

MODIFY
src/server/ocpp/services/OCPPService.ts
src/server/ocpp/services/OCPPService.ts
@@ -704,12 +704,7 @@ export default class OCPPService {
private async processConnectorStatusNotification(tenant: Tenant, chargingStation: ChargingStation, statusNotification: OCPPStatusNotificationRequestExtended) {
// Get Connector
- const { connector, newConnector } = await this.checkAndGetConnectorFromStatusNotification(
- tenant, chargingStation, statusNotification);
- // Status must be different
- if (!newConnector && !await this.hasStatusNotificationChanged(tenant, chargingStation, connector, statusNotification)) {
- return;
- }
+ const connector = await this.checkAndGetConnectorFromStatusNotification(tenant, chargingStation, statusNotification);
// Check last Transaction
await this.checkAndUpdateLastCompletedTransaction(tenant, chargingStation, statusNotification, connector);
// Update Connector
@@ -781,25 +776,6 @@ export default class OCPPService {
}
}
- private async hasStatusNotificationChanged(tenant: Tenant, chargingStation: ChargingStation, connector: Connector,
- statusNotification: OCPPStatusNotificationRequestExtended): Promise<boolean> {
- if (connector.status === statusNotification.status &&
- connector.errorCode === statusNotification.errorCode &&
- connector.info === statusNotification.info) {
- // No Change
- await Logging.logWarning({
- tenantID: tenant.id,
- source: chargingStation.id,
- module: MODULE_NAME, method: 'hasStatusNotificationChanged',
- action: ServerAction.STATUS_NOTIFICATION,
- message: `${OCPPUtils.buildConnectorInfo(statusNotification.connectorId, connector.currentTransactionID)} Status has not changed: '${this.buildConnectorStatusDescription(connector)}'`,
- detailedMessages: { connector: connector }
- });
- return false;
- }
- return true;
- }
-
private buildConnectorStatusDescription(connector: Connector): string {
const connectorStatusDescriptions = [];
connectorStatusDescriptions.push(connector.status);
@@ -813,12 +789,9 @@ export default class OCPPService {
}
private async checkAndGetConnectorFromStatusNotification(tenant: Tenant, chargingStation: ChargingStation,
- statusNotification: OCPPStatusNotificationRequestExtended): Promise<{ connector: Connector, newConnector: boolean }> {
- let newConnector = false;
+ statusNotification: OCPPStatusNotificationRequestExtended): Promise<Connector> {
let foundConnector = Utils.getConnectorFromID(chargingStation, statusNotification.connectorId);
if (!foundConnector) {
- // To be saved
- newConnector = true;
// Check backup first
foundConnector = Utils.getBackupConnectorFromID(chargingStation, statusNotification.connectorId);
if (foundConnector) {
@@ -848,7 +821,7 @@ export default class OCPPService {
}
}
}
- return { connector: foundConnector, newConnector };
+ return foundConnector;
}
private async checkAndUpdateLastCompletedTransaction(tenant: Tenant, chargingStation: ChargingStation,
@@ -864,6 +837,8 @@ export default class OCPPService {
if (Utils.objectHasProperty(statusNotification, 'timestamp')) {
// Session is finished
if (!lastTransaction.stop.extraInactivityComputed) {
+ // Init
+ lastTransaction.stop.extraInactivitySecs = 0;
// Calculate Extra Inactivity only between Finishing and Available status notification
if (connector.status === ChargePointStatus.FINISHING) {
const transactionStopTimestamp = Utils.convertToDate(lastTransaction.stop.timestamp);
@@ -900,7 +875,6 @@ export default class OCPPService {
}
// No extra inactivity
} else {
- lastTransaction.stop.extraInactivitySecs = 0;
await Logging.logInfo({
tenantID: tenant.id,
source: chargingStation.id,
@@ -2029,7 +2003,7 @@ export default class OCPPService {
detailedMessages: { headers, meterValues }
});
}
- const transaction = await TransactionStorage.getTransaction(tenant.id, meterValues.transactionId);
+ const transaction = await TransactionStorage.getTransaction(tenant.id, meterValues.transactionId, { withUser: true });
if (!transaction) {
throw new BackendError({
source: chargingStation.id,
@@ -2055,7 +2029,7 @@ export default class OCPPService {
private async getTransactionFromStopTransaction(tenant: Tenant, chargingStation: ChargingStation,
headers: OCPPHeader, stopTransaction: OCPPStopTransactionRequestExtended): Promise<Transaction> {
- const transaction = await TransactionStorage.getTransaction(tenant.id, stopTransaction.transactionId);
+ const transaction = await TransactionStorage.getTransaction(tenant.id, stopTransaction.transactionId, { withUser: true });
if (!transaction) {
throw new BackendError({
source: chargingStation.id,

MODIFY
src/server/rest/v1/service/ChargingStationService.ts
src/server/rest/v1/service/ChargingStationService.ts
@@ -1824,7 +1824,8 @@ export default class ChargingStationService {
});
}
// Get Transaction
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.args.transactionId);
+ const transaction = await TransactionStorage.getTransaction(
+ req.user.tenantID, filteredRequest.args.transactionId, { withUser: true });
UtilsService.assertObjectExists(action, transaction, `Transaction ID '${filteredRequest.args.transactionId as string}' does not exist`,
MODULE_NAME, 'handleAction', req.user);
// Add connector ID

MODIFY
src/server/rest/v1/service/TransactionService.ts
src/server/rest/v1/service/TransactionService.ts
@@ -99,7 +99,7 @@ export default class TransactionService {
}
const transactionsToRefund: Transaction[] = [];
for (const transactionId of filteredRequest.transactionIds) {
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, transactionId);
+ const transaction = await TransactionStorage.getTransaction(req.user.tenantID, transactionId, { withUser: true });
if (!transaction) {
await Logging.logError({
tenantID: req.user.tenantID,
@@ -191,7 +191,7 @@ export default class TransactionService {
});
}
// Check Transaction
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.transactionId);
+ const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.transactionId, { withUser: true });
UtilsService.assertObjectExists(action, transaction, `Transaction ID '${filteredRequest.transactionId}' does not exist`,
MODULE_NAME, 'handlePushTransactionCdr', req.user);
// Check Charging Station
@@ -339,7 +339,8 @@ export default class TransactionService {
const filteredRequest = TransactionSecurity.filterTransactionRequest(req.query);
UtilsService.assertIdIsProvided(action, filteredRequest.ID.toString(), MODULE_NAME, 'handleRebuildTransactionConsumptions', req.user);
// Get Transaction
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.ID);
+ const transaction = await TransactionStorage.getTransaction(
+ req.user.tenantID, filteredRequest.ID, { withUser: true });
UtilsService.assertObjectExists(action, transaction, `Transaction ID '${filteredRequest.ID}' does not exist`,
MODULE_NAME, 'handleRebuildTransactionConsumptions', req.user);
// Get unassigned transactions
@@ -477,14 +478,6 @@ export default class TransactionService {
const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, transaction.chargeBoxID);
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${transaction.chargeBoxID}' does not exist`,
MODULE_NAME, 'handleTransactionSoftStop', req.user);
- // Check User
- let user: User;
- if (!transaction.user && transaction.userID) {
- // Get Transaction User
- user = await UserStorage.getUser(req.user.tenantID, transaction.userID);
- UtilsService.assertObjectExists(action, user, `User ID '${transaction.userID}' does not exist`,
- MODULE_NAME, 'handleTransactionSoftStop', req.user);
- }
// Stop Transaction
const result = await new OCPPService(Configuration.getChargingStationConfig()).handleStopTransaction(
{
@@ -504,7 +497,7 @@ export default class TransactionService {
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
source: chargingStation.id,
- user: req.user, actionOnUser: user,
+ user: req.user, actionOnUser: transaction.userID,
module: MODULE_NAME, method: 'handleTransactionSoftStop',
message: `${OCPPUtils.buildConnectorInfo(transaction.connectorId, transaction.id)} Transaction has been stopped successfully`,
action: action,
@@ -553,7 +546,7 @@ export default class TransactionService {
}
// Get Transaction
const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.TransactionId,
- { withTag: filteredRequest.WithTag, withCar: filteredRequest.WithCar }, projectFields);
+ { withTag: filteredRequest.WithTag, withCar: filteredRequest.WithCar, withUser: filteredRequest.WithUser }, projectFields);
UtilsService.assertObjectExists(action, transaction, `Transaction ID '${filteredRequest.TransactionId}' does not exist`,
MODULE_NAME, 'handleGetConsumptionFromTransaction', req.user);
// Check Transaction
@@ -624,7 +617,9 @@ export default class TransactionService {
const filteredRequest = TransactionSecurity.filterTransactionRequest(req.query);
UtilsService.assertIdIsProvided(action, filteredRequest.ID, MODULE_NAME, 'handleGetTransaction', req.user);
// Get Transaction
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.ID, { withTag: true }, [
+ const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.ID,
+ { withTag: filteredRequest.WithTag, withCar: filteredRequest.WithCar, withUser: filteredRequest.WithUser },
+ [
'id', 'chargeBoxID', 'timestamp', 'issuer', 'stateOfCharge', 'tagID', 'tag.visualID', 'tag.description', 'timezone', 'connectorId', 'meterStart', 'siteAreaID', 'siteID', 'companyID',
'userID', 'user.id', 'user.name', 'user.firstName', 'user.email', 'roundedPrice', 'price', 'priceUnit',
'stop.userID', 'stop.user.id', 'stop.user.name', 'stop.user.firstName', 'stop.user.email',
@@ -634,7 +629,9 @@ export default class TransactionService {
'stop.totalDurationSecs', 'stop.totalInactivitySecs', 'stop.extraInactivitySecs', 'stop.pricingSource', 'stop.signedData',
'stop.tagID', 'stop.tag.visualID', 'stop.tag.description', 'billingData.stop.status', 'billingData.stop.invoiceID',
'billingData.stop.invoiceStatus', 'billingData.stop.invoiceNumber',
- ]);
+ 'carID' ,'carCatalogID', 'carCatalog.vehicleMake', 'carCatalog.vehicleModel', 'carCatalog.vehicleModelVersion',
+ ]
+ );
UtilsService.assertObjectExists(action, transaction, `Transaction ID '${filteredRequest.ID}' does not exist`,
MODULE_NAME, 'handleGetTransaction', req.user);
// Check Transaction
@@ -707,7 +704,8 @@ export default class TransactionService {
const transactions = await TransactionService.getTransactions(req, action, {}, [
'id', 'chargeBoxID', 'timestamp', 'issuer', 'stateOfCharge', 'timezone', 'connectorId', 'meterStart', 'siteAreaID', 'siteID', 'companyID',
'stop.roundedPrice', 'stop.price', 'stop.priceUnit', 'stop.inactivityStatus', 'stop.stateOfCharge', 'stop.timestamp', 'stop.totalConsumptionWh',
- 'stop.totalDurationSecs', 'stop.totalInactivitySecs', 'stop.extraInactivitySecs', 'stop.meterStop', 'site.name', 'siteArea.name', 'company.name',
+ 'stop.totalDurationSecs', 'stop.totalInactivitySecs', 'stop.extraInactivitySecs', 'stop.meterStop',
+ 'site.name', 'siteArea.name', 'company.name',
'billingData.stop.invoiceNumber', 'stop.reason', 'ocpi', 'ocpiWithCdr', 'tagID', 'tag.visualID', 'stop.tagID', 'stop.tag.visualID'
]);
res.json(transactions);

MODIFY
src/server/rest/v1/service/security/TransactionSecurity.ts
src/server/rest/v1/service/security/TransactionSecurity.ts
@@ -39,7 +39,10 @@ export default class TransactionSecurity {
public static filterTransactionRequest(request: any): HttpTransactionRequest {
return {
- ID: Utils.convertToInt(sanitize(request.ID))
+ ID: Utils.convertToInt(sanitize(request.ID)),
+ WithCar: UtilsSecurity.filterBoolean(request.WithCar),
+ WithTag: UtilsSecurity.filterBoolean(request.WithTag),
+ WithUser: UtilsSecurity.filterBoolean(request.WithUser),
};
}
@@ -114,6 +117,9 @@ export default class TransactionSecurity {
if (Utils.objectHasProperty(request, 'WithCar')) {
filteredRequest.WithCar = UtilsSecurity.filterBoolean(request.WithCar);
}
+ if (Utils.objectHasProperty(request, 'WithUser')) {
+ filteredRequest.WithUser = UtilsSecurity.filterBoolean(request.WithUser);
+ }
if (Utils.objectHasProperty(request, 'LoadAllConsumptions')) {
filteredRequest.LoadAllConsumptions = Utils.convertToBoolean(sanitize(request.LoadAllConsumptions));
}

MODIFY
src/storage/mongodb/TransactionStorage.ts
src/storage/mongodb/TransactionStorage.ts
@@ -1018,12 +1018,12 @@ export default class TransactionStorage {
}
public static async getTransaction(tenantID: string, id: number = Constants.UNKNOWN_NUMBER_ID,
- params: { withTag?: boolean; withCar?: boolean; } = {}, projectFields?: string[]): Promise<Transaction> {
+ params: { withTag?: boolean; withCar?: boolean; withUser?: boolean } = {}, projectFields?: string[]): Promise<Transaction> {
const transactionsMDB = await TransactionStorage.getTransactions(tenantID, {
transactionIDs: [id],
withTag: params.withTag,
withCar: params.withCar,
- withUser: true,
+ withUser: params.withUser,
}, Constants.DB_PARAMS_SINGLE_RECORD, projectFields);
return transactionsMDB.count === 1 ? transactionsMDB.result[0] : null;
}

MODIFY
src/types/requests/HttpTransactionRequest.ts
src/types/requests/HttpTransactionRequest.ts
@@ -16,6 +16,9 @@ export interface HttpUnassignTransactionsToUserRequest {
export interface HttpTransactionRequest {
ID: number;
+ WithTag: boolean;
+ WithCar: boolean;
+ WithUser: boolean;
}
export interface HttpPushTransactionCdrRequest {
@@ -54,6 +57,7 @@ export interface HttpConsumptionFromTransactionRequest {
TransactionId: number;
WithTag: boolean;
WithCar: boolean;
+ WithUser: boolean;
LoadAllConsumptions?: boolean;
StartDateTime: Date;
EndDateTime: Date;

Handle WithUser in get Transaction