added site id to charging station
MODIFY
src/migration/MigrationHandler.ts
src/migration/MigrationHandler.ts
@@ -11,6 +11,7 @@ import AddNotificationsFlagsToUsersTask from './tasks/AddNotificationsFlagsToUse
import AddSensitiveDataInSettingsTask from './tasks/AddSensitiveDataInSettingsTask';
import AddSiteAreaIDToAssetConsumptionTask from './tasks/AddSiteAreaIDToAssetConsumptionTask';
import AddSiteAreaLimitToConsumptionsTask from './tasks/AddSiteAreaLimitToConsumptionsTask';
+import AddSiteIDToChargingStationTask from './tasks/AddSiteIDToChargingStationTask';
import AddTagTypeTask from './tasks/AddTagTypeTask';
import AddTransactionRefundStatusTask from './tasks/AddTransactionRefundStatusTask';
import AddUserInTransactionsTask from './tasks/AddUserInTransactionsTask';
@@ -35,6 +36,7 @@ import MigrateUserSettingsTask from './tasks/MigrateUserSettingsTask';
import MigrationStorage from '../storage/mongodb/MigrationStorage';
import MigrationTask from './MigrationTask';
import RecomputeAllTransactionsConsumptionsTask from './tasks/RecomputeAllTransactionsConsumptionsTask';
+import RecomputeAllTransactionsWithSimplePricingTask from './tasks/RecomputeAllTransactionsWithSimplePricingTask';
import RenameChargingStationPropertiesTask from './tasks/RenameChargingStationPropertiesTask';
import RenameSMTPAuthErrorTask from './tasks/RenameSMTPAuthErrorTask';
import RenameTagPropertiesTask from './tasks/RenameTagPropertiesTask';
@@ -49,7 +51,6 @@ import UpdateConsumptionsToObjectIDsTask from './tasks/UpdateConsumptionsToObjec
import UpdateLimitsInConsumptionsTask from './tasks/UpdateLimitsInConsumptionsTask';
import cluster from 'cluster';
import moment from 'moment';
-import RecomputeAllTransactionsWithSimplePricingTask from './tasks/RecomputeAllTransactionsWithSimplePricingTask';
const MODULE_NAME = 'MigrationHandler';
@@ -117,6 +118,7 @@ export default class MigrationHandler {
currentMigrationTasks.push(new ResetCarCatalogsHashTask());
currentMigrationTasks.push(new AddSiteAreaIDToAssetConsumptionTask());
currentMigrationTasks.push(new RecomputeAllTransactionsWithSimplePricingTask());
+ currentMigrationTasks.push(new AddSiteIDToChargingStationTask());
// Get the already done migrations from the DB
const migrationTasksDone = await MigrationStorage.getMigrations();
// Check

ADD
src/migration/tasks/AddSiteIDToChargingStationTask.ts
+import Constants from '../../utils/Constants';
+import Logging from '../../utils/Logging';
+import MigrationTask from '../MigrationTask';
+import { ServerAction } from '../../types/Server';
+import SiteAreaStorage from '../../storage/mongodb/SiteAreaStorage';
+import Tenant from '../../types/Tenant';
+import TenantStorage from '../../storage/mongodb/TenantStorage';
+import Utils from '../../utils/Utils';
+import global from '../../types/GlobalType';
+
+const MODULE_NAME = 'AddSiteIDToChargingStationTask';
+
+export default class AddSiteIDToChargingStationTask extends MigrationTask {
+ async migrate(): Promise<void> {
+ const tenants = await TenantStorage.getTenants({}, Constants.DB_PARAMS_MAX_LIMIT);
+ for (const tenant of tenants.result) {
+ await this.migrateTenant(tenant);
+ }
+ }
+
+ async migrateTenant(tenant: Tenant): Promise<void> {
+ let modifiedCount = 0;
+ // Get Assets
+ const siteAreas = await SiteAreaStorage.getSiteAreas(tenant.id, null, Constants.DB_PARAMS_MAX_LIMIT);
+ for (const siteArea of siteAreas.result) {
+ const result = await global.database.getCollection(tenant.id, 'chargingstations').updateMany(
+ {
+ siteAreaID: Utils.convertToObjectID(siteArea.id),
+ },
+ {
+ $set: {
+ siteID: Utils.convertToObjectID(siteArea.siteID),
+ }
+ }
+ );
+ modifiedCount += result.modifiedCount;
+ }
+ // Log in the default tenant
+ if (modifiedCount > 0) {
+ await Logging.logDebug({
+ tenantID: Constants.DEFAULT_TENANT,
+ action: ServerAction.MIGRATION,
+ module: MODULE_NAME, method: 'migrateTenant',
+ message: `${modifiedCount} Charging stations have been updated in Tenant '${tenant.name}'`
+ });
+ }
+ }
+
+ getVersion(): string {
+ return '1.0';
+ }
+
+ getName(): string {
+ return 'AddSiteIDToChargingStationTask';
+ }
+
+ isAsynchronous(): boolean {
+ return true;
+ }
+}

MODIFY
src/server/ocpp/services/OCPPService.ts
src/server/ocpp/services/OCPPService.ts
@@ -128,6 +128,7 @@ export default class OCPPService {
const siteArea = await SiteAreaStorage.getSiteArea(headers.tenantID, token.siteAreaID);
if (siteArea) {
chargingStation.siteAreaID = token.siteAreaID;
+ chargingStation.siteID = siteArea.siteID;
// Set the same coordinates
if (siteArea?.address?.coordinates?.length === 2) {
chargingStation.coordinates = siteArea.address.coordinates;

MODIFY
src/server/rest/v1/service/ChargingStationService.ts
src/server/rest/v1/service/ChargingStationService.ts
@@ -144,6 +144,7 @@ export default class ChargingStationService {
});
}
chargingStation.siteAreaID = siteArea.id;
+ chargingStation.siteID = siteArea.siteID;
// Check number of phases corresponds to the site area one
for (const connector of chargingStation.connectors) {
const numberOfConnectedPhase = Utils.getNumberOfConnectedPhases(chargingStation, null, connector.connectorId);
@@ -165,6 +166,7 @@ export default class ChargingStationService {
} else {
delete chargingStation.excludeFromSmartCharging;
chargingStation.siteAreaID = null;
+ chargingStation.siteID = null;
}
if (filteredRequest.coordinates && filteredRequest.coordinates.length === 2) {
chargingStation.coordinates = [
@@ -728,6 +730,8 @@ export default class ChargingStationService {
// Remove Site Area
chargingStation.siteArea = null;
chargingStation.siteAreaID = null;
+ // Remove Site
+ chargingStation.siteID = null;
// Set as deleted
chargingStation.deleted = true;
// Check if charging station has had transactions
@@ -770,7 +774,7 @@ export default class ChargingStationService {
let projectFields = [
'id', 'inactive', 'public', 'chargingStationURL', 'issuer', 'maximumPower', 'excludeFromSmartCharging', 'lastReboot',
'siteAreaID', 'siteArea.id', 'siteArea.name', 'siteArea.smartCharging', 'siteArea.siteID',
- 'siteArea.site.id', 'siteArea.site.name', 'voltage', 'coordinates', 'forceInactive', 'firmwareUpdateStatus',
+ 'siteArea.site.id', 'siteArea.site.name', 'siteID', 'voltage', 'coordinates', 'forceInactive', 'firmwareUpdateStatus',
'capabilities', 'endpoint', 'chargePointVendor', 'chargePointModel', 'ocppVersion', 'ocppProtocol', 'lastSeen',
'firmwareVersion', 'currentIPAddress', 'ocppStandardParameters', 'ocppVendorParameters', 'connectors', 'chargePoints',
'createdOn', 'chargeBoxSerialNumber', 'chargePointSerialNumber', 'powerLimitUnit'
@@ -1284,7 +1288,7 @@ export default class ChargingStationService {
projectFields = [
'id', 'inactive', 'connectorsStatus', 'connectorsConsumption', 'public', 'firmwareVersion', 'chargePointVendor', 'chargePointModel',
'ocppVersion', 'ocppProtocol', 'lastSeen', 'firmwareUpdateStatus', 'coordinates', 'issuer', 'voltage',
- 'siteAreaID', 'siteArea.id', 'siteArea.name', 'siteArea.siteID', 'siteArea.site.name', 'siteArea.address', 'maximumPower', 'powerLimitUnit',
+ 'siteAreaID', 'siteArea.id', 'siteArea.name', 'siteArea.siteID', 'siteArea.site.name', 'siteArea.address', 'siteID', 'maximumPower', 'powerLimitUnit',
'chargePointModel', 'chargePointSerialNumber', 'chargeBoxSerialNumber', 'connectors.connectorId', 'connectors.status', 'connectors.type', 'connectors.power', 'connectors.errorCode',
'connectors.currentTotalConsumptionWh', 'connectors.currentInstantWatts', 'connectors.currentStateOfCharge',
'connectors.currentTransactionID', 'connectors.currentTotalInactivitySecs', 'connectors.currentTagID', 'chargePoints', 'lastReboot', 'createdOn',

MODIFY
src/storage/mongodb/ChargingStationStorage.ts
src/storage/mongodb/ChargingStationStorage.ts
@@ -160,7 +160,6 @@ export default class ChargingStationStorage {
dbParams: DbParams, projectFields?: string[]): Promise<DataResult<ChargingStation>> {
// Debug
const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getChargingStations');
- let siteAreaLookUpAdded = false;
// Check Tenant
await DatabaseUtils.checkTenant(tenantID);
// Clone before updating the values
@@ -269,29 +268,14 @@ export default class ChargingStationStorage {
// With no Site Area
if (params.withNoSiteArea) {
filters.siteAreaID = null;
- } else {
+ } else if (!Utils.isEmptyArray(params.siteAreaIDs)) {
// Query by siteAreaID
- if (!Utils.isEmptyArray(params.siteAreaIDs)) {
filters.siteAreaID = { $in: params.siteAreaIDs.map((id) => Utils.convertToObjectID(id)) };
}
// Check Site ID
if (!Utils.isEmptyArray(params.siteIDs)) {
- // TODO: Optimization: Assign SiteID to the charging station object
- // Site Area
- siteAreaLookUpAdded = true;
- DatabaseUtils.pushSiteAreaLookupInAggregation({
- tenantID, aggregation: aggregation, localField: 'siteAreaID', foreignField: '_id',
- asField: 'siteArea', oneToOneCardinality: true
- });
- // Build filter
- aggregation.push({
- $match: {
- 'siteArea.siteID': {
- $in: params.siteIDs.map((id) => Utils.convertToObjectID(id))
- }
- }
- });
- }
+ // Query by siteID
+ filters.siteID = { $in: params.siteIDs.map((id) => Utils.convertToObjectID(id)) };
}
// Date before provided
if (params.statusChangedBefore && moment(params.statusChangedBefore).isValid()) {
@@ -345,12 +329,10 @@ export default class ChargingStationStorage {
asField: 'connectors.user', oneToOneCardinality: true, objectIDFields: ['createdBy', 'lastChangedBy']
}, { sort: dbParams.sort });
// Site Area
- if (!siteAreaLookUpAdded) {
DatabaseUtils.pushSiteAreaLookupInAggregation({
tenantID, aggregation: aggregation, localField: 'siteAreaID', foreignField: '_id',
asField: 'siteArea', oneToOneCardinality: true
});
- }
// Site
if (params.withSite && !params.withNoSiteArea) {
DatabaseUtils.pushSiteLookupInAggregation({
@@ -532,6 +514,7 @@ export default class ChargingStationStorage {
issuer: Utils.convertToBoolean(chargingStationToSave.issuer),
public: Utils.convertToBoolean(chargingStationToSave.public),
siteAreaID: Utils.convertToObjectID(chargingStationToSave.siteAreaID),
+ siteID: Utils.convertToObjectID(chargingStationToSave.siteID),
chargePointSerialNumber: chargingStationToSave.chargePointSerialNumber,
chargePointModel: chargingStationToSave.chargePointModel,
chargeBoxSerialNumber: chargingStationToSave.chargeBoxSerialNumber,

MODIFY
src/types/ChargingStation.ts
src/types/ChargingStation.ts
@@ -18,6 +18,7 @@ export default interface ChargingStation extends CreatedUpdatedProps {
issuer: boolean;
public: boolean;
siteAreaID?: string;
+ siteID?: string;
chargePointSerialNumber: string;
chargePointModel: string;
chargeBoxSerialNumber: string;

MODIFY
test/api/context/TenantContext.ts
test/api/context/TenantContext.ts
@@ -297,6 +297,9 @@ export default class TenantContext {
this.getAdminCentralServerService().chargingStationApi, chargingStation);
// Charging Station
expect(createdChargingStation.voltage).to.eql(230);
+ if (siteArea) {
+ expect(createdChargingStation.siteID).to.eql(siteArea.siteID);
+ }
// Connectors
expect(createdChargingStation.connectors.length).to.eql(2,
`Number of connector of charging station ${createdChargingStation.id} must be 2`);
@@ -380,6 +383,9 @@ export default class TenantContext {
this.getAdminCentralServerService().chargingStationApi, chargingStation);
// Charging Station
expect(createdChargingStation.voltage).to.eql(230);
+ if (siteArea) {
+ expect(createdChargingStation.siteID).to.eql(siteArea.siteID);
+ }
// Connectors
expect(createdChargingStation.connectors.length).to.eql(2,
`Number of connector of charging station ${createdChargingStation.id} must be 2`);
@@ -469,6 +475,9 @@ export default class TenantContext {
this.getAdminCentralServerService().chargingStationApi, chargingStation);
// Charging Station
expect(createdChargingStation.voltage).to.eql(230);
+ if (siteArea) {
+ expect(createdChargingStation.siteID).to.eql(siteArea.siteID);
+ }
// Connectors
expect(createdChargingStation.connectors.length).to.eql(2,
`Number of connector of charging station ${createdChargingStation.id} must be 2`);

added site id to charging station