diff --git a/package-lock.json b/package-lock.json
index bae1c36be9..fb53db51d9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "ev-server",
- "version": "2.4.79",
+ "version": "2.4.80",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 67588f1912..26c4bcd23c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ev-server",
- "version": "2.4.79",
+ "version": "2.4.80",
"engines": {
"node": "14.x.x",
"npm": "6.x.x"
diff --git a/src/assets/configs-aws b/src/assets/configs-aws
index d60f6b08be..d6656e9fef 160000
--- a/src/assets/configs-aws
+++ b/src/assets/configs-aws
@@ -1 +1 @@
-Subproject commit d60f6b08be5421586c6bdb6ddfebd2b8def91bc5
+Subproject commit d6656e9fef1de04904e5044c1894e8c24ceddb16
diff --git a/src/assets/server/notification/email/de/user-create-password.json b/src/assets/server/notification/email/de/user-create-password.json
new file mode 100644
index 0000000000..ed6d991520
--- /dev/null
+++ b/src/assets/server/notification/email/de/user-create-password.json
@@ -0,0 +1,37 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- subdomain %> organisation.",
+ "Click on the link bellow to create your password.",
+ "You will have to log in at least once to this organisation to be able to charge your car."
+ ],
+ "actions": [{
+ "title": "Create your password",
+ "url": "<%- evseDashboardCreatePasswordURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
diff --git a/src/assets/server/notification/email/de/verification-email-user-import.json b/src/assets/server/notification/email/de/verification-email-user-import.json
new file mode 100644
index 0000000000..f542791354
--- /dev/null
+++ b/src/assets/server/notification/email/de/verification-email-user-import.json
@@ -0,0 +1,38 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- tenantName %> organisation.",
+ "",
+ "Click on the link below to complete the activation."
+ ],
+ "actions": [{
+ "title": "Activate your Account",
+ "url": "<%- evseDashboardVerifyEmailURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
+
diff --git a/src/assets/server/notification/email/en/user-create-password.json b/src/assets/server/notification/email/en/user-create-password.json
new file mode 100644
index 0000000000..40e460d82d
--- /dev/null
+++ b/src/assets/server/notification/email/en/user-create-password.json
@@ -0,0 +1,37 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- tenantName %> organisation.",
+ "Click on the link bellow to create your password.",
+ "You will have to log in at least once to this organisation to be able to charge your car."
+ ],
+ "actions": [{
+ "title": "Create your password",
+ "url": "<%- evseDashboardCreatePasswordURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
diff --git a/src/assets/server/notification/email/en/verification-email-user-import.json b/src/assets/server/notification/email/en/verification-email-user-import.json
new file mode 100644
index 0000000000..f542791354
--- /dev/null
+++ b/src/assets/server/notification/email/en/verification-email-user-import.json
@@ -0,0 +1,38 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- tenantName %> organisation.",
+ "",
+ "Click on the link below to complete the activation."
+ ],
+ "actions": [{
+ "title": "Activate your Account",
+ "url": "<%- evseDashboardVerifyEmailURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
+
diff --git a/src/assets/server/notification/email/es/user-create-password.json b/src/assets/server/notification/email/es/user-create-password.json
new file mode 100644
index 0000000000..ed6d991520
--- /dev/null
+++ b/src/assets/server/notification/email/es/user-create-password.json
@@ -0,0 +1,37 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- subdomain %> organisation.",
+ "Click on the link bellow to create your password.",
+ "You will have to log in at least once to this organisation to be able to charge your car."
+ ],
+ "actions": [{
+ "title": "Create your password",
+ "url": "<%- evseDashboardCreatePasswordURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
diff --git a/src/assets/server/notification/email/es/verification-email-user-import.json b/src/assets/server/notification/email/es/verification-email-user-import.json
new file mode 100644
index 0000000000..f542791354
--- /dev/null
+++ b/src/assets/server/notification/email/es/verification-email-user-import.json
@@ -0,0 +1,38 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- tenantName %> organisation.",
+ "",
+ "Click on the link below to complete the activation."
+ ],
+ "actions": [{
+ "title": "Activate your Account",
+ "url": "<%- evseDashboardVerifyEmailURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
+
diff --git a/src/assets/server/notification/email/fr/account-verification-notification.json b/src/assets/server/notification/email/fr/account-verification-notification.json
index 5e411ac16b..3acee7bd7e 100644
--- a/src/assets/server/notification/email/fr/account-verification-notification.json
+++ b/src/assets/server/notification/email/fr/account-verification-notification.json
@@ -28,7 +28,7 @@
"url": "<%- evseDashboardURL %>"
}],
"afterActionLines": [
- "Best Regards,",
+ "Cordialement,",
"EV Admins."
],
"footer": {
diff --git a/src/assets/server/notification/email/fr/admin-account-verification-notification.json b/src/assets/server/notification/email/fr/admin-account-verification-notification.json
index cc2c93e5a9..09d5c4fdf3 100644
--- a/src/assets/server/notification/email/fr/admin-account-verification-notification.json
+++ b/src/assets/server/notification/email/fr/admin-account-verification-notification.json
@@ -28,7 +28,7 @@
"url": "<%- evseUserToVerifyURL %>"
}],
"afterActionLines": [
- "Best Regards,",
+ "Cordialement,",
"EV Admins."
],
"footer": {
diff --git a/src/assets/server/notification/email/fr/compute-and-apply-charging-profiles-failed.json b/src/assets/server/notification/email/fr/compute-and-apply-charging-profiles-failed.json
index c153e9cd99..f3b33530c2 100644
--- a/src/assets/server/notification/email/fr/compute-and-apply-charging-profiles-failed.json
+++ b/src/assets/server/notification/email/fr/compute-and-apply-charging-profiles-failed.json
@@ -28,7 +28,7 @@
"url": "<%- evseDashboardURL %>"
},
"afterActionLines": [
- "Best Regards,",
+ "Cordialement,",
"EV Admins."
],
"footer": {
diff --git a/src/assets/server/notification/email/fr/user-create-password.json b/src/assets/server/notification/email/fr/user-create-password.json
new file mode 100644
index 0000000000..27fd831889
--- /dev/null
+++ b/src/assets/server/notification/email/fr/user-create-password.json
@@ -0,0 +1,37 @@
+{
+ "subject": "Nouveau compte créé",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "Nouveau compte créé",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Bonjour <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "Un compte a été créé en votre nom sur l'organisation <%- subdomain %>.",
+ "Cliquez sur le lien ci-dessous pour créer un mot de passe.",
+ "Vous devrez vous connecter au moins une fois sur cette organisation pour pouvoir charger votre voiture."
+ ],
+ "actions": [{
+ "title": "Créer votre mot de passe",
+ "url": "<%- evseDashboardCreatePasswordURL %>"
+ }],
+ "afterActionLines": [
+ "Cordialement,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
diff --git a/src/assets/server/notification/email/fr/verification-email-user-import.json b/src/assets/server/notification/email/fr/verification-email-user-import.json
new file mode 100644
index 0000000000..5525f38dc4
--- /dev/null
+++ b/src/assets/server/notification/email/fr/verification-email-user-import.json
@@ -0,0 +1,37 @@
+{
+ "subject": "Nouveau compte créé",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "Nouveau compte créé",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Bonjour <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "Un compte a été créé en votre nom sur l'organisation <%- subdomain %>.",
+ "Cliquez sur le lien ci-dessous pour compléter l'activation."
+ ],
+ "actions": [{
+ "title": "Activez votre Compte",
+ "url": "<%- evseDashboardVerifyEmailURL %>"
+ }],
+ "afterActionLines": [
+ "Cordialement,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
+
diff --git a/src/assets/server/notification/email/it/user-create-password.json b/src/assets/server/notification/email/it/user-create-password.json
new file mode 100644
index 0000000000..ed6d991520
--- /dev/null
+++ b/src/assets/server/notification/email/it/user-create-password.json
@@ -0,0 +1,37 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- subdomain %> organisation.",
+ "Click on the link bellow to create your password.",
+ "You will have to log in at least once to this organisation to be able to charge your car."
+ ],
+ "actions": [{
+ "title": "Create your password",
+ "url": "<%- evseDashboardCreatePasswordURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
diff --git a/src/assets/server/notification/email/it/verification-email-user-import.json b/src/assets/server/notification/email/it/verification-email-user-import.json
new file mode 100644
index 0000000000..f542791354
--- /dev/null
+++ b/src/assets/server/notification/email/it/verification-email-user-import.json
@@ -0,0 +1,38 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- tenantName %> organisation.",
+ "",
+ "Click on the link below to complete the activation."
+ ],
+ "actions": [{
+ "title": "Activate your Account",
+ "url": "<%- evseDashboardVerifyEmailURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
+
diff --git a/src/assets/server/notification/email/pt/user-create-password.json b/src/assets/server/notification/email/pt/user-create-password.json
new file mode 100644
index 0000000000..ed6d991520
--- /dev/null
+++ b/src/assets/server/notification/email/pt/user-create-password.json
@@ -0,0 +1,37 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- subdomain %> organisation.",
+ "Click on the link bellow to create your password.",
+ "You will have to log in at least once to this organisation to be able to charge your car."
+ ],
+ "actions": [{
+ "title": "Create your password",
+ "url": "<%- evseDashboardCreatePasswordURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
diff --git a/src/assets/server/notification/email/pt/verification-email-user-import.json b/src/assets/server/notification/email/pt/verification-email-user-import.json
new file mode 100644
index 0000000000..f542791354
--- /dev/null
+++ b/src/assets/server/notification/email/pt/verification-email-user-import.json
@@ -0,0 +1,38 @@
+{
+ "subject": "New account created",
+ "tenant": "",
+ "baseURL": "<%- evseDashboardURL %>",
+ "body": {
+ "header": {
+ "title": "New account created",
+ "image": {
+ "left": {
+ "height": 60,
+ "url": "<%- tenantLogoURL %>"
+ },
+ "right": {
+ "height": 50,
+ "url": "<%- evseDashboardURL %>/assets/img/info.png"
+ }
+ }
+ },
+ "beforeActionLines": [
+ "Hi <%- (user.firstName?user.firstName:user.name) %>,",
+ "",
+ "An account has just been created on your behalf in <%- tenantName %> organisation.",
+ "",
+ "Click on the link below to complete the activation."
+ ],
+ "actions": [{
+ "title": "Activate your Account",
+ "url": "<%- evseDashboardVerifyEmailURL %>"
+ }],
+ "afterActionLines": [
+ "Best Regards,",
+ "EV Admins."
+ ],
+ "footer": {
+ }
+ }
+}
+
diff --git a/src/assets/server/rest/v1/docs/e-mobility-oas.json b/src/assets/server/rest/v1/docs/e-mobility-oas.json
index 75cb1523fc..a6dd62bd83 100644
--- a/src/assets/server/rest/v1/docs/e-mobility-oas.json
+++ b/src/assets/server/rest/v1/docs/e-mobility-oas.json
@@ -892,6 +892,57 @@
"$ref": "#/components/responses/BackendError"
}
}
+ },
+ "delete": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "description": "Delete several Transactions",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "transactionIDs": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Transactions"
+ ],
+ "responses": {
+ "200": {
+ "description": "Transaction deletion result",
+ "content": {
+ "application/json": {
+ "example": {
+ "status": "Success",
+ "inSuccess": 42,
+ "inError": 0
+ }
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/BackendError"
+ }
+ }
}
},
"/api/transactions/{id}": {
@@ -971,6 +1022,227 @@
"$ref": "#/components/responses/BackendError"
}
}
+ },
+ "delete": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "description": "Delete a Transaction",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/transactionID"
+ }
+ ],
+ "tags": [
+ "Transactions"
+ ],
+ "responses": {
+ "200": {
+ "description": "Transaction deletion result",
+ "content": {
+ "application/json": {
+ "example": {
+ "status": "Success",
+ "inSuccess": 1,
+ "inError": 0
+ }
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/BackendError"
+ }
+ }
+ }
+ },
+ "/api/transactions/{id}/ocpi/cdr": {
+ "post": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "description": "Push Transaction CDR",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/transactionID"
+ }
+ ],
+ "tags": [
+ "Transactions"
+ ],
+ "responses": {
+ "200": {
+ "description": "Transaction CDR pushed successfully",
+ "content": {
+ "application/json": {
+ "example": {
+ "status": "Success"
+ }
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/BackendError"
+ },
+ "580": {
+ "description": "The transaction belongs to an external organization"
+ },
+ "581": {
+ "description": "The transaction has no OCPI or OICP session data"
+ },
+ "582": {
+ "description": "The CDR of the transaction has already been pushed"
+ }
+ }
+ }
+ },
+ "/api/transactions/{id}/ocpi/cdr/export": {
+ "get": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/WithUser"
+ },
+ {
+ "$ref": "#/components/parameters/WithCar"
+ },
+ {
+ "$ref": "#/components/parameters/WithTag"
+ }
+ ],
+ "description": "Export Transaction CDR",
+ "tags": [
+ "Transactions"
+ ],
+ "responses": {
+ "200": {
+ "description": "Exported Transaction CDR",
+ "content": {
+ "application/json": {
+ "example": {
+ "id": "###",
+ "start_date_time": "2020-06-30T14:08:50.000Z",
+ "stop_date_time": "2020-06-30T14:33:56.000Z",
+ "total_parking_time": 0,
+ "total_time": 1506,
+ "total_energy": 4.502,
+ "total_cost": 0.72,
+ "currency": "EUR",
+ "auth_id": "###",
+ "authorization_id": "###",
+ "auth_method": "AUTH_REQUEST",
+ "location": {
+ "id": "###",
+ "name": "###",
+ "address": "###",
+ "city": "###",
+ "postal_code": "###",
+ "country": "###",
+ "coordinates": {
+ "latitude": "###",
+ "longitude": "###"
+ },
+ "type": "UNKNOWN",
+ "evses": [
+ {
+ "uid": "###",
+ "evse_id": "###",
+ "status": "BLOCKED",
+ "capabilities": [
+ "REMOTE_START_STOP_CAPABLE",
+ "RFID_READER"
+ ],
+ "connectors": [
+ {
+ "id": "###",
+ "standard": "IEC_62196_T2",
+ "format": "SOCKET",
+ "voltage": 230,
+ "amperage": 96,
+ "power_type": "AC_3_PHASE",
+ "last_updated": "2020-06-30T14:08:47.621Z"
+ }
+ ],
+ "coordinates": {
+ "latitude": "###",
+ "longitude": "###"
+ },
+ "last_updated": "2020-06-30T14:08:47.621Z"
+ }
+ ],
+ "last_updated": "2020-05-06T09:18:10.227Z"
+ },
+ "charging_periods": [
+ {
+ "start_date_time": "2020-06-30T14:08:50.000Z",
+ "dimensions": [
+ {
+ "type": "ENERGY",
+ "volume": 0.108
+ },
+ {
+ "type": "MAX_CURRENT",
+ "volume": 96
+ }
+ ]
+ },
+ {
+ "start_date_time": "2020-06-30T14:10:50.000Z",
+ "dimensions": [
+ {
+ "type": "ENERGY",
+ "volume": 0.182
+ },
+ {
+ "type": "MAX_CURRENT",
+ "volume": 96
+ }
+ ]
+ }
+ ],
+ "last_updated": "2020-06-30T14:33:56.000Z"
+ }
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/BackendError"
+ },
+ "580": {
+ "description": "The transaction belongs to an external organization"
+ },
+ "581": {
+ "description": "The transaction has no OCPI or OICP session data"
+ },
+ "582": {
+ "description": "The CDR of the transaction has already been pushed"
+ }
+ }
}
},
"/api/transactions/{id}/consumptions": {
@@ -1081,6 +1353,320 @@
}
}
},
+ "/api/transactions/{id}/consumptions/rebuild": {
+ "post": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "description": "Rebuild a Transaction consumptions",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/transactionID"
+ }
+ ],
+ "tags": [
+ "Transactions"
+ ],
+ "responses": {
+ "200": {
+ "description": "Consumptions rebuild result",
+ "content": {
+ "application/json": {
+ "example": {
+ "status": "Success",
+ "nbrOfConsumptions": 1
+ }
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/BackendError"
+ }
+ }
+ }
+ },
+ "/api/transactions/{id}/stop/soft": {
+ "post": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "description": "Stop a Transaction",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/transactionID"
+ }
+ ],
+ "tags": [
+ "Transactions"
+ ],
+ "responses": {
+ "200": {
+ "description": "Transaction stopped successfully",
+ "content": {
+ "application/json": {
+ "example": {
+ "status": "Success"
+ }
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/BackendError"
+ }
+ }
+ }
+ },
+ "/api/transactions/action/refund": {
+ "post": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "description": "Refund Transactions",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "transactionIds": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Transactions"
+ ],
+ "responses": {
+ "200": {
+ "description": "Transactions refund result",
+ "content": {
+ "application/json": {
+ "example": {
+ "status": "Success",
+ "inSuccess": 42,
+ "inError": 1
+ }
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/BackendError"
+ },
+ "552": {
+ "description": "No Refund valid connection found"
+ }
+ }
+ }
+ },
+ "/api/transactions/action/assign": {
+ "post": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "description": "Assign Transactions to a user",
+ "parameters": [
+ {
+ "in": "query",
+ "name": "TagID",
+ "description": "Tag ID",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "UserID",
+ "description": "User ID",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "tags": [
+ "Transactions"
+ ],
+ "responses": {
+ "200": {
+ "description": "Transactions successfully assigned",
+ "content": {
+ "application/json": {
+ "example": {
+ "status": "Success"
+ }
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/BackendError"
+ }
+ }
+ }
+ },
+ "/api/transactions/action/export": {
+ "get": {
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "description": "Export Transactions",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/Issuer"
+ },
+ {
+ "$ref": "#/components/parameters/Search"
+ },
+ {
+ "$ref": "#/components/parameters/StartDateTime"
+ },
+ {
+ "$ref": "#/components/parameters/EndDateTime"
+ },
+ {
+ "$ref": "#/components/parameters/WithChargingStation"
+ },
+ {
+ "$ref": "#/components/parameters/ChargingStationIDs"
+ },
+ {
+ "$ref": "#/components/parameters/ConnectorIDs"
+ },
+ {
+ "$ref": "#/components/parameters/WithCar"
+ },
+ {
+ "$ref": "#/components/parameters/WithUser"
+ },
+ {
+ "$ref": "#/components/parameters/UserIDs"
+ },
+ {
+ "$ref": "#/components/parameters/TagIDs"
+ },
+ {
+ "$ref": "#/components/parameters/VisualTagIDs"
+ },
+ {
+ "$ref": "#/components/parameters/SiteIDs"
+ },
+ {
+ "$ref": "#/components/parameters/WithSite"
+ },
+ {
+ "$ref": "#/components/parameters/SiteAreaIDs"
+ },
+ {
+ "$ref": "#/components/parameters/WithSiteArea"
+ },
+ {
+ "$ref": "#/components/parameters/WithCompany"
+ },
+ {
+ "$ref": "#/components/parameters/InactivityStatuses"
+ },
+ {
+ "$ref": "#/components/parameters/TransactionStatistics"
+ },
+ {
+ "$ref": "#/components/parameters/RefundStatus"
+ },
+ {
+ "in": "query",
+ "name": "MinimalPrice",
+ "description": "Transactions minimal price",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "ReportIDs",
+ "description": "Pipe separated report IDs",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "$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": "Transactions successfully exported",
+ "content": {
+ "text/csv": {
+ "example": "id,chargingStationID,connectorID,companyName,siteName,siteAreaName,userID,user,tagID,visualTagID,tagDescription,timezone,startDate,startTime,endDate,endTime,totalConsumptionkWh,totalDurationMins,totalInactivityMins,price,priceUnit\n1155141205,\"###\",1,,,,\"\",\"\",\"###\",\"###\",\"###\",\"Europe/Paris\",\"2021-07-07\",\"16:21:59\",\"2021-07-07\",\"16:22:27\",0,0.46,0.46,0,\"EUR\""
+ }
+ }
+ },
+ "401": {
+ "$ref": "#/components/responses/UnauthorizedError"
+ },
+ "403": {
+ "$ref": "#/components/responses/ForbiddenError"
+ },
+ "500": {
+ "$ref": "#/components/responses/BackendError"
+ }
+ }
+ }
+ },
"/api/charging-stations": {
"get": {
"security": [
diff --git a/src/assets/server/rest/v1/schemas/tag/imported-tag-create-req.json b/src/assets/server/rest/v1/schemas/tag/imported-tag-create-req.json
index 46de46266c..ab90e727a1 100644
--- a/src/assets/server/rest/v1/schemas/tag/imported-tag-create-req.json
+++ b/src/assets/server/rest/v1/schemas/tag/imported-tag-create-req.json
@@ -11,6 +11,32 @@
},
"visualID": {
"$ref": "tag.json#/definitions/visualID"
+ },
+ "siteIDs": {
+ "type": "string",
+ "sanitize": "mongo"
+ },
+ "importedData": {
+ "type": "object",
+ "properties": {
+ "autoActivateUserAtImport": {
+ "type": "boolean",
+ "sanitize": "mongo"
+ },
+ "autoActivateTagAtImport": {
+ "type": "boolean",
+ "sanitize": "mongo"
+ }
+ }
+ },
+ "email": {
+ "$ref": "user.json#/definitions/email"
+ },
+ "name": {
+ "$ref": "user.json#/definitions/name"
+ },
+ "firstName": {
+ "$ref": "user.json#/definitions/firstName"
}
},
"required": [
diff --git a/src/assets/server/rest/v1/schemas/tag/tags-get.json b/src/assets/server/rest/v1/schemas/tag/tags-get.json
index 2802ccef22..960d9e3757 100644
--- a/src/assets/server/rest/v1/schemas/tag/tags-get.json
+++ b/src/assets/server/rest/v1/schemas/tag/tags-get.json
@@ -30,6 +30,10 @@
},
"ProjectFields": {
"$ref": "common.json#/definitions/projectFields"
+ },
+ "WithUser": {
+ "type": "boolean",
+ "sanitize": "mongo"
}
},
"required": []
diff --git a/src/assets/server/rest/v1/schemas/user/imported-user-create-req.json b/src/assets/server/rest/v1/schemas/user/imported-user-create-req.json
index 6e0ea2e02e..fb72cbc65c 100644
--- a/src/assets/server/rest/v1/schemas/user/imported-user-create-req.json
+++ b/src/assets/server/rest/v1/schemas/user/imported-user-create-req.json
@@ -38,6 +38,19 @@
},
"notifications": {
"$ref": "user.json#/definitions/notifications"
+ },
+ "siteIDs": {
+ "type": "string",
+ "sanitize": "mongo"
+ },
+ "importedData": {
+ "type": "object",
+ "properties": {
+ "autoActivateUserAtImport": {
+ "type": "boolean",
+ "sanitize": "mongo"
+ }
+ }
}
},
"required": [
diff --git a/src/assets/server/rest/v1/schemas/user/users-get.json b/src/assets/server/rest/v1/schemas/user/users-get.json
index f7b8d43adb..cd1ef76412 100644
--- a/src/assets/server/rest/v1/schemas/user/users-get.json
+++ b/src/assets/server/rest/v1/schemas/user/users-get.json
@@ -6,10 +6,6 @@
"type": "boolean",
"sanitize": "mongo"
},
- "WithTag": {
- "type": "boolean",
- "sanitize": "mongo"
- },
"SiteID": {
"$ref": "common.json#/definitions/ids"
},
diff --git a/src/async-task/tasks/BillTransactionAsyncTask.ts b/src/async-task/tasks/BillTransactionAsyncTask.ts
index aec207b944..b60665af00 100644
--- a/src/async-task/tasks/BillTransactionAsyncTask.ts
+++ b/src/async-task/tasks/BillTransactionAsyncTask.ts
@@ -25,7 +25,7 @@ export default class BillTransactionAsyncTask extends AbstractAsyncTask {
const lock = await LockingHelper.acquireBillUserLock(tenant.id, userID);
if (lock) {
try {
- const transaction = await TransactionStorage.getTransaction(tenant.id, Number(transactionID), { withUser: true, withChargingStation: true });
+ const transaction = await TransactionStorage.getTransaction(tenant, Number(transactionID), { withUser: true, withChargingStation: true });
if (!transaction) {
throw new Error(`Unknown Transaction ID '${this.asyncTask.parameters.transactionID}'`);
}
@@ -43,7 +43,7 @@ export default class BillTransactionAsyncTask extends AbstractAsyncTask {
transaction.billingData.stop = billingDataStop;
transaction.billingData.lastUpdate = new Date();
// Save
- await TransactionStorage.saveTransactionBillingData(tenant.id, transaction.id, transaction.billingData);
+ await TransactionStorage.saveTransactionBillingData(tenant, transaction.id, transaction.billingData);
} finally {
// Release the lock
await LockingManager.release(lock);
diff --git a/src/async-task/tasks/ImportHelper.ts b/src/async-task/tasks/ImportHelper.ts
new file mode 100644
index 0000000000..b252618951
--- /dev/null
+++ b/src/async-task/tasks/ImportHelper.ts
@@ -0,0 +1,181 @@
+import Tag, { ImportedTag } from '../../types/Tag';
+import User, { ImportedUser, UserRole, UserStatus } from '../../types/User';
+
+import Constants from '../../utils/Constants';
+import Logging from '../../utils/Logging';
+import NotificationHandler from '../../notification/NotificationHandler';
+import { ServerAction } from '../../types/Server';
+import Site from '../../types/Site';
+import SiteStorage from '../../storage/mongodb/SiteStorage';
+import TagStorage from '../../storage/mongodb/TagStorage';
+import Tenant from '../../types/Tenant';
+import TenantComponents from '../../types/TenantComponents';
+import UserStorage from '../../storage/mongodb/UserStorage';
+import Utils from '../../utils/Utils';
+
+const MODULE_NAME = 'ImportHelper';
+
+export default class ImportHelper {
+ public async processImportedUser(tenant: Tenant, importedUser: ImportedUser, existingSites: Map): Promise {
+ // Get User
+ let user = await UserStorage.getUserByEmail(tenant, importedUser.email);
+ // If one found lets update it else create new User
+ if (user) {
+ await this.updateUser(tenant, user, importedUser);
+ } else {
+ user = await this.createUser(tenant, importedUser);
+ }
+ if (Utils.isTenantComponentActive(tenant, TenantComponents.ORGANIZATION) && importedUser.siteIDs) {
+ await this.processSiteAssignment(tenant, user, importedUser, existingSites);
+ }
+ return user;
+ }
+
+ public async processImportedTag(tenant: Tenant, importedTag: ImportedTag, existingSites: Map): Promise {
+ // Get Tag
+ let tag = await TagStorage.getTag(tenant.id, importedTag.id, { withNbrTransactions: true });
+ // Try to get Tag with Visual ID
+ if (!tag && importedTag.visualID) {
+ tag = await TagStorage.getTagByVisualID(tenant.id, importedTag.visualID, { withNbrTransactions: true });
+ }
+ // If one found lets update it else create new tag
+ if (tag) {
+ this.updateTag(tag, importedTag);
+ } else {
+ tag = this.createTag(importedTag);
+ }
+ // Save user if any and get the ID to assign current tag
+ if (importedTag.email && importedTag.name && importedTag.firstName) {
+ // Check & Import the User
+ const user = await this.processImportedUser(tenant, importedTag as ImportedUser, existingSites);
+ // Assign
+ tag.userID = user.id;
+ // Make this Tag default
+ await TagStorage.clearDefaultUserTag(tenant.id, user.id);
+ tag.default = true;
+ }
+ // Save the new Tag
+ await TagStorage.saveTag(tenant.id, tag);
+ return tag;
+ }
+
+ private updateTag(tag: Tag, importedTag: ImportedTag): void {
+ // Check tag is already in use
+ if (!tag.issuer) {
+ throw new Error('Tag is not local to the organization');
+ }
+ if (tag.userID) {
+ throw new Error('Tag is already assigned to a user');
+ }
+ if (tag.active) {
+ throw new Error('Tag is already active');
+ }
+ if (tag.transactionsCount > 0) {
+ throw new Error(`Tag is already used in ${tag.transactionsCount} transaction(s)`);
+ }
+ if (tag.id !== importedTag.id) {
+ throw new Error('Tag Visual ID is already assigned to another tag');
+ }
+ // Update
+ tag.visualID = importedTag.visualID;
+ tag.active = importedTag.importedData?.autoActivateTagAtImport;
+ tag.description = importedTag.description;
+ tag.importedData = importedTag.importedData;
+ }
+
+ private createTag(importedTag: ImportedTag): Tag {
+ // New Tag
+ return {
+ id: importedTag.id,
+ visualID: importedTag.visualID,
+ description: importedTag.description,
+ issuer: true,
+ active: importedTag.importedData?.autoActivateTagAtImport,
+ createdBy: { id: importedTag.importedBy },
+ createdOn: importedTag.importedOn,
+ importedData: importedTag.importedData
+ };
+ }
+
+ private async updateUser(tenant: Tenant, user: User, importedUser: ImportedUser): Promise {
+ // Check user is already in use
+ if (!user.issuer) {
+ throw new Error('User is not local to the organization');
+ }
+ // Update it
+ user.name = importedUser.name;
+ user.firstName = importedUser.firstName;
+ await UserStorage.saveUser(tenant, user);
+ }
+
+ private async createUser(tenant: Tenant, importedUser: ImportedUser): Promise {
+ // New User
+ const newUser = UserStorage.createNewUser() as User;
+ // Set
+ newUser.firstName = importedUser.firstName;
+ newUser.name = importedUser.name;
+ newUser.email = importedUser.email;
+ newUser.createdBy = { id: importedUser.importedBy };
+ newUser.createdOn = importedUser.importedOn;
+ newUser.importedData = importedUser.importedData;
+ // Save the new User
+ newUser.id = await UserStorage.saveUser(tenant, newUser);
+ await UserStorage.saveUserRole(tenant, newUser.id, UserRole.BASIC);
+ await UserStorage.saveUserStatus(tenant, newUser.id, UserStatus.PENDING);
+ await this.sendNotifications(tenant, newUser);
+ return newUser;
+ }
+
+ private async processSiteAssignment(tenant: Tenant, user: User, importedUser: ImportedUser, existingSites: Map): Promise {
+ // If we never got the sites from db -> construct array of existing sites
+ if (existingSites.size === 0) {
+ // Init Site collections
+ const sites = await SiteStorage.getSites(tenant, {}, Constants.DB_PARAMS_MAX_LIMIT, ['id', 'name']);
+ for (const site of sites.result) {
+ existingSites.set(site.id, site);
+ }
+ }
+ const importedSiteIDs = importedUser.siteIDs.split('|');
+ for (const importedSiteID of importedSiteIDs) {
+ const existingSite = existingSites.get(importedSiteID);
+ if (existingSite) {
+ // Assign Site
+ await UserStorage.addSiteToUser(tenant, user.id, importedSiteID);
+ } else {
+ // Site does not exist
+ await Logging.logError({
+ tenantID: tenant.id,
+ action: ServerAction.USERS_IMPORT,
+ module: MODULE_NAME, method: 'executeAsyncTask',
+ user,
+ message: `Site ID '${importedSiteID}' does not exist`
+ });
+ }
+ }
+ }
+
+ private async sendNotifications(tenant: Tenant, user: User): Promise {
+ // Handle sending email for reseting password if user auto activated
+ // Init Password info
+ const resetHash = Utils.generateUUID();
+ await UserStorage.saveUserPassword(tenant, user.id, { passwordResetHash: resetHash });
+ // Generate new verificationToken
+ const verificationToken = Utils.generateToken(user.email);
+ // Save User Verification Account
+ await UserStorage.saveUserAccountVerification(tenant, user.id, { verificationToken });
+ // Build account verif email with reset password embeded
+ const evseDashboardVerifyEmailURL = Utils.buildEvseURL(tenant.subdomain) +
+ '/verify-email?VerificationToken=' + verificationToken + '&Email=' + user.email + '&ResetToken=' + resetHash;
+ // Send activate account link
+ await NotificationHandler.sendVerificationEmailUserImport(
+ tenant.id,
+ Utils.generateUUID(),
+ user,
+ {
+ 'tenantName': tenant.name,
+ 'user': user,
+ 'evseDashboardURL': Utils.buildEvseURL(tenant.subdomain),
+ 'evseDashboardVerifyEmailURL': evseDashboardVerifyEmailURL
+ });
+ }
+}
diff --git a/src/async-task/tasks/TagsImportAsyncTask.ts b/src/async-task/tasks/TagsImportAsyncTask.ts
index 436112aa6e..fed19db83a 100644
--- a/src/async-task/tasks/TagsImportAsyncTask.ts
+++ b/src/async-task/tasks/TagsImportAsyncTask.ts
@@ -1,19 +1,19 @@
import { ActionsResponse, ImportStatus } from '../../types/GlobalType';
-import Tag, { ImportedTag } from '../../types/Tag';
-import User, { UserRole, UserStatus } from '../../types/User';
import AbstractAsyncTask from '../AsyncTask';
import Constants from '../../utils/Constants';
import { DataResult } from '../../types/DataResult';
import DbParams from '../../types/database/DbParams';
+import ImportHelper from './ImportHelper';
+import { ImportedTag } from '../../types/Tag';
import LockingHelper from '../../locking/LockingHelper';
import LockingManager from '../../locking/LockingManager';
import Logging from '../../utils/Logging';
import { ServerAction } from '../../types/Server';
+import Site from '../../types/Site';
+import SiteStorage from '../../storage/mongodb/SiteStorage';
import TagStorage from '../../storage/mongodb/TagStorage';
-import Tenant from '../../types/Tenant';
import TenantStorage from '../../storage/mongodb/TenantStorage';
-import UserStorage from '../../storage/mongodb/UserStorage';
import Utils from '../../utils/Utils';
const MODULE_NAME = 'TagsImportAsyncTask';
@@ -21,9 +21,18 @@ const MODULE_NAME = 'TagsImportAsyncTask';
export default class TagsImportAsyncTask extends AbstractAsyncTask {
protected async executeAsyncTask(): Promise {
const importTagsLock = await LockingHelper.acquireImportTagsLock(this.asyncTask.tenantID);
+ const importHelper = new ImportHelper();
+ const existingSites: Map = new Map();
if (importTagsLock) {
const tenant = await TenantStorage.getTenant(this.asyncTask.tenantID);
try {
+ // If we never got the sites from db -> construct array of existing sites
+ if (existingSites.size === 0) {
+ const sites = await SiteStorage.getSites(tenant, {}, Constants.DB_PARAMS_MAX_LIMIT, ['id', 'name']);
+ for (const site of sites.result) {
+ existingSites.set(site.id, site);
+ }
+ }
const dbParams: DbParams = { limit: Constants.IMPORT_PAGE_SIZE, skip: 0 };
let importedTags: DataResult;
const result: ActionsResponse = {
@@ -44,69 +53,28 @@ export default class TagsImportAsyncTask extends AbstractAsyncTask {
do {
// Get the imported tags
importedTags = await TagStorage.getImportedTags(tenant.id, { status: ImportStatus.READY }, dbParams);
- let tagToSave: Tag;
for (const importedTag of importedTags.result) {
try {
- // Existing tags
- let foundTag = await TagStorage.getTag(tenant.id, importedTag.id, { withNbrTransactions: true });
- foundTag = foundTag ? foundTag : await TagStorage.getTagByVisualID(tenant.id, importedTag.visualID);
- if (foundTag) {
- // Check tag is already in use
- if (!foundTag.issuer) {
- throw new Error('Tag is not local to the organization');
- }
- if (foundTag.userID) {
- throw new Error('Tag is already assigned to an user');
- }
- if (foundTag.active) {
- throw new Error('Tag is already active');
- }
- if (foundTag.transactionsCount > 0) {
- throw new Error(`Tag is already used in ${foundTag.transactionsCount} transaction(s)`);
- }
- if (foundTag.id !== importedTag.id) {
- throw new Error('Tag VisualID is already assigned to another tag');
- }
- tagToSave = { ...foundTag, ...importedTag };
- } else {
- // New Tag
- tagToSave = {
- id: importedTag.id,
- visualID: importedTag.visualID,
- description: importedTag.description,
- issuer: true,
- active: false,
- createdBy: { id: importedTag.importedBy },
- createdOn: importedTag.importedOn,
- };
- }
- // Save user if any and get the ID to assign tag
- if (importedTag.email && importedTag.name && importedTag.firstName) {
- await this.assignTag(tenant, importedTag, tagToSave);
- }
- // Save the new Tag
- await TagStorage.saveTag(tenant.id, tagToSave);
+ // Check & Import the Tag (+ User if present)
+ await importHelper.processImportedTag(tenant, importedTag, existingSites);
// Remove the imported Tag
await TagStorage.deleteImportedTag(tenant.id, importedTag.id);
result.inSuccess++;
} catch (error) {
- // Update the imported Tag
+ // Mark the imported Tag faulty with the reason
importedTag.status = ImportStatus.ERROR;
importedTag.errorDescription = error.message;
result.inError++;
- // Update it
await TagStorage.saveImportedTag(tenant.id, importedTag);
- // Log
await Logging.logError({
tenantID: tenant.id,
action: ServerAction.TAGS_IMPORT,
module: MODULE_NAME, method: 'processTenant',
- message: `Error when importing Tag ID '${importedTag.id}': ${error.message}`,
- detailedMessages: { tag: importedTag, error: error.stack }
+ message: `Cannot import Tag ID '${importedTag.id}': ${error.message}`,
+ detailedMessages: { importedTag, error: error.stack }
});
}
}
- // Log
if (!Utils.isEmptyArray(importedTags.result) && (result.inError + result.inSuccess) > 0) {
const intermediateDurationSecs = Math.round((new Date().getTime() - startTime) / 1000);
await Logging.logDebug({
@@ -134,27 +102,4 @@ export default class TagsImportAsyncTask extends AbstractAsyncTask {
}
}
}
-
- private async assignTag(tenant: Tenant, importedTag: ImportedTag, tag: Tag) {
- // Save user if any and get the ID to assign tag
- const foundUser = await UserStorage.getUserByEmail(tenant.id, importedTag.email);
- if (!foundUser) {
- const user = {
- name: importedTag.name,
- firstName: importedTag.firstName,
- email: importedTag.email,
- createdBy: { id: importedTag.importedBy },
- createdOn: Utils.convertToDate(importedTag.importedOn),
- issuer: true,
- status: UserStatus.PENDING,
- role: UserRole.BASIC,
- } as User;
- const userID = await UserStorage.saveUser(tenant.id, user);
- await UserStorage.saveUserStatus(tenant.id, userID, user.status);
- await UserStorage.saveUserRole(tenant.id, userID, user.role);
- tag.userID = userID;
- } else {
- tag.userID = foundUser.id;
- }
- }
}
diff --git a/src/async-task/tasks/UsersImportAsyncTask.ts b/src/async-task/tasks/UsersImportAsyncTask.ts
index 761f83603e..e2bde7c551 100644
--- a/src/async-task/tasks/UsersImportAsyncTask.ts
+++ b/src/async-task/tasks/UsersImportAsyncTask.ts
@@ -1,14 +1,17 @@
import { ActionsResponse, ImportStatus } from '../../types/GlobalType';
-import User, { ImportedUser, UserRole, UserStatus } from '../../types/User';
import AbstractAsyncTask from '../AsyncTask';
import Constants from '../../utils/Constants';
import { DataResult } from '../../types/DataResult';
import DbParams from '../../types/database/DbParams';
+import ImportHelper from './ImportHelper';
+import { ImportedUser } from '../../types/User';
import LockingHelper from '../../locking/LockingHelper';
import LockingManager from '../../locking/LockingManager';
import Logging from '../../utils/Logging';
import { ServerAction } from '../../types/Server';
+import Site from '../../types/Site';
+import SiteStorage from '../../storage/mongodb/SiteStorage';
import TenantStorage from '../../storage/mongodb/TenantStorage';
import UserStorage from '../../storage/mongodb/UserStorage';
import Utils from '../../utils/Utils';
@@ -18,9 +21,17 @@ const MODULE_NAME = 'UsersImportAsyncTask';
export default class UsersImportAsyncTask extends AbstractAsyncTask {
protected async executeAsyncTask(): Promise {
const importUsersLock = await LockingHelper.acquireImportUsersLock(this.asyncTask.tenantID);
+ const importHelper = new ImportHelper();
+ const existingSites: Map = new Map();
if (importUsersLock) {
const tenant = await TenantStorage.getTenant(this.asyncTask.tenantID);
try {
+ if (existingSites.size === 0) {
+ const sites = await SiteStorage.getSites(tenant, {}, Constants.DB_PARAMS_MAX_LIMIT, ['id', 'name']);
+ for (const site of sites.result) {
+ existingSites.set(site.id, site);
+ }
+ }
const dbParams: DbParams = { limit: Constants.IMPORT_PAGE_SIZE, skip: 0 };
let importedUsers: DataResult;
const result: ActionsResponse = {
@@ -29,7 +40,7 @@ export default class UsersImportAsyncTask extends AbstractAsyncTask {
};
const startTime = new Date().getTime();
// Get total number of Users to import
- const totalUsersToImport = await UserStorage.getImportedUsersCount(tenant.id);
+ const totalUsersToImport = await UserStorage.getImportedUsersCount(tenant);
if (totalUsersToImport > 0) {
await Logging.logInfo({
tenantID: tenant.id,
@@ -40,62 +51,30 @@ export default class UsersImportAsyncTask extends AbstractAsyncTask {
}
do {
// Get the imported users
- importedUsers = await UserStorage.getImportedUsers(tenant.id, { status: ImportStatus.READY }, dbParams);
+ importedUsers = await UserStorage.getImportedUsers(tenant, { status: ImportStatus.READY }, dbParams);
for (const importedUser of importedUsers.result) {
try {
- // Existing Users
- const foundUser = await UserStorage.getUserByEmail(tenant.id, importedUser.email);
- if (foundUser) {
- // Check tag is already in use
- if (!foundUser.issuer) {
- throw new Error('User is not local to the organization');
- }
- if (foundUser.status !== UserStatus.PENDING) {
- throw new Error('User account is already in use');
- }
- // Update it
- foundUser.name = importedUser.name;
- foundUser.firstName = importedUser.firstName;
- await UserStorage.saveUser(tenant.id, foundUser);
- // Remove the imported User
- await UserStorage.deleteImportedUser(tenant.id, importedUser.id);
- result.inSuccess++;
- continue;
- }
- // New User
- const newUser = UserStorage.createNewUser() as User;
- // Set
- newUser.firstName = importedUser.firstName;
- newUser.name = importedUser.name;
- newUser.email = importedUser.email;
- newUser.createdBy = { id: importedUser.importedBy };
- newUser.createdOn = importedUser.importedOn;
- // Save the new User
- newUser.id = await UserStorage.saveUser(tenant.id, newUser);
- // Role need to be set separately
- await UserStorage.saveUserRole(tenant.id, newUser.id, UserRole.BASIC);
- // Status need to be set separately
- await UserStorage.saveUserStatus(tenant.id, newUser.id, UserStatus.PENDING);
- // Remove the imported User
- await UserStorage.deleteImportedUser(tenant.id, importedUser.id);
+ // Check & Import the User
+ await importHelper.processImportedUser(tenant, importedUser, existingSites);
+ // Remove the imported User either it's found or not
+ await UserStorage.deleteImportedUser(tenant, importedUser.id);
result.inSuccess++;
} catch (error) {
+ // Mark the imported User faulty with the reason
importedUser.status = ImportStatus.ERROR;
importedUser.errorDescription = error.message;
result.inError++;
// Update it
- await UserStorage.saveImportedUser(tenant.id, importedUser);
- // Log
+ await UserStorage.saveImportedUser(tenant, importedUser);
await Logging.logError({
tenantID: tenant.id,
action: ServerAction.USERS_IMPORT,
- module: MODULE_NAME, method: 'processTenant',
- message: `Error when importing User with email '${importedUser.email}': ${error.message}`,
- detailedMessages: { user: importedUser, error: error.stack }
+ module: MODULE_NAME, method: 'executeAsyncTask',
+ message: `Cannot import User with email '${importedUser.email}': ${error.message}`,
+ detailedMessages: { importedUser, error: error.stack }
});
}
}
- // Log
if (importedUsers.result.length > 0 && (result.inError + result.inSuccess) > 0) {
const intermediateDurationSecs = Math.round((new Date().getTime() - startTime) / 1000);
await Logging.logDebug({
diff --git a/src/authorization/Authorizations.ts b/src/authorization/Authorizations.ts
index f24b27cce5..636d03a036 100644
--- a/src/authorization/Authorizations.ts
+++ b/src/authorization/Authorizations.ts
@@ -125,12 +125,12 @@ export default class Authorizations {
return requestedSites.filter((site) => sites.has(site));
}
- public static async buildUserToken(tenantID: string, user: User, tags: Tag[]): Promise {
+ public static async buildUserToken(tenant: Tenant, user: User, tags: Tag[]): Promise {
const siteIDs = [];
const siteAdminIDs = [];
const siteOwnerIDs = [];
// Get User's site
- const sites = (await UserStorage.getUserSites(tenantID, { userIDs: [user.id] },
+ const sites = (await UserStorage.getUserSites(tenant, { userIDs: [user.id] },
Constants.DB_PARAMS_MAX_LIMIT)).result;
for (const siteUser of sites) {
if (!Authorizations.isAdmin(user)) {
@@ -147,8 +147,7 @@ export default class Authorizations {
let activeComponents = [];
let tenantName;
let tenantSubdomain;
- if (tenantID !== Constants.DEFAULT_TENANT) {
- const tenant = await TenantStorage.getTenant(tenantID);
+ if (tenant.id !== Constants.DEFAULT_TENANT) {
tenantName = tenant.name;
tenantSubdomain = tenant.subdomain;
tenantHashID = SessionHashService.buildTenantHashID(tenant);
@@ -156,7 +155,7 @@ export default class Authorizations {
}
// Currency
let currency = null;
- const pricing = await SettingStorage.getPricingSettings(tenantID);
+ const pricing = await SettingStorage.getPricingSettings(tenant.id);
if (pricing && pricing.type === PricingSettingsType.SIMPLE) {
currency = pricing.simple.currency;
}
@@ -174,7 +173,7 @@ export default class Authorizations {
locale: user.locale,
language: Utils.getLanguageFromLocale(user.locale),
currency: currency,
- tenantID: tenantID,
+ tenantID: tenant.id,
tenantName: tenantName,
tenantSubdomain: tenantSubdomain,
userHashID: SessionHashService.buildUserHashID(user),
@@ -208,7 +207,7 @@ export default class Authorizations {
alternateUser = result.user;
alternateTag = result.tag;
// Get User and Tag that started the Transaction
- user = await UserStorage.getUserByTagId(tenant.id, transaction.tagID);
+ user = await UserStorage.getUserByTagId(tenant, transaction.tagID);
tag = await TagStorage.getTag(tenant.id, transaction.tagID);
} else {
// Check User
@@ -751,7 +750,7 @@ export default class Authorizations {
foundSiteArea = false;
} else if (!chargingStation.siteArea) {
chargingStation.siteArea = await SiteAreaStorage.getSiteArea(
- tenant.id, chargingStation.siteAreaID, { withSite: true });
+ tenant, chargingStation.siteAreaID, { withSite: true });
if (!chargingStation.siteArea) {
foundSiteArea = false;
}
@@ -790,7 +789,7 @@ export default class Authorizations {
// Access Control is disabled?
if (!chargingStation.siteArea.accessControl) {
// No ACL: Always try to get the user
- const user = await UserStorage.getUserByTagId(tenant.id, tagID);
+ const user = await UserStorage.getUserByTagId(tenant, tagID);
const tag = await TagStorage.getTag(tenant.id, tagID);
return { user, tag };
}
@@ -896,7 +895,7 @@ export default class Authorizations {
for (const authorization of authorizations.result) {
if (authorization.authorizationId) {
// Check Existing Transaction with the same Auth ID
- const ocpiTransaction = await TransactionStorage.getOCPITransactionByAuthorizationID(tenant.id, authorization.authorizationId);
+ const ocpiTransaction = await TransactionStorage.getOCPITransactionByAuthorizationID(tenant, authorization.authorizationId);
// OCPI Auth ID not used yet
if (!ocpiTransaction) {
authorizationID = authorization.authorizationId;
@@ -938,7 +937,7 @@ export default class Authorizations {
// Update Remote Authorizations
if (remoteAuthorizationsUpdated) {
await ChargingStationStorage.saveChargingStationRemoteAuthorizations(
- tenant.id, chargingStation.id, chargingStation.remoteAuthorizations);
+ tenant, chargingStation.id, chargingStation.remoteAuthorizations);
}
}
return authorizationID;
@@ -947,7 +946,7 @@ export default class Authorizations {
private static async checkAndGetAuthorizedUserFromTag(action: ServerAction, tenant: Tenant, chargingStation: ChargingStation,
transaction: Transaction, tag: Tag, authAction: Action): Promise {
// Get User
- const user = await UserStorage.getUser(tenant.id, tag.user.id);
+ const user = await UserStorage.getUser(tenant, tag.user.id);
// User status
if (user.status !== UserStatus.ACTIVE) {
throw new BackendError({
@@ -962,7 +961,7 @@ export default class Authorizations {
// Check Auth if local User
if (user.issuer && authAction) {
// Build the JWT Token
- const userToken = await Authorizations.buildUserToken(tenant.id, user, [tag]);
+ const userToken = await Authorizations.buildUserToken(tenant, user, [tag]);
// Authorized?
const context: AuthorizationContext = {
user: transaction ? transaction.userID : null,
@@ -1025,7 +1024,7 @@ export default class Authorizations {
if (Utils.isTenantComponentActive(tenant, TenantComponents.OICP)) {
// Check if user has remote authorization or the session is already running
if (tagID === OICPDefaultTagId.RemoteIdentification || transaction?.oicpData?.session?.id) {
- return UserStorage.getUserByEmail(tenant.id, Constants.OICP_VIRTUAL_USER_EMAIL);
+ return UserStorage.getUserByEmail(tenant, Constants.OICP_VIRTUAL_USER_EMAIL);
}
// Get the client
const oicpClient = await OICPClientFactory.getAvailableOicpClient(tenant, OICPRole.CPO) as CpoOICPClient;
@@ -1039,7 +1038,7 @@ export default class Authorizations {
// Check the Tag and retrieve the authorization
const response = await oicpClient.authorizeStart(tagID);
if (response?.AuthorizationStatus === OICPAuthorizationStatus.Authorized) {
- const virtualOICPUser = await UserStorage.getUserByEmail(tenant.id, Constants.OICP_VIRTUAL_USER_EMAIL);
+ const virtualOICPUser = await UserStorage.getUserByEmail(tenant, Constants.OICP_VIRTUAL_USER_EMAIL);
virtualOICPUser.authorizationID = response.SessionID;
return virtualOICPUser;
}
diff --git a/src/authorization/dynamic-data-source/SitesAdminDynamicAuthorizationDataSource.ts b/src/authorization/dynamic-data-source/SitesAdminDynamicAuthorizationDataSource.ts
index 86cc7586cd..7cc3af5610 100644
--- a/src/authorization/dynamic-data-source/SitesAdminDynamicAuthorizationDataSource.ts
+++ b/src/authorization/dynamic-data-source/SitesAdminDynamicAuthorizationDataSource.ts
@@ -21,7 +21,7 @@ export default class SitesAdminDynamicAuthorizationDataSource
private async getSitesAdminSiteIDs(): Promise {
// Get the Site IDs of the Sites for which the user is Site Admin
- const sites = await UserStorage.getUserSites(this.tenant.id,
+ const sites = await UserStorage.getUserSites(this.tenant,
{
userIDs: [this.userToken.id],
siteAdmin: true
diff --git a/src/authorization/dynamic-data-source/SitesOwnerDynamicAuthorizationDataSource.ts b/src/authorization/dynamic-data-source/SitesOwnerDynamicAuthorizationDataSource.ts
index 3e903ce5fa..085b0e683c 100644
--- a/src/authorization/dynamic-data-source/SitesOwnerDynamicAuthorizationDataSource.ts
+++ b/src/authorization/dynamic-data-source/SitesOwnerDynamicAuthorizationDataSource.ts
@@ -21,7 +21,7 @@ export default class SitesOwnerDynamicAuthorizationDataSource
private async getSitesOwnerSiteIDs(): Promise {
// Get the Site IDs of the Sites for which the user is Site Owner
- const sites = await UserStorage.getUserSites(this.tenant.id,
+ const sites = await UserStorage.getUserSites(this.tenant,
{
userIDs: [this.userToken.id],
siteOwner: true
diff --git a/src/client/ocpi/CpoOCPIClient.ts b/src/client/ocpi/CpoOCPIClient.ts
index a599a20d38..f3f41ce8d2 100644
--- a/src/client/ocpi/CpoOCPIClient.ts
+++ b/src/client/ocpi/CpoOCPIClient.ts
@@ -121,7 +121,7 @@ export default class CpoOCPIClient extends OCPIClient {
let emspUser = emspUsers.get(email);
if (!emspUser) {
// Get User from DB
- emspUser = await UserStorage.getUserByEmail(this.tenant.id, email);
+ emspUser = await UserStorage.getUserByEmail(this.tenant, email);
if (emspUser) {
emspUsers.set(email, emspUser);
}
@@ -488,7 +488,7 @@ export default class CpoOCPIClient extends OCPIClient {
};
// Perfs trace
const startTime = new Date().getTime();
- const transactions = await TransactionStorage.getTransactions(this.tenant.id, {
+ const transactions = await TransactionStorage.getTransactions(this.tenant, {
issuer: true,
ocpiSessionChecked: false
}, Constants.DB_PARAMS_MAX_LIMIT);
@@ -588,7 +588,7 @@ export default class CpoOCPIClient extends OCPIClient {
};
// Perfs trace
const startTime = new Date().getTime();
- const transactions = await TransactionStorage.getTransactions(this.tenant.id, {
+ const transactions = await TransactionStorage.getTransactions(this.tenant, {
issuer: true,
ocpiCdrChecked: false
}, Constants.DB_PARAMS_MAX_LIMIT);
@@ -813,7 +813,7 @@ export default class CpoOCPIClient extends OCPIClient {
}
// Mark it as done (checked at least once)
transaction.ocpiData.cdrCheckedOn = new Date();
- await TransactionStorage.saveTransactionOcpiData(this.tenant.id, transaction.id, transaction.ocpiData);
+ await TransactionStorage.saveTransactionOcpiData(this.tenant, transaction.id, transaction.ocpiData);
// Check CDR
const cdrsUrl = this.getEndpointUrl('cdrs', ServerAction.OCPI_CHECK_CDRS);
const response = await this.axiosInstance.get(
@@ -880,7 +880,7 @@ export default class CpoOCPIClient extends OCPIClient {
}
// Mark it as done (checked at least once)
transaction.ocpiData.sessionCheckedOn = new Date();
- await TransactionStorage.saveTransactionOcpiData(this.tenant.id, transaction.id, transaction.ocpiData);
+ await TransactionStorage.saveTransactionOcpiData(this.tenant, transaction.id, transaction.ocpiData);
// Check Session
const sessionsUrl = `${this.getEndpointUrl('sessions', ServerAction.OCPI_CHECK_SESSIONS)}/${this.getLocalCountryCode(ServerAction.OCPI_CHECK_SESSIONS)}/${this.getLocalPartyID(ServerAction.OCPI_CHECK_SESSIONS)}/${transaction.ocpiData.session.id}`;
const response = await this.axiosInstance.get(
diff --git a/src/client/ocpi/EmspOCPIClient.ts b/src/client/ocpi/EmspOCPIClient.ts
index 665587892a..e7f5fabce9 100644
--- a/src/client/ocpi/EmspOCPIClient.ts
+++ b/src/client/ocpi/EmspOCPIClient.ts
@@ -345,7 +345,7 @@ export default class EmspOCPIClient extends OCPIClient {
}
const locationName = site.name + Constants.OCPI_SEPARATOR + location.id;
// Handle Site Area
- const siteAreas = await SiteAreaStorage.getSiteAreas(this.tenant.id,
+ const siteAreas = await SiteAreaStorage.getSiteAreas(this.tenant,
{ siteIDs: [site.id], name: locationName, issuer: false, withSite: true },
Constants.DB_PARAMS_SINGLE_RECORD);
let siteArea = !Utils.isEmptyArray(siteAreas.result) ? siteAreas.result[0] : null;
@@ -371,7 +371,7 @@ export default class EmspOCPIClient extends OCPIClient {
Utils.convertToFloat(location.coordinates.latitude)
];
}
- siteArea.id = await SiteAreaStorage.saveSiteArea(this.tenant.id, siteArea, false);
+ siteArea.id = await SiteAreaStorage.saveSiteArea(this.tenant, siteArea, false);
}
if (!Utils.isEmptyArray(location.evses)) {
for (const evse of location.evses) {
@@ -386,10 +386,10 @@ export default class EmspOCPIClient extends OCPIClient {
if (evse.status === OCPIEvseStatus.REMOVED) {
// Get existing charging station
const currentChargingStation = await ChargingStationStorage.getChargingStationByOcpiLocationUid(
- this.tenant.id, location.id, evse.uid, ['id']
+ this.tenant, location.id, evse.uid, ['id']
);
if (currentChargingStation) {
- await ChargingStationStorage.deleteChargingStation(this.tenant.id, currentChargingStation.id);
+ await ChargingStationStorage.deleteChargingStation(this.tenant, currentChargingStation.id);
await Logging.logDebug({
tenantID: this.tenant.id,
action: ServerAction.OCPI_PULL_LOCATIONS,
@@ -405,8 +405,8 @@ export default class EmspOCPIClient extends OCPIClient {
chargingStation.companyID = siteArea.site?.companyID;
chargingStation.siteID = siteArea.siteID;
chargingStation.siteAreaID = siteArea.id;
- await ChargingStationStorage.saveChargingStation(this.tenant.id, chargingStation);
- await ChargingStationStorage.saveChargingStationOcpiData(this.tenant.id, chargingStation.id, chargingStation.ocpiData);
+ await ChargingStationStorage.saveChargingStation(this.tenant, chargingStation);
+ await ChargingStationStorage.saveChargingStationOcpiData(this.tenant, chargingStation.id, chargingStation.ocpiData);
await Logging.logDebug({
tenantID: this.tenant.id,
action: ServerAction.OCPI_PULL_LOCATIONS,
@@ -508,7 +508,7 @@ export default class EmspOCPIClient extends OCPIClient {
const commandUrl = this.getEndpointUrl('commands', ServerAction.OCPI_START_SESSION) + '/' + OCPICommandType.STOP_SESSION;
const callbackUrl = this.getLocalEndpointUrl('commands') + '/' + OCPICommandType.STOP_SESSION;
// Get transaction
- const transaction = await TransactionStorage.getTransaction(this.tenant.id, transactionId);
+ const transaction = await TransactionStorage.getTransaction(this.tenant, transactionId);
if (!transaction) {
throw new BackendError({
action: ServerAction.OCPI_START_SESSION,
diff --git a/src/client/oicp/CpoOICPClient.ts b/src/client/oicp/CpoOICPClient.ts
index 24eae04e1d..7f2ec79e3f 100644
--- a/src/client/oicp/CpoOICPClient.ts
+++ b/src/client/oicp/CpoOICPClient.ts
@@ -209,7 +209,7 @@ export default class CpoOICPClient extends OICPClient {
let currentChargingStationSkip = 0;
do {
// Get all charging stations from tenant
- chargingStations = (await ChargingStationStorage.getChargingStations(this.tenant.id,
+ chargingStations = (await ChargingStationStorage.getChargingStations(this.tenant,
{ siteIDs: [site.id], public: true, withSiteArea: true }, { skip: currentChargingStationSkip, limit: Constants.DB_RECORD_COUNT_DEFAULT })).result;
if (!Utils.isEmptyArray(chargingStations)) {
// Convert (public) charging stations to OICP EVSEs
@@ -357,7 +357,7 @@ export default class CpoOICPClient extends OICPClient {
let currentChargingStationSkip = 0;
do {
// Get all charging stations from tenant
- chargingStations = (await ChargingStationStorage.getChargingStations(this.tenant.id,
+ chargingStations = (await ChargingStationStorage.getChargingStations(this.tenant,
{ siteIDs: [site.id], public: true, withSiteArea: true }, { skip: currentChargingStationSkip, limit: Constants.DB_RECORD_COUNT_DEFAULT })).result;
if (!Utils.isEmptyArray(chargingStations)) {
// Convert (public) charging stations to OICP EVSE Statuses
diff --git a/src/integration/asset/lacroix/LacroixAssetIntegration.ts b/src/integration/asset/lacroix/LacroixAssetIntegration.ts
index 171a9e627b..82845f470d 100644
--- a/src/integration/asset/lacroix/LacroixAssetIntegration.ts
+++ b/src/integration/asset/lacroix/LacroixAssetIntegration.ts
@@ -127,7 +127,7 @@ export default class LacroixAssetIntegration extends AssetIntegration {
- const newUsers = await UserStorage.getUsers(this.tenant.id,
+ const newUsers = await UserStorage.getUsers(this.tenant,
{
statuses: [UserStatus.ACTIVE],
notSynchronizedBillingData: true
@@ -450,7 +450,7 @@ export default abstract class BillingIntegration {
await Promise.all(billingInvoice.sessions.map(async (session) => {
const transactionID = session.transactionID;
try {
- const transaction = await TransactionStorage.getTransaction(this.tenant.id, Number(transactionID));
+ const transaction = await TransactionStorage.getTransaction(this.tenant, Number(transactionID));
// Update Billing Data
const stop: BillingDataTransactionStop = {
status: BillingStatus.UNBILLED,
@@ -464,7 +464,7 @@ export default abstract class BillingIntegration {
stop
};
// Save to clear billing data
- await TransactionStorage.saveTransactionBillingData(this.tenant.id, transaction.id, transaction.billingData);
+ await TransactionStorage.saveTransactionBillingData(this.tenant, transaction.id, transaction.billingData);
} catch (error) {
await Logging.logError({
tenantID: this.tenant.id,
@@ -507,7 +507,7 @@ export default abstract class BillingIntegration {
private async _getUsersWithTestBillingData(): Promise {
// Get the users where billingData.liveMode is set to false
- const users = await UserStorage.getUsers(this.tenant.id,
+ const users = await UserStorage.getUsers(this.tenant,
{
statuses: [UserStatus.ACTIVE],
withTestBillingData: true
@@ -529,7 +529,7 @@ export default abstract class BillingIntegration {
});
}
// Let's remove the billingData field
- await UserStorage.saveUserBillingData(this.tenant.id, user.id, null);
+ await UserStorage.saveUserBillingData(this.tenant, user.id, null);
}
private isInvoiceOutOfPeriodicOperationScope(invoice: BillingInvoice): boolean {
diff --git a/src/integration/billing/stripe/StripeBillingIntegration.ts b/src/integration/billing/stripe/StripeBillingIntegration.ts
index 4c5ddf35a7..2aa846d144 100644
--- a/src/integration/billing/stripe/StripeBillingIntegration.ts
+++ b/src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -185,7 +185,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
// Check Stripe
await this.checkConnection();
// Make sure to get fresh data
- user = await UserStorage.getUser(this.tenant.id, user.id);
+ user = await UserStorage.getUser(this.tenant, user.id);
const customerID: string = user?.billingData?.customerID;
// returns true when the customerID is properly set!
return !!customerID;
@@ -196,7 +196,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
await this.checkConnection();
// Make sure the billing data has been provided
if (!user.billingData) {
- user = await UserStorage.getUser(this.tenant.id, user.id);
+ user = await UserStorage.getUser(this.tenant, user.id);
}
// Retrieve the STRIPE customer (if any)
const customerID: string = user.billingData?.customerID;
@@ -322,7 +322,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
});
} else if (checkUserExists) {
// Let's make sure the userID is still valid
- const user = await UserStorage.getUser(this.tenant.id, userID);
+ const user = await UserStorage.getUser(this.tenant, userID);
if (!user) {
throw new BackendError({
message: `Unexpected situation - the e-Mobility user does not exist - ${userID}`,
@@ -455,13 +455,13 @@ export default class StripeBillingIntegration extends BillingIntegration {
await Promise.all(billingInvoice.sessions.map(async (session) => {
const transactionID = session.transactionID;
try {
- const transaction = await TransactionStorage.getTransaction(this.tenant.id, Number(transactionID));
+ const transaction = await TransactionStorage.getTransaction(this.tenant, Number(transactionID));
// Update Billing Data
transaction.billingData.stop.invoiceStatus = billingInvoice.status;
transaction.billingData.stop.invoiceNumber = billingInvoice.number;
transaction.billingData.lastUpdate = new Date();
// Save
- await TransactionStorage.saveTransactionBillingData(this.tenant.id, transaction.id, transaction.billingData);
+ await TransactionStorage.saveTransactionBillingData(this.tenant, transaction.id, transaction.billingData);
} catch (error) {
// Catch stripe errors and send the information back to the client
await Logging.logError({
@@ -1378,7 +1378,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
};
// Save the billing data
user.billingData = billingData;
- await UserStorage.saveUserBillingData(this.tenant.id, user.id, user.billingData);
+ await UserStorage.saveUserBillingData(this.tenant, user.id, user.billingData);
// Let's return the corresponding Billing User
return this.convertToBillingUser(customer, user);
}
@@ -1405,7 +1405,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
customer = await this.stripe.customers.update(customerID, updateParams);
// Let's update the Billing Data of our customer
user.billingData.lastChangedOn = new Date();
- await UserStorage.saveUserBillingData(this.tenant.id, user.id, user.billingData);
+ await UserStorage.saveUserBillingData(this.tenant, user.id, user.billingData);
// Let's return the corresponding Billing User
return this.convertToBillingUser(customer, user);
}
diff --git a/src/integration/charging-station-vendor/ChargingStationVendorIntegration.ts b/src/integration/charging-station-vendor/ChargingStationVendorIntegration.ts
index 1fa3609b3f..c53b9ba026 100644
--- a/src/integration/charging-station-vendor/ChargingStationVendorIntegration.ts
+++ b/src/integration/charging-station-vendor/ChargingStationVendorIntegration.ts
@@ -117,7 +117,7 @@ export default abstract class ChargingStationVendorIntegration {
// Set
connector.amperageLimit = limitAmpsPerConnector;
}
- await ChargingStationStorage.saveChargingStationConnectors(tenant.id, chargingStation.id, chargingStation.connectors);
+ await ChargingStationStorage.saveChargingStationConnectors(tenant, chargingStation.id, chargingStation.connectors);
}
return result;
}
@@ -146,7 +146,7 @@ export default abstract class ChargingStationVendorIntegration {
}
}
// Save
- await ChargingStationStorage.saveChargingStationConnectors(tenant.id, chargingStation.id, chargingStation.connectors);
+ await ChargingStationStorage.saveChargingStationConnectors(tenant, chargingStation.id, chargingStation.connectors);
}
}
}
@@ -392,7 +392,7 @@ export default abstract class ChargingStationVendorIntegration {
// Check first matching Charging Profile
if (chargingStation.capabilities?.supportChargingProfiles) {
// Get the current Charging Profiles
- const chargingProfiles = (await ChargingStationStorage.getChargingProfiles(tenant.id, {
+ const chargingProfiles = (await ChargingStationStorage.getChargingProfiles(tenant, {
chargingStationIDs: [chargingStation.id]
}, Constants.DB_PARAMS_MAX_LIMIT)).result;
// Check the TX Charging Profiles from the DB
diff --git a/src/integration/pricing/convergent-charging b/src/integration/pricing/convergent-charging
index 9a8285a718..da274a9fc0 160000
--- a/src/integration/pricing/convergent-charging
+++ b/src/integration/pricing/convergent-charging
@@ -1 +1 @@
-Subproject commit 9a8285a71850f61cb97052fb40f86d4a68d7e78b
+Subproject commit da274a9fc0589456a050e26fb745045dab4b461c
diff --git a/src/integration/refund/RefundIntegration.ts b/src/integration/refund/RefundIntegration.ts
index 59bfa947ef..7bd0cd6ae3 100644
--- a/src/integration/refund/RefundIntegration.ts
+++ b/src/integration/refund/RefundIntegration.ts
@@ -17,7 +17,7 @@ export default abstract class RefundIntegration {
public abstract canBeDeleted(transaction: Transaction): boolean;
- public abstract updateRefundStatus(id: string, transaction: Transaction): Promise;
+ public abstract updateRefundStatus(tenant: Tenant, transaction: Transaction): Promise;
public abstract createConnection(userID: string, data: unknown): Promise;
diff --git a/src/integration/refund/concur b/src/integration/refund/concur
index f27ef94664..353a264524 160000
--- a/src/integration/refund/concur
+++ b/src/integration/refund/concur
@@ -1 +1 @@
-Subproject commit f27ef94664d3c4e883b36707b74f8d4a8e177229
+Subproject commit 353a264524fd4136c9b83592ed23bb37d85e206a
diff --git a/src/integration/refund/dummy/DummyRefundIntegration.ts b/src/integration/refund/dummy/DummyRefundIntegration.ts
index 1ad26a4e15..e17da60463 100644
--- a/src/integration/refund/dummy/DummyRefundIntegration.ts
+++ b/src/integration/refund/dummy/DummyRefundIntegration.ts
@@ -19,7 +19,7 @@ export default class DummyRefundIntegration extends RefundIntegration {
+ public async updateRefundStatus(tenant: Tenant, transaction: Transaction): Promise {
return null;
}
diff --git a/src/integration/smart-charging/SmartChargingIntegration.ts b/src/integration/smart-charging/SmartChargingIntegration.ts
index e691eacb84..b62ae01a39 100644
--- a/src/integration/smart-charging/SmartChargingIntegration.ts
+++ b/src/integration/smart-charging/SmartChargingIntegration.ts
@@ -142,7 +142,7 @@ export default abstract class SmartChargingIntegration 0) {
return adminUsers.result;
@@ -443,6 +443,31 @@ export default class NotificationHandler {
}
}
+ static async sendVerificationEmailUserImport(tenantID: string, notificationID: string, user: User,
+ sourceData: VerificationEmailNotification): Promise {
+ if (tenantID !== Constants.DEFAULT_TENANT) {
+ // Get the Tenant
+ const tenant = await TenantStorage.getTenant(tenantID, { withLogo: true });
+ sourceData.tenantLogoURL = tenant.logo;
+ // For each Sources
+ for (const notificationSource of NotificationHandler.notificationSources) {
+ // Active?
+ if (notificationSource.enabled) {
+ try {
+ // Save
+ await NotificationHandler.saveNotification(
+ tenant, notificationSource.channel, notificationID, ServerAction.VERIFICATION_EMAIL_USER_IMPORT, { user });
+ // Send
+ await notificationSource.notificationTask.sendVerificationEmailUserImport(
+ sourceData, user, tenant, NotificationSeverity.INFO);
+ } catch (error) {
+ await Logging.logActionExceptionMessage(tenantID, ServerAction.VERIFICATION_EMAIL_USER_IMPORT, error);
+ }
+ }
+ }
+ }
+ }
+
public static async sendChargingStationStatusError(tenant: Tenant, notificationID: string, chargingStation: ChargingStation,
sourceData: ChargingStationStatusErrorNotification): Promise {
if (tenant.id !== Constants.DEFAULT_TENANT) {
diff --git a/src/notification/NotificationTask.ts b/src/notification/NotificationTask.ts
index c4f9cf260a..61b7d5b8dd 100644
--- a/src/notification/NotificationTask.ts
+++ b/src/notification/NotificationTask.ts
@@ -1,4 +1,4 @@
-import { AccountVerificationNotification, AdminAccountVerificationNotification, BillingInvoiceSynchronizationFailedNotification, BillingNewInvoiceNotification, BillingUserSynchronizationFailedNotification, CarCatalogSynchronizationFailedNotification, ChargingStationRegisteredNotification, ChargingStationStatusErrorNotification, ComputeAndApplyChargingProfilesFailedNotification, EndOfChargeNotification, EndOfSessionNotification, EndOfSignedSessionNotification, EndUserErrorNotification, NewRegisteredUserNotification, NotificationSeverity, OCPIPatchChargingStationsStatusesErrorNotification, OICPPatchChargingStationsErrorNotification, OICPPatchChargingStationsStatusesErrorNotification, OfflineChargingStationNotification, OptimalChargeReachedNotification, PreparingSessionNotStartedNotification, RequestPasswordNotification, SessionNotStartedNotification, SmtpErrorNotification, TransactionStartedNotification, UnknownUserBadgedNotification, UserAccountInactivityNotification, UserAccountStatusChangedNotification, VerificationEmailNotification } from '../types/UserNotifications';
+import { AccountVerificationNotification, AdminAccountVerificationNotification, BillingInvoiceSynchronizationFailedNotification, BillingNewInvoiceNotification, BillingUserSynchronizationFailedNotification, CarCatalogSynchronizationFailedNotification, ChargingStationRegisteredNotification, ChargingStationStatusErrorNotification, ComputeAndApplyChargingProfilesFailedNotification, EndOfChargeNotification, EndOfSessionNotification, EndOfSignedSessionNotification, EndUserErrorNotification, NewRegisteredUserNotification, NotificationSeverity, OCPIPatchChargingStationsStatusesErrorNotification, OICPPatchChargingStationsErrorNotification, OICPPatchChargingStationsStatusesErrorNotification, OfflineChargingStationNotification, OptimalChargeReachedNotification, PreparingSessionNotStartedNotification, RequestPasswordNotification, SessionNotStartedNotification, SmtpErrorNotification, TransactionStartedNotification, UnknownUserBadgedNotification, UserAccountInactivityNotification, UserAccountStatusChangedNotification, UserCreatePassword, VerificationEmailNotification } from '../types/UserNotifications';
import Tenant from '../types/Tenant';
import User from '../types/User';
@@ -36,4 +36,6 @@ export default interface NotificationTask {
sendBillingNewInvoiceOpen(data: BillingNewInvoiceNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise;
sendAccountVerificationNotification(data: AccountVerificationNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise;
sendAdminAccountVerificationNotification(data: AdminAccountVerificationNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise;
+ sendUserCreatePassword(data: UserCreatePassword, user: User, tenant: Tenant, severity: NotificationSeverity): Promise;
+ sendVerificationEmailUserImport(data: VerificationEmailNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise;
}
diff --git a/src/notification/email/EMailNotificationTask.ts b/src/notification/email/EMailNotificationTask.ts
index 8f334c6c7a..51b4f6740e 100644
--- a/src/notification/email/EMailNotificationTask.ts
+++ b/src/notification/email/EMailNotificationTask.ts
@@ -1,4 +1,4 @@
-import { AccountVerificationNotification, AdminAccountVerificationNotification, BillingInvoiceSynchronizationFailedNotification, BillingNewInvoiceNotification, BillingUserSynchronizationFailedNotification, CarCatalogSynchronizationFailedNotification, ChargingStationRegisteredNotification, ChargingStationStatusErrorNotification, ComputeAndApplyChargingProfilesFailedNotification, EmailNotificationMessage, EndOfChargeNotification, EndOfSessionNotification, EndOfSignedSessionNotification, EndUserErrorNotification, NewRegisteredUserNotification, NotificationSeverity, OCPIPatchChargingStationsStatusesErrorNotification, OICPPatchChargingStationsErrorNotification, OICPPatchChargingStationsStatusesErrorNotification, OfflineChargingStationNotification, OptimalChargeReachedNotification, PreparingSessionNotStartedNotification, RequestPasswordNotification, SessionNotStartedNotification, SmtpErrorNotification, TransactionStartedNotification, UnknownUserBadgedNotification, UserAccountInactivityNotification, UserAccountStatusChangedNotification, VerificationEmailNotification } from '../../types/UserNotifications';
+import { AccountVerificationNotification, AdminAccountVerificationNotification, BillingInvoiceSynchronizationFailedNotification, BillingNewInvoiceNotification, BillingUserSynchronizationFailedNotification, CarCatalogSynchronizationFailedNotification, ChargingStationRegisteredNotification, ChargingStationStatusErrorNotification, ComputeAndApplyChargingProfilesFailedNotification, EmailNotificationMessage, EndOfChargeNotification, EndOfSessionNotification, EndOfSignedSessionNotification, EndUserErrorNotification, NewRegisteredUserNotification, NotificationSeverity, OCPIPatchChargingStationsStatusesErrorNotification, OICPPatchChargingStationsErrorNotification, OICPPatchChargingStationsStatusesErrorNotification, OfflineChargingStationNotification, OptimalChargeReachedNotification, PreparingSessionNotStartedNotification, RequestPasswordNotification, SessionNotStartedNotification, SmtpErrorNotification, TransactionStartedNotification, UnknownUserBadgedNotification, UserAccountInactivityNotification, UserAccountStatusChangedNotification, UserCreatePassword, VerificationEmailNotification } from '../../types/UserNotifications';
import { Message, SMTPClient, SMTPError } from 'emailjs';
import BackendError from '../../exception/BackendError';
@@ -97,6 +97,10 @@ export default class EMailNotificationTask implements NotificationTask {
return this.prepareAndSendEmail('verification-email', data, user, tenant, severity);
}
+ public async sendVerificationEmailUserImport(data: VerificationEmailNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise {
+ return this.prepareAndSendEmail('verification-email-user-import', data, user, tenant, severity);
+ }
+
public async sendSmtpError(data: SmtpErrorNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise {
return this.prepareAndSendEmail('smtp-error', data, user, tenant, severity, true);
}
@@ -174,6 +178,10 @@ export default class EMailNotificationTask implements NotificationTask {
return this.prepareAndSendEmail('admin-account-verification-notification', data, user, tenant, severity);
}
+ public async sendUserCreatePassword(data: UserCreatePassword, user: User, tenant: Tenant, severity: NotificationSeverity): Promise {
+ return this.prepareAndSendEmail('user-create-password', data, user, tenant, severity);
+ }
+
private async sendEmail(email: EmailNotificationMessage, data: any, tenant: Tenant, user: User, severity: NotificationSeverity, useSmtpClientBackup = false): Promise {
// Email configuration sanity checks
if (!this.smtpMainClientInstance) {
diff --git a/src/notification/remote-push-notification/RemotePushNotificationTask.ts b/src/notification/remote-push-notification/RemotePushNotificationTask.ts
index acc3a70214..41253453a5 100644
--- a/src/notification/remote-push-notification/RemotePushNotificationTask.ts
+++ b/src/notification/remote-push-notification/RemotePushNotificationTask.ts
@@ -274,6 +274,11 @@ export default class RemotePushNotificationTask implements NotificationTask {
return Promise.resolve();
}
+ public async sendVerificationEmailUserImport(data: VerificationEmailNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise {
+ // Nothing to send
+ return Promise.resolve();
+ }
+
public async sendSmtpError(data: SmtpErrorNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise {
// Set the locale
const i18nManager = I18nManager.getInstanceForLocale(user.locale);
@@ -434,6 +439,11 @@ export default class RemotePushNotificationTask implements NotificationTask {
return Promise.resolve();
}
+ public async sendUserCreatePassword(): Promise {
+ // Nothing to send
+ return Promise.resolve();
+ }
+
private async sendRemotePushNotificationToUser(tenant: Tenant, notificationType: UserNotificationType,
title: string, body: string, user: User, data?: Record, severity?: NotificationSeverity): Promise {
// Checks
diff --git a/src/scheduler/tasks/CheckAndComputeSmartChargingTask.ts b/src/scheduler/tasks/CheckAndComputeSmartChargingTask.ts
index d9693d23fd..9e2e4674f7 100644
--- a/src/scheduler/tasks/CheckAndComputeSmartChargingTask.ts
+++ b/src/scheduler/tasks/CheckAndComputeSmartChargingTask.ts
@@ -17,7 +17,7 @@ export default class CheckAndComputeSmartChargingTask extends SchedulerTask {
if (Utils.isTenantComponentActive(tenant, TenantComponents.ORGANIZATION) &&
Utils.isTenantComponentActive(tenant, TenantComponents.SMART_CHARGING)) {
// Get all site areas
- const siteAreas = await SiteAreaStorage.getSiteAreas(tenant.id,
+ const siteAreas = await SiteAreaStorage.getSiteAreas(tenant,
{ smartCharging: true },
Constants.DB_PARAMS_MAX_LIMIT);
// Get Site Area
diff --git a/src/scheduler/tasks/CheckChargingStationTemplateTask.ts b/src/scheduler/tasks/CheckChargingStationTemplateTask.ts
index b84b849474..0074ed0efd 100644
--- a/src/scheduler/tasks/CheckChargingStationTemplateTask.ts
+++ b/src/scheduler/tasks/CheckChargingStationTemplateTask.ts
@@ -50,7 +50,7 @@ export default class CheckChargingStationTemplateTask extends SchedulerTask {
return;
}
// Get the charging stations
- const chargingStations = await ChargingStationStorage.getChargingStations(tenant.id, {
+ const chargingStations = await ChargingStationStorage.getChargingStations(tenant, {
issuer: true, withSiteArea: true
}, Constants.DB_PARAMS_MAX_LIMIT);
// Update
diff --git a/src/scheduler/tasks/CheckOfflineChargingStationsTask.ts b/src/scheduler/tasks/CheckOfflineChargingStationsTask.ts
index ca56c7eb8e..bf26df0346 100644
--- a/src/scheduler/tasks/CheckOfflineChargingStationsTask.ts
+++ b/src/scheduler/tasks/CheckOfflineChargingStationsTask.ts
@@ -24,10 +24,10 @@ export default class CheckOfflineChargingStationsTask extends SchedulerTask {
try {
// Compute the date some minutes ago
const offlineSince = moment().subtract(Configuration.getChargingStationConfig().maxLastSeenIntervalSecs, 'seconds').toDate();
- const chargingStations = await ChargingStationStorage.getChargingStations(tenant.id, {
+ const chargingStations = await ChargingStationStorage.getChargingStations(tenant, {
issuer: true, withSiteArea: true, offlineSince
}, Constants.DB_PARAMS_MAX_LIMIT);
- if (chargingStations.count > 0) {
+ if (!Utils.isEmptyArray(chargingStations.result)) {
for (let i = chargingStations.result.length - 1; i >= 0; i--) {
const chargingStation = chargingStations.result[i];
let ocppHeartbeatConfiguration: OCPPGetConfigurationCommandResult;
@@ -50,7 +50,7 @@ export default class CheckOfflineChargingStationsTask extends SchedulerTask {
detailedMessages: { ocppHeartbeatConfiguration }
});
// Update lastSeen
- await ChargingStationStorage.saveChargingStationLastSeen(tenant.id, chargingStation.id,
+ await ChargingStationStorage.saveChargingStationLastSeen(tenant, chargingStation.id,
{ lastSeen: new Date() }
);
// Remove charging station from notification
@@ -63,7 +63,7 @@ export default class CheckOfflineChargingStationsTask extends SchedulerTask {
}
// Notify users with the rest of the Charging Stations
if (chargingStations.result.length > 0) {
- const chargingStationIDs: string = chargingStations.result.map((chargingStation) => chargingStation.id).join(', ');
+ const chargingStationIDs = chargingStations.result.map((chargingStation) => chargingStation.id).join(', ');
// Send notification
await NotificationHandler.sendOfflineChargingStations(
tenant, {
diff --git a/src/scheduler/tasks/CheckPreparingSessionNotStartedTask.ts b/src/scheduler/tasks/CheckPreparingSessionNotStartedTask.ts
index 2ee13e9c3e..7852d9783e 100644
--- a/src/scheduler/tasks/CheckPreparingSessionNotStartedTask.ts
+++ b/src/scheduler/tasks/CheckPreparingSessionNotStartedTask.ts
@@ -21,7 +21,7 @@ export default class CheckPreparingSessionNotStartedTask extends SchedulerTask {
if (await LockingManager.acquire(sessionNotStartedLock)) {
try {
// Get Charging Stations
- const chargingStations = await ChargingStationStorage.getChargingStations(tenant.id, {
+ const chargingStations = await ChargingStationStorage.getChargingStations(tenant, {
'statusChangedBefore': moment().subtract(config.preparingStatusMaxMins, 'minutes').toDate(),
'connectorStatuses': [ChargePointStatus.PREPARING],
withSiteArea: true
diff --git a/src/scheduler/tasks/CheckSessionNotStartedAfterAuthorizeTask.ts b/src/scheduler/tasks/CheckSessionNotStartedAfterAuthorizeTask.ts
index 0dee9e0463..7bd32368a1 100644
--- a/src/scheduler/tasks/CheckSessionNotStartedAfterAuthorizeTask.ts
+++ b/src/scheduler/tasks/CheckSessionNotStartedAfterAuthorizeTask.ts
@@ -17,7 +17,7 @@ export default class CheckSessionNotStartedAfterAuthorizeTask extends SchedulerT
if (await LockingManager.acquire(sessionNotStartedLock)) {
try {
// Get notification
- const notificationTransactionNotStarted = await TransactionStorage.getNotStartedTransactions(tenant.id, {
+ const notificationTransactionNotStarted = await TransactionStorage.getNotStartedTransactions(tenant, {
'checkPastAuthorizeMins': config.checkPastAuthorizeMins,
'sessionShouldBeStartedAfterMins': config.sessionShouldBeStartedAfterMins
});
diff --git a/src/scheduler/tasks/CheckUserAccountInactivityTask.ts b/src/scheduler/tasks/CheckUserAccountInactivityTask.ts
index 701489d8bc..2586ccc54f 100644
--- a/src/scheduler/tasks/CheckUserAccountInactivityTask.ts
+++ b/src/scheduler/tasks/CheckUserAccountInactivityTask.ts
@@ -26,7 +26,7 @@ export default class CheckUserAccountInactivityTask extends SchedulerTask {
noLoginSince: someMonthsAgo
};
// Get Users
- const users = await UserStorage.getUsers(tenant.id, params, Constants.DB_PARAMS_MAX_LIMIT);
+ const users = await UserStorage.getUsers(tenant, params, Constants.DB_PARAMS_MAX_LIMIT);
for (const user of users.result) {
// Notification
moment.locale(user.locale);
diff --git a/src/scheduler/tasks/SynchronizeRefundTransactionsTask.ts b/src/scheduler/tasks/SynchronizeRefundTransactionsTask.ts
index 4cf580f993..e4205517ac 100644
--- a/src/scheduler/tasks/SynchronizeRefundTransactionsTask.ts
+++ b/src/scheduler/tasks/SynchronizeRefundTransactionsTask.ts
@@ -41,7 +41,7 @@ export default class SynchronizeRefundTransactionsTask extends SchedulerTask {
if (await LockingManager.acquire(refundLock)) {
try {
// Get the 'Submitted' transactions
- const transactions = await TransactionStorage.getTransactions(tenant.id,
+ const transactions = await TransactionStorage.getTransactions(tenant,
{ 'refundStatus': [RefundStatus.SUBMITTED] },
{ ...Constants.DB_PARAMS_MAX_LIMIT, sort: { 'userID': 1, 'refundData.reportId': 1 } });
// Check
@@ -62,7 +62,7 @@ export default class SynchronizeRefundTransactionsTask extends SchedulerTask {
for (const transaction of transactions.result) {
try {
// Update Transaction
- const updatedAction = await refundConnector.updateRefundStatus(tenant.id, transaction);
+ const updatedAction = await refundConnector.updateRefundStatus(tenant, transaction);
switch (updatedAction) {
case RefundStatus.CANCELLED:
actionsDone.cancelled++;
diff --git a/src/scheduler/tasks/ocpi/OCPIPushCdrsTask.ts b/src/scheduler/tasks/ocpi/OCPIPushCdrsTask.ts
index 700436bd01..2580b0b0c1 100644
--- a/src/scheduler/tasks/ocpi/OCPIPushCdrsTask.ts
+++ b/src/scheduler/tasks/ocpi/OCPIPushCdrsTask.ts
@@ -53,7 +53,7 @@ export default class OCPIPushCdrsTask extends SchedulerTask {
if (ocpiTransactionLock) {
try {
// Get Transaction
- const transaction = await TransactionStorage.getTransaction(tenant.id, transactionMDB._id, { withUser: true });
+ const transaction = await TransactionStorage.getTransaction(tenant, transactionMDB._id, { withUser: true });
if (!transaction) {
await Logging.logError({
tenantID: tenant.id,
@@ -73,7 +73,7 @@ export default class OCPIPushCdrsTask extends SchedulerTask {
continue;
}
// Get Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(tenant.id, transaction.chargeBoxID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(tenant, transaction.chargeBoxID);
if (!chargingStation) {
await Logging.logError({
tenantID: tenant.id,
@@ -97,7 +97,7 @@ export default class OCPIPushCdrsTask extends SchedulerTask {
// Roaming
await OCPPUtils.processTransactionRoaming(tenant, transaction, chargingStation, tag, TransactionAction.END);
// Save
- await TransactionStorage.saveTransactionOcpiData(tenant.id, transaction.id, transaction.ocpiData);
+ await TransactionStorage.saveTransactionOcpiData(tenant, transaction.id, transaction.ocpiData);
// Ok
await Logging.logInfo({
tenantID: tenant.id,
diff --git a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPIUtilsService.ts b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPIUtilsService.ts
index 25a9c39f9d..3fefec9e45 100644
--- a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPIUtilsService.ts
+++ b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPIUtilsService.ts
@@ -430,7 +430,7 @@ export default class OCPIUtilsService {
// Build evses array
const evses: OCPIEvse[] = [];
// Convert charging stations to evse(s)
- const chargingStations = await ChargingStationStorage.getChargingStations(tenant.id,
+ const chargingStations = await ChargingStationStorage.getChargingStations(tenant,
{ ...dbFilters, siteIDs: [ siteID ], public: true, issuer: true, withSiteArea: true },
dbParams ?? Constants.DB_PARAMS_MAX_LIMIT,
[ 'id', 'chargePoints', 'connectors', 'coordinates', 'lastSeen', 'siteAreaID', 'siteID' ]);
@@ -448,7 +448,7 @@ export default class OCPIUtilsService {
chargingStationEvses.push(...OCPIUtilsService.convertChargingStation2MultipleEvses(tenant, chargingStation, null, options));
}
// Always update OCPI data
- await ChargingStationStorage.saveChargingStationOcpiData(tenant.id, chargingStation.id, { evses: chargingStationEvses });
+ await ChargingStationStorage.saveChargingStationOcpiData(tenant, chargingStation.id, { evses: chargingStationEvses });
evses.push(...chargingStationEvses);
}
return evses;
@@ -481,9 +481,9 @@ export default class OCPIUtilsService {
if (!session.kwh) {
session.kwh = 0;
}
- let transaction: Transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant.id, session.id);
+ let transaction: Transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant, session.id);
if (!transaction) {
- const user = await UserStorage.getUser(tenant.id, session.auth_id);
+ const user = await UserStorage.getUser(tenant, session.auth_id);
if (!user) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -495,7 +495,7 @@ export default class OCPIUtilsService {
});
}
const evse = session.location.evses[0];
- const chargingStation = await ChargingStationStorage.getChargingStationByOcpiEvseID(tenant.id, evse.evse_id);
+ const chargingStation = await ChargingStationStorage.getChargingStationByOcpiEvseID(tenant, evse.evse_id);
if (!chargingStation) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -590,7 +590,7 @@ export default class OCPIUtilsService {
userID: transaction.userID
};
}
- await TransactionStorage.saveTransaction(tenant.id, transaction);
+ await TransactionStorage.saveTransaction(tenant, transaction);
await this.updateConnector(tenant, transaction);
}
@@ -605,7 +605,7 @@ export default class OCPIUtilsService {
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR
});
}
- const transaction: Transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant.id, cdr.id);
+ const transaction: Transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant, cdr.id);
if (!transaction) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -653,7 +653,7 @@ export default class OCPIUtilsService {
transaction.ocpiData = {};
}
transaction.ocpiData.cdr = cdr;
- await TransactionStorage.saveTransaction(tenant.id, transaction);
+ await TransactionStorage.saveTransaction(tenant, transaction);
await this.updateConnector(tenant, transaction);
}
@@ -729,9 +729,9 @@ export default class OCPIUtilsService {
locale: Utils.getLocaleFromLanguage(token.language),
} as User;
// Save User
- emspUser.id = await UserStorage.saveUser(tenant.id, emspUser);
- await UserStorage.saveUserRole(tenant.id, emspUser.id, UserRole.BASIC);
- await UserStorage.saveUserStatus(tenant.id, emspUser.id, UserStatus.ACTIVE);
+ emspUser.id = await UserStorage.saveUser(tenant, emspUser);
+ await UserStorage.saveUserRole(tenant, emspUser.id, UserRole.BASIC);
+ await UserStorage.saveUserStatus(tenant, emspUser.id, UserStatus.ACTIVE);
const tagToSave = {
id: token.uid,
issuer: false,
@@ -1061,7 +1061,7 @@ export default class OCPIUtilsService {
}
private static async updateConnector(tenant: Tenant, transaction: Transaction): Promise {
- const chargingStation = await ChargingStationStorage.getChargingStation(tenant.id, transaction.chargeBoxID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(tenant, transaction.chargeBoxID);
if (chargingStation && chargingStation.connectors) {
for (const connector of chargingStation.connectors) {
if (connector.connectorId === transaction.connectorId && connector.currentTransactionID === 0 || connector.currentTransactionID === transaction.id) {
@@ -1086,7 +1086,7 @@ export default class OCPIUtilsService {
connector.currentInstantWatts = 0;
connector.currentInactivityStatus = null;
}
- await ChargingStationStorage.saveChargingStationConnectors(tenant.id, chargingStation.id, chargingStation.connectors);
+ await ChargingStationStorage.saveChargingStationConnectors(tenant, chargingStation.id, chargingStation.connectors);
}
}
}
diff --git a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOCdrsEndpoint.ts b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOCdrsEndpoint.ts
index 9d45eadb54..3c1d08e916 100644
--- a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOCdrsEndpoint.ts
+++ b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOCdrsEndpoint.ts
@@ -48,7 +48,7 @@ export default class CPOCdrsEndpoint extends AbstractEndpoint {
private async getAllCdrs(tenant: Tenant, limit: number, skip: number, dateFrom?: Date, dateTo?: Date): Promise> {
// Get all transactions
- const transactions = await TransactionStorage.getTransactions(tenant.id,
+ const transactions = await TransactionStorage.getTransactions(tenant,
{ issuer: true, ocpiCdrDateFrom: dateFrom, ocpiCdrDateTo: dateTo, ocpiCdrChecked: true },
{ limit, skip }, ['ocpiData']
);
diff --git a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOCommandsEndpoint.ts b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOCommandsEndpoint.ts
index 0b321eec95..f184e8b3f4 100644
--- a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOCommandsEndpoint.ts
+++ b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOCommandsEndpoint.ts
@@ -108,7 +108,7 @@ export default class CPOCommandsEndpoint extends AbstractEndpoint {
}
// Get the Charging Station
const chargingStation = await ChargingStationStorage.getChargingStationByOcpiLocationUid(
- tenant.id, startSession.location_id, startSession.evse_uid);
+ tenant, startSession.location_id, startSession.evse_uid);
if (!chargingStation) {
await Logging.logError({
tenantID: tenant.id,
@@ -188,7 +188,7 @@ export default class CPOCommandsEndpoint extends AbstractEndpoint {
}
// Save Auth
await ChargingStationStorage.saveChargingStationRemoteAuthorizations(
- tenant.id, chargingStation.id, chargingStation.remoteAuthorizations);
+ tenant, chargingStation.id, chargingStation.remoteAuthorizations);
// Called Async as the response to the eMSP is sent asynchronously and this request has to finish before the command returns
void this.remoteStartTransaction(tenant, chargingStation, connector, startSession, ocpiEndpoint).catch(() => { });
// Ok
@@ -208,7 +208,7 @@ export default class CPOCommandsEndpoint extends AbstractEndpoint {
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR
});
}
- const transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant.id, stopSession.session_id);
+ const transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant, stopSession.session_id);
if (!transaction) {
await Logging.logError({
tenantID: tenant.id,
@@ -241,7 +241,7 @@ export default class CPOCommandsEndpoint extends AbstractEndpoint {
});
return this.buildOCPIResponse(OCPICommandResponseType.REJECTED);
}
- const chargingStation = await ChargingStationStorage.getChargingStation(tenant.id, transaction.chargeBoxID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(tenant, transaction.chargeBoxID);
if (!chargingStation) {
await Logging.logError({
tenantID: tenant.id,
diff --git a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOSessionsEndpoint.ts b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOSessionsEndpoint.ts
index 495deb457d..99efaf8494 100644
--- a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOSessionsEndpoint.ts
+++ b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/cpo/CPOSessionsEndpoint.ts
@@ -72,7 +72,7 @@ export default class CPOSessionsEndpoint extends AbstractEndpoint {
// Result
const sessions: OCPISession[] = [];
// Get all transactions
- const transactions = await TransactionStorage.getTransactions(tenant.id,
+ const transactions = await TransactionStorage.getTransactions(tenant,
{ issuer: true, ocpiSessionDateFrom: dateFrom, ocpiSessionDateTo: dateTo },
{ limit, skip }, ['ocpiData']);
for (const transaction of transactions.result) {
diff --git a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPCdrsEndpoint.ts b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPCdrsEndpoint.ts
index 73e38090cb..685df31431 100644
--- a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPCdrsEndpoint.ts
+++ b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPCdrsEndpoint.ts
@@ -48,7 +48,7 @@ export default class EMSPCdrsEndpoint extends AbstractEndpoint {
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR
});
}
- const transaction: Transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant.id, id);
+ const transaction: Transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant, id);
if (!transaction) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
diff --git a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPLocationsEndpoint.ts b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPLocationsEndpoint.ts
index 16668f736b..c0152bb9e0 100644
--- a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPLocationsEndpoint.ts
+++ b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPLocationsEndpoint.ts
@@ -74,7 +74,7 @@ export default class EMSPLocationsEndpoint extends AbstractEndpoint {
}
if (evseUID) {
const chargingStation = await ChargingStationStorage.getChargingStationByOcpiLocationUid(
- tenant.id, locationID, evseUID);
+ tenant, locationID, evseUID);
if (!chargingStation) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -223,7 +223,7 @@ export default class EMSPLocationsEndpoint extends AbstractEndpoint {
(chargingStationEvse) => chargingStationEvse.uid === chargingStationEvse.uid);
if (evse.status) {
if (evse.status === OCPIEvseStatus.REMOVED) {
- await ChargingStationStorage.deleteChargingStation(tenant.id, chargingStation.id);
+ await ChargingStationStorage.deleteChargingStation(tenant, chargingStation.id);
return;
}
foundChargingStationEvse.status = evse.status;
@@ -260,7 +260,7 @@ export default class EMSPLocationsEndpoint extends AbstractEndpoint {
chargingStation.connectors = patchedChargingStation.connectors;
chargingStation.maximumPower = patchedChargingStation.maximumPower;
}
- await ChargingStationStorage.saveChargingStation(tenant.id, chargingStation);
+ await ChargingStationStorage.saveChargingStation(tenant, chargingStation);
}
private async patchEvseConnector(tenant: Tenant, chargingStation: ChargingStation, ocpiConnector: Partial) {
@@ -289,16 +289,16 @@ export default class EMSPLocationsEndpoint extends AbstractEndpoint {
if (ocpiConnector.standard) {
foundConnector.type = OCPIUtilsService.convertOCPIConnectorType2ConnectorType(ocpiConnector.standard);
}
- await ChargingStationStorage.saveChargingStationConnectors(tenant.id, chargingStation.id, chargingStation.connectors);
+ await ChargingStationStorage.saveChargingStationConnectors(tenant, chargingStation.id, chargingStation.connectors);
}
private async updateEvse(tenant: Tenant, evse: OCPIEvse, location: OCPILocation) {
if (evse.status === OCPIEvseStatus.REMOVED) {
const chargingStation = await ChargingStationStorage.getChargingStationByOcpiLocationUid(
- tenant.id, location.id, evse.uid);
+ tenant, location.id, evse.uid);
if (chargingStation) {
// Delete
- await ChargingStationStorage.deleteChargingStation(tenant.id, chargingStation.id);
+ await ChargingStationStorage.deleteChargingStation(tenant, chargingStation.id);
await Logging.logInfo({
tenantID: tenant.id,
action: ServerAction.OCPI_PATCH_LOCATION,
@@ -311,7 +311,7 @@ export default class EMSPLocationsEndpoint extends AbstractEndpoint {
} else {
// Create/Update
const chargingStation = OCPIUtilsService.convertEvseToChargingStation(evse, location);
- await ChargingStationStorage.saveChargingStation(tenant.id, chargingStation);
+ await ChargingStationStorage.saveChargingStation(tenant, chargingStation);
await Logging.logDebug({
tenantID: tenant.id,
action: ServerAction.OCPI_PATCH_LOCATION,
@@ -325,7 +325,7 @@ export default class EMSPLocationsEndpoint extends AbstractEndpoint {
private async updateConnector(tenant: Tenant, evse: OCPIEvse, evseConnector: OCPIConnector, location: OCPILocation) {
const chargingStation = await ChargingStationStorage.getChargingStationByOcpiLocationUid(
- tenant.id, location.id, evse.uid);
+ tenant, location.id, evse.uid);
if (!chargingStation) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -359,7 +359,7 @@ export default class EMSPLocationsEndpoint extends AbstractEndpoint {
type: OCPIUtilsService.convertOCPIConnectorType2ConnectorType(evseConnector.standard),
});
}
- await ChargingStationStorage.saveChargingStationConnectors(tenant.id, chargingStation.id, chargingStation.connectors);
+ await ChargingStationStorage.saveChargingStationConnectors(tenant, chargingStation.id, chargingStation.connectors);
}
}
diff --git a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPSessionsEndpoint.ts b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPSessionsEndpoint.ts
index 54aaa4e16e..80a4afd6a4 100644
--- a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPSessionsEndpoint.ts
+++ b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPSessionsEndpoint.ts
@@ -53,7 +53,7 @@ export default class EMSPSessionsEndpoint extends AbstractEndpoint {
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR
});
}
- const transaction: Transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant.id, sessionId);
+ const transaction: Transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant, sessionId);
if (!transaction) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -120,7 +120,7 @@ export default class EMSPSessionsEndpoint extends AbstractEndpoint {
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR
});
}
- const transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant.id, sessionId);
+ const transaction = await TransactionStorage.getOCPITransactionBySessionID(tenant, sessionId);
if (!transaction) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
diff --git a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPTokensEndpoint.ts b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPTokensEndpoint.ts
index 9fc263926a..c58dfba5de 100644
--- a/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPTokensEndpoint.ts
+++ b/src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPTokensEndpoint.ts
@@ -104,7 +104,7 @@ export default class EMSPTokensEndpoint extends AbstractEndpoint {
});
}
const chargingStation = await ChargingStationStorage.getChargingStationByOcpiEvseID(
- tenant.id, locationReference.evse_uids[0]);
+ tenant, locationReference.evse_uids[0]);
if (!chargingStation) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
diff --git a/src/server/ocpp/json/JsonRestWSConnection.ts b/src/server/ocpp/json/JsonRestWSConnection.ts
index d985d9dcae..be96274d83 100644
--- a/src/server/ocpp/json/JsonRestWSConnection.ts
+++ b/src/server/ocpp/json/JsonRestWSConnection.ts
@@ -62,7 +62,7 @@ export default class JsonRestWSConnection extends WSConnection {
public async handleRequest(messageId: string, commandName: ServerAction, commandPayload: Record | string): Promise {
// Get the Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(this.getTenantID(), this.getChargingStationID());
+ const chargingStation = await ChargingStationStorage.getChargingStation(this.getTenant(), this.getChargingStationID());
if (!chargingStation) {
throw new BackendError({
source: this.getChargingStationID(),
diff --git a/src/server/ocpp/json/JsonWSConnection.ts b/src/server/ocpp/json/JsonWSConnection.ts
index 0dfd293cf5..85a40fec86 100644
--- a/src/server/ocpp/json/JsonWSConnection.ts
+++ b/src/server/ocpp/json/JsonWSConnection.ts
@@ -31,6 +31,7 @@ export default class JsonWSConnection extends WSConnection {
constructor(wsConnection: WebSocket, req: http.IncomingMessage, wsServer: JsonCentralSystemServer) {
// Call super
super(wsConnection, req, wsServer);
+ let backendError: BackendError;
// Check Protocol (required field of OCPP spec)
switch (wsConnection.protocol) {
// OCPP 1.6?
@@ -42,13 +43,22 @@ export default class JsonWSConnection extends WSConnection {
break;
// Not Found
default:
- // Error
- throw new BackendError({
+ backendError = new BackendError({
source: this.getChargingStationID(),
module: MODULE_NAME,
method: 'constructor',
- message: `Protocol ${wsConnection.protocol} not supported`
+ message: wsConnection.protocol ?
+ `Web Socket Protocol '${wsConnection.protocol}' not supported` : 'Web Socket Protocol is mandatory'
});
+ // Log in the right Tenants
+ void Logging.logException(
+ backendError,
+ ServerAction.WS_JSON_CONNECTION_ERROR,
+ this.getChargingStationID(),
+ MODULE_NAME, 'constructor',
+ this.getTenantID()
+ );
+ throw backendError;
}
this.isConnectionAlive = true;
// Handle Socket ping
@@ -75,15 +85,15 @@ export default class JsonWSConnection extends WSConnection {
}
};
// Update the Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(this.getTenantID(), this.getChargingStationID(), {}, ['id']);
+ const chargingStation = await ChargingStationStorage.getChargingStation(this.getTenant(), this.getChargingStationID(), {}, ['id']);
if (chargingStation) {
// Update Last Seen
- await ChargingStationStorage.saveChargingStationLastSeen(this.getTenantID(),
+ await ChargingStationStorage.saveChargingStationLastSeen(this.getTenant(),
chargingStation.id, { lastSeen: new Date() });
// Update CF Instance
if (Configuration.isCloudFoundry()) {
await ChargingStationStorage.saveChargingStationCFApplicationIDAndInstanceIndex(
- this.getTenantID(), chargingStation.id, Configuration.getCFApplicationIDAndInstanceIndex());
+ this.getTenant(), chargingStation.id, Configuration.getCFApplicationIDAndInstanceIndex());
}
// Must have a valid Token
} else {
@@ -148,7 +158,7 @@ export default class JsonWSConnection extends WSConnection {
}
public async handleRequest(messageId: string, commandName: ServerAction, commandPayload: Record | string): Promise {
- await Logging.logChargingStationServerReceiveAction(MODULE_NAME, this.getTenantID(), this.getChargingStationID(), commandName, commandPayload);
+ await Logging.logChargingStationServerReceiveAction(Constants.MODULE_JSON_OCPP_SERVER_16, this.getTenantID(), this.getChargingStationID(), commandName, commandPayload);
const methodName = `handle${commandName}`;
// Check if method exist in the service
if (typeof this.chargingStationService[methodName] === 'function') {
@@ -158,7 +168,7 @@ export default class JsonWSConnection extends WSConnection {
// Call it
const result = await this.chargingStationService[methodName](this.headers, commandPayload);
// Log
- await Logging.logChargingStationServerRespondAction(MODULE_NAME, this.getTenantID(), this.getChargingStationID(), commandName, result);
+ await Logging.logChargingStationServerRespondAction(Constants.MODULE_JSON_OCPP_SERVER_16, this.getTenantID(), this.getChargingStationID(), commandName, result);
// Send Response
await this.sendMessage(messageId, result, OCPPMessageType.CALL_RESULT_MESSAGE, commandName);
} else {
@@ -192,10 +202,10 @@ export default class JsonWSConnection extends WSConnection {
if (!this.lastSeen || (Date.now() - this.lastSeen.getTime()) > Constants.LAST_SEEN_UPDATE_INTERVAL_MILLIS) {
// Update last seen
this.lastSeen = new Date();
- const chargingStation = await ChargingStationStorage.getChargingStation(this.getTenantID(),
+ const chargingStation = await ChargingStationStorage.getChargingStation(this.getTenant(),
this.getChargingStationID(), { issuer: true }, ['id']);
if (chargingStation) {
- await ChargingStationStorage.saveChargingStationLastSeen(this.getTenantID(), this.getChargingStationID(),
+ await ChargingStationStorage.saveChargingStationLastSeen(this.getTenant(), this.getChargingStationID(),
{ lastSeen: this.lastSeen });
}
}
diff --git a/src/server/ocpp/json/WSConnection.ts b/src/server/ocpp/json/WSConnection.ts
index 44f2194ba5..e722e9c9bd 100644
--- a/src/server/ocpp/json/WSConnection.ts
+++ b/src/server/ocpp/json/WSConnection.ts
@@ -28,7 +28,6 @@ export default abstract class WSConnection {
private clientIP: string | string[];
private wsConnection: WebSocket;
private requests: { [id: string]: OCPPRequest };
- private validTenant: boolean;
constructor(wsConnection: WebSocket, req: http.IncomingMessage, wsServer: JsonCentralSystemServer) {
// Init
@@ -44,7 +43,6 @@ export default abstract class WSConnection {
message: `WS connection opening attempts with URL: '${req.url}'`,
});
// Default
- this.validTenant = false;
this.requests = {};
// Check URL: remove starting and trailing '/'
if (this.url.endsWith('/')) {
@@ -120,7 +118,6 @@ export default abstract class WSConnection {
try {
// Check Tenant?
this.tenant = await DatabaseUtils.checkTenant(this.tenantID);
- this.validTenant = true;
} catch (error) {
// Custom Error
await Logging.logException(error, ServerAction.WS_CONNECTION, this.getChargingStationID(), 'WSConnection', 'initialize', this.tenantID);
@@ -328,11 +325,7 @@ export default abstract class WSConnection {
}
public getTenantID(): string {
- if (this.isTenantValid()) {
- return this.tenantID;
- }
- // No: go to the master tenant
- return Constants.DEFAULT_TENANT;
+ return this.tenantID;
}
public getTenant(): Tenant {
@@ -347,10 +340,6 @@ export default abstract class WSConnection {
return `${this.getTenantID()}~${this.getChargingStationID()}`;
}
- public isTenantValid(): boolean {
- return this.validTenant;
- }
-
public isWSConnectionOpen(): boolean {
return this.getConnectionStatus() === OPEN;
}
diff --git a/src/server/ocpp/services/OCPPService.ts b/src/server/ocpp/services/OCPPService.ts
index 92c9556027..10198d027b 100644
--- a/src/server/ocpp/services/OCPPService.ts
+++ b/src/server/ocpp/services/OCPPService.ts
@@ -82,7 +82,7 @@ export default class OCPPService {
});
}
// Get Charging Station
- let chargingStation = await ChargingStationStorage.getChargingStation(tenant.id, headers.chargeBoxIdentity);
+ let chargingStation = await ChargingStationStorage.getChargingStation(tenant, headers.chargeBoxIdentity);
if (!chargingStation) {
// Create Charging Station
chargingStation = await this.checkAndCreateChargingStation(tenant, bootNotification, headers);
@@ -94,12 +94,12 @@ export default class OCPPService {
this.enrichChargingStation(chargingStation, headers, bootNotification);
// Clear Firmware Status
if (chargingStation.firmwareUpdateStatus) {
- await ChargingStationStorage.saveChargingStationFirmwareStatus(tenant.id, chargingStation.id, null);
+ await ChargingStationStorage.saveChargingStationFirmwareStatus(tenant, chargingStation.id, null);
}
// Apply Charging Station Template
const templateUpdateResult = await this.applyChargingStationTemplate(tenant, chargingStation);
// Save Charging Station
- await ChargingStationStorage.saveChargingStation(tenant.id, chargingStation);
+ await ChargingStationStorage.saveChargingStation(tenant, chargingStation);
// Save Boot Notification
await OCPPStorage.saveBootNotification(tenant, bootNotification);
// Send Notification (Async)
@@ -151,7 +151,7 @@ export default class OCPPService {
timezone: Utils.getTimezone(chargingStation.coordinates)
};
// Save Charging Station lastSeen date
- await ChargingStationStorage.saveChargingStationLastSeen(tenant.id, chargingStation.id, {
+ await ChargingStationStorage.saveChargingStationLastSeen(tenant, chargingStation.id, {
lastSeen: chargingStation.lastSeen,
currentIPAddress: chargingStation.currentIPAddress,
});
@@ -269,13 +269,13 @@ export default class OCPPService {
// Roaming
await OCPPUtils.processTransactionRoaming(tenant, transaction, chargingStation, transaction.tag, TransactionAction.UPDATE);
// Save Transaction
- await TransactionStorage.saveTransaction(tenant.id, transaction);
+ await TransactionStorage.saveTransaction(tenant, transaction);
// Update Charging Station
await this.updateChargingStationWithTransaction(tenant, chargingStation, transaction);
// Handle End Of charge
await this.checkNotificationEndOfCharge(tenant, chargingStation, transaction);
// Save Charging Station
- await ChargingStationStorage.saveChargingStation(tenant.id, chargingStation);
+ await ChargingStationStorage.saveChargingStation(tenant, chargingStation);
// First Meter Value -> Trigger Smart Charging to adjust the limit
if (transaction.numberOfMeterValues === 1 && transaction.phasesUsed) {
// Yes: Trigger Smart Charging
@@ -391,7 +391,7 @@ export default class OCPPService {
// Enrich
this.enrichOCPPRequest(chargingStation, firmwareStatusNotification);
// Save the status to Charging Station
- await ChargingStationStorage.saveChargingStationFirmwareStatus(tenant.id, chargingStation.id, firmwareStatusNotification.status);
+ await ChargingStationStorage.saveChargingStationFirmwareStatus(tenant, chargingStation.id, firmwareStatusNotification.status);
// Save it
await OCPPStorage.saveFirmwareStatusNotification(tenant, firmwareStatusNotification);
// Log
@@ -446,11 +446,11 @@ export default class OCPPService {
// Roaming
await OCPPUtils.processTransactionRoaming(tenant, newTransaction, chargingStation, tag, TransactionAction.START);
// Save it
- await TransactionStorage.saveTransaction(tenant.id, newTransaction);
+ await TransactionStorage.saveTransaction(tenant, newTransaction);
// Clean up
await this.updateChargingStationConnectorWithTransaction(tenant, newTransaction, chargingStation, user);
// Save
- await ChargingStationStorage.saveChargingStation(tenant.id, chargingStation);
+ await ChargingStationStorage.saveChargingStation(tenant, chargingStation);
// Notify
this.notifyStartTransaction(tenant, newTransaction, chargingStation, user);
// Log
@@ -551,7 +551,7 @@ export default class OCPPService {
// Free the connector
OCPPUtils.clearChargingStationConnector(chargingStation, transaction.connectorId);
// Save Charging Station
- await ChargingStationStorage.saveChargingStation(tenant.id, chargingStation);
+ await ChargingStationStorage.saveChargingStation(tenant, chargingStation);
// Soft Stop
this.checkSoftStopTransaction(transaction, stopTransaction, isSoftStop);
// Transaction End has already been received?
@@ -565,7 +565,7 @@ export default class OCPPService {
// Roaming
await OCPPUtils.processTransactionRoaming(tenant, transaction, chargingStation, transaction.tag, TransactionAction.STOP);
// Save the transaction
- await TransactionStorage.saveTransaction(tenant.id, transaction);
+ await TransactionStorage.saveTransaction(tenant, transaction);
// Notify User
this.notifyStopTransaction(tenant, chargingStation, transaction, user, alternateUser);
// Recompute the Smart Charging Plan
@@ -633,7 +633,7 @@ export default class OCPPService {
alternateUser = authorizedUsers.alternateUser;
} else {
// Get the User
- user = await UserStorage.getUserByTagId(tenant.id, tagId);
+ user = await UserStorage.getUserByTagId(tenant, tagId);
}
// Already Stopped?
if (transaction.stop) {
@@ -675,7 +675,7 @@ export default class OCPPService {
}
private async deleteAllTransactionTxProfile(tenant: Tenant, transaction: Transaction) {
- const chargingProfiles = await ChargingStationStorage.getChargingProfiles(tenant.id, {
+ const chargingProfiles = await ChargingStationStorage.getChargingProfiles(tenant, {
chargingStationIDs: [transaction.chargeBoxID],
connectorID: transaction.connectorId,
profilePurposeType: ChargingProfilePurposeType.TX_PROFILE,
@@ -728,9 +728,9 @@ export default class OCPPService {
connector1?.connectorId - connector2?.connectorId);
}
// Save Charging Station
- await ChargingStationStorage.saveChargingStationConnectors(tenant.id, chargingStation.id,
+ await ChargingStationStorage.saveChargingStationConnectors(tenant, chargingStation.id,
chargingStation.connectors, chargingStation.backupConnectors);
- await ChargingStationStorage.saveChargingStationLastSeen(tenant.id, chargingStation.id, { lastSeen: new Date() });
+ await ChargingStationStorage.saveChargingStationLastSeen(tenant, chargingStation.id, { lastSeen: new Date() });
// Process Smart Charging
await this.processSmartChargingStatusNotification(tenant, chargingStation, connector);
// Log
@@ -834,7 +834,7 @@ export default class OCPPService {
if (statusNotification.status === ChargePointStatus.AVAILABLE) {
// Get the last transaction
const lastTransaction = await TransactionStorage.getLastTransactionFromChargingStation(
- tenant.id, chargingStation.id, connector.connectorId, { withChargingStation: true, withUser: true, withTag: true });
+ tenant, chargingStation.id, connector.connectorId, { withChargingStation: true, withUser: true, withTag: true });
// Transaction completed
if (lastTransaction?.stop) {
// Check Inactivity
@@ -902,7 +902,7 @@ export default class OCPPService {
await this.checkAndSendOICPTransactionCdr(tenant, lastTransaction, chargingStation, lastTransaction.tag);
}
// Save
- await TransactionStorage.saveTransaction(tenant.id, lastTransaction);
+ await TransactionStorage.saveTransaction(tenant, lastTransaction);
} else if (!Utils.isNullOrUndefined(lastTransaction)) {
await Logging.logWarning({
tenantID: tenant.id,
@@ -1426,7 +1426,7 @@ export default class OCPPService {
let activeTransaction: Transaction, lastCheckedTransactionID: number;
do {
// Check if the charging station has already a transaction
- activeTransaction = await TransactionStorage.getActiveTransaction(tenant.id, chargingStation.id, connectorId);
+ activeTransaction = await TransactionStorage.getActiveTransaction(tenant, chargingStation.id, connectorId);
// Exists already?
if (activeTransaction) {
// Avoid infinite Loop
@@ -1445,7 +1445,7 @@ export default class OCPPService {
message: `${Utils.buildConnectorInfo(activeTransaction.connectorId, activeTransaction.id)} Transaction with no consumption has been deleted`
});
// Delete
- await TransactionStorage.deleteTransaction(tenant.id, activeTransaction.id);
+ await TransactionStorage.deleteTransaction(tenant, activeTransaction.id);
// Clear connector
OCPPUtils.clearChargingStationConnector(chargingStation, activeTransaction.connectorId);
} else {
@@ -1596,7 +1596,7 @@ export default class OCPPService {
// Smart Charging must be active
if (Utils.isTenantComponentActive(tenant, TenantComponents.SMART_CHARGING)) {
// Get Site Area
- const siteArea = await SiteAreaStorage.getSiteArea(tenant.id, chargingStation.siteAreaID);
+ const siteArea = await SiteAreaStorage.getSiteArea(tenant, chargingStation.siteAreaID);
if (siteArea && siteArea.smartCharging) {
const siteAreaLock = await LockingHelper.acquireSiteAreaSmartChargingLock(tenant.id, siteArea, 30);
if (siteAreaLock) {
@@ -1657,7 +1657,7 @@ export default class OCPPService {
transaction.carCatalogID = car?.carCatalogID;
}
// Clear
- await UserStorage.saveUserLastSelectedCarID(tenant.id, user.id, null);
+ await UserStorage.saveUserLastSelectedCarID(tenant, user.id, null);
}
}
@@ -1685,7 +1685,7 @@ export default class OCPPService {
private async createTransaction(tenant: Tenant, startTransaction: OCPPStartTransactionRequestExtended): Promise {
return {
- id: await TransactionStorage.findAvailableID(tenant.id),
+ id: await TransactionStorage.findAvailableID(tenant),
issuer: true,
chargeBoxID: startTransaction.chargeBoxID,
tagID: startTransaction.idTag,
@@ -1754,7 +1754,7 @@ export default class OCPPService {
newChargingStation.registrationStatus = RegistrationStatus.ACCEPTED;
// Assign to Site Area
if (token.siteAreaID) {
- const siteArea = await SiteAreaStorage.getSiteArea(tenant.id, token.siteAreaID, { withSite: true });
+ const siteArea = await SiteAreaStorage.getSiteArea(tenant, token.siteAreaID, { withSite: true });
if (siteArea) {
newChargingStation.companyID = siteArea.site?.companyID;
newChargingStation.siteID = siteArea.siteID;
@@ -1985,7 +1985,7 @@ export default class OCPPService {
detailedMessages: { headers, meterValues }
});
}
- const transaction = await TransactionStorage.getTransaction(tenant.id, meterValues.transactionId, { withUser: true, withTag: true });
+ const transaction = await TransactionStorage.getTransaction(tenant, meterValues.transactionId, { withUser: true, withTag: true });
if (!transaction) {
// Try a Remote Stop the Transaction
if (meterValues.transactionId) {
@@ -2051,7 +2051,7 @@ export default class OCPPService {
private async getTransactionFromStopTransaction(tenant: Tenant, chargingStation: ChargingStation,
headers: OCPPHeader, stopTransaction: OCPPStopTransactionRequestExtended): Promise {
- const transaction = await TransactionStorage.getTransaction(tenant.id, stopTransaction.transactionId, { withUser: true, withTag: true });
+ const transaction = await TransactionStorage.getTransaction(tenant, stopTransaction.transactionId, { withUser: true, withTag: true });
if (!transaction) {
throw new BackendError({
source: chargingStation.id,
diff --git a/src/server/ocpp/soap/services/SoapCentralSystemService12.ts b/src/server/ocpp/soap/services/SoapCentralSystemService12.ts
index a4d0e21068..eb36483a48 100644
--- a/src/server/ocpp/soap/services/SoapCentralSystemService12.ts
+++ b/src/server/ocpp/soap/services/SoapCentralSystemService12.ts
@@ -7,7 +7,7 @@ import { ServerAction } from '../../../../types/Server';
import Utils from '../../../../utils/Utils';
import global from '../../../../types/GlobalType';
-const MODULE_NAME = 'SoapCentralSystemService12';
+const MODULE_NAME = Constants.MODULE_SOAP_OCPP_SERVER_12;
export default { /* Services */
CentralSystemService: { /* Ports */
diff --git a/src/server/ocpp/soap/services/SoapCentralSystemService15.ts b/src/server/ocpp/soap/services/SoapCentralSystemService15.ts
index b919693981..d558f882b0 100644
--- a/src/server/ocpp/soap/services/SoapCentralSystemService15.ts
+++ b/src/server/ocpp/soap/services/SoapCentralSystemService15.ts
@@ -7,7 +7,7 @@ import { ServerAction } from '../../../../types/Server';
import Utils from '../../../../utils/Utils';
import global from '../../../../types/GlobalType';
-const MODULE_NAME = 'SoapCentralSystemService15';
+const MODULE_NAME = Constants.MODULE_SOAP_OCPP_SERVER_15;
export default { /* Services */
CentralSystemService: { /* Ports */
diff --git a/src/server/ocpp/soap/services/SoapCentralSystemService16.ts b/src/server/ocpp/soap/services/SoapCentralSystemService16.ts
index 96d1eda636..5a462039dd 100644
--- a/src/server/ocpp/soap/services/SoapCentralSystemService16.ts
+++ b/src/server/ocpp/soap/services/SoapCentralSystemService16.ts
@@ -7,7 +7,7 @@ import { ServerAction } from '../../../../types/Server';
import Utils from '../../../../utils/Utils';
import global from '../../../../types/GlobalType';
-const MODULE_NAME = 'SoapCentralSystemService16';
+const MODULE_NAME = Constants.MODULE_SOAP_OCPP_SERVER_16;
export default { /* Services */
CentralSystemService: { /* Ports */
diff --git a/src/server/ocpp/utils/OCPPUtils.ts b/src/server/ocpp/utils/OCPPUtils.ts
index d2a5232ea6..9c30922dcb 100644
--- a/src/server/ocpp/utils/OCPPUtils.ts
+++ b/src/server/ocpp/utils/OCPPUtils.ts
@@ -64,7 +64,7 @@ export default class OCPPUtils {
});
}
// Get the Token
- const token = await RegistrationTokenStorage.getRegistrationToken(tenant.id, tokenID);
+ const token = await RegistrationTokenStorage.getRegistrationToken(tenant, tokenID);
if (!token) {
throw new BackendError({
source: chargingStationID,
@@ -537,7 +537,7 @@ export default class OCPPUtils {
transaction.roundedPrice = Utils.truncTo(transaction.price, 2);
transaction.stop.price = transaction.currentCumulatedPrice;
transaction.stop.roundedPrice = Utils.truncTo(transaction.currentCumulatedPrice, 2);
- await TransactionStorage.saveTransaction(tenant.id, transaction);
+ await TransactionStorage.saveTransaction(tenant, transaction);
}
public static async rebuildTransactionConsumptions(tenant: Tenant, transaction: Transaction): Promise {
@@ -564,7 +564,7 @@ export default class OCPPUtils {
transactionSimplePricePerkWh = Utils.roundTo(transaction.stop.price / (transaction.stop.totalConsumptionWh / 1000), 2);
}
// Get the Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(tenant.id,
+ const chargingStation = await ChargingStationStorage.getChargingStation(tenant,
transaction.chargeBoxID, { includeDeleted: true });
if (!chargingStation) {
throw new BackendError({
@@ -665,7 +665,7 @@ export default class OCPPUtils {
// Build extra inactivity consumption
const consumptionCreated = await OCPPUtils.buildExtraConsumptionInactivity(tenant, transaction);
// Save
- await TransactionStorage.saveTransaction(tenant.id, transaction);
+ await TransactionStorage.saveTransaction(tenant, transaction);
return consumptions.length + (consumptionCreated ? 1 : 0);
}
@@ -1056,7 +1056,7 @@ export default class OCPPUtils {
consumption.limitSiteAreaSource = SiteAreaLimitSource.SITE_AREA;
} else {
// Compute it for Charging Stations
- const chargingStationsOfSiteArea = await ChargingStationStorage.getChargingStations(tenant.id,
+ const chargingStationsOfSiteArea = await ChargingStationStorage.getChargingStations(tenant,
{ siteAreaIDs: [siteArea.id], withSiteArea: true }, Constants.DB_PARAMS_MAX_LIMIT);
for (const chargingStationOfSiteArea of chargingStationsOfSiteArea.result) {
if (Utils.objectHasProperty(chargingStationOfSiteArea, 'connectors')) {
@@ -1070,7 +1070,7 @@ export default class OCPPUtils {
// Save Site Area max consumption
if (siteArea) {
siteArea.maximumPower = consumption.limitSiteAreaWatts;
- await SiteAreaStorage.saveSiteArea(tenant.id, siteArea);
+ await SiteAreaStorage.saveSiteArea(tenant, siteArea);
}
}
consumption.smartChargingActive = siteArea.smartCharging;
@@ -1250,7 +1250,7 @@ export default class OCPPUtils {
sectionsUpdated.push('OCPP');
}
// Save
- await ChargingStationStorage.saveChargingStation(tenant.id, chargingStation);
+ await ChargingStationStorage.saveChargingStation(tenant, chargingStation);
await Logging.logInfo({
tenantID: tenant.id,
source: chargingStation.id,
@@ -1303,7 +1303,7 @@ export default class OCPPUtils {
inSuccess: 0
};
for (const chargingStation of siteArea.chargingStations) {
- const chargingProfiles = await ChargingStationStorage.getChargingProfiles(tenant.id, {
+ const chargingProfiles = await ChargingStationStorage.getChargingProfiles(tenant, {
chargingStationIDs: [chargingStation.id],
profilePurposeType: params.profilePurposeType,
transactionId: params.transactionId
@@ -1330,7 +1330,7 @@ export default class OCPPUtils {
public static async clearAndDeleteChargingProfile(tenant: Tenant, chargingProfile: ChargingProfile): Promise {
// Get charging station
- const chargingStation = await ChargingStationStorage.getChargingStation(tenant.id, chargingProfile.chargingStationID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(tenant, chargingProfile.chargingStationID);
// Check if Charging Profile is supported
if (!chargingStation.capabilities?.supportChargingProfiles) {
throw new BackendError({
@@ -1369,7 +1369,7 @@ export default class OCPPUtils {
throw error;
}
// Delete from database
- await ChargingStationStorage.deleteChargingProfile(tenant.id, chargingProfile.id);
+ await ChargingStationStorage.deleteChargingProfile(tenant, chargingProfile.id);
await Logging.logInfo({
tenantID: tenant.id,
source: chargingStation.id,
@@ -1407,7 +1407,7 @@ export default class OCPPUtils {
public static async setAndSaveChargingProfile(tenant: Tenant, chargingProfile: ChargingProfile): Promise {
// Get charging station
- const chargingStation = await ChargingStationStorage.getChargingStation(tenant.id, chargingProfile.chargingStationID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(tenant, chargingProfile.chargingStationID);
if (!chargingStation) {
throw new BackendError({
source: chargingProfile.chargingStationID,
@@ -1453,7 +1453,7 @@ export default class OCPPUtils {
});
}
// Save
- const chargingProfileID = await ChargingStationStorage.saveChargingProfile(tenant.id, chargingProfile);
+ const chargingProfileID = await ChargingStationStorage.saveChargingProfile(tenant, chargingProfile);
await Logging.logInfo({
tenantID: tenant.id,
source: chargingStation.id,
@@ -1549,7 +1549,7 @@ export default class OCPPUtils {
let chargingStation: ChargingStation;
try {
chargingStation = await ChargingStationStorage.getChargingStation(
- ocppHeader.tenantID, ocppHeader.chargeBoxIdentity);
+ tenant, ocppHeader.chargeBoxIdentity);
if (!chargingStation) {
throw new BackendError({
source: ocppHeader.chargeBoxIdentity,
@@ -1599,7 +1599,7 @@ export default class OCPPUtils {
timestamp: new Date()
};
// Get saved OCPP configuration from DB
- const ocppParametersFromDB = await ChargingStationStorage.getOcppParameters(tenant.id, chargingStation.id);
+ const ocppParametersFromDB = await ChargingStationStorage.getOcppParameters(tenant, chargingStation.id);
// Charging Station configuration not found
if (!chargingStationOcppParameters.configuration) {
if (ocppParametersFromDB.count === 0) {
@@ -1621,7 +1621,7 @@ export default class OCPPUtils {
}
}
// Save configuration
- await ChargingStationStorage.saveOcppParameters(tenant.id, chargingStationOcppParameters);
+ await ChargingStationStorage.saveOcppParameters(tenant, chargingStationOcppParameters);
// Ok
await Logging.logInfo({
tenantID: tenant.id,
@@ -1646,7 +1646,7 @@ export default class OCPPUtils {
let rebootRequired = false;
// Get current OCPP parameters in DB
let currentOcppParameters: OcppParameter[];
- const ocppParametersFromDB = await ChargingStationStorage.getOcppParameters(tenant.id, chargingStation.id);
+ const ocppParametersFromDB = await ChargingStationStorage.getOcppParameters(tenant, chargingStation.id);
if (ocppParametersFromDB.count > 0) {
currentOcppParameters = ocppParametersFromDB.result;
}
@@ -2188,7 +2188,7 @@ export default class OCPPUtils {
private static async setConnectorPhaseAssignment(tenant: Tenant, chargingStation: ChargingStation, connector: Connector, nrOfPhases?: number): Promise {
const csNumberOfPhases = nrOfPhases ?? Utils.getNumberOfConnectedPhases(chargingStation, null, connector.connectorId);
if (chargingStation.siteAreaID) {
- const siteArea = await SiteAreaStorage.getSiteArea(tenant.id, chargingStation.siteAreaID);
+ const siteArea = await SiteAreaStorage.getSiteArea(tenant, chargingStation.siteAreaID);
// Phase Assignment to Grid has to be handled only for Site Area with 3 phases
if (siteArea.numberOfPhases === 3) {
switch (csNumberOfPhases) {
diff --git a/src/server/oicp/OICPUtils.ts b/src/server/oicp/OICPUtils.ts
index 803547f06f..c1920903bb 100644
--- a/src/server/oicp/OICPUtils.ts
+++ b/src/server/oicp/OICPUtils.ts
@@ -56,7 +56,7 @@ export default class OICPUtils {
if (chargingStation.issuer && chargingStation.public) {
const chargingStationEvses = OICPUtils.convertChargingStation2MultipleEvses(site, chargingStation.siteArea, chargingStation, options);
// Update the Charging Station's OICP Data
- await ChargingStationStorage.saveChargingStationOicpData(tenant.id, chargingStation.id, {
+ await ChargingStationStorage.saveChargingStationOicpData(tenant, chargingStation.id, {
evses: chargingStationEvses
});
evses.push(...chargingStationEvses);
@@ -130,7 +130,7 @@ export default class OICPUtils {
public static async getChargingStationConnectorFromEvseID(tenant: Tenant, evseID: OICPEvseID): Promise<{ chargingStation: ChargingStation, connector: Connector }> {
const evseIDComponents = RoamingUtils.getEvseIdComponents(evseID);
- const chargingStation = await ChargingStationStorage.getChargingStationByOicpEvseID(tenant.id, evseID);
+ const chargingStation = await ChargingStationStorage.getChargingStationByOicpEvseID(tenant, evseID);
let foundConnector: Connector;
if (chargingStation) {
for (const connector of chargingStation.connectors) {
@@ -213,7 +213,7 @@ export default class OICPUtils {
// Get the first non used Authorization OICP ID / Session ID
for (const authorization of authorizations.result) {
if (authorization.authorizationId) {
- const oicpTransaction = await TransactionStorage.getOICPTransactionBySessionID(tenant.id, authorization.authorizationId);
+ const oicpTransaction = await TransactionStorage.getOICPTransactionBySessionID(tenant, authorization.authorizationId);
// OICP SessionID not used yet
if (!oicpTransaction) {
sessionId = authorization.authorizationId;
@@ -228,7 +228,7 @@ export default class OICPUtils {
}
}
- public static async createOICPVirtualUser(tenantID: string): Promise {
+ public static async createOICPVirtualUser(tenant: Tenant): Promise {
// Create the virtual OICP user
const newVirtualOICPUser = UserStorage.createNewUser() as User;
newVirtualOICPUser.email = Constants.OICP_VIRTUAL_USER_EMAIL;
@@ -238,9 +238,9 @@ export default class OICPUtils {
newVirtualOICPUser.status = UserStatus.ACTIVE;
newVirtualOICPUser.notificationsActive = false;
// Save User
- newVirtualOICPUser.id = await UserStorage.saveUser(tenantID, newVirtualOICPUser);
+ newVirtualOICPUser.id = await UserStorage.saveUser(tenant, newVirtualOICPUser);
// Save User Status
- await UserStorage.saveUserStatus(tenantID, newVirtualOICPUser.id, UserStatus.ACTIVE);
+ await UserStorage.saveUserStatus(tenant, newVirtualOICPUser.id, UserStatus.ACTIVE);
}
private static convertConnector2OICPChargingFacility(chargingStation: ChargingStation, connector: Connector): OICPChargingFacility {
diff --git a/src/server/oicp/oicp-services-impl/oicp-2.3.0/CPORemoteAuthorizationsEndpoint.ts b/src/server/oicp/oicp-services-impl/oicp-2.3.0/CPORemoteAuthorizationsEndpoint.ts
index 3b2c3daec1..6a15032548 100644
--- a/src/server/oicp/oicp-services-impl/oicp-2.3.0/CPORemoteAuthorizationsEndpoint.ts
+++ b/src/server/oicp/oicp-services-impl/oicp-2.3.0/CPORemoteAuthorizationsEndpoint.ts
@@ -136,7 +136,7 @@ export default class CPORemoteAuthorizationsEndpoint extends AbstractEndpoint {
}
// Save Auth
await ChargingStationStorage.saveChargingStationRemoteAuthorizations(
- tenant.id, chargingStation.id, chargingStation.remoteAuthorizations);
+ tenant, chargingStation.id, chargingStation.remoteAuthorizations);
// Start the transaction
const result = await this.remoteStartTransaction(tenant, chargingStation, connector, authorizeRemoteStart);
if (result?.status === OCPPRemoteStartStopStatus.ACCEPTED) {
@@ -152,7 +152,7 @@ export default class CPORemoteAuthorizationsEndpoint extends AbstractEndpoint {
const session = {} as Partial;
session.id = authorizeRemoteStop.SessionID;
session.providerID = authorizeRemoteStop.ProviderID;
- const transaction = await TransactionStorage.getOICPTransactionBySessionID(tenant.id, authorizeRemoteStop.SessionID);
+ const transaction = await TransactionStorage.getOICPTransactionBySessionID(tenant, authorizeRemoteStop.SessionID);
if (!transaction) {
await Logging.logError({
tenantID: tenant.id,
@@ -180,7 +180,7 @@ export default class CPORemoteAuthorizationsEndpoint extends AbstractEndpoint {
});
return OICPUtils.noSuccess(session, `Transaction with OICP Transaction ID '${authorizeRemoteStop.SessionID}' is already stopped`);
}
- const chargingStation = await ChargingStationStorage.getChargingStation(tenant.id, transaction.chargeBoxID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(tenant, transaction.chargeBoxID);
if (!chargingStation) {
await Logging.logError({
tenantID: tenant.id,
diff --git a/src/server/rest/v1/router/api/TransactionRouter.ts b/src/server/rest/v1/router/api/TransactionRouter.ts
index 85c8c0fb4c..a3cc2eeac6 100644
--- a/src/server/rest/v1/router/api/TransactionRouter.ts
+++ b/src/server/rest/v1/router/api/TransactionRouter.ts
@@ -16,6 +16,15 @@ export default class TransactionRouter {
this.buildRouteTransactions();
this.buildRouteTransaction();
this.buildRouteTransactionConsumption();
+ this.buildRouteDeleteTransaction();
+ this.buildRouteDeleteTransactions();
+ this.buildRoutePushTransactionCDR();
+ this.buildRouteExportTransactionCDR();
+ this.buildRouteRebuildTransactionConsumption();
+ this.buildRouteTransactionSoftStop();
+ this.buildRouteTransactionsRefund();
+ this.buildRouteTransactionsAssignUser();
+ this.buildRouteTransactionsExport();
return this.router;
}
@@ -32,10 +41,69 @@ export default class TransactionRouter {
});
}
+ protected buildRouteDeleteTransactions(): void {
+ this.router.delete(`/${ServerRoute.REST_TRANSACTIONS}`, async (req: Request, res: Response, next: NextFunction) => {
+ await RouterUtils.handleServerAction(TransactionService.handleDeleteTransactions.bind(this), ServerAction.TRANSACTIONS_DELETE, req, res, next);
+ });
+ }
+
+ protected buildRouteDeleteTransaction(): void {
+ this.router.delete(`/${ServerRoute.REST_TRANSACTION}`, async (req: Request, res: Response, next: NextFunction) => {
+ req.query.ID = req.params.id;
+ await RouterUtils.handleServerAction(TransactionService.handleDeleteTransaction.bind(this), ServerAction.TRANSACTION_DELETE, req, res, next);
+ });
+ }
+
+ protected buildRoutePushTransactionCDR(): void {
+ this.router.post(`/${ServerRoute.REST_TRANSACTION_CDR}`, async (req: Request, res: Response, next: NextFunction) => {
+ req.body.transactionId = req.params.id;
+ await RouterUtils.handleServerAction(TransactionService.handlePushTransactionCdr.bind(this), ServerAction.OCPI_PUSH_CDRS, req, res, next);
+ });
+ }
+
+ protected buildRouteExportTransactionCDR(): void {
+ this.router.get(`/${ServerRoute.REST_TRANSACTION_CDR_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => {
+ req.query.ID = req.params.id;
+ await RouterUtils.handleServerAction(TransactionService.handleExportTransactionOcpiCdr.bind(this), ServerAction.TRANSACTION_OCPI_CDR_EXPORT, req, res, next);
+ });
+ }
+
protected buildRouteTransactionConsumption(): void {
this.router.get(`/${ServerRoute.REST_TRANSACTIONS_CONSUMPTION}`, async (req: Request, res: Response, next: NextFunction) => {
req.query.TransactionId = req.params.id;
await RouterUtils.handleServerAction(TransactionService.handleGetTransactionConsumption.bind(this), ServerAction.TRANSACTION_CONSUMPTION, req, res, next);
});
}
+
+ protected buildRouteRebuildTransactionConsumption(): void {
+ this.router.post(`/${ServerRoute.REST_TRANSACTION_CONSUMPTIONS_REBUILD}`, async (req: Request, res: Response, next: NextFunction) => {
+ req.query.ID = req.params.id;
+ await RouterUtils.handleServerAction(TransactionService.handleRebuildTransactionConsumptions.bind(this), ServerAction.REBUILD_TRANSACTION_CONSUMPTIONS, req, res, next);
+ });
+ }
+
+ protected buildRouteTransactionSoftStop(): void {
+ this.router.put(`/${ServerRoute.REST_TRANSACTION_SOFT_STOP}`, async (req: Request, res: Response, next: NextFunction) => {
+ req.body.ID = req.params.id;
+ await RouterUtils.handleServerAction(TransactionService.handleTransactionSoftStop.bind(this), ServerAction.TRANSACTION_SOFT_STOP, req, res, next);
+ });
+ }
+
+ protected buildRouteTransactionsRefund(): void {
+ this.router.post(`/${ServerRoute.REST_TRANSACTIONS_REFUND}`, async (req: Request, res: Response, next: NextFunction) => {
+ await RouterUtils.handleServerAction(TransactionService.handleRefundTransactions.bind(this), ServerAction.TRANSACTIONS_REFUND, req, res, next);
+ });
+ }
+
+ protected buildRouteTransactionsAssignUser(): void {
+ this.router.put(`/${ServerRoute.REST_TRANSACTIONS_ASSIGN_USER}`, async (req: Request, res: Response, next: NextFunction) => {
+ await RouterUtils.handleServerAction(TransactionService.handleAssignTransactionsToUser.bind(this), ServerAction.ASSIGN_TRANSACTIONS_TO_USER, req, res, next);
+ });
+ }
+
+ protected buildRouteTransactionsExport(): void {
+ this.router.get(`/${ServerRoute.REST_TRANSACTIONS_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => {
+ await RouterUtils.handleServerAction(TransactionService.handleExportTransactions.bind(this), ServerAction.TRANSACTIONS_EXPORT, req, res, next);
+ });
+ }
}
diff --git a/src/server/rest/v1/service/AssetService.ts b/src/server/rest/v1/service/AssetService.ts
index 16fb97398d..81a2457bc8 100644
--- a/src/server/rest/v1/service/AssetService.ts
+++ b/src/server/rest/v1/service/AssetService.ts
@@ -527,7 +527,7 @@ export default class AssetService {
// Check Site Area
let siteArea: SiteArea = null;
if (filteredRequest.siteAreaID) {
- siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, filteredRequest.siteAreaID);
+ siteArea = await SiteAreaStorage.getSiteArea(req.tenant, filteredRequest.siteAreaID);
UtilsService.assertObjectExists(action, siteArea, `Site Area ID '${filteredRequest.siteAreaID}' does not exist`,
MODULE_NAME, 'handleCreateAsset', req.user);
}
@@ -585,7 +585,7 @@ export default class AssetService {
// Check Site Area
let siteArea: SiteArea = null;
if (filteredRequest.siteAreaID) {
- siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, filteredRequest.siteAreaID);
+ siteArea = await SiteAreaStorage.getSiteArea(req.tenant, filteredRequest.siteAreaID);
UtilsService.assertObjectExists(action, siteArea, `Site Area ID '${filteredRequest.siteAreaID}' does not exist`,
MODULE_NAME, 'handleUpdateAsset', req.user);
}
diff --git a/src/server/rest/v1/service/AuthService.ts b/src/server/rest/v1/service/AuthService.ts
index 8588bbe0b8..a340219019 100644
--- a/src/server/rest/v1/service/AuthService.ts
+++ b/src/server/rest/v1/service/AuthService.ts
@@ -69,8 +69,8 @@ export default class AuthService {
// Filter
const filteredRequest = AuthValidator.getInstance().validateAuthSignIn(req.body);
// Get Tenant
- const tenantID = await AuthService.getTenantID(filteredRequest.tenant);
- if (!tenantID) {
+ const tenant = await AuthService.getTenant(filteredRequest.tenant);
+ if (!tenant) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
errorCode: HTTPError.OBJECT_DOES_NOT_EXIST_ERROR,
@@ -80,8 +80,8 @@ export default class AuthService {
action: action
});
}
- req.user = { tenantID };
- const user = await UserStorage.getUserByEmail(tenantID, filteredRequest.email);
+ req.user = { tenantID: tenant.id };
+ const user = await UserStorage.getUserByEmail(tenant, filteredRequest.email);
UtilsService.assertObjectExists(action, user, `User with email '${filteredRequest.email}' does not exist`,
MODULE_NAME, 'handleLogIn', req.user);
// Check if the number of trials is reached
@@ -98,14 +98,14 @@ export default class AuthService {
message: 'User has been unlocked after a period of time can try to login again'
});
// Save User Status
- await UserStorage.saveUserStatus(req.user.tenantID, user.id, UserStatus.ACTIVE);
+ await UserStorage.saveUserStatus(req.tenant, user.id, UserStatus.ACTIVE);
// Init User Password
- await UserStorage.saveUserPassword(req.user.tenantID, user.id,
+ await UserStorage.saveUserPassword(req.tenant, user.id,
{ passwordWrongNbrTrials: 0, passwordBlockedUntil: null, passwordResetHash: null });
// Read user again
- const updatedUser = await UserStorage.getUser(tenantID, user.id);
+ const updatedUser = await UserStorage.getUser(tenant, user.id);
// Check user
- await AuthService.checkUserLogin(action, tenantID, updatedUser, filteredRequest, req, res, next);
+ await AuthService.checkUserLogin(action, tenant, updatedUser, filteredRequest, req, res, next);
} else {
// Return data
throw new AppError({
@@ -121,11 +121,11 @@ export default class AuthService {
user.passwordWrongNbrTrials = 0;
user.passwordBlockedUntil = null;
// Check user
- await AuthService.checkUserLogin(action, tenantID, user, filteredRequest, req, res, next);
+ await AuthService.checkUserLogin(action, tenant, user, filteredRequest, req, res, next);
}
} else {
// Nbr trials OK: Check user
- await AuthService.checkUserLogin(action, tenantID, user, filteredRequest, req, res, next);
+ await AuthService.checkUserLogin(action, tenant, user, filteredRequest, req, res, next);
}
}
@@ -172,7 +172,7 @@ export default class AuthService {
// Check Mandatory field
UtilsService.checkIfUserValid(filteredRequest as User, null, req);
// Check email
- const user = await UserStorage.getUserByEmail(tenant.id, filteredRequest.email);
+ const user = await UserStorage.getUserByEmail(tenant, filteredRequest.email);
if (user) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -192,17 +192,17 @@ export default class AuthService {
newUser.locale = filteredRequest.locale;
newUser.createdOn = new Date();
const verificationToken = Utils.generateToken(filteredRequest.email);
- const endUserLicenseAgreement = await UserStorage.getEndUserLicenseAgreement(tenant.id, Utils.getLanguageFromLocale(newUser.locale));
+ const endUserLicenseAgreement = await UserStorage.getEndUserLicenseAgreement(tenant, Utils.getLanguageFromLocale(newUser.locale));
// Save User
- newUser.id = await UserStorage.saveUser(tenant.id, newUser);
+ newUser.id = await UserStorage.saveUser(tenant, newUser);
// Save User Status
if (tenant.id === Constants.DEFAULT_TENANT) {
- await UserStorage.saveUserRole(tenant.id, newUser.id, UserRole.SUPER_ADMIN);
+ await UserStorage.saveUserRole(tenant, newUser.id, UserRole.SUPER_ADMIN);
} else {
- await UserStorage.saveUserRole(tenant.id, newUser.id, UserRole.BASIC);
+ await UserStorage.saveUserRole(tenant, newUser.id, UserRole.BASIC);
}
// Save User Status
- await UserStorage.saveUserStatus(tenant.id, newUser.id, UserStatus.PENDING);
+ await UserStorage.saveUserStatus(tenant, newUser.id, UserStatus.PENDING);
// Get the i18n translation class
const i18nManager = I18nManager.getInstanceForLocale(newUser.locale);
const tag: Tag = {
@@ -217,7 +217,7 @@ export default class AuthService {
};
await TagStorage.saveTag(req.user.tenantID, tag);
// Save User password
- await UserStorage.saveUserPassword(tenant.id, newUser.id,
+ await UserStorage.saveUserPassword(tenant, newUser.id,
{
password: newPasswordHashed,
passwordWrongNbrTrials: 0,
@@ -225,9 +225,9 @@ export default class AuthService {
passwordBlockedUntil: null
});
// Save User Account Verification
- await UserStorage.saveUserAccountVerification(tenant.id, newUser.id, { verificationToken });
+ await UserStorage.saveUserAccountVerification(tenant, newUser.id, { verificationToken });
// Save User EULA
- await UserStorage.saveUserEULA(tenant.id, newUser.id,
+ await UserStorage.saveUserEULA(tenant, newUser.id,
{
eulaAcceptedOn: new Date(),
eulaAcceptedVersion: endUserLicenseAgreement.version,
@@ -241,7 +241,7 @@ export default class AuthService {
if (sites.count > 0) {
const siteIDs = sites.result.map((site) => site.id);
if (siteIDs && siteIDs.length > 0) {
- await UserStorage.addSitesToUser(tenant.id, newUser.id, siteIDs);
+ await UserStorage.addSitesToUser(tenant, newUser.id, siteIDs);
}
}
// Log
@@ -308,12 +308,12 @@ export default class AuthService {
});
}
// Generate a new password
- const user = await UserStorage.getUserByEmail(tenant.id, filteredRequest.email);
+ const user = await UserStorage.getUserByEmail(tenant, filteredRequest.email);
UtilsService.assertObjectExists(action, user, `User with email '${filteredRequest.email}' does not exist`,
MODULE_NAME, 'checkAndSendResetPasswordConfirmationEmail', req.user);
const resetHash = Utils.generateUUID();
// Init Password info
- await UserStorage.saveUserPassword(tenant.id, user.id, { passwordResetHash: resetHash });
+ await UserStorage.saveUserPassword(tenant, user.id, { passwordResetHash: resetHash });
// Log
await Logging.logSecurityInfo({
tenantID: tenant.id,
@@ -340,15 +340,16 @@ export default class AuthService {
next();
}
- public static async resetUserPassword(tenantID: string, filteredRequest: Partial, action: ServerAction, req: Request, res: Response, next: NextFunction): Promise {
+ public static async resetUserPassword(tenant: Tenant, filteredRequest: Partial,
+ action: ServerAction, req: Request, res: Response, next: NextFunction): Promise {
// Get the user
- const user = await UserStorage.getUserByPasswordResetHash(tenantID, filteredRequest.hash);
+ const user = await UserStorage.getUserByPasswordResetHash(tenant, filteredRequest.hash);
UtilsService.assertObjectExists(action, user, `User with password reset hash '${filteredRequest.hash}' does not exist`,
MODULE_NAME, 'handleUserPasswordReset', req.user);
// Hash it
const newHashedPassword = await Utils.hashPasswordBcrypt(filteredRequest.password);
// Save new password
- await UserStorage.saveUserPassword(tenantID, user.id,
+ await UserStorage.saveUserPassword(tenant, user.id,
{
password: newHashedPassword,
passwordWrongNbrTrials: 0,
@@ -358,11 +359,11 @@ export default class AuthService {
);
// Unlock
if (user.status === UserStatus.LOCKED) {
- await UserStorage.saveUserStatus(tenantID, user.id, UserStatus.ACTIVE);
+ await UserStorage.saveUserStatus(tenant, user.id, UserStatus.ACTIVE);
}
// Log
await Logging.logSecurityInfo({
- tenantID: tenantID,
+ tenantID: tenant.id,
user: user, action: action,
module: MODULE_NAME,
method: 'handleUserPasswordReset',
@@ -390,7 +391,7 @@ export default class AuthService {
// Check hash
if (filteredRequest.hash) {
// Send the new password
- await AuthService.resetUserPassword(tenant.id, filteredRequest, action, req, res, next);
+ await AuthService.resetUserPassword(tenant, filteredRequest, action, req, res, next);
} else {
// Send Confirmation Email for requesting a new password
await AuthService.checkAndSendResetPasswordConfirmationEmail(tenant, filteredRequest, action, req, res, next);
@@ -401,8 +402,8 @@ export default class AuthService {
// Filter
const filteredRequest = AuthValidator.getInstance().validateAuthCheckEula(req.query);
// Get Tenant
- const tenantID = await AuthService.getTenantID(filteredRequest.Tenant);
- if (!tenantID) {
+ const tenant = await AuthService.getTenant(filteredRequest.Tenant);
+ if (!tenant) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
errorCode: HTTPError.GENERAL_ERROR,
@@ -412,7 +413,7 @@ export default class AuthService {
});
}
// Get User
- const user = await UserStorage.getUserByEmail(tenantID, filteredRequest.Email);
+ const user = await UserStorage.getUserByEmail(tenant, filteredRequest.Email);
if (!user) {
// Do not return error, only reject it
res.json({ eulaAccepted: false });
@@ -420,7 +421,7 @@ export default class AuthService {
return;
}
// Get last Eula version
- const endUserLicenseAgreement = await UserStorage.getEndUserLicenseAgreement(tenantID, Utils.getLanguageFromLocale(user.locale));
+ const endUserLicenseAgreement = await UserStorage.getEndUserLicenseAgreement(tenant, Utils.getLanguageFromLocale(user.locale));
if (user.eulaAcceptedHash === endUserLicenseAgreement.hash) {
// Check if version matches
res.json({ eulaAccepted: true });
@@ -436,7 +437,7 @@ export default class AuthService {
// Filter
const filteredRequest = AuthValidator.getInstance().validateAuthEula(req.query);
// Get it
- const endUserLicenseAgreement = await UserStorage.getEndUserLicenseAgreement(Constants.DEFAULT_TENANT, filteredRequest.Language);
+ const endUserLicenseAgreement = await UserStorage.getEndUserLicenseAgreement(Constants.DEFAULT_TENANT_OBJECT, filteredRequest.Language);
res.json(endUserLicenseAgreement);
next();
}
@@ -478,7 +479,7 @@ export default class AuthService {
});
}
// Check email
- const user = await UserStorage.getUserByEmail(tenant.id, filteredRequest.Email);
+ const user = await UserStorage.getUserByEmail(tenant, filteredRequest.Email);
UtilsService.assertObjectExists(action, user, `User with email '${filteredRequest.Email}' does not exist`,
MODULE_NAME, 'handleVerifyEmail', req.user);
// Check if account is already active
@@ -503,10 +504,18 @@ export default class AuthService {
message: 'Wrong Verification Token'
});
}
- const userSettings = await SettingStorage.getUserSettings(tenant.id);
- const userStatus = userSettings.user.autoActivateAccountAfterValidation ? UserStatus.ACTIVE : UserStatus.INACTIVE;
// Save User Status
- await UserStorage.saveUserStatus(tenant.id, user.id, userStatus);
+ let userStatus: UserStatus;
+ // When it's user creation case we take the user settings
+ if (!user.importedData) {
+ const userSettings = await SettingStorage.getUserSettings(tenant.id);
+ userStatus = userSettings.user.autoActivateAccountAfterValidation ? UserStatus.ACTIVE : UserStatus.INACTIVE;
+ } else {
+ // When it's user import case we take checkbox param saved to db
+ userStatus = user.importedData.autoActivateUserAtImport ? UserStatus.ACTIVE : UserStatus.INACTIVE;
+ }
+ // Save User Status
+ await UserStorage.saveUserStatus(tenant, user.id, userStatus);
// For integration with billing
const billingImpl = await BillingFactory.getBillingImpl(tenant);
if (billingImpl) {
@@ -531,7 +540,7 @@ export default class AuthService {
}
}
// Save User Verification Account
- await UserStorage.saveUserAccountVerification(tenant.id, user.id,
+ await UserStorage.saveUserAccountVerification(tenant, user.id,
{ verificationToken: null, verifiedAt: new Date() });
// Log
await Logging.logSecurityInfo({
@@ -606,7 +615,7 @@ export default class AuthService {
});
}
// Is valid email?
- const user = await UserStorage.getUserByEmail(tenant.id, filteredRequest.email);
+ const user = await UserStorage.getUserByEmail(tenant, filteredRequest.email);
UtilsService.assertObjectExists(action, user, `User with email '${filteredRequest.email}' does not exist`,
MODULE_NAME, 'handleResendVerificationEmail', req.user);
// Check if account is already active
@@ -630,7 +639,7 @@ export default class AuthService {
verificationToken = Utils.generateToken(filteredRequest.email);
user.verificationToken = verificationToken;
// Save User Verification Account
- await UserStorage.saveUserAccountVerification(tenant.id, user.id, { verificationToken });
+ await UserStorage.saveUserAccountVerification(tenant, user.id, { verificationToken });
} else {
// Get existing verificationToken
verificationToken = user.verificationToken;
@@ -669,7 +678,7 @@ export default class AuthService {
res.status(StatusCodes.OK).send({});
}
- public static async userLoginWrongPassword(action: ServerAction, tenantID: string, user: User, req: Request, res: Response, next: NextFunction): Promise {
+ public static async userLoginWrongPassword(action: ServerAction, tenant: Tenant, user: User, req: Request, res: Response, next: NextFunction): Promise {
// Add wrong trial + 1
if (isNaN(user.passwordWrongNbrTrials)) {
user.passwordWrongNbrTrials = 0;
@@ -679,9 +688,9 @@ export default class AuthService {
if (passwordWrongNbrTrials >= _centralSystemRestConfig.passwordWrongNumberOfTrial) {
// Too many attempts, lock user
// Save User Status
- await UserStorage.saveUserStatus(tenantID, user.id, UserStatus.LOCKED);
+ await UserStorage.saveUserStatus(tenant, user.id, UserStatus.LOCKED);
// Save User Blocked Date
- await UserStorage.saveUserPassword(tenantID, user.id,
+ await UserStorage.saveUserPassword(tenant, user.id,
{
passwordWrongNbrTrials,
passwordBlockedUntil: moment().add(_centralSystemRestConfig.passwordBlockedWaitTimeMin, 'm').toDate()
@@ -698,7 +707,7 @@ export default class AuthService {
});
} else {
// Save User Nbr Password Trials
- await UserStorage.saveUserPassword(tenantID, user.id, { passwordWrongNbrTrials });
+ await UserStorage.saveUserPassword(tenant, user.id, { passwordWrongNbrTrials });
// Log
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -712,10 +721,10 @@ export default class AuthService {
}
}
- public static async userLoginSucceeded(action: ServerAction, tenantID: string, user: User, req: Request, res: Response, next: NextFunction): Promise {
+ public static async userLoginSucceeded(action: ServerAction, tenant: Tenant, user: User, req: Request, res: Response, next: NextFunction): Promise {
// Password / Login OK
await Logging.logSecurityInfo({
- tenantID: tenantID,
+ tenantID: tenant.id,
user: user,
module: MODULE_NAME, method: 'checkUserLogin',
action: action, message: 'User logged in successfully'
@@ -723,8 +732,8 @@ export default class AuthService {
// Set Eula Info on Login Only
if (action === ServerAction.LOGIN) {
// Save EULA
- const endUserLicenseAgreement = await UserStorage.getEndUserLicenseAgreement(tenantID, Utils.getLanguageFromLocale(user.locale));
- await UserStorage.saveUserEULA(tenantID, user.id,
+ const endUserLicenseAgreement = await UserStorage.getEndUserLicenseAgreement(tenant, Utils.getLanguageFromLocale(user.locale));
+ await UserStorage.saveUserEULA(tenant, user.id,
{
eulaAcceptedOn: new Date(),
eulaAcceptedVersion: endUserLicenseAgreement.version,
@@ -733,12 +742,12 @@ export default class AuthService {
);
}
// Reset wrong number of trial
- await UserStorage.saveUserPassword(tenantID, user.id,
+ await UserStorage.saveUserPassword(tenant, user.id,
{ passwordWrongNbrTrials: 0, passwordBlockedUntil: null, passwordResetHash: null });
// Get the tags (limited) to avoid an overweighted token
- const tags = await TagStorage.getTags(tenantID, { userIDs: [user.id] }, Constants.DB_PARAMS_DEFAULT_RECORD);
+ const tags = await TagStorage.getTags(tenant.id, { userIDs: [user.id] }, Constants.DB_PARAMS_DEFAULT_RECORD);
// Yes: build token
- const payload = await Authorizations.buildUserToken(tenantID, user, tags.result);
+ const payload = await Authorizations.buildUserToken(tenant, user, tags.result);
// Build token
let token: string;
// Role Demo?
@@ -777,7 +786,7 @@ export default class AuthService {
return (tenant ? tenant : null);
}
- public static async checkUserLogin(action: ServerAction, tenantID: string, user: User,
+ public static async checkUserLogin(action: ServerAction, tenant: Tenant, user: User,
filteredRequest: Partial, req: Request, res: Response, next: NextFunction): Promise {
// User Found?
if (!user) {
@@ -837,10 +846,10 @@ export default class AuthService {
});
}
// Login OK
- await AuthService.userLoginSucceeded(action, tenantID, user, req, res, next);
+ await AuthService.userLoginSucceeded(action, tenant, user, req, res, next);
} else {
// Login KO
- await AuthService.userLoginWrongPassword(action, tenantID, user, req, res, next);
+ await AuthService.userLoginWrongPassword(action, tenant, user, req, res, next);
}
}
}
diff --git a/src/server/rest/v1/service/AuthorizationService.ts b/src/server/rest/v1/service/AuthorizationService.ts
index fee2c6db72..ed629a0b1d 100644
--- a/src/server/rest/v1/service/AuthorizationService.ts
+++ b/src/server/rest/v1/service/AuthorizationService.ts
@@ -171,7 +171,7 @@ export default class AuthorizationService {
// Not an Admin?
if (userToken.role !== UserRole.ADMIN) {
// Get Site IDs for which user is admin from db
- const siteAdminSiteIDs = await AuthorizationService.getSiteAdminSiteIDs(tenant.id, userToken);
+ const siteAdminSiteIDs = await AuthorizationService.getSiteAdminSiteIDs(tenant, userToken);
// Check Site
if (!Utils.isEmptyArray(siteAdminSiteIDs) && siteAdminSiteIDs.includes(siteArea.siteID)) {
// Site Authorized, now check Assets
@@ -580,9 +580,9 @@ export default class AuthorizationService {
return authorizationFilters;
}
- public static async getSiteAdminSiteIDs(tenantID: string, userToken: UserToken): Promise {
+ public static async getSiteAdminSiteIDs(tenant: Tenant, userToken: UserToken): Promise {
// Get the Sites where the user is Site Admin
- const userSites = await UserStorage.getUserSites(tenantID,
+ const userSites = await UserStorage.getUserSites(tenant,
{
userIDs: [userToken.id],
siteAdmin: true
@@ -592,9 +592,9 @@ export default class AuthorizationService {
return userSites.result.map((userSite) => userSite.siteID);
}
- private static async getSiteOwnerSiteIDs(tenantID: string, userToken: UserToken): Promise {
+ private static async getSiteOwnerSiteIDs(tenant: Tenant, userToken: UserToken): Promise {
// Get the Sites where the user is Site Owner
- const userSites = await UserStorage.getUserSites(tenantID,
+ const userSites = await UserStorage.getUserSites(tenant,
{
userIDs: [userToken.id],
siteOwner: true
@@ -660,8 +660,8 @@ export default class AuthorizationService {
if (userToken.role !== UserRole.ADMIN && userToken.role !== UserRole.SUPER_ADMIN) {
if (Utils.isTenantComponentActive(tenant, TenantComponents.ORGANIZATION)) {
// Get Site IDs from Site Admin & Site Owner flag
- const siteAdminSiteIDs = await AuthorizationService.getSiteAdminSiteIDs(tenant.id, userToken);
- const siteOwnerSiteIDs = await AuthorizationService.getSiteOwnerSiteIDs(tenant.id, userToken);
+ const siteAdminSiteIDs = await AuthorizationService.getSiteAdminSiteIDs(tenant, userToken);
+ const siteOwnerSiteIDs = await AuthorizationService.getSiteOwnerSiteIDs(tenant, userToken);
const allSites = _.uniq([...siteAdminSiteIDs, ...siteOwnerSiteIDs]);
if (!Utils.isEmptyArray(allSites)) {
// Force the filters
diff --git a/src/server/rest/v1/service/BillingService.ts b/src/server/rest/v1/service/BillingService.ts
index a65d08dad1..a176494506 100644
--- a/src/server/rest/v1/service/BillingService.ts
+++ b/src/server/rest/v1/service/BillingService.ts
@@ -204,7 +204,7 @@ export default class BillingService {
});
}
// Get user
- const userToSynchronize = await UserStorage.getUser(req.user.tenantID, filteredRequest.id);
+ const userToSynchronize = await UserStorage.getUser(req.tenant, filteredRequest.id);
UtilsService.assertObjectExists(action, userToSynchronize, `User ID '${filteredRequest.id}' does not exist`,
MODULE_NAME, 'handleSynchronizeUser', req.user);
// Get the lock
@@ -257,7 +257,7 @@ export default class BillingService {
});
}
// Get user
- const user = await UserStorage.getUser(req.user.tenantID, filteredRequest.id);
+ const user = await UserStorage.getUser(req.tenant, filteredRequest.id);
UtilsService.assertObjectExists(action, user, `User ID '${filteredRequest.id}' does not exist`,
MODULE_NAME, 'handleSynchronizeUser', req.user);
// Get the User lock
@@ -407,7 +407,7 @@ export default class BillingService {
let user: User;
if (!Authorizations.isAdmin(req.user)) {
// Get the User
- user = await UserStorage.getUser(req.user.tenantID, req.user.id);
+ user = await UserStorage.getUser(req.tenant, req.user.id);
UtilsService.assertObjectExists(action, user, `User ID '${req.user.id}' does not exist`,
MODULE_NAME, 'handleSynchronizeUserInvoices', req.user);
}
@@ -477,7 +477,7 @@ export default class BillingService {
}
const filteredRequest = BillingSecurity.filterForceSynchronizeUserInvoicesRequest(req.body);
// Get the User
- const user = await UserStorage.getUser(req.user.tenantID, filteredRequest.userID);
+ const user = await UserStorage.getUser(req.tenant, filteredRequest.userID);
UtilsService.assertObjectExists(action, user, `User ID '${filteredRequest.userID}' does not exist`,
MODULE_NAME, 'handleForceSynchronizeUserInvoices', req.user);
// Get the Invoice lock
@@ -536,7 +536,7 @@ export default class BillingService {
});
}
// Get user - ACHTUNG user !== req.user
- const user: User = await UserStorage.getUser(req.user.tenantID, filteredRequest.userID);
+ const user: User = await UserStorage.getUser(req.tenant, filteredRequest.userID);
UtilsService.assertObjectExists(action, user, `User ID '${filteredRequest.userID}' does not exist`,
MODULE_NAME, 'handleSetupPaymentMethod', req.user);
// Invoke the billing implementation
@@ -576,7 +576,7 @@ export default class BillingService {
});
}
// Get user - ACHTUNG user !== req.user
- const user: User = await UserStorage.getUser(req.user.tenantID, filteredRequest.userID);
+ const user: User = await UserStorage.getUser(req.tenant, filteredRequest.userID);
UtilsService.assertObjectExists(action, user, `User ID '${filteredRequest.userID}' does not exist`,
MODULE_NAME, 'handleBillingGetPaymentMethods', req.user);
// Invoke the billing implementation
@@ -624,7 +624,7 @@ export default class BillingService {
});
}
const userID = filteredRequest.userID;
- const user: User = await UserStorage.getUser(req.user.tenantID, userID);
+ const user: User = await UserStorage.getUser(req.tenant, userID);
UtilsService.assertObjectExists(action, user, `User ID '${userID}' does not exist`,
MODULE_NAME, 'handleBillingDeletePaymentMethod', req.user);
// Invoke the billing implementation
diff --git a/src/server/rest/v1/service/ChargingStationService.ts b/src/server/rest/v1/service/ChargingStationService.ts
index bed6816320..f195bae57e 100644
--- a/src/server/rest/v1/service/ChargingStationService.ts
+++ b/src/server/rest/v1/service/ChargingStationService.ts
@@ -55,7 +55,7 @@ export default class ChargingStationService {
// Filter
const filteredRequest = ChargingStationValidator.getInstance().validateChargingStationUpdateParametersReq({ ...req.params, ...req.body });
// Check the Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, filteredRequest.id);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, filteredRequest.id);
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${filteredRequest.id}' does not exist.`,
MODULE_NAME, 'handleUpdateChargingStationParams', req.user);
// OCPI Charging Station
@@ -72,7 +72,7 @@ export default class ChargingStationService {
let siteArea: SiteArea = null;
// Check the Site Area
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION) && filteredRequest.siteAreaID) {
- siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, filteredRequest.siteAreaID, { withSite: true });
+ siteArea = await SiteAreaStorage.getSiteArea(req.tenant, filteredRequest.siteAreaID, { withSite: true });
UtilsService.assertObjectExists(action, siteArea, `Site Area ID '${filteredRequest.siteAreaID}' does not exist.`,
MODULE_NAME, 'handleUpdateChargingStationParams', req.user);
}
@@ -302,7 +302,7 @@ export default class ChargingStationService {
chargingStation.lastChangedBy = { 'id': req.user.id };
chargingStation.lastChangedOn = new Date();
// Update
- await ChargingStationStorage.saveChargingStation(req.user.tenantID, chargingStation);
+ await ChargingStationStorage.saveChargingStation(req.tenant, chargingStation);
// Reboot the Charging Station to reapply the templates
if (resetAndApplyTemplate) {
try {
@@ -350,7 +350,7 @@ export default class ChargingStationService {
});
}
// Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, filteredRequest.chargingStationID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, filteredRequest.chargingStationID);
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${filteredRequest.chargingStationID}' does not exist.`,
MODULE_NAME, 'handleChargingStationLimitPower', req.user);
// Charge Point
@@ -372,7 +372,7 @@ export default class ChargingStationService {
let siteID = null;
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION)) {
// Get the Site Area
- const siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, chargingStation.siteAreaID);
+ const siteArea = await SiteAreaStorage.getSiteArea(req.tenant, chargingStation.siteAreaID);
siteID = siteArea ? siteArea.siteID : null;
}
// Check Auth
@@ -409,7 +409,7 @@ export default class ChargingStationService {
});
}
// Check Charging Profile
- const chargingProfiles = await ChargingStationStorage.getChargingProfiles(req.user.tenantID,
+ const chargingProfiles = await ChargingStationStorage.getChargingProfiles(req.tenant,
{ chargingStationIDs: [chargingStation.id], connectorID: 0 },
Constants.DB_PARAMS_MAX_LIMIT);
const updatedChargingProfiles: ChargingProfile[] = Utils.cloneObject(chargingProfiles.result);
@@ -517,7 +517,7 @@ export default class ChargingStationService {
projectFields = projectFields.filter((projectField) => httpProjectFields.includes(projectField));
}
// Get the profiles
- const chargingProfiles = await ChargingStationStorage.getChargingProfiles(req.user.tenantID,
+ const chargingProfiles = await ChargingStationStorage.getChargingProfiles(req.tenant,
{
search: filteredRequest.Search,
chargingStationIDs: filteredRequest.ChargingStationID ? filteredRequest.ChargingStationID.split('|') : null,
@@ -547,7 +547,7 @@ export default class ChargingStationService {
const filteredRequest = ChargingStationValidator.getInstance().validateSmartChargingTriggerReq(req.query);
UtilsService.assertIdIsProvided(action, filteredRequest.SiteAreaID, MODULE_NAME, 'handleTriggerSmartCharging', req.user);
// Get Site Area
- const siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, filteredRequest.SiteAreaID);
+ const siteArea = await SiteAreaStorage.getSiteArea(req.tenant, filteredRequest.SiteAreaID);
UtilsService.assertObjectExists(action, siteArea, `Site Area ID '${filteredRequest.SiteAreaID}' does not exist`,
MODULE_NAME, 'handleTriggerSmartCharging', req.user);
// Check auth
@@ -614,7 +614,7 @@ export default class ChargingStationService {
// Check ConnectorID
UtilsService.assertIdIsProvided(action, filteredRequest.ConnectorID, MODULE_NAME, 'handleGenerateQrCodeForConnector', req.user);
// Get the Charging Station`
- const chargingStation: ChargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, filteredRequest.ChargingStationID);
+ const chargingStation: ChargingStation = await ChargingStationStorage.getChargingStation(req.tenant, filteredRequest.ChargingStationID);
// Found ChargingStation ?
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${filteredRequest.ChargingStationID}' does not exist`,
MODULE_NAME, 'handleGetChargingStationOcppParameters', req.user);
@@ -647,7 +647,7 @@ export default class ChargingStationService {
// Filter
const filteredRequest = ChargingStationValidator.getInstance().validateChargingProfileUpdateReq({ ...req.params, ...req.body });
// Check for existing charging profile
- const chargingProfile = await ChargingStationStorage.getChargingProfile(req.tenant.id, filteredRequest.id);
+ const chargingProfile = await ChargingStationStorage.getChargingProfile(req.tenant, filteredRequest.id);
UtilsService.assertObjectExists(action, chargingProfile, `Charging Profile ID '${filteredRequest.id}' does not exist.`,
MODULE_NAME, 'handleUpdateChargingProfile', req.user);
const chargingProfileID = await ChargingStationService.setAndSaveChargingProfile(filteredRequest, action, req);
@@ -659,11 +659,11 @@ export default class ChargingStationService {
// Check existence
const chargingProfileID = ChargingStationValidator.getInstance().validateChargingProfileDeleteReq(req.query).ID;
// Get Profile
- const chargingProfile = await ChargingStationStorage.getChargingProfile(req.user.tenantID, chargingProfileID);
+ const chargingProfile = await ChargingStationStorage.getChargingProfile(req.tenant, chargingProfileID);
UtilsService.assertObjectExists(action, chargingProfile, `Charging Profile ID '${chargingProfileID}' does not exist.`,
MODULE_NAME, 'handleDeleteChargingProfile', req.user);
// Get Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, chargingProfile.chargingStationID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, chargingProfile.chargingStationID);
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${chargingProfile.chargingStationID}' does not exist.`,
MODULE_NAME, 'handleDeleteChargingProfile', req.user);
// OCPI Charging Station
@@ -681,7 +681,7 @@ export default class ChargingStationService {
let siteID = null;
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION)) {
// Get the Site Area
- const siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, chargingStation.siteAreaID);
+ const siteArea = await SiteAreaStorage.getSiteArea(req.tenant, chargingStation.siteAreaID);
siteID = siteArea ? siteArea.siteID : null;
}
// Check Auth
@@ -720,7 +720,7 @@ export default class ChargingStationService {
// Check
UtilsService.assertIdIsProvided(action, filteredRequest.ChargingStationID, MODULE_NAME, 'handleGetChargingStationOcppParameters', req.user);
// Get the Charging Station`
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, filteredRequest.ChargingStationID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, filteredRequest.ChargingStationID);
// Found?
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${filteredRequest.ChargingStationID}' does not exist`,
MODULE_NAME, 'handleGetChargingStationOcppParameters', req.user);
@@ -735,7 +735,7 @@ export default class ChargingStationService {
});
}
// Get the Parameters
- const parameters = await ChargingStationStorage.getOcppParameters(req.user.tenantID, chargingStation.id);
+ const parameters = await ChargingStationStorage.getOcppParameters(req.tenant, chargingStation.id);
// Return the result
res.json(parameters);
next();
@@ -756,7 +756,7 @@ export default class ChargingStationService {
});
}
// Get the Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, filteredRequest.chargingStationID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, filteredRequest.chargingStationID);
// Found?
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${filteredRequest.chargingStationID}' does not exist`,
MODULE_NAME, 'handleRequestChargingStationOcppParameters', req.user);
@@ -776,7 +776,7 @@ export default class ChargingStationService {
UtilsService.assertIdIsProvided(action, chargingStationID, MODULE_NAME,
'handleDeleteChargingStation', req.user);
// Get
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, chargingStationID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, chargingStationID);
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${chargingStationID}' does not exist`,
MODULE_NAME, 'handleDeleteChargingStation', req.user);
// OCPI Charging Station
@@ -793,7 +793,7 @@ export default class ChargingStationService {
let siteID = null;
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION)) {
// Get the Site Area
- const siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, chargingStation.siteAreaID);
+ const siteArea = await SiteAreaStorage.getSiteArea(req.tenant, chargingStation.siteAreaID);
siteID = siteArea ? siteArea.siteID : null;
}
// Check auth
@@ -820,7 +820,7 @@ export default class ChargingStationService {
}
for (const connector of chargingStation.connectors) {
if (connector && connector.currentTransactionID) {
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, connector.currentTransactionID);
+ const transaction = await TransactionStorage.getTransaction(req.tenant, connector.currentTransactionID);
if (transaction && !transaction.stop) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -873,16 +873,16 @@ export default class ChargingStationService {
// Set as deleted
chargingStation.deleted = true;
// Check if charging station has had transactions
- const transactions = await TransactionStorage.getTransactions(req.user.tenantID,
+ const transactions = await TransactionStorage.getTransactions(req.tenant,
{ chargeBoxIDs: [chargingStation.id] }, Constants.DB_PARAMS_SINGLE_RECORD, ['id']);
if (!Utils.isEmptyArray(transactions.result)) {
// Delete logically
- await ChargingStationStorage.saveChargingStation(req.tenant.id, chargingStation);
+ await ChargingStationStorage.saveChargingStation(req.tenant, chargingStation);
// Delete Charging Profiles
- await ChargingStationStorage.deleteChargingProfiles(req.tenant.id, chargingStation.id);
+ await ChargingStationStorage.deleteChargingProfiles(req.tenant, chargingStation.id);
} else {
// Delete physically
- await ChargingStationStorage.deleteChargingStation(req.user.tenantID, chargingStation.id);
+ await ChargingStationStorage.deleteChargingStation(req.tenant, chargingStation.id);
}
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
@@ -946,7 +946,7 @@ export default class ChargingStationService {
res.attachment('exported-ocpp-params.csv');
let writeHeader = true;
for (const chargingStation of chargingStations.result) {
- const ocppParameters = await ChargingStationStorage.getOcppParameters(req.user.tenantID, chargingStation.id);
+ const ocppParameters = await ChargingStationStorage.getOcppParameters(req.tenant, chargingStation.id);
// Get OCPP Params
const dataToExport = ChargingStationService.convertOCPPParamsToCSV({
params: ocppParameters.result,
@@ -1027,7 +1027,7 @@ export default class ChargingStationService {
projectFields = projectFields.filter((projectField) => projectHttpFields.includes(projectField));
}
// Get Charging Stations
- const chargingStations = await ChargingStationStorage.getChargingStationsInError(req.user.tenantID,
+ const chargingStations = await ChargingStationStorage.getChargingStationsInError(req.tenant,
{
search: filteredRequest.Search,
siteIDs: Authorizations.getAuthorizedSiteIDs(req.user, filteredRequest.SiteID ? filteredRequest.SiteID.split('|') : null),
@@ -1267,7 +1267,7 @@ export default class ChargingStationService {
return { count: 0, result: [] };
}
// Get Charging Stations
- const chargingStations = await ChargingStationStorage.getChargingStations(req.user.tenantID,
+ const chargingStations = await ChargingStationStorage.getChargingStations(req.tenant,
{
search: filteredRequest.Search,
withNoSiteArea: filteredRequest.WithNoSiteArea,
@@ -1508,7 +1508,7 @@ export default class ChargingStationService {
// Custom param?
if (params.custom) {
// Get OCPP Parameters from DB
- const ocppParametersFromDB = await ChargingStationStorage.getOcppParameters(tenant.id, chargingStation.id);
+ const ocppParametersFromDB = await ChargingStationStorage.getOcppParameters(tenant, chargingStation.id);
// Set new structure
const chargingStationOcppParameters: ChargingStationOcppParameters = {
id: chargingStation.id,
@@ -1523,7 +1523,7 @@ export default class ChargingStationService {
// Save config
if (foundOcppParam.custom) {
// Save
- await ChargingStationStorage.saveOcppParameters(tenant.id, chargingStationOcppParameters);
+ await ChargingStationStorage.saveOcppParameters(tenant, chargingStationOcppParameters);
} else {
// Not a custom param: refresh the whole OCPP Parameters
await OCPPUtils.requestAndSaveChargingStationOcppParameters(tenant, chargingStation);
@@ -1532,7 +1532,7 @@ export default class ChargingStationService {
// Add custom param
chargingStationOcppParameters.configuration.push(params);
// Save
- await ChargingStationStorage.saveOcppParameters(tenant.id, chargingStationOcppParameters);
+ await ChargingStationStorage.saveOcppParameters(tenant, chargingStationOcppParameters);
}
} else {
// Refresh the whole OCPP Parameters
@@ -1640,7 +1640,7 @@ export default class ChargingStationService {
private static async setAndSaveChargingProfile(filteredRequest: ChargingProfile, action: ServerAction, req: Request): Promise {
// Check existence
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, filteredRequest.chargingStationID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, filteredRequest.chargingStationID);
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${filteredRequest.chargingStationID}' does not exist.`,
MODULE_NAME, 'setAndSaveChargingProfile', req.user);
// OCPI Charging Station
@@ -1662,7 +1662,7 @@ export default class ChargingStationService {
let siteID = null;
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION)) {
// Get the Site Area
- const siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, chargingStation.siteAreaID);
+ const siteArea = await SiteAreaStorage.getSiteArea(req.tenant, chargingStation.siteAreaID);
siteID = siteArea ? siteArea.siteID : null;
}
// Check Auth
@@ -1802,7 +1802,7 @@ export default class ChargingStationService {
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.CAR)) {
if (result?.status === OCPPRemoteStartStopStatus.ACCEPTED) {
if (filteredRequest.carID && filteredRequest.carID !== user.lastSelectedCarID) {
- await UserStorage.saveUserLastSelectedCarID(req.user.tenantID, user.id, filteredRequest.carID);
+ await UserStorage.saveUserLastSelectedCarID(req.tenant, user.id, filteredRequest.carID);
}
}
}
@@ -1825,7 +1825,7 @@ export default class ChargingStationService {
}
// Get Transaction
const transaction = await TransactionStorage.getTransaction(
- req.user.tenantID, filteredRequest.args.transactionId, { withUser: true });
+ req.tenant, 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
@@ -1855,7 +1855,7 @@ export default class ChargingStationService {
userID: req.user.id
};
// Save Transaction
- await TransactionStorage.saveTransaction(req.user.tenantID, transaction);
+ await TransactionStorage.saveTransaction(req.tenant, transaction);
// Ok: Execute it
return ChargingStationService.executeChargingStationCommand(
req.tenant, req.user, chargingStation, action, command, filteredRequest.args);
diff --git a/src/server/rest/v1/service/LoggingService.ts b/src/server/rest/v1/service/LoggingService.ts
index fa7a4bda92..f6c7e86399 100644
--- a/src/server/rest/v1/service/LoggingService.ts
+++ b/src/server/rest/v1/service/LoggingService.ts
@@ -105,7 +105,7 @@ export default class LoggingService {
// Add filter for Site Admins
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION) && Authorizations.isSiteAdmin(req.user)) {
// Optimization: Retrieve Charging Stations to get the logs only for the Site Admin user
- const chargingStations = await ChargingStationStorage.getChargingStations(req.user.tenantID,
+ const chargingStations = await ChargingStationStorage.getChargingStations(req.tenant,
{ siteIDs: req.user.sitesAdmin, withSiteArea: true }, Constants.DB_PARAMS_MAX_LIMIT);
// Check if Charging Station is already filtered
if (chargingStations.count === 0) {
diff --git a/src/server/rest/v1/service/NotificationService.ts b/src/server/rest/v1/service/NotificationService.ts
index 12c7c36160..317ff72df1 100644
--- a/src/server/rest/v1/service/NotificationService.ts
+++ b/src/server/rest/v1/service/NotificationService.ts
@@ -69,7 +69,7 @@ export default class NotificationService {
// Save mobile number
if (filteredRequest.mobile && user.mobile !== filteredRequest.mobile) {
user.mobile = filteredRequest.mobile;
- await UserStorage.saveUserMobilePhone(req.user.tenantID, user.id, { mobile: filteredRequest.mobile });
+ await UserStorage.saveUserMobilePhone(req.tenant, user.id, { mobile: filteredRequest.mobile });
}
// Set
const endUserErrorNotification: EndUserErrorNotification = {
diff --git a/src/server/rest/v1/service/RegistrationTokenService.ts b/src/server/rest/v1/service/RegistrationTokenService.ts
index 527bbd18f3..4865b83e01 100644
--- a/src/server/rest/v1/service/RegistrationTokenService.ts
+++ b/src/server/rest/v1/service/RegistrationTokenService.ts
@@ -27,7 +27,7 @@ export default class RegistrationTokenService {
// Check Auth
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION) && filteredRequest.siteAreaID) {
// Get the Site Area
- const siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, filteredRequest.siteAreaID);
+ const siteArea = await SiteAreaStorage.getSiteArea(req.tenant, filteredRequest.siteAreaID);
UtilsService.assertObjectExists(action, siteArea, `Site Area ID '${filteredRequest.siteAreaID}' does not exist`,
MODULE_NAME, 'handleCreateRegistrationToken', req.user);
if (!await Authorizations.canCreateRegistrationToken(req.user, siteArea.siteID)) {
@@ -79,7 +79,7 @@ export default class RegistrationTokenService {
createdOn: new Date()
};
// Save
- registrationToken.id = await RegistrationTokenStorage.saveRegistrationToken(req.user.tenantID, registrationToken);
+ registrationToken.id = await RegistrationTokenStorage.saveRegistrationToken(req.tenant, registrationToken);
// Build OCPP URLs
registrationToken.ocpp15SOAPUrl = Utils.buildOCPPServerURL(req.user.tenantID, OCPPVersion.VERSION_15, OCPPProtocol.SOAP, registrationToken.id);
registrationToken.ocpp16SOAPUrl = Utils.buildOCPPServerURL(req.user.tenantID, OCPPVersion.VERSION_16, OCPPProtocol.SOAP, registrationToken.id);
@@ -107,13 +107,13 @@ export default class RegistrationTokenService {
});
}
// Get Token
- const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.user.tenantID, filteredRequest.id);
+ const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.tenant, filteredRequest.id);
UtilsService.assertObjectExists(action, registrationToken, `Token ID '${filteredRequest.id}' does not exist`,
MODULE_NAME, 'handleUpdateRegistrationToken', req.user);
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION)) {
// Check Site Area if it's provided
if (filteredRequest.siteAreaID) {
- const siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, filteredRequest.siteAreaID);
+ const siteArea = await SiteAreaStorage.getSiteArea(req.tenant, filteredRequest.siteAreaID);
UtilsService.assertObjectExists(action, siteArea, `Site Area ID '${filteredRequest.siteAreaID}' does not exist`,
MODULE_NAME, 'handleUpdateRegistrationToken', req.user);
}
@@ -136,7 +136,7 @@ export default class RegistrationTokenService {
registrationToken.lastChangedOn = new Date();
registrationToken.revocationDate = null;
// Save
- registrationToken.id = await RegistrationTokenStorage.saveRegistrationToken(req.user.tenantID, registrationToken);
+ registrationToken.id = await RegistrationTokenStorage.saveRegistrationToken(req.tenant, registrationToken);
// Build OCPP URLs
registrationToken.ocpp15SOAPUrl = Utils.buildOCPPServerURL(req.user.tenantID, OCPPVersion.VERSION_15, OCPPProtocol.SOAP, registrationToken.id);
registrationToken.ocpp16SOAPUrl = Utils.buildOCPPServerURL(req.user.tenantID, OCPPVersion.VERSION_16, OCPPProtocol.SOAP, registrationToken.id);
@@ -153,7 +153,7 @@ export default class RegistrationTokenService {
const tokenID = RegistrationTokenSecurity.filterRegistrationTokenByIDRequest(req.query);
UtilsService.assertIdIsProvided(action, tokenID, MODULE_NAME, 'handleDeleteRegistrationToken', req.user);
// Get Token
- const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.user.tenantID, tokenID);
+ const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.tenant, tokenID);
UtilsService.assertObjectExists(action, registrationToken, `Registration Token ID '${tokenID}' does not exist`,
MODULE_NAME, 'handleDeleteRegistrationToken', req.user);
// Check auth
@@ -167,7 +167,7 @@ export default class RegistrationTokenService {
});
}
// Delete
- await RegistrationTokenStorage.deleteRegistrationToken(req.user.tenantID, tokenID);
+ await RegistrationTokenStorage.deleteRegistrationToken(req.tenant, tokenID);
// Log
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
@@ -185,7 +185,7 @@ export default class RegistrationTokenService {
const tokenID = RegistrationTokenSecurity.filterRegistrationTokenByIDRequest(req.query);
UtilsService.assertIdIsProvided(action, tokenID, MODULE_NAME, 'handleDeleteRegistrationToken', req.user);
// Get Token
- const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.user.tenantID, tokenID);
+ const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.tenant, tokenID);
UtilsService.assertObjectExists(action, registrationToken, `Registration Token ID '${tokenID}' does not exist`,
MODULE_NAME, 'handleRevokeRegistrationToken', req.user);
// Check auth
@@ -212,7 +212,7 @@ export default class RegistrationTokenService {
registrationToken.revocationDate = new Date();
registrationToken.lastChangedBy = { 'id': req.user.id };
registrationToken.lastChangedOn = new Date();
- await RegistrationTokenStorage.saveRegistrationToken(req.user.tenantID, registrationToken);
+ await RegistrationTokenStorage.saveRegistrationToken(req.tenant, registrationToken);
// Log
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
@@ -244,7 +244,7 @@ export default class RegistrationTokenService {
userProject = [ 'createdBy.name', 'createdBy.firstName', 'lastChangedBy.name', 'lastChangedBy.firstName' ];
}
// Get the tokens
- const registrationTokens = await RegistrationTokenStorage.getRegistrationTokens(req.user.tenantID,
+ const registrationTokens = await RegistrationTokenStorage.getRegistrationTokens(req.tenant,
{
siteAreaID: filteredRequest.SiteAreaID,
siteIDs: Authorizations.getAuthorizedSiteAdminIDs(req.user, null),
@@ -283,7 +283,7 @@ export default class RegistrationTokenService {
userProject = [ 'createdBy.name', 'createdBy.firstName', 'lastChangedBy.name', 'lastChangedBy.firstName' ];
}
// Get the token
- const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.user.tenantID,
+ const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.tenant,
filteredRequest,
[
'id', 'status', 'description', 'createdOn', 'lastChangedOn', 'expirationDate', 'revocationDate',
diff --git a/src/server/rest/v1/service/SessionHashService.ts b/src/server/rest/v1/service/SessionHashService.ts
index 0ab463ae91..06bf43c259 100644
--- a/src/server/rest/v1/service/SessionHashService.ts
+++ b/src/server/rest/v1/service/SessionHashService.ts
@@ -30,7 +30,7 @@ export default class SessionHashService {
tenant = await TenantStorage.getTenant(tenantID);
}
// Get User
- const user = await UserStorage.getUser(tenantID, userID);
+ const user = await UserStorage.getUser(tenant, userID);
// User or Tenant no longer exists
if (!tenant || !user) {
return true;
diff --git a/src/server/rest/v1/service/SiteAreaService.ts b/src/server/rest/v1/service/SiteAreaService.ts
index a0818a5dcb..35f104b1e6 100644
--- a/src/server/rest/v1/service/SiteAreaService.ts
+++ b/src/server/rest/v1/service/SiteAreaService.ts
@@ -20,6 +20,7 @@ import SiteAreaSecurity from './security/SiteAreaSecurity';
import SiteAreaStorage from '../../../../storage/mongodb/SiteAreaStorage';
import SmartChargingFactory from '../../../../integration/smart-charging/SmartChargingFactory';
import TenantComponents from '../../../../types/TenantComponents';
+import TenantStorage from '../../../../storage/mongodb/TenantStorage';
import Utils from '../../../../utils/Utils';
import UtilsService from './UtilsService';
import moment from 'moment';
@@ -42,9 +43,9 @@ export default class SiteAreaService {
req.tenant, req.user, siteArea, filteredRequest.assetIDs, action);
// Save
if (action === ServerAction.ADD_ASSET_TO_SITE_AREA) {
- await SiteAreaStorage.addAssetsToSiteArea(req.user.tenantID, siteArea, assets.map((asset) => asset.id));
+ await SiteAreaStorage.addAssetsToSiteArea(req.tenant, siteArea, assets.map((asset) => asset.id));
} else {
- await SiteAreaStorage.removeAssetsFromSiteArea(req.user.tenantID, filteredRequest.siteAreaID, assets.map((asset) => asset.id));
+ await SiteAreaStorage.removeAssetsFromSiteArea(req.tenant, filteredRequest.siteAreaID, assets.map((asset) => asset.id));
}
// Log
await Logging.logSecurityInfo({
@@ -95,10 +96,10 @@ export default class SiteAreaService {
// Save
if (action === ServerAction.ADD_CHARGING_STATIONS_TO_SITE_AREA) {
await SiteAreaStorage.addChargingStationsToSiteArea(
- req.user.tenantID, siteArea, chargingStations.map((chargingStation) => chargingStation.id));
+ req.tenant, siteArea, chargingStations.map((chargingStation) => chargingStation.id));
} else {
await SiteAreaStorage.removeChargingStationsFromSiteArea(
- req.user.tenantID, filteredRequest.siteAreaID, chargingStations.map((chargingStation) => chargingStation.id));
+ req.tenant, filteredRequest.siteAreaID, chargingStations.map((chargingStation) => chargingStation.id));
}
// Log
await Logging.logSecurityInfo({
@@ -124,7 +125,7 @@ export default class SiteAreaService {
const siteArea = await UtilsService.checkAndGetSiteAreaAuthorization(
req.tenant, req.user, siteAreaID, Action.DELETE, action);
// Delete
- await SiteAreaStorage.deleteSiteArea(req.user.tenantID, siteArea.id);
+ await SiteAreaStorage.deleteSiteArea(req.tenant, siteArea.id);
// Log
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
@@ -163,7 +164,8 @@ export default class SiteAreaService {
// Check mandatory fields
UtilsService.assertIdIsProvided(action, filteredRequest.ID, MODULE_NAME, 'handleGetSiteAreaImage', req.user);
// Get it
- const siteAreaImage = await SiteAreaStorage.getSiteAreaImage(filteredRequest.TenantID, filteredRequest.ID);
+ const siteAreaImage = await SiteAreaStorage.getSiteAreaImage(
+ await TenantStorage.getTenant(filteredRequest.TenantID), filteredRequest.ID);
// Return
if (siteAreaImage?.image) {
let header = 'image';
@@ -196,7 +198,7 @@ export default class SiteAreaService {
return;
}
// Get the SiteAreas
- const siteAreas = await SiteAreaStorage.getSiteAreas(req.user.tenantID,
+ const siteAreas = await SiteAreaStorage.getSiteAreas(req.tenant,
{
issuer: filteredRequest.Issuer,
search: filteredRequest.Search,
@@ -300,7 +302,7 @@ export default class SiteAreaService {
createdOn: new Date()
} as SiteArea;
// Save
- newSiteArea.id = await SiteAreaStorage.saveSiteArea(req.user.tenantID, newSiteArea, true);
+ newSiteArea.id = await SiteAreaStorage.saveSiteArea(req.tenant, newSiteArea, true);
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
user: req.user, module: MODULE_NAME, method: 'handleCreateSiteArea',
@@ -367,7 +369,7 @@ export default class SiteAreaService {
siteArea.lastChangedBy = { 'id': req.user.id };
siteArea.lastChangedOn = new Date();
// Save
- await SiteAreaStorage.saveSiteArea(req.user.tenantID, siteArea, Utils.objectHasProperty(filteredRequest, 'image'));
+ await SiteAreaStorage.saveSiteArea(req.tenant, siteArea, Utils.objectHasProperty(filteredRequest, 'image'));
// Retrigger Smart Charging
if (filteredRequest.smartCharging) {
// FIXME: the lock acquisition can wait for 30s before timeout and the whole code execution timeout at 3s
diff --git a/src/server/rest/v1/service/StatisticService.ts b/src/server/rest/v1/service/StatisticService.ts
index 6a92f53c59..dcd08247af 100644
--- a/src/server/rest/v1/service/StatisticService.ts
+++ b/src/server/rest/v1/service/StatisticService.ts
@@ -39,7 +39,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getChargingStationStats(
- req.user.tenantID, filter, StatsGroupBy.CONSUMPTION);
+ req.tenant, filter, StatsGroupBy.CONSUMPTION);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.CHARGING_STATION);
@@ -69,7 +69,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getChargingStationStats(
- req.user.tenantID, filter, StatsGroupBy.USAGE);
+ req.tenant, filter, StatsGroupBy.USAGE);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.CHARGING_STATION);
@@ -99,7 +99,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getChargingStationStats(
- req.user.tenantID, filter, StatsGroupBy.INACTIVITY);
+ req.tenant, filter, StatsGroupBy.INACTIVITY);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.CHARGING_STATION);
@@ -129,7 +129,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getChargingStationStats(
- req.user.tenantID, filter, StatsGroupBy.TRANSACTIONS);
+ req.tenant, filter, StatsGroupBy.TRANSACTIONS);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.CHARGING_STATION);
@@ -159,7 +159,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getChargingStationStats(
- req.user.tenantID, filter, StatsGroupBy.PRICING);
+ req.tenant, filter, StatsGroupBy.PRICING);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.CHARGING_STATION);
@@ -189,7 +189,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getUserStats(
- req.user.tenantID, filter, StatsGroupBy.CONSUMPTION);
+ req.tenant, filter, StatsGroupBy.CONSUMPTION);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.USER);
@@ -219,7 +219,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getUserStats(
- req.user.tenantID, filter, StatsGroupBy.USAGE);
+ req.tenant, filter, StatsGroupBy.USAGE);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.USER);
@@ -249,7 +249,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getUserStats(
- req.user.tenantID, filter, StatsGroupBy.INACTIVITY);
+ req.tenant, filter, StatsGroupBy.INACTIVITY);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.USER);
@@ -279,7 +279,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getUserStats(
- req.user.tenantID, filter, StatsGroupBy.TRANSACTIONS);
+ req.tenant, filter, StatsGroupBy.TRANSACTIONS);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.USER);
@@ -309,7 +309,7 @@ export default class StatisticService {
const filter = StatisticService.buildFilter(filteredRequest, req.user);
// Get Stats
const transactionStats = await StatisticsStorage.getUserStats(
- req.user.tenantID, filter, StatsGroupBy.PRICING);
+ req.tenant, filter, StatsGroupBy.PRICING);
// Convert
const transactions = StatisticService.convertToGraphData(
transactionStats, StatsDataCategory.USER);
@@ -361,9 +361,9 @@ export default class StatisticService {
// Query data
let transactionStats: ChargingStationStats[] | UserStats[];
if (filteredRequest.DataCategory === StatsDataCategory.CHARGING_STATION) {
- transactionStats = await StatisticsStorage.getChargingStationStats(req.user.tenantID, filter, groupBy);
+ transactionStats = await StatisticsStorage.getChargingStationStats(req.tenant, filter, groupBy);
} else {
- transactionStats = await StatisticsStorage.getUserStats(req.user.tenantID, filter, groupBy);
+ transactionStats = await StatisticsStorage.getUserStats(req.tenant, filter, groupBy);
}
// Set the attachement name
res.attachment('exported-' + filteredRequest.DataType.toLowerCase() + '-statistics.csv');
diff --git a/src/server/rest/v1/service/TagService.ts b/src/server/rest/v1/service/TagService.ts
index 5e00a32ecc..39a3a7ba76 100644
--- a/src/server/rest/v1/service/TagService.ts
+++ b/src/server/rest/v1/service/TagService.ts
@@ -34,6 +34,7 @@ import TransactionStorage from '../../../../storage/mongodb/TransactionStorage';
import UserToken from '../../../../types/UserToken';
import UserValidator from '../validator/UserValidator';
import Utils from '../../../../utils/Utils';
+import UtilsSecurity from './security/UtilsSecurity';
import UtilsService from './UtilsService';
import csvToJson from 'csvtojson/v2';
@@ -116,7 +117,7 @@ export default class TagService {
});
}
// Check if Tag has been already used
- const transactions = await TransactionStorage.getTransactions(req.user.tenantID,
+ const transactions = await TransactionStorage.getTransactions(req.tenant,
{ tagIDs: [filteredRequest.id.toUpperCase()], hasUserID: true }, Constants.DB_PARAMS_SINGLE_RECORD, ['id']);
if (!Utils.isEmptyArray(transactions.result)) {
throw new AppError({
@@ -336,6 +337,10 @@ export default class TagService {
// Set default value
tag.importedBy = importedBy;
tag.importedOn = importedOn;
+ tag.importedData = {
+ 'autoActivateUserAtImport' : UtilsSecurity.filterBoolean(req.headers.autoactivateuseratimport),
+ 'autoActivateTagAtImport' : UtilsSecurity.filterBoolean(req.headers.autoactivatetagatimport)
+ };
// Import
const importSuccess = await TagService.processTag(action, req, tag, tagsToBeImported);
if (!importSuccess) {
@@ -622,32 +627,39 @@ export default class TagService {
const newImportedTag: ImportedTag = {
id: importedTag.id.toUpperCase(),
visualID: importedTag.visualID,
- description: importedTag.description ? importedTag.description : `Tag ID '${importedTag.id}'`
+ description: importedTag.description ? importedTag.description : `Tag ID '${importedTag.id}'`,
+ importedData: importedTag.importedData
};
- if (importedTag.name && importedTag.firstName && importedTag.email) {
- newImportedTag.name = importedTag.name.toUpperCase();
- newImportedTag.firstName = importedTag.firstName;
- newImportedTag.email = importedTag.email;
- }
// Validate Tag data
TagValidator.getInstance().validateImportedTagCreation(newImportedTag);
// Set properties
newImportedTag.importedBy = importedTag.importedBy;
newImportedTag.importedOn = importedTag.importedOn;
newImportedTag.status = ImportStatus.READY;
- try {
- UserValidator.getInstance().validateImportedUserCreation(newImportedTag as ImportedUser);
- } catch (error) {
- await Logging.logWarning({
- tenantID: req.user.tenantID,
- module: MODULE_NAME, method: 'processTag',
- action: action,
- message: `User cannot be imported tag ${newImportedTag.id}`,
- detailedMessages: { tag: newImportedTag, error: error.stack }
- });
+ let tagToImport = newImportedTag;
+ // handle user part
+ if (importedTag.name && importedTag.firstName && importedTag.email) {
+ const newImportedUser: ImportedUser = {
+ name: importedTag.name.toUpperCase(),
+ firstName: importedTag.firstName,
+ email: importedTag.email,
+ siteIDs: importedTag.siteIDs
+ };
+ try {
+ UserValidator.getInstance().validateImportedUserCreation(newImportedUser);
+ tagToImport = { ...tagToImport, ...newImportedUser as ImportedTag };
+ } catch (error) {
+ await Logging.logWarning({
+ tenantID: req.user.tenantID,
+ module: MODULE_NAME, method: 'processTag',
+ action: action,
+ message: `User cannot be imported with tag ${newImportedTag.id}`,
+ detailedMessages: { tag: newImportedTag, error: error.message, stack: error.stack }
+ });
+ }
}
// Save it later on
- tagsToBeImported.push(newImportedTag);
+ tagsToBeImported.push(tagToImport);
return true;
} catch (error) {
await Logging.logError({
diff --git a/src/server/rest/v1/service/TenantService.ts b/src/server/rest/v1/service/TenantService.ts
index 5f09c29c23..90a72c9cfe 100644
--- a/src/server/rest/v1/service/TenantService.ts
+++ b/src/server/rest/v1/service/TenantService.ts
@@ -270,25 +270,27 @@ export default class TenantService {
tenantUser.name = filteredRequest.name;
tenantUser.firstName = 'Admin';
tenantUser.email = filteredRequest.email;
+ // Get Tenant
+ const tenant = await TenantStorage.getTenant(filteredRequest.id);
// Save User
- tenantUser.id = await UserStorage.saveUser(filteredRequest.id, tenantUser);
+ tenantUser.id = await UserStorage.saveUser(tenant, tenantUser);
// Save User Role
- await UserStorage.saveUserRole(filteredRequest.id, tenantUser.id, UserRole.ADMIN);
+ await UserStorage.saveUserRole(tenant, tenantUser.id, UserRole.ADMIN);
// Save User Status
- await UserStorage.saveUserStatus(filteredRequest.id, tenantUser.id, tenantUser.status);
+ await UserStorage.saveUserStatus(tenant, tenantUser.id, tenantUser.status);
// Save User Account Verification
const verificationToken = Utils.generateToken(filteredRequest.email);
- await UserStorage.saveUserAccountVerification(filteredRequest.id, tenantUser.id, { verificationToken });
+ await UserStorage.saveUserAccountVerification(tenant, tenantUser.id, { verificationToken });
const resetHash = Utils.generateUUID();
// Init Password info
- await UserStorage.saveUserPassword(filteredRequest.id, tenantUser.id, { passwordResetHash: resetHash });
+ await UserStorage.saveUserPassword(tenant, tenantUser.id, { passwordResetHash: resetHash });
// Send activation link
const evseDashboardVerifyEmailURL = Utils.buildEvseURL(filteredRequest.subdomain) +
'/verify-email?VerificationToken=' + verificationToken + '&Email=' +
tenantUser.email + '&ResetToken=' + resetHash;
// Send Register User (Async)
NotificationHandler.sendNewRegisteredUser(
- await TenantStorage.getTenant(filteredRequest.id),
+ tenant,
Utils.generateUUID(),
tenantUser,
{
@@ -344,7 +346,7 @@ export default class TenantService {
if (filteredRequest.components && filteredRequest.components.smartCharging &&
tenant.components && tenant.components.smartCharging &&
!filteredRequest.components.smartCharging.active && tenant.components.smartCharging.active) {
- const siteAreas = await SiteAreaStorage.getSiteAreas(filteredRequest.id, { smartCharging: true }, Constants.DB_PARAMS_MAX_LIMIT);
+ const siteAreas = await SiteAreaStorage.getSiteAreas(tenant, { smartCharging: true }, Constants.DB_PARAMS_MAX_LIMIT);
if (siteAreas.count !== 0) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -432,17 +434,17 @@ export default class TenantService {
// OICP
if (tenant.components && tenant.components.oicp) {
// Virtual user needed for unknown roaming user
- const virtualOICPUser = await UserStorage.getUserByEmail(tenant.id, Constants.OICP_VIRTUAL_USER_EMAIL);
+ const virtualOICPUser = await UserStorage.getUserByEmail(tenant, Constants.OICP_VIRTUAL_USER_EMAIL);
// Activate or deactivate virtual user depending on the oicp component status
if (tenant.components.oicp.active) {
// Create OICP user
if (!virtualOICPUser) {
- await OICPUtils.createOICPVirtualUser(tenant.id);
+ await OICPUtils.createOICPVirtualUser(tenant);
}
} else if (virtualOICPUser) {
// Clean up user
if (virtualOICPUser) {
- await UserStorage.deleteUser(tenant.id, virtualOICPUser.id);
+ await UserStorage.deleteUser(tenant, virtualOICPUser.id);
}
// Delete Endpoints if component is inactive
const oicpEndpoints = await OICPEndpointStorage.getOicpEndpoints(tenant, { role: OICPRole.CPO }, Constants.DB_PARAMS_MAX_LIMIT);
diff --git a/src/server/rest/v1/service/TransactionService.ts b/src/server/rest/v1/service/TransactionService.ts
index f2ca21da1c..9a35d5d78e 100644
--- a/src/server/rest/v1/service/TransactionService.ts
+++ b/src/server/rest/v1/service/TransactionService.ts
@@ -100,7 +100,7 @@ export default class TransactionService {
}
const transactionsToRefund: Transaction[] = [];
for (const transactionId of filteredRequest.transactionIds) {
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, transactionId, { withUser: true });
+ const transaction = await TransactionStorage.getTransaction(req.tenant, transactionId, { withUser: true });
if (!transaction) {
await Logging.logError({
tenantID: req.user.tenantID,
@@ -136,7 +136,7 @@ export default class TransactionService {
transactionsToRefund.push(transaction);
}
// Get Transaction User
- const user: User = await UserStorage.getUser(req.user.tenantID, req.user.id);
+ const user: User = await UserStorage.getUser(req.tenant, req.user.id);
UtilsService.assertObjectExists(action, user, `User ID '${req.user.id}' does not exist`,
MODULE_NAME, 'handleRefundTransactions', req.user);
const refundConnector = await RefundFactory.getRefundImpl(req.tenant);
@@ -192,11 +192,11 @@ export default class TransactionService {
});
}
// Check Transaction
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.transactionId, { withUser: true, withTag: true });
+ const transaction = await TransactionStorage.getTransaction(req.tenant, filteredRequest.transactionId, { withUser: true, withTag: true });
UtilsService.assertObjectExists(action, transaction, `Transaction ID '${filteredRequest.transactionId}' does not exist`,
MODULE_NAME, 'handlePushTransactionCdr', req.user);
// Check Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, transaction.chargeBoxID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, transaction.chargeBoxID);
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${transaction.chargeBoxID}' does not exist`,
MODULE_NAME, 'handlePushTransactionCdr', req.user);
// Check Issuer
@@ -238,7 +238,7 @@ export default class TransactionService {
// Roaming
await OCPPUtils.processTransactionRoaming(req.tenant, transaction, chargingStation, transaction.tag, TransactionAction.END);
// Save
- await TransactionStorage.saveTransactionOcpiData(req.user.tenantID, transaction.id, transaction.ocpiData);
+ await TransactionStorage.saveTransactionOcpiData(req.tenant, transaction.id, transaction.ocpiData);
// Ok
await Logging.logInfo({
tenantID: req.user.tenantID,
@@ -274,7 +274,7 @@ export default class TransactionService {
// Post CDR
await OCPPUtils.processOICPTransaction(req.tenant, transaction, chargingStation, TransactionAction.END);
// Save
- await TransactionStorage.saveTransactionOicpData(req.user.tenantID, transaction.id, transaction.oicpData);
+ await TransactionStorage.saveTransactionOicpData(req.tenant, transaction.id, transaction.oicpData);
// Ok
await Logging.logInfo({
tenantID: req.user.tenantID,
@@ -320,7 +320,7 @@ export default class TransactionService {
UtilsService.assertObjectExists(action, tag, `Tag ID '${filteredRequest.TagID}' does not exist`,
MODULE_NAME, 'handleAssignTransactionsToUser', req.user);
// Get unassigned transactions
- const count = await TransactionStorage.getUnassignedTransactionsCount(req.user.tenantID, tag.id);
+ const count = await TransactionStorage.getUnassignedTransactionsCount(req.tenant, tag.id);
// Return
res.json(count);
next();
@@ -340,8 +340,7 @@ 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, { withUser: true });
+ const transaction = await TransactionStorage.getTransaction(req.tenant, filteredRequest.ID, { withUser: true });
UtilsService.assertObjectExists(action, transaction, `Transaction ID '${filteredRequest.ID}' does not exist`,
MODULE_NAME, 'handleRebuildTransactionConsumptions', req.user);
// Get unassigned transactions
@@ -383,7 +382,7 @@ export default class TransactionService {
});
}
// Get the user
- const user: User = await UserStorage.getUser(req.user.tenantID, filteredRequest.UserID);
+ const user: User = await UserStorage.getUser(req.tenant, filteredRequest.UserID);
UtilsService.assertObjectExists(action, user, `User ID '${filteredRequest.UserID}' does not exist`,
MODULE_NAME, 'handleAssignTransactionsToUser', req.user);
// Get the tag
@@ -409,7 +408,7 @@ export default class TransactionService {
});
}
// Assign
- await TransactionStorage.assignTransactionsToUser(req.user.tenantID, user.id, tag.id);
+ await TransactionStorage.assignTransactionsToUser(req.tenant, user.id, tag.id);
res.json(Constants.REST_RESPONSE_SUCCESS);
next();
}
@@ -428,7 +427,7 @@ export default class TransactionService {
});
}
// Get
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, transactionId);
+ const transaction = await TransactionStorage.getTransaction(req.tenant, transactionId);
UtilsService.assertObjectExists(action, transaction, `Transaction ID '${transactionId}' does not exist`,
MODULE_NAME, 'handleDeleteTransaction', req.user);
// Delete
@@ -472,11 +471,11 @@ export default class TransactionService {
});
}
// Get Transaction
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, transactionId);
+ const transaction = await TransactionStorage.getTransaction(req.tenant, transactionId);
UtilsService.assertObjectExists(action, transaction, `Transaction ID ${transactionId} does not exist`,
MODULE_NAME, 'handleTransactionSoftStop', req.user);
// Get the Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, transaction.chargeBoxID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, transaction.chargeBoxID);
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${transaction.chargeBoxID}' does not exist`,
MODULE_NAME, 'handleTransactionSoftStop', req.user);
// Check if already stopped
@@ -484,7 +483,7 @@ export default class TransactionService {
// Clear Connector
OCPPUtils.clearChargingStationConnector(chargingStation, transaction.connectorId);
// Save Connectors
- await ChargingStationStorage.saveChargingStationConnectors(req.tenant.id, chargingStation.id, chargingStation.connectors);
+ await ChargingStationStorage.saveChargingStationConnectors(req.tenant, chargingStation.id, chargingStation.connectors);
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
source: chargingStation.id,
@@ -569,7 +568,7 @@ export default class TransactionService {
];
}
// Get Transaction
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.TransactionId,
+ const transaction = await TransactionStorage.getTransaction(req.tenant, filteredRequest.TransactionId,
{ 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);
@@ -641,7 +640,7 @@ 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,
+ const transaction = await TransactionStorage.getTransaction(req.tenant, 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',
@@ -700,7 +699,7 @@ export default class TransactionService {
public static async handleGetTransactionYears(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise {
// Get Transactions
- const transactionsYears = await TransactionStorage.getTransactionYears(req.user.tenantID);
+ const transactionsYears = await TransactionStorage.getTransactionYears(req.tenant);
const result: any = {};
if (transactionsYears) {
result.years = [];
@@ -789,7 +788,7 @@ export default class TransactionService {
filter.siteAdminIDs = Authorizations.getAuthorizedSiteAdminIDs(req.user);
}
// Get Reports
- const reports = await TransactionStorage.getRefundReports(req.user.tenantID, filter, {
+ const reports = await TransactionStorage.getRefundReports(req.tenant, filter, {
limit: filteredRequest.Limit,
skip: filteredRequest.Skip,
sort: filteredRequest.SortFields,
@@ -854,7 +853,7 @@ export default class TransactionService {
const filteredRequest = TransactionSecurity.filterTransactionRequest(req.query);
UtilsService.assertIdIsProvided(action, filteredRequest.ID, MODULE_NAME, 'handleExportTransactionOcpiCdr', req.user);
// Get Transaction
- const transaction = await TransactionStorage.getTransaction(req.user.tenantID, filteredRequest.ID, {}, ['id', 'ocpiData']);
+ const transaction = await TransactionStorage.getTransaction(req.tenant, filteredRequest.ID, {}, ['id', 'ocpiData']);
UtilsService.assertObjectExists(action, transaction, `Transaction ID '${filteredRequest.ID}' does not exist`,
MODULE_NAME, 'handleExportTransactionOcpiCdr', req.user);
// Check
@@ -911,7 +910,7 @@ export default class TransactionService {
// Filter
const filteredRequest = TransactionSecurity.filterTransactionsInErrorRequest(req.query);
// Site Area
- const transactions = await TransactionStorage.getTransactionsInError(req.user.tenantID,
+ const transactions = await TransactionStorage.getTransactionsInError(req.tenant,
{
...filter, search: filteredRequest.Search,
issuer: true,
@@ -1009,7 +1008,7 @@ export default class TransactionService {
const billingImpl = await BillingFactory.getBillingImpl(tenant);
for (const transactionID of transactionsIDs) {
// Get
- const transaction = await TransactionStorage.getTransaction(loggedUser.tenantID, transactionID);
+ const transaction = await TransactionStorage.getTransaction(await TenantStorage.getTenant(loggedUser.tenantID), transactionID);
// Not Found
if (!transaction) {
result.inError++;
@@ -1052,7 +1051,8 @@ export default class TransactionService {
const foundConnector = Utils.getConnectorFromID(transaction.chargeBox, transaction.connectorId);
if (foundConnector && transaction.id === foundConnector.currentTransactionID) {
OCPPUtils.clearChargingStationConnector(transaction.chargeBox, transaction.connectorId);
- await ChargingStationStorage.saveChargingStationConnectors(loggedUser.tenantID, transaction.chargeBox.id, transaction.chargeBox.connectors);
+ await ChargingStationStorage.saveChargingStationConnectors(await TenantStorage.getTenant(loggedUser.tenantID),
+ transaction.chargeBox.id, transaction.chargeBox.connectors);
}
// To Delete
transactionsIDsToDelete.push(transactionID);
@@ -1063,7 +1063,7 @@ export default class TransactionService {
}
}
// Delete All Transactions
- result.inSuccess = await TransactionStorage.deleteTransactions(loggedUser.tenantID, transactionsIDsToDelete);
+ result.inSuccess = await TransactionStorage.deleteTransactions(await TenantStorage.getTenant(loggedUser.tenantID), transactionsIDsToDelete);
// Log
await Logging.logActionsResponse(loggedUser.tenantID,
ServerAction.TRANSACTIONS_DELETE,
@@ -1135,7 +1135,7 @@ export default class TransactionService {
}
}
// Get the transactions
- const transactions = await TransactionStorage.getTransactions(req.user.tenantID,
+ const transactions = await TransactionStorage.getTransactions(req.tenant,
{
...extrafilters,
chargeBoxIDs: filteredRequest.ChargingStationID ? filteredRequest.ChargingStationID.split('|') : null,
diff --git a/src/server/rest/v1/service/UserService.ts b/src/server/rest/v1/service/UserService.ts
index 1bb1c8d5e2..880cefa393 100644
--- a/src/server/rest/v1/service/UserService.ts
+++ b/src/server/rest/v1/service/UserService.ts
@@ -39,6 +39,7 @@ import UserStorage from '../../../../storage/mongodb/UserStorage';
import UserToken from '../../../../types/UserToken';
import UserValidator from '../validator/UserValidator';
import Utils from '../../../../utils/Utils';
+import UtilsSecurity from './security/UtilsSecurity';
import UtilsService from './UtilsService';
import _ from 'lodash';
import csvToJson from 'csvtojson/v2';
@@ -102,9 +103,9 @@ export default class UserService {
req.tenant, req.user, user, filteredRequest.siteIDs, action);
// Save
if (action === ServerAction.ADD_SITES_TO_USER) {
- await UserStorage.addSitesToUser(req.user.tenantID, filteredRequest.userID, sites.map((site) => site.id));
+ await UserStorage.addSitesToUser(req.tenant, filteredRequest.userID, sites.map((site) => site.id));
} else {
- await UserStorage.removeSitesFromUser(req.user.tenantID, filteredRequest.userID, sites.map((site) => site.id));
+ await UserStorage.removeSitesFromUser(req.tenant, filteredRequest.userID, sites.map((site) => site.id));
}
// Log
await Logging.logSecurityInfo({
@@ -127,7 +128,7 @@ export default class UserService {
// Delete OCPI User
if (!user.issuer) {
// Delete User
- await UserStorage.deleteUser(req.user.tenantID, user.id);
+ await UserStorage.deleteUser(req.tenant, user.id);
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
user: req.user, actionOnUser: user,
@@ -146,7 +147,7 @@ export default class UserService {
// Delete Car
await UserService.checkAndDeleteCar(req.tenant, req.user, user);
// Delete User
- await UserStorage.deleteUser(req.user.tenantID, user.id);
+ await UserStorage.deleteUser(req.tenant, user.id);
// Log
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
@@ -167,7 +168,7 @@ export default class UserService {
let user = await UtilsService.checkAndGetUserAuthorization(
req.tenant, req.user, filteredRequest.id, Action.UPDATE, action, filteredRequest);
// Check email already exists
- const userWithEmail = await UserStorage.getUserByEmail(req.user.tenantID, filteredRequest.email);
+ const userWithEmail = await UserStorage.getUserByEmail(req.tenant, filteredRequest.email);
if (userWithEmail && user.id !== userWithEmail.id) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -197,12 +198,12 @@ export default class UserService {
lastChangedOn: lastChangedOn,
};
// Update User (override TagIDs because it's not of the same type as in filteredRequest)
- await UserStorage.saveUser(req.user.tenantID, user, true);
+ await UserStorage.saveUser(req.tenant, user, true);
// Save User's password
if (filteredRequest.password) {
// Update the password
const newPasswordHashed = await Utils.hashPasswordBcrypt(filteredRequest.password);
- await UserStorage.saveUserPassword(req.user.tenantID, filteredRequest.id,
+ await UserStorage.saveUserPassword(req.tenant, filteredRequest.id,
{
password: newPasswordHashed,
passwordWrongNbrTrials: 0,
@@ -214,17 +215,17 @@ export default class UserService {
if (Authorizations.isAdmin(req.user) || Authorizations.isSuperAdmin(req.user)) {
// Save User's Status
if (filteredRequest.status) {
- await UserStorage.saveUserStatus(req.user.tenantID, user.id, filteredRequest.status);
+ await UserStorage.saveUserStatus(req.tenant, user.id, filteredRequest.status);
}
// Save User's Role
if (filteredRequest.role) {
- await UserStorage.saveUserRole(req.user.tenantID, user.id, filteredRequest.role);
+ await UserStorage.saveUserRole(req.tenant, user.id, filteredRequest.role);
}
// Save Admin Data
if (Utils.objectHasProperty(filteredRequest, 'plateID')) {
const adminData: { plateID?: string; } = {};
adminData.plateID = filteredRequest.plateID || null;
- await UserStorage.saveUserAdminData(req.user.tenantID, user.id, adminData);
+ await UserStorage.saveUserAdminData(req.tenant, user.id, adminData);
}
}
// Update Billing
@@ -272,7 +273,7 @@ export default class UserService {
const user = await UtilsService.checkAndGetUserAuthorization(
req.tenant, req.user, filteredRequest.id, Action.UPDATE, action);
// Update User (override TagIDs because it's not of the same type as in filteredRequest)
- await UserStorage.saveUserMobileToken(req.user.tenantID, user.id, {
+ await UserStorage.saveUserMobileToken(req.tenant, user.id, {
mobileToken: filteredRequest.mobileToken,
mobileOs: filteredRequest.mobileOS,
mobileLastChangedOn: new Date()
@@ -310,16 +311,14 @@ export default class UserService {
const userID = UserValidator.getInstance().validateUserGetByID(req.query).ID.toString();
// Check and Get User
const user = await UtilsService.checkAndGetUserAuthorization(
- req.tenant, req.user, userID, Action.READ, action);
+ req.tenant, req.user, userID, Action.READ, action, null, null, null, false);
// Get the user image
- const userImage = await UserStorage.getUserImage(req.user.tenantID, user.id);
+ const userImage = await UserStorage.getUserImage(req.tenant, user.id);
res.json(userImage);
next();
}
public static async handleExportUsers(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise {
- // Export with tags
- req.query['WithTag'] = 'true';
await UtilsService.exportToCSV(req, res, 'exported-users.csv',
UserService.getUsers.bind(this),
UserService.convertToCSV.bind(this));
@@ -346,7 +345,7 @@ export default class UserService {
return;
}
// Get Sites
- const sites = await UserStorage.getUserSites(req.user.tenantID,
+ const sites = await UserStorage.getUserSites(req.tenant,
{
search: filteredRequest.Search,
userIDs: [filteredRequest.UserID],
@@ -384,7 +383,7 @@ export default class UserService {
const authorizationUserInErrorFilters = await AuthorizationService.checkAndGetUsersInErrorAuthorizations(
req.tenant, req.user, filteredRequest);
// Get users
- const users = await UserStorage.getUsersInError(req.user.tenantID,
+ const users = await UserStorage.getUsersInError(req.tenant,
{
search: filteredRequest.Search,
roles: (filteredRequest.Role ? filteredRequest.Role.split('|') : null),
@@ -439,7 +438,7 @@ export default class UserService {
};
try {
// Delete all previously imported users
- await UserStorage.deleteImportedUsers(req.user.tenantID);
+ await UserStorage.deleteImportedUsers(req.tenant);
// Get the stream
const busboy = new Busboy({ headers: req.headers });
req.pipe(busboy);
@@ -483,6 +482,9 @@ export default class UserService {
// Set default value
user.importedBy = importedBy;
user.importedOn = importedOn;
+ user.importedData = {
+ 'autoActivateUserAtImport' : UtilsSecurity.filterBoolean(req.headers.autoactivateuseratimport)
+ };
// Import
const importSuccess = await UserService.processUser(action, req, user, usersToBeImported);
if (!importSuccess) {
@@ -490,7 +492,7 @@ export default class UserService {
}
// Insert batched
if (!Utils.isEmptyArray(usersToBeImported) && (usersToBeImported.length % Constants.IMPORT_BATCH_INSERT_SIZE) === 0) {
- await UserService.insertUsers(req.user.tenantID, req.user, action, usersToBeImported, result);
+ await UserService.insertUsers(req.tenant, req.user, action, usersToBeImported, result);
}
// eslint-disable-next-line @typescript-eslint/no-misused-promises
}, async (error: CSVError) => {
@@ -517,7 +519,7 @@ export default class UserService {
connectionClosed = true;
// Insert batched
if (usersToBeImported.length > 0) {
- await UserService.insertUsers(req.user.tenantID, req.user, action, usersToBeImported, result);
+ await UserService.insertUsers(req.tenant, req.user, action, usersToBeImported, result);
}
// Release the lock
await LockingManager.release(importUsersLock);
@@ -562,7 +564,7 @@ export default class UserService {
}
// Insert batched
if ((usersToBeImported.length % Constants.IMPORT_BATCH_INSERT_SIZE) === 0) {
- await UserService.insertUsers(req.user.tenantID, req.user, action, usersToBeImported, result);
+ await UserService.insertUsers(req.tenant, req.user, action, usersToBeImported, result);
}
});
// eslint-disable-next-line @typescript-eslint/no-misused-promises
@@ -627,7 +629,7 @@ export default class UserService {
});
}
// Get the email
- const foundUser = await UserStorage.getUserByEmail(req.user.tenantID, filteredRequest.email);
+ const foundUser = await UserStorage.getUserByEmail(req.tenant, filteredRequest.email);
if (foundUser) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
@@ -648,11 +650,11 @@ export default class UserService {
issuer: true,
} as User;
// Create the User
- newUser.id = await UserStorage.saveUser(req.user.tenantID, newUser, true);
+ newUser.id = await UserStorage.saveUser(req.tenant, newUser, true);
// Save password
if (newUser.password) {
const newPasswordHashed = await Utils.hashPasswordBcrypt(newUser.password);
- await UserStorage.saveUserPassword(req.user.tenantID, newUser.id,
+ await UserStorage.saveUserPassword(req.tenant, newUser.id,
{
password: newPasswordHashed,
passwordWrongNbrTrials: 0,
@@ -664,11 +666,11 @@ export default class UserService {
if (Authorizations.isAdmin(req.user) || Authorizations.isSuperAdmin(req.user)) {
// Save User Status
if (newUser.status) {
- await UserStorage.saveUserStatus(req.user.tenantID, newUser.id, newUser.status);
+ await UserStorage.saveUserStatus(req.tenant, newUser.id, newUser.status);
}
// Save User Role
if (newUser.role) {
- await UserStorage.saveUserRole(req.user.tenantID, newUser.id, newUser.role);
+ await UserStorage.saveUserRole(req.tenant, newUser.id, newUser.role);
}
// Save Admin Data
if (newUser.plateID || Utils.objectHasProperty(newUser, 'notificationsActive')) {
@@ -683,7 +685,7 @@ export default class UserService {
}
}
// Save User Admin data
- await UserStorage.saveUserAdminData(req.user.tenantID, newUser.id, adminData);
+ await UserStorage.saveUserAdminData(req.tenant, newUser.id, adminData);
}
}
// Assign user to all sites with auto-assign flag set
@@ -693,7 +695,7 @@ export default class UserService {
);
if (!Utils.isEmptyArray(sites.result)) {
const siteIDs = sites.result.map((site) => site.id);
- await UserStorage.addSitesToUser(req.user.tenantID, newUser.id, siteIDs);
+ await UserStorage.addSitesToUser(req.tenant, newUser.id, siteIDs);
}
// Update Billing
await UserService.updateUserBilling(ServerAction.USER_CREATE, req.tenant, req.user, newUser);
@@ -709,16 +711,16 @@ export default class UserService {
next();
}
- private static async insertUsers(tenantID: string, user: UserToken, action: ServerAction, usersToBeImported: ImportedUser[], result: ActionsResponse): Promise {
+ private static async insertUsers(tenant: Tenant, user: UserToken, action: ServerAction, usersToBeImported: ImportedUser[], result: ActionsResponse): Promise {
try {
- const nbrInsertedUsers = await UserStorage.saveImportedUsers(tenantID, usersToBeImported);
+ const nbrInsertedUsers = await UserStorage.saveImportedUsers(tenant, usersToBeImported);
result.inSuccess += nbrInsertedUsers;
} catch (error) {
// Handle dup keys
result.inSuccess += error.result.nInserted;
result.inError += error.writeErrors.length;
await Logging.logError({
- tenantID: tenantID,
+ tenantID: tenant.id,
module: MODULE_NAME, method: 'insertUsers',
action: action,
user: user.id,
@@ -733,7 +735,7 @@ export default class UserService {
let headers = null;
// Header
if (writeHeader) {
- const headerArray = [
+ headers = [
'id',
'name',
'firstName',
@@ -744,11 +746,10 @@ export default class UserService {
'eulaAcceptedOn',
'createdOn',
'changedOn',
- 'changedBy'
- ];
- headers = headerArray.join(Constants.CSV_SEPARATOR);
+ 'changedBy',
+ ].join(Constants.CSV_SEPARATOR);
}
- // Conten t
+ // Content
const rows = users.map((user) => {
const row = [
user.id,
@@ -786,7 +787,7 @@ export default class UserService {
}
}
// Get users
- const users = await UserStorage.getUsers(req.user.tenantID,
+ const users = await UserStorage.getUsers(req.tenant,
{
search: filteredRequest.Search,
issuer: Utils.isBoolean(filteredRequest.Issuer) || filteredRequest.Issuer ? Utils.convertToBoolean(filteredRequest.Issuer) : null,
@@ -817,6 +818,8 @@ export default class UserService {
name: importedUser.name.toUpperCase(),
firstName: importedUser.firstName,
email: importedUser.email,
+ importedData: importedUser.importedData,
+ siteIDs: importedUser.siteIDs
};
// Validate User data
UserValidator.getInstance().validateImportedUserCreation(newImportedUser);
diff --git a/src/server/rest/v1/service/UtilsService.ts b/src/server/rest/v1/service/UtilsService.ts
index 71df78db30..d8ac48a414 100644
--- a/src/server/rest/v1/service/UtilsService.ts
+++ b/src/server/rest/v1/service/UtilsService.ts
@@ -72,7 +72,7 @@ export default class UtilsService {
});
}
// Get ChargingStation
- const chargingStation = await ChargingStationStorage.getChargingStation(tenant.id, chargingStationID,
+ const chargingStation = await ChargingStationStorage.getChargingStation(tenant, chargingStationID,
{
...additionalFilters,
...authorizationFilter.filters
@@ -176,7 +176,7 @@ export default class UtilsService {
});
}
// Get User
- const user = await UserStorage.getUser(tenant.id, userID,
+ const user = await UserStorage.getUser(tenant, userID,
{
...additionalFilters,
...authorizationFilter.filters
@@ -354,7 +354,7 @@ export default class UtilsService {
});
}
// Get Users
- let users = (await UserStorage.getUsers(tenant.id,
+ let users = (await UserStorage.getUsers(tenant,
{
userIDs,
...additionalFilters,
@@ -478,7 +478,7 @@ export default class UtilsService {
});
}
// Get Charging Stations
- const chargingStations = (await ChargingStationStorage.getChargingStations(tenant.id,
+ const chargingStations = (await ChargingStationStorage.getChargingStations(tenant,
{
chargingStationIDs,
...additionalFilters,
@@ -530,7 +530,7 @@ export default class UtilsService {
});
}
// Get SiteArea & check it exists
- const siteArea = await SiteAreaStorage.getSiteArea(tenant.id, siteAreaID,
+ const siteArea = await SiteAreaStorage.getSiteArea(tenant, siteAreaID,
{
...additionalFilters,
...authorizationFilter.filters,
diff --git a/src/storage/mongodb/ChargingStationStorage.ts b/src/storage/mongodb/ChargingStationStorage.ts
index 7d51c5d73d..d05e6a1f81 100644
--- a/src/storage/mongodb/ChargingStationStorage.ts
+++ b/src/storage/mongodb/ChargingStationStorage.ts
@@ -15,6 +15,7 @@ import DbParams from '../../types/database/DbParams';
import { InactivityStatus } from '../../types/Transaction';
import Logging from '../../utils/Logging';
import { ServerAction } from '../../types/Server';
+import Tenant from '../../types/Tenant';
import TenantComponents from '../../types/TenantComponents';
import TenantStorage from './TenantStorage';
import Utils from '../../utils/Utils';
@@ -132,9 +133,9 @@ export default class ChargingStationStorage {
await Logging.traceEnd(Constants.DEFAULT_TENANT, MODULE_NAME, 'saveChargingStationTemplate', uniqueTimerID, chargingStationTemplate);
}
- public static async getChargingStation(tenantID: string, id: string = Constants.UNKNOWN_STRING_ID,
+ public static async getChargingStation(tenant: Tenant, id: string = Constants.UNKNOWN_STRING_ID,
params: { includeDeleted?: boolean, issuer?: boolean; siteIDs?: string[] } = {}, projectFields?: string[]): Promise {
- const chargingStationsMDB = await ChargingStationStorage.getChargingStations(tenantID, {
+ const chargingStationsMDB = await ChargingStationStorage.getChargingStations(tenant, {
chargingStationIDs: [id],
withSite: true,
withSiteArea: true,
@@ -145,19 +146,19 @@ export default class ChargingStationStorage {
return chargingStationsMDB.count === 1 ? chargingStationsMDB.result[0] : null;
}
- public static async getChargingStationByOcpiEvseID(tenantID: string, ocpiEvseID: string = Constants.UNKNOWN_STRING_ID,
+ public static async getChargingStationByOcpiEvseID(tenant: Tenant, ocpiEvseID: string = Constants.UNKNOWN_STRING_ID,
projectFields?: string[]): Promise {
- const chargingStationsMDB = await ChargingStationStorage.getChargingStations(tenantID, {
+ const chargingStationsMDB = await ChargingStationStorage.getChargingStations(tenant, {
ocpiEvseID,
withSiteArea: true,
}, Constants.DB_PARAMS_SINGLE_RECORD, projectFields);
return chargingStationsMDB.count === 1 ? chargingStationsMDB.result[0] : null;
}
- public static async getChargingStationByOcpiLocationUid(tenantID: string, ocpiLocationID: string = Constants.UNKNOWN_STRING_ID,
+ public static async getChargingStationByOcpiLocationUid(tenant: Tenant, ocpiLocationID: string = Constants.UNKNOWN_STRING_ID,
ocpiEvseUid: string = Constants.UNKNOWN_STRING_ID,
projectFields?: string[]): Promise {
- const chargingStationsMDB = await ChargingStationStorage.getChargingStations(tenantID, {
+ const chargingStationsMDB = await ChargingStationStorage.getChargingStations(tenant, {
ocpiLocationID,
ocpiEvseUid,
withSiteArea: true
@@ -165,16 +166,16 @@ export default class ChargingStationStorage {
return chargingStationsMDB.count === 1 ? chargingStationsMDB.result[0] : null;
}
- public static async getChargingStationByOicpEvseID(tenantID: string, oicpEvseID: string = Constants.UNKNOWN_STRING_ID,
+ public static async getChargingStationByOicpEvseID(tenant: Tenant, oicpEvseID: string = Constants.UNKNOWN_STRING_ID,
projectFields?: string[]): Promise {
- const chargingStationsMDB = await ChargingStationStorage.getChargingStations(tenantID, {
+ const chargingStationsMDB = await ChargingStationStorage.getChargingStations(tenant, {
oicpEvseID: oicpEvseID,
withSiteArea: true
}, Constants.DB_PARAMS_SINGLE_RECORD, projectFields);
return chargingStationsMDB.count === 1 ? chargingStationsMDB.result[0] : null;
}
- public static async getChargingStations(tenantID: string,
+ public static async getChargingStations(tenant: Tenant,
params: {
search?: string; chargingStationIDs?: string[]; chargingStationSerialNumbers?: string[]; siteAreaIDs?: string[]; withNoSiteArea?: boolean;
connectorStatuses?: string[]; connectorTypes?: string[]; statusChangedBefore?: Date; withSiteArea?: boolean;
@@ -184,9 +185,9 @@ export default class ChargingStationStorage {
},
dbParams: DbParams, projectFields?: string[]): Promise> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getChargingStations');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getChargingStations');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Clone before updating the values
dbParams = Utils.cloneObject(dbParams);
// Check Limit
@@ -335,13 +336,13 @@ export default class ChargingStationStorage {
aggregation.push({ $limit: Constants.DB_RECORD_COUNT_CEIL });
}
// Count Records
- const chargingStationsCountMDB = await global.database.getCollection(tenantID, 'chargingstations')
+ const chargingStationsCountMDB = await global.database.getCollection(tenant.id, 'chargingstations')
.aggregate([...aggregation, { $count: 'count' }])
.toArray();
// Check if only the total count is requested
if (dbParams.onlyRecordCount) {
// Return only the count
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getChargingStations', uniqueTimerID, chargingStationsCountMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getChargingStations', uniqueTimerID, chargingStationsCountMDB);
return {
count: (chargingStationsCountMDB.length > 0 ? chargingStationsCountMDB[0].count : 0),
result: []
@@ -371,20 +372,20 @@ export default class ChargingStationStorage {
});
// Users on connectors
DatabaseUtils.pushArrayLookupInAggregation('connectors', DatabaseUtils.pushUserLookupInAggregation.bind(this), {
- tenantID, aggregation: aggregation, localField: 'connectors.currentUserID', foreignField: '_id',
+ tenantID: tenant.id, aggregation: aggregation, localField: 'connectors.currentUserID', foreignField: '_id',
asField: 'connectors.user', oneToOneCardinality: true, objectIDFields: ['createdBy', 'lastChangedBy']
}, { sort: dbParams.sort });
// Site Area
if (params.withSiteArea) {
DatabaseUtils.pushSiteAreaLookupInAggregation({
- tenantID, aggregation: aggregation, localField: 'siteAreaID', foreignField: '_id',
+ tenantID: tenant.id, aggregation: aggregation, localField: 'siteAreaID', foreignField: '_id',
asField: 'siteArea', oneToOneCardinality: true
});
}
// Site
if (params.withSite) {
DatabaseUtils.pushSiteLookupInAggregation({
- tenantID, aggregation: aggregation, localField: 'siteID', foreignField: '_id',
+ tenantID: tenant.id, aggregation: aggregation, localField: 'siteID', foreignField: '_id',
asField: 'site', oneToOneCardinality: true
});
}
@@ -393,7 +394,7 @@ export default class ChargingStationStorage {
// Convert siteID back to string after having queried the site
DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteArea.siteID');
// Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenant.id, aggregation);
// Convert Object ID to string
DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteAreaID');
DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteID');
@@ -406,13 +407,13 @@ export default class ChargingStationStorage {
});
}
// Read DB
- const chargingStationsMDB = await global.database.getCollection(tenantID, 'chargingstations')
+ const chargingStationsMDB = await global.database.getCollection(tenant.id, 'chargingstations')
.aggregate(aggregation, {
allowDiskUse: true
})
.toArray();
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getChargingStations', uniqueTimerID, chargingStationsMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getChargingStations', uniqueTimerID, chargingStationsMDB);
return {
count: (chargingStationsCountMDB.length > 0 ?
(chargingStationsCountMDB[0].count === Constants.DB_RECORD_COUNT_CEIL ? -1 : chargingStationsCountMDB[0].count) : 0),
@@ -420,13 +421,13 @@ export default class ChargingStationStorage {
};
}
- public static async getChargingStationsInError(tenantID: string,
+ public static async getChargingStationsInError(tenant: Tenant,
params: { search?: string; siteIDs?: string[]; siteAreaIDs: string[]; errorType?: string[] },
dbParams: DbParams, projectFields?: string[]): Promise> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getChargingStations');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getChargingStations');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Clone before updating the values
dbParams = Utils.cloneObject(dbParams);
// Check Limit
@@ -462,7 +463,7 @@ export default class ChargingStationStorage {
// Build lookups to fetch sites from chargers
aggregation.push({
$lookup: {
- from: DatabaseUtils.getCollectionName(tenantID, 'siteareas'),
+ from: DatabaseUtils.getCollectionName(tenant.id, 'siteareas'),
localField: 'siteAreaID',
foreignField: '_id',
as: 'sitearea'
@@ -486,7 +487,7 @@ export default class ChargingStationStorage {
const facets: any = { $facet: {} };
if (!Utils.isEmptyArray(params.errorType)) {
// Check allowed
- if (!Utils.isTenantComponentActive(await TenantStorage.getTenant(tenantID), TenantComponents.ORGANIZATION)
+ if (!Utils.isTenantComponentActive(tenant, TenantComponents.ORGANIZATION)
&& params.errorType.includes(ChargingStationInErrorType.MISSING_SITE_AREA)) {
throw new BackendError({
source: Constants.CENTRAL_SERVER,
@@ -510,7 +511,7 @@ export default class ChargingStationStorage {
aggregation.push({ $addFields: { 'uniqueId': { $concat: ['$_id', '#', '$errorCode'] } } });
}
// Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenant.id, aggregation);
// Sort
if (!dbParams.sort) {
dbParams.sort = { _id: 1 };
@@ -531,24 +532,24 @@ export default class ChargingStationStorage {
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
- const chargingStationsMDB = await global.database.getCollection(tenantID, 'chargingstations')
+ const chargingStationsMDB = await global.database.getCollection(tenant.id, 'chargingstations')
.aggregate(aggregation, {
allowDiskUse: true
})
.toArray();
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getChargingStations', uniqueTimerID, chargingStationsMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getChargingStations', uniqueTimerID, chargingStationsMDB);
return {
count: chargingStationsMDB.length,
result: chargingStationsMDB
};
}
- public static async saveChargingStation(tenantID: string, chargingStationToSave: ChargingStation): Promise {
+ public static async saveChargingStation(tenant: Tenant, chargingStationToSave: ChargingStation): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingStation');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveChargingStation');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Build Request
const chargingStationMDB = {
_id: chargingStationToSave.id,
@@ -602,20 +603,20 @@ export default class ChargingStationStorage {
// Add Created/LastChanged By
DatabaseUtils.addLastChangedCreatedProps(chargingStationMDB, chargingStationToSave);
// Modify and return the modified document
- await global.database.getCollection(tenantID, 'chargingstations').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'chargingstations').findOneAndUpdate(
{ _id: chargingStationToSave.id },
{ $set: chargingStationMDB },
{ upsert: true });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStation', uniqueTimerID, chargingStationMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveChargingStation', uniqueTimerID, chargingStationMDB);
return chargingStationMDB._id;
}
- public static async saveChargingStationConnectors(tenantID: string, id: string, connectors: Connector[], backupConnectors?: Connector[]): Promise {
+ public static async saveChargingStationConnectors(tenant: Tenant, id: string, connectors: Connector[], backupConnectors?: Connector[]): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingStationConnectors');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveChargingStationConnectors');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
const updatedProps: any = {};
// Set connectors
updatedProps.connectors = connectors.map((connector) =>
@@ -626,24 +627,24 @@ export default class ChargingStationStorage {
ChargingStationStorage.filterConnectorMDB(backupConnector));
}
// Modify document
- await global.database.getCollection(tenantID, 'chargingstations').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'chargingstations').findOneAndUpdate(
{ '_id': id },
{
$set: updatedProps
},
{ upsert: true });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStationConnectors', uniqueTimerID, connectors);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveChargingStationConnectors', uniqueTimerID, connectors);
}
- public static async saveChargingStationCFApplicationIDAndInstanceIndex(tenantID: string, id: string,
+ public static async saveChargingStationCFApplicationIDAndInstanceIndex(tenant: Tenant, id: string,
cfApplicationIDAndInstanceIndex: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingStationCFApplicationIDAndInstanceIndex');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveChargingStationCFApplicationIDAndInstanceIndex');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify document
- await global.database.getCollection(tenantID, 'chargingstations').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'chargingstations').findOneAndUpdate(
{ '_id': id },
{
$set: {
@@ -652,17 +653,17 @@ export default class ChargingStationStorage {
},
{ upsert: true });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStationCFApplicationIDAndInstanceIndex', uniqueTimerID, cfApplicationIDAndInstanceIndex);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveChargingStationCFApplicationIDAndInstanceIndex', uniqueTimerID, cfApplicationIDAndInstanceIndex);
}
- public static async saveChargingStationOicpData(tenantID: string, id: string,
+ public static async saveChargingStationOicpData(tenant: Tenant, id: string,
oicpData: ChargingStationOicpData): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingStationOicpData');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveChargingStationOicpData');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify document
- await global.database.getCollection(tenantID, 'chargingstations').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'chargingstations').findOneAndUpdate(
{ '_id': id },
{
$set: {
@@ -671,33 +672,33 @@ export default class ChargingStationStorage {
},
{ upsert: false });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStationOicpData', uniqueTimerID, oicpData);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveChargingStationOicpData', uniqueTimerID, oicpData);
}
- public static async saveChargingStationLastSeen(tenantID: string, id: string,
+ public static async saveChargingStationLastSeen(tenant: Tenant, id: string,
params: { lastSeen: Date; currentIPAddress?: string | string[] }): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingStationLastSeen');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveChargingStationLastSeen');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Set data
// Modify document
- await global.database.getCollection(tenantID, 'chargingstations').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'chargingstations').findOneAndUpdate(
{ '_id': id },
{ $set: params },
{ upsert: true });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStationLastSeen', uniqueTimerID, params);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveChargingStationLastSeen', uniqueTimerID, params);
}
- public static async saveChargingStationOcpiData(tenantID: string, id: string,
+ public static async saveChargingStationOcpiData(tenant: Tenant, id: string,
ocpiData: ChargingStationOcpiData): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingStationOcpiData');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveChargingStationOcpiData');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify document
- await global.database.getCollection(tenantID, 'chargingstations').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'chargingstations').findOneAndUpdate(
{ '_id': id },
{
$set: {
@@ -706,17 +707,17 @@ export default class ChargingStationStorage {
},
{ upsert: false });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStationOcpiData', uniqueTimerID, ocpiData);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveChargingStationOcpiData', uniqueTimerID, ocpiData);
}
- public static async saveChargingStationRemoteAuthorizations(tenantID: string, id: string,
+ public static async saveChargingStationRemoteAuthorizations(tenant: Tenant, id: string,
remoteAuthorizations: RemoteAuthorization[]): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingStationRemoteAuthorizations');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveChargingStationRemoteAuthorizations');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify document
- await global.database.getCollection(tenantID, 'chargingstations').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'chargingstations').findOneAndUpdate(
{ '_id': id },
{
$set: {
@@ -725,43 +726,43 @@ export default class ChargingStationStorage {
},
{ upsert: false });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStationRemoteAuthorizations', uniqueTimerID, remoteAuthorizations);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveChargingStationRemoteAuthorizations', uniqueTimerID, remoteAuthorizations);
}
- public static async saveChargingStationFirmwareStatus(tenantID: string, id: string, firmwareUpdateStatus: OCPPFirmwareStatus): Promise {
+ public static async saveChargingStationFirmwareStatus(tenant: Tenant, id: string, firmwareUpdateStatus: OCPPFirmwareStatus): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingStationFirmwareStatus');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveChargingStationFirmwareStatus');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify document
- await global.database.getCollection(tenantID, 'chargingstations').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'chargingstations').findOneAndUpdate(
{ '_id': id },
{ $set: { firmwareUpdateStatus } },
{ upsert: true });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStationFirmwareStatus', uniqueTimerID, firmwareUpdateStatus);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveChargingStationFirmwareStatus', uniqueTimerID, firmwareUpdateStatus);
}
- public static async deleteChargingStation(tenantID: string, id: string): Promise {
+ public static async deleteChargingStation(tenant: Tenant, id: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'deleteChargingStation');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'deleteChargingStation');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Delete Configuration
- await global.database.getCollection(tenantID, 'configurations')
+ await global.database.getCollection(tenant.id, 'configurations')
.findOneAndDelete({ '_id': id });
// Delete Charging Profiles
- await ChargingStationStorage.deleteChargingProfiles(tenantID, id);
+ await ChargingStationStorage.deleteChargingProfiles(tenant, id);
// Delete Charging Station
- await global.database.getCollection(tenantID, 'chargingstations')
+ await global.database.getCollection(tenant.id, 'chargingstations')
.findOneAndDelete({ '_id': id });
// Keep the rest (boot notification, authorize...)
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'deleteChargingStation', uniqueTimerID, { id });
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'deleteChargingStation', uniqueTimerID, { id });
}
- public static async getOcppParameterValue(tenantID: string, chargeBoxID: string, paramName: string): Promise {
- const configuration = await ChargingStationStorage.getOcppParameters(tenantID, chargeBoxID);
+ public static async getOcppParameterValue(tenant: Tenant, chargeBoxID: string, paramName: string): Promise {
+ const configuration = await ChargingStationStorage.getOcppParameters(tenant, chargeBoxID);
let value: string = null;
if (configuration) {
// Get the value
@@ -777,13 +778,13 @@ export default class ChargingStationStorage {
return value;
}
- static async saveOcppParameters(tenantID: string, parameters: ChargingStationOcppParameters): Promise {
+ static async saveOcppParameters(tenant: Tenant, parameters: ChargingStationOcppParameters): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveOcppParameters');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveOcppParameters');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify
- await global.database.getCollection(tenantID, 'configurations').findOneAndUpdate({
+ await global.database.getCollection(tenant.id, 'configurations').findOneAndUpdate({
'_id': parameters.id
}, {
$set: {
@@ -795,16 +796,16 @@ export default class ChargingStationStorage {
returnDocument: 'after'
});
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveOcppParameters', uniqueTimerID, parameters);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveOcppParameters', uniqueTimerID, parameters);
}
- public static async getOcppParameters(tenantID: string, id: string): Promise> {
+ public static async getOcppParameters(tenant: Tenant, id: string): Promise> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getOcppParameters');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getOcppParameters');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Read DB
- const parametersMDB = await global.database.getCollection(tenantID, 'configurations')
+ const parametersMDB = await global.database.getCollection(tenant.id, 'configurations')
.findOne({ '_id': id });
if (parametersMDB) {
// Sort
@@ -820,28 +821,28 @@ export default class ChargingStationStorage {
});
}
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getOcppParameters', uniqueTimerID, parametersMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getOcppParameters', uniqueTimerID, parametersMDB);
return {
count: parametersMDB.configuration.length,
result: parametersMDB.configuration
};
}
// No conf
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getOcppParameters', uniqueTimerID, parametersMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getOcppParameters', uniqueTimerID, parametersMDB);
return {
count: 0,
result: []
};
}
- public static async getChargingProfile(tenantID: string, id: string): Promise {
- const chargingProfilesMDB = await ChargingStationStorage.getChargingProfiles(tenantID, {
+ public static async getChargingProfile(tenant: Tenant, id: string): Promise {
+ const chargingProfilesMDB = await ChargingStationStorage.getChargingProfiles(tenant, {
chargingProfileID: id
}, Constants.DB_PARAMS_SINGLE_RECORD);
return chargingProfilesMDB.count === 1 ? chargingProfilesMDB.result[0] : null;
}
- public static async getChargingProfiles(tenantID: string,
+ public static async getChargingProfiles(tenant: Tenant,
params: {
search?: string; chargingStationIDs?: string[]; connectorID?: number; chargingProfileID?: string;
profilePurposeType?: ChargingProfilePurposeType; transactionId?: number; withChargingStation?: boolean;
@@ -849,9 +850,9 @@ export default class ChargingStationStorage {
} = {},
dbParams: DbParams, projectFields?: string[]): Promise> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getChargingProfiles');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getChargingProfiles');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Clone before updating the values
dbParams = Utils.cloneObject(dbParams);
// Check Limit
@@ -898,13 +899,13 @@ export default class ChargingStationStorage {
if (params.withChargingStation || params.withSiteArea || !Utils.isEmptyArray(params.siteIDs)) {
// Charging Stations
DatabaseUtils.pushChargingStationLookupInAggregation({
- tenantID, aggregation, localField: 'chargingStationID', foreignField: '_id',
+ tenantID: tenant.id, aggregation, localField: 'chargingStationID', foreignField: '_id',
asField: 'chargingStation', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
// Site Areas
if (params.withSiteArea || !Utils.isEmptyArray(params.siteIDs)) {
DatabaseUtils.pushSiteAreaLookupInAggregation({
- tenantID, aggregation, localField: 'chargingStation.siteAreaID', foreignField: '_id',
+ tenantID: tenant.id, aggregation, localField: 'chargingStation.siteAreaID', foreignField: '_id',
asField: 'chargingStation.siteArea', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
// Convert
@@ -930,12 +931,12 @@ export default class ChargingStationStorage {
aggregation.push({ $limit: Constants.DB_RECORD_COUNT_CEIL });
}
// Count Records
- const chargingProfilesCountMDB = await global.database.getCollection>(tenantID, 'chargingprofiles')
+ const chargingProfilesCountMDB = await global.database.getCollection>(tenant.id, 'chargingprofiles')
.aggregate([...aggregation, { $count: 'count' }], { allowDiskUse: true })
.toArray();
// Check if only the total count is requested
if (dbParams.onlyRecordCount) {
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getChargingProfiles', uniqueTimerID, chargingProfilesCountMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getChargingProfiles', uniqueTimerID, chargingProfilesCountMDB);
return {
count: (chargingProfilesCountMDB.length > 0 ? chargingProfilesCountMDB[0].count : 0),
result: []
@@ -944,7 +945,7 @@ export default class ChargingStationStorage {
// Remove the limit
aggregation.pop();
// Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenant.id, aggregation);
// Rename ID
DatabaseUtils.pushRenameDatabaseID(aggregation);
// Sort
@@ -970,13 +971,13 @@ export default class ChargingStationStorage {
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
- const chargingProfilesMDB = await global.database.getCollection(tenantID, 'chargingprofiles')
+ const chargingProfilesMDB = await global.database.getCollection(tenant.id, 'chargingprofiles')
.aggregate(aggregation, {
allowDiskUse: true
})
.toArray();
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getChargingProfiles', uniqueTimerID, chargingProfilesMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getChargingProfiles', uniqueTimerID, chargingProfilesMDB);
return {
count: (chargingProfilesCountMDB.length > 0 ?
(chargingProfilesCountMDB[0].count === Constants.DB_RECORD_COUNT_CEIL ? -1 : chargingProfilesCountMDB[0].count) : 0),
@@ -984,10 +985,10 @@ export default class ChargingStationStorage {
};
}
- public static async saveChargingProfile(tenantID: string, chargingProfileToSave: ChargingProfile): Promise {
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingProfile');
+ public static async saveChargingProfile(tenant: Tenant, chargingProfileToSave: ChargingProfile): Promise {
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveChargingProfile');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
const chargingProfileFilter: any = {};
// Build Request
if (chargingProfileToSave.id) {
@@ -1004,36 +1005,36 @@ export default class ChargingStationStorage {
chargePointID: Utils.convertToInt(chargingProfileToSave.chargePointID),
profile: chargingProfileToSave.profile
};
- await global.database.getCollection(tenantID, 'chargingprofiles').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'chargingprofiles').findOneAndUpdate(
chargingProfileFilter,
{ $set: chargingProfileMDB },
{ upsert: true });
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingProfile', uniqueTimerID, chargingProfileMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveChargingProfile', uniqueTimerID, chargingProfileMDB);
return chargingProfileFilter._id as string;
}
- public static async deleteChargingProfile(tenantID: string, id: string): Promise {
+ public static async deleteChargingProfile(tenant: Tenant, id: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'deleteChargingProfile');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'deleteChargingProfile');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Delete Charging Profile
- await global.database.getCollection(tenantID, 'chargingprofiles')
+ await global.database.getCollection(tenant.id, 'chargingprofiles')
.findOneAndDelete({ '_id': id });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'deleteChargingProfile', uniqueTimerID, { id });
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'deleteChargingProfile', uniqueTimerID, { id });
}
- public static async deleteChargingProfiles(tenantID: string, chargingStationID: string): Promise {
+ public static async deleteChargingProfiles(tenant: Tenant, chargingStationID: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'deleteChargingProfile');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'deleteChargingProfile');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Delete Charging Profiles
- await global.database.getCollection(tenantID, 'chargingprofiles')
+ await global.database.getCollection(tenant.id, 'chargingprofiles')
.findOneAndDelete({ 'chargingStationID': chargingStationID });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'deleteChargingProfile', uniqueTimerID, { chargingStationID });
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'deleteChargingProfile', uniqueTimerID, { chargingStationID });
}
public static getChargingStationFirmware(filename: string): GridFSBucketReadStream {
diff --git a/src/storage/mongodb/RegistrationTokenStorage.ts b/src/storage/mongodb/RegistrationTokenStorage.ts
index 173b98edbc..b2d7a77394 100644
--- a/src/storage/mongodb/RegistrationTokenStorage.ts
+++ b/src/storage/mongodb/RegistrationTokenStorage.ts
@@ -7,16 +7,17 @@ import DbParams from '../../types/database/DbParams';
import Logging from '../../utils/Logging';
import { ObjectId } from 'mongodb';
import RegistrationToken from '../../types/RegistrationToken';
+import Tenant from '../../types/Tenant';
import Utils from '../../utils/Utils';
const MODULE_NAME = 'RegistrationTokenStorage';
export default class RegistrationTokenStorage {
- static async saveRegistrationToken(tenantID: string, registrationToken: RegistrationToken): Promise {
+ static async saveRegistrationToken(tenant: Tenant, registrationToken: RegistrationToken): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveRegistrationToken');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveRegistrationToken');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Set
const registrationTokenMDB = {
_id: registrationToken.id ? DatabaseUtils.convertToObjectID(registrationToken.id) : new ObjectId(),
@@ -28,23 +29,23 @@ export default class RegistrationTokenStorage {
// Add Last Changed/Created props
DatabaseUtils.addLastChangedCreatedProps(registrationTokenMDB, registrationToken);
// Modify
- await global.database.getCollection(tenantID, 'registrationtokens').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'registrationtokens').findOneAndUpdate(
{ _id: registrationTokenMDB._id },
{ $set: registrationTokenMDB },
{ upsert: true, returnDocument: 'after' }
);
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveRegistrationToken', uniqueTimerID, registrationTokenMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveRegistrationToken', uniqueTimerID, registrationTokenMDB);
return registrationTokenMDB._id.toString();
}
- static async getRegistrationTokens(tenantID: string,
+ static async getRegistrationTokens(tenant: Tenant,
params: { tokenIDs?: string[]; siteIDs?: string[]; siteAreaID?: string } = {}, dbParams: DbParams, projectFields?: string[]):
Promise> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getRegistrationTokens');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getRegistrationTokens');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Clone before updating the values
dbParams = Utils.cloneObject(dbParams);
// Check Limit
@@ -55,7 +56,7 @@ export default class RegistrationTokenStorage {
const aggregation = [];
// Add Site Area
DatabaseUtils.pushSiteAreaLookupInAggregation({
- tenantID, aggregation, localField: 'siteAreaID', foreignField: '_id',
+ tenantID: tenant.id, aggregation, localField: 'siteAreaID', foreignField: '_id',
asField: 'siteArea', oneToOneCardinality: true
});
// Set the filters
@@ -88,13 +89,13 @@ export default class RegistrationTokenStorage {
aggregation.push({ $limit: Constants.DB_RECORD_COUNT_CEIL });
}
// Count Records
- const registrationTokensCountMDB = await global.database.getCollection>(tenantID, 'registrationtokens')
+ const registrationTokensCountMDB = await global.database.getCollection>(tenant.id, 'registrationtokens')
.aggregate([...aggregation, { $count: 'count' }], { allowDiskUse: true })
.toArray();
// Check if only the total count is requested
if (dbParams.onlyRecordCount) {
// Return only the count
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getRegistrationTokens', uniqueTimerID, registrationTokensCountMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getRegistrationTokens', uniqueTimerID, registrationTokensCountMDB);
return {
count: (registrationTokensCountMDB.length > 0 ? registrationTokensCountMDB[0].count : 0),
result: []
@@ -120,17 +121,17 @@ export default class RegistrationTokenStorage {
$limit: (dbParams.limit > 0 && dbParams.limit < Constants.DB_RECORD_COUNT_CEIL) ? dbParams.limit : Constants.DB_RECORD_COUNT_CEIL
});
// Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenant.id, aggregation);
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
- const registrationTokens = await global.database.getCollection(tenantID, 'registrationtokens')
+ const registrationTokens = await global.database.getCollection(tenant.id, 'registrationtokens')
.aggregate(aggregation, {
allowDiskUse: true
})
.toArray();
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getRegistrationTokens', uniqueTimerID, registrationTokens);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getRegistrationTokens', uniqueTimerID, registrationTokens);
// Ok
return {
count: (registrationTokensCountMDB.length > 0 ?
@@ -139,20 +140,20 @@ export default class RegistrationTokenStorage {
};
}
- static async getRegistrationToken(tenantID: string, id: string = Constants.UNKNOWN_OBJECT_ID,
+ static async getRegistrationToken(tenant: Tenant, id: string = Constants.UNKNOWN_OBJECT_ID,
projectFields?: string[]): Promise {
- const registrationTokensMDB = await RegistrationTokenStorage.getRegistrationTokens(tenantID, {
+ const registrationTokensMDB = await RegistrationTokenStorage.getRegistrationTokens(tenant, {
tokenIDs: [id]
}, Constants.DB_PARAMS_SINGLE_RECORD, projectFields);
return registrationTokensMDB.count === 1 ? registrationTokensMDB.result[0] : null;
}
- static async deleteRegistrationToken(tenantID: string, id: string): Promise {
+ static async deleteRegistrationToken(tenant: Tenant, id: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'deleteRegistrationToken');
- await global.database.getCollection(tenantID, 'registrationtokens')
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'deleteRegistrationToken');
+ await global.database.getCollection(tenant.id, 'registrationtokens')
.findOneAndDelete({ '_id': DatabaseUtils.convertToObjectID(id) });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'deleteRegistrationToken', uniqueTimerID, { id });
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'deleteRegistrationToken', uniqueTimerID, { id });
}
}
diff --git a/src/storage/mongodb/SiteAreaStorage.ts b/src/storage/mongodb/SiteAreaStorage.ts
index 7ce6c599ab..b2b58ac51e 100644
--- a/src/storage/mongodb/SiteAreaStorage.ts
+++ b/src/storage/mongodb/SiteAreaStorage.ts
@@ -7,22 +7,23 @@ import DbParams from '../../types/database/DbParams';
import Logging from '../../utils/Logging';
import { ObjectId } from 'mongodb';
import SiteArea from '../../types/SiteArea';
+import Tenant from '../../types/Tenant';
import Utils from '../../utils/Utils';
const MODULE_NAME = 'SiteAreaStorage';
export default class SiteAreaStorage {
- public static async addAssetsToSiteArea(tenantID: string, siteArea: SiteArea, assetIDs: string[]): Promise {
+ public static async addAssetsToSiteArea(tenant: Tenant, siteArea: SiteArea, assetIDs: string[]): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'addAssetsToSiteArea');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'addAssetsToSiteArea');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Site Area provided?
if (siteArea) {
// At least one Asset
if (assetIDs && assetIDs.length > 0) {
// Update all assets
- await global.database.getCollection(tenantID, 'assets').updateMany(
+ await global.database.getCollection(tenant.id, 'assets').updateMany(
{ '_id': { $in: assetIDs.map((assetID) => DatabaseUtils.convertToObjectID(assetID)) } },
{
$set: {
@@ -33,20 +34,20 @@ export default class SiteAreaStorage {
}
}
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'addAssetsToSiteArea', uniqueTimerID, assetIDs);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'addAssetsToSiteArea', uniqueTimerID, assetIDs);
}
- public static async removeAssetsFromSiteArea(tenantID: string, siteAreaID: string, assetIDs: string[]): Promise {
+ public static async removeAssetsFromSiteArea(tenant: Tenant, siteAreaID: string, assetIDs: string[]): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'removeAssetsFromSiteArea');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'removeAssetsFromSiteArea');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Site Area provided?
if (siteAreaID) {
// At least one Asset
if (assetIDs && assetIDs.length > 0) {
// Update all assets
- await global.database.getCollection(tenantID, 'assets').updateMany(
+ await global.database.getCollection(tenant.id, 'assets').updateMany(
{ '_id': { $in: assetIDs.map((assetID) => DatabaseUtils.convertToObjectID(assetID)) } },
{
$set: {
@@ -57,28 +58,28 @@ export default class SiteAreaStorage {
}
}
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'removeAssetsFromSiteArea', uniqueTimerID, assetIDs);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'removeAssetsFromSiteArea', uniqueTimerID, assetIDs);
}
- public static async getSiteAreaImage(tenantID: string, id: string): Promise {
+ public static async getSiteAreaImage(tenant: Tenant, id: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getSiteAreaImage');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getSiteAreaImage');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Read DB
- const siteAreaImageMDB = await global.database.getCollection<{ _id: ObjectId; image: string }>(tenantID, 'siteareaimages')
+ const siteAreaImageMDB = await global.database.getCollection<{ _id: ObjectId; image: string }>(tenant.id, 'siteareaimages')
.findOne({ _id: DatabaseUtils.convertToObjectID(id) });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getSiteAreaImage', uniqueTimerID, siteAreaImageMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getSiteAreaImage', uniqueTimerID, siteAreaImageMDB);
return {
id: id, image: siteAreaImageMDB ? siteAreaImageMDB.image : null
};
}
- public static async getSiteArea(tenantID: string, id: string = Constants.UNKNOWN_OBJECT_ID,
+ public static async getSiteArea(tenant: Tenant, id: string = Constants.UNKNOWN_OBJECT_ID,
params: { withSite?: boolean; withChargingStations?: boolean, withAvailableChargingStations?: boolean; withImage?: boolean } = {},
projectFields?: string[]): Promise {
- const siteAreasMDB = await SiteAreaStorage.getSiteAreas(tenantID, {
+ const siteAreasMDB = await SiteAreaStorage.getSiteAreas(tenant, {
siteAreaIDs: [id],
withSite: params.withSite,
withChargingStations: params.withChargingStations,
@@ -88,11 +89,11 @@ export default class SiteAreaStorage {
return siteAreasMDB.count === 1 ? siteAreasMDB.result[0] : null;
}
- public static async saveSiteArea(tenantID: string, siteAreaToSave: SiteArea, saveImage = false): Promise {
+ public static async saveSiteArea(tenant: Tenant, siteAreaToSave: SiteArea, saveImage = false): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveSiteArea');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveSiteArea');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Set
const siteAreaMDB: any = {
_id: !siteAreaToSave.id ? new ObjectId() : DatabaseUtils.convertToObjectID(siteAreaToSave.id),
@@ -121,20 +122,20 @@ export default class SiteAreaStorage {
// Add Last Changed/Created props
DatabaseUtils.addLastChangedCreatedProps(siteAreaMDB, siteAreaToSave);
// Modify
- await global.database.getCollection(tenantID, 'siteareas').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'siteareas').findOneAndUpdate(
{ _id: siteAreaMDB._id },
{ $set: siteAreaMDB },
{ upsert: true, returnDocument: 'after' }
);
if (saveImage) {
- await SiteAreaStorage.saveSiteAreaImage(tenantID, siteAreaMDB._id.toString(), siteAreaToSave.image);
+ await SiteAreaStorage.saveSiteAreaImage(tenant, siteAreaMDB._id.toString(), siteAreaToSave.image);
}
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveSiteArea', uniqueTimerID, siteAreaMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveSiteArea', uniqueTimerID, siteAreaMDB);
return siteAreaMDB._id.toString();
}
- public static async getSiteAreas(tenantID: string,
+ public static async getSiteAreas(tenant: Tenant,
params: {
siteAreaIDs?: string[]; search?: string; siteIDs?: string[]; companyIDs?: string[]; withSite?: boolean; issuer?: boolean; name?: string;
withChargingStations?: boolean; withOnlyChargingStations?: boolean; withAvailableChargingStations?: boolean;
@@ -142,9 +143,9 @@ export default class SiteAreaStorage {
} = {},
dbParams: DbParams, projectFields?: string[]): Promise> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getSiteAreas');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getSiteAreas');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Clone before updating the values
dbParams = Utils.cloneObject(dbParams);
// Check Limit
@@ -190,7 +191,7 @@ export default class SiteAreaStorage {
// Company
if (!Utils.isEmptyArray(params.companyIDs)) {
DatabaseUtils.pushSiteLookupInAggregation({
- tenantID, aggregation, localField: 'siteID', foreignField: '_id',
+ tenantID: tenant.id, aggregation, localField: 'siteID', foreignField: '_id',
asField: 'site', oneToOneCardinality: true
});
filters['site.companyID'] = {
@@ -219,13 +220,13 @@ export default class SiteAreaStorage {
aggregation.push({ $limit: Constants.DB_RECORD_COUNT_CEIL });
}
// Count Records
- const siteAreasCountMDB = await global.database.getCollection>(tenantID, 'siteareas')
+ const siteAreasCountMDB = await global.database.getCollection>(tenant.id, 'siteareas')
.aggregate([...aggregation, { $count: 'count' }], { allowDiskUse: true })
.toArray();
// Check if only the total count is requested
if (dbParams.onlyRecordCount) {
// Return only the count
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getSiteAreas', uniqueTimerID, siteAreasCountMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getSiteAreas', uniqueTimerID, siteAreasCountMDB);
return {
count: (siteAreasCountMDB.length > 0 ? siteAreasCountMDB[0].count : 0),
result: []
@@ -255,14 +256,14 @@ export default class SiteAreaStorage {
// Sites
if (params.withSite) {
DatabaseUtils.pushSiteLookupInAggregation({
- tenantID, aggregation, localField: 'siteID', foreignField: '_id',
+ tenantID: tenant.id, aggregation, localField: 'siteID', foreignField: '_id',
asField: 'site', oneToOneCardinality: true
});
}
// Charging Stations
if (params.withChargingStations || params.withOnlyChargingStations || params.withAvailableChargingStations) {
DatabaseUtils.pushChargingStationLookupInAggregation({
- tenantID, aggregation, localField: '_id', foreignField: 'siteAreaID',
+ tenantID: tenant.id, aggregation, localField: '_id', foreignField: 'siteAreaID',
asField: 'chargingStations'
});
}
@@ -274,7 +275,7 @@ export default class SiteAreaStorage {
$concat: [
`${Utils.buildRestServerURL()}/client/util/SiteAreaImage?ID=`,
{ $toString: '$_id' },
- `&TenantID=${tenantID}&LastChangedOn=`,
+ `&TenantID=${tenant.id}&LastChangedOn=`,
{ $toString: '$lastChangedOn' }
]
}
@@ -284,7 +285,7 @@ export default class SiteAreaStorage {
// Convert Object ID to string
DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteID');
// Add Last Changed / Created
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenant.id, aggregation);
// Handle the ID
DatabaseUtils.pushRenameDatabaseID(aggregation);
// Project
@@ -294,7 +295,7 @@ export default class SiteAreaStorage {
'chargingStations.deleted', 'chargingStations.cannotChargeInParallel', 'chargingStations.public', 'chargingStations.inactive']);
}
// Read DB
- const siteAreasMDB = await global.database.getCollection(tenantID, 'siteareas')
+ const siteAreasMDB = await global.database.getCollection(tenant.id, 'siteareas')
.aggregate(aggregation, {
allowDiskUse: true
})
@@ -324,7 +325,7 @@ export default class SiteAreaStorage {
}
}
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getSiteAreas', uniqueTimerID, siteAreasMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getSiteAreas', uniqueTimerID, siteAreasMDB);
// Ok
return {
projectedFields: projectFields,
@@ -334,17 +335,17 @@ export default class SiteAreaStorage {
};
}
- public static async addChargingStationsToSiteArea(tenantID: string, siteArea: SiteArea, chargingStationIDs: string[]): Promise {
+ public static async addChargingStationsToSiteArea(tenant: Tenant, siteArea: SiteArea, chargingStationIDs: string[]): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'addChargingStationsToSiteArea');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'addChargingStationsToSiteArea');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Site provided?
if (siteArea) {
// At least one ChargingStation
if (chargingStationIDs && chargingStationIDs.length > 0) {
// Update all chargers
- await global.database.getCollection(tenantID, 'chargingstations').updateMany(
+ await global.database.getCollection(tenant.id, 'chargingstations').updateMany(
{ '_id': { $in: chargingStationIDs } },
{
$set: {
@@ -356,20 +357,20 @@ export default class SiteAreaStorage {
}
}
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'addChargingStationsToSiteArea', uniqueTimerID, chargingStationIDs);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'addChargingStationsToSiteArea', uniqueTimerID, chargingStationIDs);
}
- public static async removeChargingStationsFromSiteArea(tenantID: string, siteAreaID: string, chargingStationIDs: string[]): Promise {
+ public static async removeChargingStationsFromSiteArea(tenant: Tenant, siteAreaID: string, chargingStationIDs: string[]): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'removeChargingStationsFromSiteArea');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'removeChargingStationsFromSiteArea');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Site provided?
if (siteAreaID) {
// At least one ChargingStation
if (chargingStationIDs && chargingStationIDs.length > 0) {
// Update all chargers
- await global.database.getCollection(tenantID, 'chargingstations').updateMany(
+ await global.database.getCollection(tenant.id, 'chargingstations').updateMany(
{ '_id': { $in: chargingStationIDs } },
{
$set: {
@@ -381,67 +382,67 @@ export default class SiteAreaStorage {
}
}
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'removeChargingStationsFromSiteArea', uniqueTimerID, chargingStationIDs);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'removeChargingStationsFromSiteArea', uniqueTimerID, chargingStationIDs);
}
- public static async deleteSiteArea(tenantID: string, id: string): Promise {
- await SiteAreaStorage.deleteSiteAreas(tenantID, [id]);
+ public static async deleteSiteArea(tenant: Tenant, id: string): Promise {
+ await SiteAreaStorage.deleteSiteAreas(tenant, [id]);
}
- public static async deleteSiteAreas(tenantID: string, siteAreaIDs: string[]): Promise {
+ public static async deleteSiteAreas(tenant: Tenant, siteAreaIDs: string[]): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'deleteSiteAreas');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'deleteSiteAreas');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Remove Charging Station's Site Area
- await global.database.getCollection(tenantID, 'chargingstations').updateMany(
+ await global.database.getCollection(tenant.id, 'chargingstations').updateMany(
{ siteAreaID: { $in: siteAreaIDs.map((ID) => DatabaseUtils.convertToObjectID(ID)) } },
{ $set: { siteAreaID: null } }
);
// Remove Asset's Site Area
- await global.database.getCollection(tenantID, 'assets').updateMany(
+ await global.database.getCollection(tenant.id, 'assets').updateMany(
{ siteAreaID: { $in: siteAreaIDs.map((ID) => DatabaseUtils.convertToObjectID(ID)) } },
{ $set: { siteAreaID: null } }
);
// Delete SiteArea
- await global.database.getCollection(tenantID, 'siteareas').deleteMany(
+ await global.database.getCollection(tenant.id, 'siteareas').deleteMany(
{ '_id': { $in: siteAreaIDs.map((ID) => DatabaseUtils.convertToObjectID(ID)) } }
);
// Delete Image
- await global.database.getCollection(tenantID, 'sitesareaimages').deleteMany(
+ await global.database.getCollection(tenant.id, 'sitesareaimages').deleteMany(
{ '_id': { $in: siteAreaIDs.map((ID) => DatabaseUtils.convertToObjectID(ID)) } }
);
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'deleteSiteAreas', uniqueTimerID, siteAreaIDs);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'deleteSiteAreas', uniqueTimerID, siteAreaIDs);
}
- public static async deleteSiteAreasFromSites(tenantID: string, siteIDs: string[]): Promise {
+ public static async deleteSiteAreasFromSites(tenant: Tenant, siteIDs: string[]): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'deleteSiteAreasFromSites');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'deleteSiteAreasFromSites');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Find site areas to delete
- const siteareas: string[] = (await global.database.getCollection(tenantID, 'siteareas')
+ const siteareas: string[] = (await global.database.getCollection(tenant.id, 'siteareas')
.find({ siteID: { $in: siteIDs.map((id) => DatabaseUtils.convertToObjectID(id)) } })
.project({ _id: 1 }).toArray()).map((idWrapper): string => idWrapper._id.toString());
// Delete site areas
- await SiteAreaStorage.deleteSiteAreas(tenantID, siteareas);
+ await SiteAreaStorage.deleteSiteAreas(tenant, siteareas);
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'deleteSiteAreasFromSites', uniqueTimerID, siteIDs);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'deleteSiteAreasFromSites', uniqueTimerID, siteIDs);
}
- private static async saveSiteAreaImage(tenantID: string, siteAreaID: string, siteAreaImageToSave: string): Promise {
+ private static async saveSiteAreaImage(tenant: Tenant, siteAreaID: string, siteAreaImageToSave: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveSiteAreaImage');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveSiteAreaImage');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify
- await global.database.getCollection(tenantID, 'siteareaimages').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'siteareaimages').findOneAndUpdate(
{ '_id': DatabaseUtils.convertToObjectID(siteAreaID) },
{ $set: { image: siteAreaImageToSave } },
{ upsert: true, returnDocument: 'after' }
);
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveSiteAreaImage', uniqueTimerID, siteAreaImageToSave);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveSiteAreaImage', uniqueTimerID, siteAreaImageToSave);
}
}
diff --git a/src/storage/mongodb/SiteStorage.ts b/src/storage/mongodb/SiteStorage.ts
index 15b081b0c1..ff608de23b 100644
--- a/src/storage/mongodb/SiteStorage.ts
+++ b/src/storage/mongodb/SiteStorage.ts
@@ -469,7 +469,7 @@ export default class SiteStorage {
for (const siteMDB of sitesMDB) {
if (params.withOnlyChargingStations || params.withAvailableChargingStations) {
// Get the chargers
- const chargingStations = await ChargingStationStorage.getChargingStations(tenant.id,
+ const chargingStations = await ChargingStationStorage.getChargingStations(tenant,
{ siteIDs: [siteMDB.id], includeDeleted: false, withSiteArea: true }, Constants.DB_PARAMS_MAX_LIMIT);
// Skip site with no charging stations if asked
if (params.withOnlyChargingStations && chargingStations.count === 0) {
@@ -508,7 +508,7 @@ export default class SiteStorage {
// Check Tenant
DatabaseUtils.checkTenantObject(tenant);
// Delete all Site Areas
- await SiteAreaStorage.deleteSiteAreasFromSites(tenant.id, ids);
+ await SiteAreaStorage.deleteSiteAreasFromSites(tenant, ids);
// Convert
const cids: ObjectId[] = ids.map((id) => DatabaseUtils.convertToObjectID(id));
// Delete Site
@@ -536,7 +536,7 @@ export default class SiteStorage {
.toArray())
.map((site): string => site._id.toString());
// Delete all Site Areas
- await SiteAreaStorage.deleteSiteAreasFromSites(tenant.id, siteIDs);
+ await SiteAreaStorage.deleteSiteAreasFromSites(tenant, siteIDs);
// Delete Sites
await SiteStorage.deleteSites(tenant, siteIDs);
// Debug
diff --git a/src/storage/mongodb/StatisticsStorage.ts b/src/storage/mongodb/StatisticsStorage.ts
index 01606ee443..5c037950ec 100644
--- a/src/storage/mongodb/StatisticsStorage.ts
+++ b/src/storage/mongodb/StatisticsStorage.ts
@@ -2,6 +2,7 @@ import StatisticFilter, { ChargingStationStats, StatsGroupBy, UserStats } from '
import DatabaseUtils from './DatabaseUtils';
import Logging from '../../utils/Logging';
+import Tenant from '../../types/Tenant';
import Utils from '../../utils/Utils';
import global from '../../types/GlobalType';
@@ -9,11 +10,11 @@ const MODULE_NAME = 'StatisticsStorage';
export default class StatisticsStorage {
- static async getChargingStationStats(tenantID: string, params: StatisticFilter, groupBy: string): Promise {
+ static async getChargingStationStats(tenant: Tenant, params: StatisticFilter, groupBy: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getChargingStationStats');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getChargingStationStats');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Build filter
const filters: any = {};
// Date provided?
@@ -122,19 +123,19 @@ export default class StatisticsStorage {
$sort: { 'month': 1, 'unit': 1, 'chargeBox': 1 }
});
// Read DB
- const chargingStationStatsMDB = await global.database.getCollection(tenantID, 'transactions')
+ const chargingStationStatsMDB = await global.database.getCollection(tenant.id, 'transactions')
.aggregate(aggregation, { allowDiskUse: true })
.toArray();
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getChargingStationStats', uniqueTimerID, chargingStationStatsMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getChargingStationStats', uniqueTimerID, chargingStationStatsMDB);
return chargingStationStatsMDB;
}
- static async getUserStats(tenantID: string, params: StatisticFilter, groupBy: string): Promise {
+ static async getUserStats(tenant: Tenant, params: StatisticFilter, groupBy: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getUserStats');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getUserStats');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Build filter
const filters: any = {};
// Date provided?
@@ -234,7 +235,7 @@ export default class StatisticsStorage {
}
// Lookup for users
DatabaseUtils.pushUserLookupInAggregation({
- tenantID, aggregation, localField: '_id.userID', foreignField: '_id',
+ tenantID: tenant.id, aggregation, localField: '_id.userID', foreignField: '_id',
asField: 'user', oneToOneCardinality: true, oneToOneCardinalityNotNull: true
}, [ { $project: { _id: 1, name: 1, firstName: 1 } } ]);
// Single Record
@@ -252,11 +253,11 @@ export default class StatisticsStorage {
$sort: { 'month': 1, 'unit': 1, 'userID': 1 } // Instead of chargeBox userID ?
});
// Read DB
- const userStatsMDB = await global.database.getCollection(tenantID, 'transactions')
+ const userStatsMDB = await global.database.getCollection(tenant.id, 'transactions')
.aggregate(aggregation, { allowDiskUse: true })
.toArray();
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getUserStats', uniqueTimerID, userStatsMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getUserStats', uniqueTimerID, userStatsMDB);
return userStatsMDB;
}
}
diff --git a/src/storage/mongodb/TagStorage.ts b/src/storage/mongodb/TagStorage.ts
index 68dc83e5b2..13a99b033c 100644
--- a/src/storage/mongodb/TagStorage.ts
+++ b/src/storage/mongodb/TagStorage.ts
@@ -27,7 +27,8 @@ export default class TagStorage {
default: Utils.convertToBoolean(tag.default),
visualID: tag.visualID ?? new ObjectId().toString(),
ocpiToken: tag.ocpiToken,
- description: tag.description
+ description: tag.description,
+ importedData: tag.importedData
};
// Check Created/Last Changed By
DatabaseUtils.addLastChangedCreatedProps(tagMDB, tag);
@@ -52,7 +53,9 @@ export default class TagStorage {
status: importedTagToSave.status,
errorDescription: importedTagToSave.errorDescription,
importedOn: importedTagToSave.importedOn,
- importedBy: importedTagToSave.importedBy
+ importedBy: importedTagToSave.importedBy,
+ siteIDs: importedTagToSave.siteIDs,
+ importedData: importedTagToSave.importedData
};
await global.database.getCollection(tenantID, 'importedtags').findOneAndUpdate(
{ _id: tagMDB._id },
@@ -76,7 +79,9 @@ export default class TagStorage {
status: importedTagToSave.status,
errorDescription: importedTagToSave.errorDescription,
importedOn: importedTagToSave.importedOn,
- importedBy: importedTagToSave.importedBy
+ importedBy: importedTagToSave.importedBy,
+ siteIDs: importedTagToSave.siteIDs,
+ importedData: importedTagToSave.importedData
}));
// Insert all at once
const result = await global.database.getCollection(tenantID, 'importedtags').insertMany(
@@ -119,7 +124,7 @@ export default class TagStorage {
// Check Tenant
await DatabaseUtils.checkTenant(tenantID);
// Count documents
- const nbrOfDocuments = await global.database.getCollection(tenantID, 'importedtags').count();
+ const nbrOfDocuments = await global.database.getCollection(tenantID, 'importedtags').countDocuments();
// Debug
await Logging.traceEnd(tenantID, MODULE_NAME, 'getImportedTagsCount', uniqueTimerID);
return nbrOfDocuments;
diff --git a/src/storage/mongodb/TransactionStorage.ts b/src/storage/mongodb/TransactionStorage.ts
index bae4cd773c..a58f9f2572 100644
--- a/src/storage/mongodb/TransactionStorage.ts
+++ b/src/storage/mongodb/TransactionStorage.ts
@@ -12,42 +12,43 @@ import DbParams from '../../types/database/DbParams';
import Logging from '../../utils/Logging';
import { NotifySessionNotStarted } from '../../types/UserNotifications';
import { ServerAction } from '../../types/Server';
+import Tenant from '../../types/Tenant';
import Utils from '../../utils/Utils';
import moment from 'moment';
const MODULE_NAME = 'TransactionStorage';
export default class TransactionStorage {
- public static async deleteTransaction(tenantID: string, transactionID: number): Promise {
- await TransactionStorage.deleteTransactions(tenantID, [transactionID]);
+ public static async deleteTransaction(tenant: Tenant, transactionID: number): Promise {
+ await TransactionStorage.deleteTransactions(tenant, [transactionID]);
}
- public static async deleteTransactions(tenantID: string, transactionsIDs: number[]): Promise {
+ public static async deleteTransactions(tenant: Tenant, transactionsIDs: number[]): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'deleteTransaction');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'deleteTransaction');
// Check
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Delete
- const result = await global.database.getCollection(tenantID, 'transactions')
+ const result = await global.database.getCollection(tenant.id, 'transactions')
.deleteMany({ '_id': { $in: transactionsIDs } });
// Delete Meter Values
- await global.database.getCollection(tenantID, 'metervalues')
+ await global.database.getCollection(tenant.id, 'metervalues')
.deleteMany({ 'transactionId': { $in: transactionsIDs } });
// Delete Consumptions
- await ConsumptionStorage.deleteConsumptions(tenantID, transactionsIDs);
+ await ConsumptionStorage.deleteConsumptions(tenant.id, transactionsIDs);
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'deleteTransaction', uniqueTimerID, { transactionsIDs });
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'deleteTransaction', uniqueTimerID, { transactionsIDs });
return result.deletedCount;
}
- public static async saveTransaction(tenantID: string, transactionToSave: Transaction): Promise {
+ public static async saveTransaction(tenant: Tenant, transactionToSave: Transaction): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveTransaction');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveTransaction');
// Check
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// ID not provided?
if (!transactionToSave.id) {
- transactionToSave.id = await TransactionStorage.findAvailableID(tenantID);
+ transactionToSave.id = await TransactionStorage.findAvailableID(tenant);
}
// Transfer
const transactionMDB: any = {
@@ -201,24 +202,24 @@ export default class TransactionStorage {
};
}
// Modify
- await global.database.getCollection(tenantID, 'transactions').findOneAndReplace(
+ await global.database.getCollection(tenant.id, 'transactions').findOneAndReplace(
{ '_id': Utils.convertToInt(transactionToSave.id) },
transactionMDB,
{ upsert: true });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveTransaction', uniqueTimerID, transactionMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveTransaction', uniqueTimerID, transactionMDB);
// Return
return transactionToSave.id;
}
- public static async saveTransactionOcpiData(tenantID: string, id: number,
+ public static async saveTransactionOcpiData(tenant: Tenant, id: number,
ocpiData: TransactionOcpiData): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveTransactionOcpiData');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveTransactionOcpiData');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify document
- await global.database.getCollection(tenantID, 'transactions').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'transactions').findOneAndUpdate(
{ '_id': id },
{
$set: {
@@ -227,17 +228,17 @@ export default class TransactionStorage {
},
{ upsert: false });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveTransactionOcpiData', uniqueTimerID, ocpiData);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveTransactionOcpiData', uniqueTimerID, ocpiData);
}
- public static async saveTransactionOicpData(tenantID: string, id: number,
+ public static async saveTransactionOicpData(tenant: Tenant, id: number,
oicpData: TransactionOicpData): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveTransactionOicpData');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveTransactionOicpData');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify document
- await global.database.getCollection(tenantID, 'transactions').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'transactions').findOneAndUpdate(
{ '_id': id },
{
$set: {
@@ -246,17 +247,17 @@ export default class TransactionStorage {
},
{ upsert: false });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveTransactionOicpData', uniqueTimerID, oicpData);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveTransactionOicpData', uniqueTimerID, oicpData);
}
- public static async saveTransactionBillingData(tenantID: string, id: number,
+ public static async saveTransactionBillingData(tenant: Tenant, id: number,
billingData: TransactionBillingData): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveTransactionBillingData');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveTransactionBillingData');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify document
- await global.database.getCollection(tenantID, 'transactions').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'transactions').findOneAndUpdate(
{ '_id': id },
{
$set: {
@@ -265,17 +266,17 @@ export default class TransactionStorage {
},
{ upsert: false });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveTransactionBillingData', uniqueTimerID, billingData);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveTransactionBillingData', uniqueTimerID, billingData);
}
- public static async saveTransactionRefundData(tenantID: string, id: number,
+ public static async saveTransactionRefundData(tenant: Tenant, id: number,
refundData: TransactionRefundData): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveTransactionRefundData');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveTransactionRefundData');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Modify document
- await global.database.getCollection(tenantID, 'transactions').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'transactions').findOneAndUpdate(
{ '_id': id },
{
$set: {
@@ -284,14 +285,14 @@ export default class TransactionStorage {
},
{ upsert: false });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveTransactionRefundData', uniqueTimerID, refundData);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveTransactionRefundData', uniqueTimerID, refundData);
}
- public static async assignTransactionsToUser(tenantID: string, userID: string, tagID: string): Promise {
+ public static async assignTransactionsToUser(tenant: Tenant, userID: string, tagID: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'assignTransactionsToUser');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'assignTransactionsToUser');
// Assign transactions
- await global.database.getCollection(tenantID, 'transactions').updateMany({
+ await global.database.getCollection(tenant.id, 'transactions').updateMany({
$and: [
{ 'userID': null },
{ 'tagID': tagID }
@@ -302,30 +303,30 @@ export default class TransactionStorage {
}
});
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'assignTransactionsToUser', uniqueTimerID);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'assignTransactionsToUser', uniqueTimerID);
}
- public static async getUnassignedTransactionsCount(tenantID: string, tagID: string): Promise {
+ public static async getUnassignedTransactionsCount(tenant: Tenant, tagID: string): Promise {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getUnassignedTransactionsCount');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getUnassignedTransactionsCount');
// Get the number of unassigned transactions
- const unassignedCount = await global.database.getCollection