billing extra inactivity
MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -936,12 +936,26 @@ export default class StripeBillingIntegration extends BillingIntegration {
};
}
if (transaction.billingData?.stop?.status === BillingStatus.BILLED) {
- // Make sure we don't get called when the invoice is already billed
- throw new Error('Operation aborted - unexpected situation - the session has already been billed');
+ await Logging.logWarning({
+ tenantID: this.tenant.id,
+ action: ServerAction.BILLING_TRANSACTION,
+ module: MODULE_NAME, method: 'endTransaction',
+ message: 'Operation aborted - unexpected situation - the session has already been billed'
+ });
+ return {
+ status: transaction.billingData?.stop?.status
+ };
}
if (!transaction.stop?.extraInactivityComputed) {
- // This should not happen
- throw new Error('Operation aborted - unexpected situation - the extra inactivity is not yet known');
+ await Logging.logWarning({
+ tenantID: this.tenant.id,
+ action: ServerAction.BILLING_TRANSACTION,
+ module: MODULE_NAME, method: 'endTransaction',
+ message: 'Operation aborted - unexpected situation - the extra inactivity is not yet known'
+ });
+ return {
+ status: transaction.billingData?.stop?.status
+ };
}
if (transaction.billingData?.stop?.status === BillingStatus.UNBILLED) {
// Make sure to preserve the decision made during the STOP transaction

MODIFY
src/scheduler/tasks/BillPendingTransactionTask.ts
src/scheduler/tasks/BillPendingTransactionTask.ts
@@ -3,7 +3,6 @@ import Tenant, { TenantComponents } from '../../types/Tenant';
import BillingFactory from '../../integration/billing/BillingFactory';
import { BillingStatus } from '../../types/Billing';
import { ChargePointStatus } from '../../types/ocpp/OCPPServer';
-import ChargingStationStorage from '../../storage/mongodb/ChargingStationStorage';
import LockingHelper from '../../locking/LockingHelper';
import LockingManager from '../../locking/LockingManager';
import Logging from '../../utils/Logging';
@@ -56,7 +55,7 @@ export default class BillPendingTransactionTask extends SchedulerTask {
if (transactionLock) {
try {
// Get Transaction
- const transaction = await TransactionStorage.getTransaction(tenant, transactionMDB._id, { withUser: true });
+ const transaction = await TransactionStorage.getTransaction(tenant, transactionMDB._id, { withUser: true, withChargingStation: true });
if (!transaction) {
await Logging.logError({
tenantID: tenant.id,
@@ -67,7 +66,7 @@ export default class BillPendingTransactionTask extends SchedulerTask {
continue;
}
// Get Charging Station
- const chargingStation = await ChargingStationStorage.getChargingStation(tenant, transaction.chargeBoxID);
+ const chargingStation = transaction.chargeBox;
if (!chargingStation) {
await Logging.logError({
tenantID: tenant.id,

MODIFY
src/server/ocpp/services/OCPPService.ts
src/server/ocpp/services/OCPPService.ts
@@ -794,24 +794,14 @@ export default class OCPPService {
detailedMessages: { statusNotification }
});
lastTransaction.stop.extraInactivitySecs = 0;
- } else {
+ } else if (lastTransaction.stop.extraInactivitySecs > 0) {
// Fix the Inactivity severity
- lastTransaction.stop.inactivityStatus = Utils.getInactivityStatusLevel(chargingStation, lastTransaction.connectorId,
- lastTransaction.stop.totalInactivitySecs + lastTransaction.stop.extraInactivitySecs);
+ lastTransaction.stop.inactivityStatus = Utils.getInactivityStatusLevel(chargingStation,
+ lastTransaction.connectorId,
+ lastTransaction.stop.totalInactivitySecs + lastTransaction.stop.extraInactivitySecs
+ );
// Build extra inactivity consumption
- const lastConsumption = await OCPPUtils.buildExtraConsumptionInactivity(tenant, chargingStation, lastTransaction);
- if (lastConsumption) {
- // Pricing of the extra inactivity
- if (lastConsumption?.toPrice) {
- await OCPPUtils.processTransactionPricing(tenant, lastTransaction, chargingStation, lastConsumption, TransactionAction.END);
- }
- // Save the last consumption
- await ConsumptionStorage.saveConsumption(tenant, lastConsumption);
- // Update transaction stop
- lastTransaction.stop.timestamp = lastConsumption.endedAt;
- lastTransaction.stop.totalDurationSecs = moment.duration(moment(lastTransaction.stop.timestamp).diff(lastTransaction.timestamp)).asSeconds();
- lastTransaction.stop.price = lastTransaction.currentCumulatedPrice;
- lastTransaction.stop.roundedPrice = lastTransaction.currentCumulatedRoundedPrice;
+ await OCPPUtils.buildAndPriceExtraConsumptionInactivity(tenant, chargingStation, lastTransaction);
await Logging.logInfo({
tenantID: tenant.id,
...LoggingHelper.getChargingStationProperties(chargingStation),
@@ -821,10 +811,11 @@ export default class OCPPService {
message: `${Utils.buildConnectorInfo(lastTransaction.connectorId, lastTransaction.id)} Extra Inactivity of ${lastTransaction.stop.extraInactivitySecs} secs has been added`,
detailedMessages: { statusNotification, connector, lastTransaction }
});
- }
- }
+ } else {
// No extra inactivity
+ }
} else {
+ // No extra inactivity - connector status is not set to FINISHING
await Logging.logInfo({
tenantID: tenant.id,
...LoggingHelper.getChargingStationProperties(chargingStation),
@@ -837,10 +828,10 @@ export default class OCPPService {
}
// Flag
lastTransaction.stop.extraInactivityComputed = true;
- // Billing - We now know the extra inactivity - the invoice can be generated
- await OCPPUtils.processTransactionBilling(tenant, lastTransaction, TransactionAction.END);
}
}
+ // Billing
+ await OCPPUtils.processTransactionBilling(tenant, lastTransaction, TransactionAction.END);
// OCPI: Post the CDR
if (lastTransaction.ocpiData?.session) {
await this.checkAndSendOCPITransactionCdr(tenant, lastTransaction, chargingStation, lastTransaction.tag);

MODIFY
src/server/ocpp/utils/OCPPUtils.ts
src/server/ocpp/utils/OCPPUtils.ts
@@ -195,6 +195,23 @@ export default class OCPPUtils {
}
}
+ public static async buildAndPriceExtraConsumptionInactivity(tenant: Tenant, chargingStation: ChargingStation, lastTransaction: Transaction): Promise<void> {
+ const lastConsumption = await OCPPUtils.buildExtraConsumptionInactivity(tenant, chargingStation, lastTransaction);
+ if (lastConsumption) {
+ // Pricing of the extra inactivity
+ if (lastConsumption?.toPrice) {
+ await OCPPUtils.processTransactionPricing(tenant, lastTransaction, chargingStation, lastConsumption, TransactionAction.END);
+ }
+ // Save the last consumption
+ await ConsumptionStorage.saveConsumption(tenant, lastConsumption);
+ // Update transaction stop
+ lastTransaction.stop.timestamp = lastConsumption.endedAt;
+ lastTransaction.stop.totalDurationSecs = moment.duration(moment(lastTransaction.stop.timestamp).diff(lastTransaction.timestamp)).asSeconds();
+ lastTransaction.stop.price = lastTransaction.currentCumulatedPrice;
+ lastTransaction.stop.roundedPrice = lastTransaction.currentCumulatedRoundedPrice;
+ }
+ }
+
public static async buildExtraConsumptionInactivity(tenant: Tenant, chargingStation: ChargingStation, transaction: Transaction): Promise<Consumption> {
// Extra inactivity
if (transaction.stop.extraInactivitySecs > 0) {

billing extra inactivity