UNPKG

@citrineos/data

Version:

The OCPP data module which includes all persistence layer implementation.

155 lines 7.15 kB
// SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project // // SPDX-License-Identifier: Apache-2.0 import { CrudRepository, OCPP2_0_1 } from '@citrineos/base'; import { SequelizeRepository } from './Base.js'; import { ChargingNeeds, ChargingProfile, ChargingSchedule, CompositeSchedule, Evse, EvseType, SalesTariff, Transaction, } from '../model/index.js'; import { Sequelize } from 'sequelize-typescript'; import { Logger } from 'tslog'; export class SequelizeChargingProfileRepository extends SequelizeRepository { chargingNeeds; chargingSchedule; salesTariff; transaction; evse; compositeSchedule; constructor(config, logger, sequelizeInstance, chargingNeeds, chargingSchedule, salesTariff, transaction, evse, compositeSchedule) { super(config, ChargingProfile.MODEL_NAME, logger, sequelizeInstance); this.chargingNeeds = chargingNeeds ? chargingNeeds : new SequelizeRepository(config, ChargingNeeds.MODEL_NAME, logger, sequelizeInstance); this.chargingSchedule = chargingSchedule ? chargingSchedule : new SequelizeRepository(config, ChargingSchedule.MODEL_NAME, logger, sequelizeInstance); this.evse = evse ? evse : new SequelizeRepository(config, EvseType.MODEL_NAME, logger, sequelizeInstance); this.salesTariff = salesTariff ? salesTariff : new SequelizeRepository(config, SalesTariff.MODEL_NAME, logger, sequelizeInstance); this.transaction = transaction ? transaction : new SequelizeRepository(config, Transaction.MODEL_NAME, logger, sequelizeInstance); this.compositeSchedule = compositeSchedule ? compositeSchedule : new SequelizeRepository(config, CompositeSchedule.MODEL_NAME, logger, sequelizeInstance); } async createOrUpdateChargingProfile(tenantId, chargingProfile, stationId, evseId, chargingLimitSource, isActive) { let transactionDBId; if (chargingProfile.transactionId) { const activeTransaction = await Transaction.findOne({ where: { stationId, transactionId: chargingProfile.transactionId, }, }); transactionDBId = activeTransaction?.id; } const [savedChargingProfile, profileCreated] = await this.readOrCreateByQuery(tenantId, { where: { tenantId: tenantId, stationId: stationId, id: chargingProfile.id, }, defaults: { ...chargingProfile, evseId: evseId, transactionDatabaseId: transactionDBId, chargingLimitSource: chargingLimitSource ?? OCPP2_0_1.ChargingLimitSourceEnumType.CSO, isActive: isActive === undefined ? false : isActive, }, }); if (!profileCreated) { await this.updateByKey(tenantId, { ...chargingProfile, chargingSchedule: chargingProfile.chargingSchedule.map((s) => ({ ...s })), stationId: stationId, transactionDatabaseId: transactionDBId, evseId: evseId, chargingLimitSource: chargingLimitSource ?? OCPP2_0_1.ChargingLimitSourceEnumType.CSO, isActive: isActive === undefined ? false : isActive, }, savedChargingProfile.databaseId.toString()); // delete existed charging schedules and sales tariff const deletedChargingSchedules = await this.chargingSchedule.deleteAllByQuery(tenantId, { where: { chargingProfileDatabaseId: savedChargingProfile.databaseId, }, }); for (const deletedSchedule of deletedChargingSchedules) { await this.salesTariff.deleteAllByQuery(tenantId, { where: { chargingScheduleDatabaseId: deletedSchedule.databaseId, }, }); } } for (const chargingSchedule of chargingProfile.chargingSchedule) { const savedChargingSchedule = await this.chargingSchedule.create(tenantId, ChargingSchedule.build({ tenantId, stationId, chargingProfileDatabaseId: savedChargingProfile.databaseId, ...chargingSchedule, })); if (chargingSchedule.salesTariff) { await this.salesTariff.create(tenantId, SalesTariff.build({ tenantId, chargingScheduleDatabaseId: savedChargingSchedule.databaseId, ...chargingSchedule.salesTariff, })); } } return savedChargingProfile; } async createChargingNeeds(tenantId, chargingNeedsReq, stationId) { const activeTransaction = await Transaction.findOne({ where: { stationId, isActive: true, }, include: [{ model: Evse, where: { evseTypeId: chargingNeedsReq.evseId }, required: true }], }); if (!activeTransaction) { throw new Error(`No active transaction found on station ${stationId} evse ${chargingNeedsReq.evseId}`); } return await this.chargingNeeds.create(tenantId, ChargingNeeds.build({ tenantId, ...chargingNeedsReq.chargingNeeds, evseId: activeTransaction.evseId, transactionDatabaseId: activeTransaction.id, maxScheduleTuples: chargingNeedsReq.maxScheduleTuples, })); } async findChargingNeedsByEvseDBIdAndTransactionDBId(tenantId, evseDBId, transactionDataBaseId) { const chargingNeedsArray = await this.chargingNeeds.readAllByQuery(tenantId, { where: { evseId: evseDBId, transactionDatabaseId: transactionDataBaseId, }, order: [['createdAt', 'DESC']], }); return chargingNeedsArray.length > 0 ? chargingNeedsArray[0] : undefined; } async createCompositeSchedule(tenantId, compositeSchedule, stationId) { return await this.compositeSchedule.create(tenantId, CompositeSchedule.build({ tenantId, ...compositeSchedule, stationId, })); } async getNextChargingScheduleId(tenantId, stationId) { return await this.chargingSchedule.readNextValue(tenantId, 'id', { where: { stationId } }); } async getNextChargingProfileId(tenantId, stationId) { return await this.readNextValue(tenantId, 'id', { where: { stationId } }); } async getNextStackLevel(tenantId, stationId, transactionDatabaseId, profilePurpose) { return await this.readNextValue(tenantId, 'stackLevel', { where: { stationId, transactionDatabaseId: transactionDatabaseId, chargingProfilePurpose: profilePurpose, }, }, 0); } } //# sourceMappingURL=ChargingProfile.js.map