feat: added billing-platform tenant component
MODIFY
src/assets/schemas/tenant/tenant-components.json
src/assets/schemas/tenant/tenant-components.json
}
}
},
+ "billingPlatform": {
+ "type": "object",
+ "properties": {
+ "active": {
+ "type": "boolean",
+ "sanitize": "mongo"
+ }
+ }
+ },
"organization": {
"type": "object",
"properties": {

ADD
src/assets/server/rest/v1/schemas/setting/setting-billing-platform-set.json
+{
+ "$id": "setting-billing-platform-set",
+ "title": "Set Billing Platform Settings",
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "object",
+ "properties": {
+ }
+ },
+ "id": {
+ "$ref": "common#/definitions/id"
+ },
+ "identifier": {
+ "type": "string",
+ "sanitize": "mongo",
+ "enum": ["billingPlatform"]
+ },
+ "sensitiveData": {
+ "$ref": "setting#/definitions/sensitiveData"
+ }
+ },
+ "required": [
+ "identifier"
+ ]
+}

MODIFY
src/server/rest/v1/service/BillingService.ts
src/server/rest/v1/service/BillingService.ts
@@ -473,7 +473,7 @@ export default class BillingService {
public static async handleCreateSubAccount(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Check if component is active
- UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING,
+ UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING_PLATFORM,
Action.BILLING_CREATE_SUB_ACCOUNT, Entity.BILLING, MODULE_NAME, 'handleCreateSubAccount');
const filteredRequest = BillingValidator.getInstance().validateBillingCreateSubAccountReq(req.body);
// Check authorization

MODIFY
src/server/rest/v1/service/SettingService.ts
src/server/rest/v1/service/SettingService.ts
@@ -329,6 +329,8 @@ export default class SettingService {
return SettingValidator.getInstance().validateSettingCarConnectorSetReq(req.body);
case IntegrationSettings.BILLING:
return SettingValidator.getInstance().validateSettingBillingSetReq(req.body);
+ case IntegrationSettings.BILLING_PLATFORM:
+ return SettingValidator.getInstance().validateSettingBillingPlatformSetReq(req.body);
case IntegrationSettings.CAR:
return SettingValidator.getInstance().validateSettingCarSetReq(req.body);
case IntegrationSettings.ORGANIZATION:

MODIFY
src/server/rest/v1/service/UtilsService.ts
src/server/rest/v1/service/UtilsService.ts
@@ -1158,6 +1158,14 @@ export default class UtilsService {
user: req.user.id
});
}
+ if (tenant.components.billingPlatform?.active && !tenant.components.billing?.active) {
+ throw new AppError({
+ errorCode: HTTPError.GENERAL_ERROR,
+ message: 'Billing sub-accounts cannot be active without the Billing component',
+ module: MODULE_NAME, method: 'checkIfTenantValid',
+ user: req.user.id
+ });
+ }
if (tenant.components.smartCharging?.active && !tenant.components.organization?.active) {
throw new AppError({
errorCode: HTTPError.GENERAL_ERROR,

MODIFY
src/server/rest/v1/validator/SettingValidator.ts
src/server/rest/v1/validator/SettingValidator.ts
@@ -17,6 +17,7 @@ export default class SettingValidator extends SchemaValidator {
private settingAnalyticsSet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-analytics-set.json`, 'utf8'));
private settingOICPSet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-oicp-set.json`, 'utf8'));
private settingBillingSet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-billing-set.json`, 'utf8'));
+ private settingBillingPlatformSet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-billing-platform-set.json`, 'utf8'));
private settingAssetSet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-asset-set.json`, 'utf8'));
private settingCarConnectorSet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-car-connector-set.json`, 'utf8'));
private settingCarSet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-car-set.json`, 'utf8'));
@@ -85,6 +86,10 @@ export default class SettingValidator extends SchemaValidator {
return this.validate(this.settingBillingSet, data);
}
+ public validateSettingBillingPlatformSetReq(data: Record<string, unknown>): SettingDB {
+ return this.validate(this.settingBillingPlatformSet, data);
+ }
+
public validateSettingAssetSetReq(data: Record<string, unknown>): SettingDB {
return this.validate(this.settingAssetSet, data);
}

MODIFY
src/types/Setting.ts
src/types/Setting.ts
@@ -17,6 +17,7 @@ export enum IntegrationSettings {
ASSET = 'asset',
CAR_CONNECTOR = 'carConnector',
BILLING = 'billing',
+ BILLING_PLATFORM = 'billingPlatform',
CAR = 'car',
ORGANIZATION = 'organization',
STATISTICS = 'statistics'

MODIFY
src/types/Tenant.ts
src/types/Tenant.ts
@@ -17,6 +17,7 @@ export interface TenantComponent {
organization?: TenantComponentContent;
pricing?: TenantComponentContent;
billing?: TenantComponentContent;
+ billingPlatform?: TenantComponentContent;
refund?: TenantComponentContent;
statistics?: TenantComponentContent;
analytics?: TenantComponentContent;
@@ -45,6 +46,7 @@ export enum TenantComponents {
STATISTICS = 'statistics',
ANALYTICS = 'analytics',
BILLING = 'billing',
+ BILLING_PLATFORM = 'billingPlatform',
ASSET = 'asset',
SMART_CHARGING = 'smartCharging',
CAR = 'car',

MODIFY
test/api/BillingTest.ts
test/api/BillingTest.ts
@@ -273,7 +273,7 @@ describeif(isBillingProperlyConfigured)('Billing', () => {
describe('Billing Service (utbilling)', () => {
beforeAll(async () => {
- await billingTestHelper.initialize();
+ await billingTestHelper.initialize(ContextDefinition.TENANT_CONTEXTS.TENANT_BILLING);
});
describe('with Transaction Billing ON', () => {
@@ -393,46 +393,6 @@ describeif(isBillingProperlyConfigured)('Billing', () => {
expect(response.status).to.be.eq(StatusCodes.OK);
expect(response.data.result.length).to.be.gt(0);
});
-
- it('should create a sub account', async () => {
- const response = await billingTestHelper.userService.billingApi.createSubAccount({
- userID: billingTestHelper.userContext.id
- });
- expect(response.status).to.be.eq(StatusCodes.CREATED);
- expect(response.data.id).to.not.be.null;
- expect(response.data.accountID).to.not.be.null;
- expect(response.data.userID).to.eq(billingTestHelper.userContext.id);
- expect(response.data.activationLink).to.not.be.null;
- expect(response.data.pending).to.be.true;
- });
-
- it('should create a sub account and activate it', async () => {
- const response = await billingTestHelper.userService.billingApi.createSubAccount({
- userID: billingTestHelper.userContext.id
- });
- expect(response.status).to.be.eq(StatusCodes.CREATED);
-
- const activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: response.data.id, TenantID: billingTestHelper.tenantContext.getTenant().id });
- expect(activationResponse.status).to.be.eq(StatusCodes.OK);
- expect(activationResponse.data.pending).to.be.false;
- });
-
- it('should not activate an inexistent sub account', async () => {
- const activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: '5ce249a1a39ae1c056c389bd', TenantID: billingTestHelper.tenantContext.getTenant().id });
- expect(activationResponse.status).to.be.eq(HTTPError.OBJECT_DOES_NOT_EXIST_ERROR);
- });
-
- it('should not activate a sub account twice', async () => {
- const response = await billingTestHelper.userService.billingApi.createSubAccount({
- userID: billingTestHelper.userContext.id
- });
- expect(response.status).to.be.eq(StatusCodes.CREATED);
-
- let activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: response.data.id, TenantID: billingTestHelper.tenantContext.getTenant().id });
- expect(activationResponse.status).to.be.eq(StatusCodes.OK);
- activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: response.data.id, TenantID: billingTestHelper.tenantContext.getTenant().id });
- expect(activationResponse.status).to.be.eq(StatusCodes.INTERNAL_SERVER_ERROR);
- });
});
describe('Where basic user', () => {
@@ -492,18 +452,6 @@ describeif(isBillingProperlyConfigured)('Billing', () => {
const itemsAfter = await billingTestHelper.getNumberOfSessions(basicUser.id);
expect(itemsAfter).to.be.eq(itemsBefore + 1);
});
-
- it('should not be able to create a sub account', async () => {
- const response = await billingTestHelper.userService.billingApi.createSubAccount({
- userID: billingTestHelper.userContext.id
- });
- expect(response.status).to.be.eq(StatusCodes.FORBIDDEN);
- });
-
- it('should not activate an inexistent sub account', async () => {
- const activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: '5ce249a1a39ae1c056c389bd', TenantID: billingTestHelper.tenantContext.getTenant().id });
- expect(activationResponse.status).to.be.eq(HTTPError.OBJECT_DOES_NOT_EXIST_ERROR);
- });
});
describe('Negative tests as an admin user', () => {
@@ -1014,6 +962,88 @@ describeif(isBillingProperlyConfigured)('Billing', () => {
});
});
+ describe('Billing Service (utbillingplatform)', () => {
+ beforeAll(async () => {
+ await billingTestHelper.initialize(ContextDefinition.TENANT_CONTEXTS.TENANT_BILLING_PLATFORM);
+ // Initialize the Billing module
+ billingTestHelper.billingImpl = await billingTestHelper.setBillingSystemValidCredentials();
+ });
+
+ describe('Where admin user', () => {
+ // eslint-disable-next-line @typescript-eslint/require-await
+ beforeAll(async () => {
+ billingTestHelper.initUserContextAsAdmin();
+ });
+
+ describe('Sub accounts', () => {
+ it('should create a sub account', async () => {
+ const response = await billingTestHelper.userService.billingApi.createSubAccount({
+ userID: billingTestHelper.userContext.id
+ });
+ expect(response.status).to.be.eq(StatusCodes.CREATED);
+ expect(response.data.id).to.not.be.null;
+ expect(response.data.accountID).to.not.be.null;
+ expect(response.data.userID).to.eq(billingTestHelper.userContext.id);
+ expect(response.data.activationLink).to.not.be.null;
+ expect(response.data.pending).to.be.true;
+ });
+
+ it('should create a sub account and activate it', async () => {
+ const response = await billingTestHelper.userService.billingApi.createSubAccount({
+ userID: billingTestHelper.userContext.id
+ });
+ expect(response.status).to.be.eq(StatusCodes.CREATED);
+
+ const activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: response.data.id, TenantID: billingTestHelper.tenantContext.getTenant().id });
+ expect(activationResponse.status).to.be.eq(StatusCodes.OK);
+ expect(activationResponse.data.pending).to.be.false;
+ });
+
+ it('should not activate an inexistent sub account', async () => {
+ const activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: '5ce249a1a39ae1c056c389bd', TenantID: billingTestHelper.tenantContext.getTenant().id });
+ expect(activationResponse.status).to.be.eq(StatusCodes.NOT_FOUND);
+ });
+
+ it('should not activate a sub account twice', async () => {
+ const response = await billingTestHelper.userService.billingApi.createSubAccount({
+ userID: billingTestHelper.userContext.id
+ });
+ expect(response.status).to.be.eq(StatusCodes.CREATED);
+
+ let activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: response.data.id, TenantID: billingTestHelper.tenantContext.getTenant().id });
+ expect(activationResponse.status).to.be.eq(StatusCodes.OK);
+ activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: response.data.id, TenantID: billingTestHelper.tenantContext.getTenant().id });
+ expect(activationResponse.status).to.be.eq(StatusCodes.INTERNAL_SERVER_ERROR);
+ });
+ });
+ });
+
+ describe('Where basic user', () => {
+
+ beforeAll(async () => {
+ billingTestHelper.billingImpl = await billingTestHelper.setBillingSystemValidCredentials();
+ billingTestHelper.userContext = billingTestHelper.tenantContext.getUserContext(ContextDefinition.USER_CONTEXTS.BASIC_USER);
+ billingTestHelper.userService = new CentralServerService(
+ billingTestHelper.tenantContext.getTenant().subdomain,
+ billingTestHelper.userContext
+ );
+ expect(billingTestHelper.userService).to.not.be.null;
+ });
+
+ it('should not be able to create a sub account', async () => {
+ const response = await billingTestHelper.userService.billingApi.createSubAccount({
+ userID: billingTestHelper.userContext.id
+ });
+ expect(response.status).to.be.eq(StatusCodes.FORBIDDEN);
+ });
+
+ it('should not activate an inexistent sub account', async () => {
+ const activationResponse = await billingTestHelper.userService.billingApi.activateSubAccount({ accountID: '5ce249a1a39ae1c056c389bd', TenantID: billingTestHelper.tenantContext.getTenant().id });
+ expect(activationResponse.status).to.be.eq(StatusCodes.NOT_FOUND);
+ });
+ });
+ });
+
describe('Billing Test Data Cleanup (utbilling)', () => {
beforeAll(async () => {
await stripeTestHelper.initialize();

MODIFY
test/api/BillingTestHelper.ts
test/api/BillingTestHelper.ts
@@ -58,8 +58,8 @@ export default class BillingTestHelper {
public billingImpl: StripeBillingIntegration;
public billingUser: BillingUser; // DO NOT CONFUSE - BillingUser is not a User!
- public async initialize() : Promise<void> {
- this.tenantContext = await ContextProvider.defaultInstance.getTenantContext(ContextDefinition.TENANT_CONTEXTS.TENANT_BILLING);
+ public async initialize(tenant: string) : Promise<void> {
+ this.tenantContext = await ContextProvider.defaultInstance.getTenantContext(tenant);
this.adminUserContext = this.tenantContext.getUserContext(ContextDefinition.USER_CONTEXTS.DEFAULT_ADMIN);
this.adminUserService = new CentralServerService(
this.tenantContext.getTenant().subdomain,

MODIFY
test/api/ComponentActivationTenantTest.ts
test/api/ComponentActivationTenantTest.ts
@@ -64,6 +64,7 @@ describe('Tenant Settings', () => {
pricing: { active: false, type: null },
refund: { active: false, type: null },
billing: { active: false, type: null },
+ billingPlatform: { active: false, type: null },
smartCharging: { active: false, type: null },
statistics: { active: false, type: null },
analytics: { active: false, type: null },
@@ -198,6 +199,62 @@ describe('Tenant Settings', () => {
}
);
+ it(
+ 'Billing sub-accounts : Check that the setting has been created in the tenant after activation',
+ async () => {
+ // Fill in the data
+ testData.data = {
+ id: testData.credentials.tenantId,
+ name: ContextDefinition.TENANT_CONTEXTS.TENANT_WITH_NO_COMPONENTS,
+ email: testData.credentials.email,
+ subdomain: ContextDefinition.TENANT_CONTEXTS.TENANT_WITH_NO_COMPONENTS,
+ components: {
+ ocpi: { active: false, type: null },
+ organization: { active: false, type: null },
+ pricing: { active: false, type: null },
+ refund: { active: false, type: null },
+ billing: { active: false, type: null },
+ billingPlatform: { active: true, type: null },
+ smartCharging: { active: false, type: null },
+ statistics: { active: false, type: null },
+ analytics: { active: false, type: null },
+ asset: { active: false, type: null }
+ }
+ };
+ let res = await testData.superAdminCentralService.updateEntity(
+ testData.centralService.tenantApi, testData.data, false);
+ expect(res.status).to.equal(StatusCodes.INTERNAL_SERVER_ERROR);
+
+ // Fill in the data
+ testData.data = {
+ id: testData.credentials.tenantId,
+ name: ContextDefinition.TENANT_CONTEXTS.TENANT_WITH_NO_COMPONENTS,
+ email: testData.credentials.email,
+ subdomain: ContextDefinition.TENANT_CONTEXTS.TENANT_WITH_NO_COMPONENTS,
+ components: {
+ ocpi: { active: false, type: null },
+ organization: { active: false, type: null },
+ pricing: { active: true, type: PricingSettingsType.SIMPLE },
+ refund: { active: false, type: null },
+ billing: { active: true, type: BillingSettingsType.STRIPE },
+ billingPlatform: { active: true, type: null },
+ smartCharging: { active: false, type: null },
+ statistics: { active: false, type: null },
+ analytics: { active: false, type: null },
+ asset: { active: false, type: null }
+ }
+ };
+ res = await testData.superAdminCentralService.updateEntity(
+ testData.centralService.tenantApi, testData.data);
+ expect(res.status).to.equal(StatusCodes.OK);
+ testData.connectUser();
+ const tenant = await testData.superAdminCentralService.tenantApi.readById(testData.data.id);
+ expect(tenant.status).to.equal(StatusCodes.OK);
+ expect(tenant.data.components.billingPlatform).to.exist;
+ expect(tenant.data.components.billingPlatform.active).to.be.true;
+ }
+ );
+
it(
'Refund : Check that the setting has been created in the tenant after activation',
async () => {

MODIFY
test/api/context/ContextDefinition.ts
test/api/context/ContextDefinition.ts
@@ -19,13 +19,14 @@ export interface TenantDefinition {
analytics?: { content?: SettingDBContent };
smartCharging?: { content?: SettingDBContent };
billing?: { content?: SettingDBContent };
+ billingPlatform?: { content?: SettingDBContent };
asset?: { content?: SettingDBContent };
car?: { content?: SettingDBContent };
};
}
export default class ContextDefinition {
- static readonly TENANT_CONTEXTS: Record<string, string> = {
+ public static readonly TENANT_CONTEXTS: Record<string, string> = {
TENANT_WITH_ALL_COMPONENTS: 'utall', // All components are active
TENANT_WITH_NO_COMPONENTS: 'utnothing', // No components are active
TENANT_ORGANIZATION: 'utorg', // Only organization component is active
@@ -34,19 +35,20 @@ export default class ContextDefinition {
TENANT_OICP: 'utoicp', // Only ocpi component is active
TENANT_FUNDING: 'utrefund', // Only refund component is active
TENANT_BILLING: 'utbilling', // Only billing and pricing component is active
+ TENANT_BILLING_PLATFORM: 'utbillingplatform', // Only billing, pricing and billingplatform component is active
TENANT_ASSET: 'utasset', // Only asset component is active
TENANT_CAR: 'utcar', // Only car component is active
TENANT_SMART_CHARGING: 'utsmartcharging' // Organization and Smart Charging components are active
};
- static readonly SITE_CONTEXTS: Record<string, string> = {
+ public static readonly SITE_CONTEXTS: Record<string, string> = {
NO_SITE: 'No site', // Used for unassigned Charging Station or CS in tenant with no organizations
SITE_BASIC: 'ut-site', // Default site with no settings
SITE_WITH_AUTO_USER_ASSIGNMENT: 'ut-site-auto', // Automatic user assignment is active
SITE_WITH_OTHER_USER_STOP_AUTHORIZATION: 'ut-site-stop' // Authorization to stop other users transaction is active
};
- static readonly SITE_AREA_CONTEXTS: Record<string, string> = {
+ public static readonly SITE_AREA_CONTEXTS: Record<string, string> = {
NO_SITE: 'No site', // Used for unassigned Charging Station or CS in tenant with no organizations
WITH_ACL: 'withACL', // ACL is active
WITHOUT_ACL: 'withoutACL', // ACL is inactive
@@ -55,7 +57,7 @@ export default class ContextDefinition {
WITH_SMART_CHARGING_DC: 'withSmartChargingDC', // Smart Charging is active DC
};
- static readonly CHARGING_STATION_CONTEXTS: Record<string, string> = {
+ public static readonly CHARGING_STATION_CONTEXTS: Record<string, string> = {
UNREGISTERED_OCPP16: faker.random.alphaNumeric(10),
INVALID_IDENTIFIER_OCPP16: 'inv@l!d:1.6',
ASSIGNED_OCPP16: 'cs-16', // Charging Station is assigned to each site area with OCPP16
@@ -68,7 +70,7 @@ export default class ContextDefinition {
UNKNOWN_OCPP15: 'cs-unknown15' // Charging station is not in template and use OCPP15
};
- static readonly USER_CONTEXTS: Record<string, any> = {
+ public static readonly USER_CONTEXTS: Record<string, any> = {
DEFAULT_ADMIN: {
role: 'A', status: 'A', assignedToSite: true, withTags: true, issuer: true
},
@@ -102,12 +104,12 @@ export default class ContextDefinition {
/**
* Price of the consumed energy - 1 Euros / kWh
*/
- static readonly DEFAULT_PRICE = 1;
+ public static readonly DEFAULT_PRICE = 1;
/**
* Definition of the different contexts
*/
- static readonly TENANT_CONTEXT_LIST: TenantDefinition[] = [{
+ public static readonly TENANT_CONTEXT_LIST: TenantDefinition[] = [{
tenantName: ContextDefinition.TENANT_CONTEXTS.TENANT_WITH_ALL_COMPONENTS,
id: 'aaaaaaaaaaaaaaaaaaaaaaa1',
subdomain: ContextDefinition.TENANT_CONTEXTS.TENANT_WITH_ALL_COMPONENTS,
@@ -390,10 +392,45 @@ export default class ContextDefinition {
},
},
},
+ {
+ tenantName: ContextDefinition.TENANT_CONTEXTS.TENANT_BILLING_PLATFORM,
+ id: 'aaaaaaaaaaaaaaaaaaaaaab4',
+ subdomain: ContextDefinition.TENANT_CONTEXTS.TENANT_BILLING_PLATFORM,
+ componentSettings: {
+ pricing: {
+ content: {
+ type: PricingSettingsType.SIMPLE,
+ simple: {
+ price: ContextDefinition.DEFAULT_PRICE,
+ currency: 'EUR'
+ }
+ }
+ },
+ billing: {
+ content: {
+ type: BillingSettingsType.STRIPE,
+ billing: {
+ isTransactionBillingActivated: true,
+ immediateBillingAllowed: true,
+ periodicBillingAllowed: true,
+ taxID: ''
+ },
+ stripe: {
+ url: '',
+ secretKey: '',
+ publicKey: '',
+ }
+ }
+ },
+ billingPlatform: {
+ },
+ organization: {},
+ },
+ },
];
// List of users created in a tenant
- static readonly TENANT_USER_LIST: any[] = [
+ public static readonly TENANT_USER_LIST: any[] = [
// Email and password are taken from config file for all users
{ // Default Admin user.
id: '5ce249a1a39ae1c056c389bd',
@@ -582,7 +619,7 @@ export default class ContextDefinition {
];
// List of companies created in a tenant where organization component is active
- static readonly TENANT_COMPANY_LIST: any[] = [
+ public static readonly TENANT_COMPANY_LIST: any[] = [
{ // Default company no settings yet
id: '5ce249a2372f0b1c8caf928f'
},
@@ -592,7 +629,7 @@ export default class ContextDefinition {
];
// List of sites created in a tenant where organization component is active
- static readonly TENANT_SITE_LIST: any[] = [
+ public static readonly TENANT_SITE_LIST: any[] = [
{ // Default site
// contextName: ContextDefinition.SITE_CONTEXTS.SITE_BASIC,
id: '5ce249a2372f0b1c8caf9294',
@@ -621,7 +658,7 @@ export default class ContextDefinition {
// List of siteArea created in a tenant where organization component is active
// sitename must refer an existing site from TENANT_SITE_LIST
- static readonly TENANT_SITEAREA_LIST: any[] = [
+ public static readonly TENANT_SITEAREA_LIST: any[] = [
{ // With access control
id: '5ce249a2372f0b1c8caf9294',
name: `${ContextDefinition.SITE_CONTEXTS.SITE_BASIC}-${ContextDefinition.SITE_AREA_CONTEXTS.WITH_ACL}`,
@@ -707,7 +744,7 @@ export default class ContextDefinition {
// List of Charging Station created in a tenant
// siteAreaNames must refer the site Areas where teh charging station will be created
// if siteAreaNames is null then the CS will not be assigned or created in tenant with no organization, so the baseName MUST be unique
- static readonly TENANT_CHARGING_STATION_LIST: any[] = [
+ public static readonly TENANT_CHARGING_STATION_LIST: any[] = [
{
baseName: ContextDefinition.CHARGING_STATION_CONTEXTS.ASSIGNED_OCPP16, // Concatenated with siteAreaName
ocppVersion: OCPPVersion.VERSION_16,
@@ -746,7 +783,7 @@ export default class ContextDefinition {
];
// List of assets created in a tenant where organization component is active
- static readonly TENANT_ASSET_LIST: any[] = [
+ public static readonly TENANT_ASSET_LIST: any[] = [
{
id: '5e68ae9e2fa3df719875edef',
siteAreaID: '5ce249a2372f0b1c8caf9294'

feat: added billing-platform tenant component