pricing/billing on end transaction
MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -942,17 +942,23 @@ export default class StripeBillingIntegration extends BillingIntegration {
}
public async endTransaction(transaction: Transaction): Promise<BillingDataTransactionStop> {
+ // Make sure we don't get called when the invoice is already billed
+ if (transaction.billingData?.stop?.status === BillingStatus.BILLED) {
+ throw new Error('Operation aborted - unexpected situation - the session has already been billed');
+ }
+ if (!transaction.stop?.extraInactivityComputed) {
+ throw new Error('Operation aborted - unexpected situation - the extra inactivity is not yet known');
+ }
// Check whether the billing was activated on start transaction
if (!transaction.billingData?.withBillingActive) {
return {
status: BillingStatus.UNBILLED
};
}
- // Do not bill suspicious StopTransaction events
+ // Do not bill sessions with suspicious data
if (FeatureToggles.isFeatureActive(Feature.BILLING_CHECK_THRESHOLD_ON_STOP) && !Utils.isDevelopmentEnv()) {
- // Suspicious StopTransaction may occur after a 'Housing temperature approaching limit' error on some charging stations
+ // Suspicious data may occur after a 'Housing temperature approaching limit' error on some charging stations
const timeSpent = this.computeTimeSpentInSeconds(transaction);
- // TODO - make it part of the pricing or billing settings!
if (timeSpent < 60 /* seconds */ || transaction.stop.totalConsumptionWh < 1000 /* 1kWh */) {
await Logging.logWarning({
tenantID: this.tenant.id,

MODIFY
src/server/ocpp/services/OCPPService.ts
src/server/ocpp/services/OCPPService.ts
@@ -808,7 +808,6 @@ export default class OCPPService {
}
// 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();
@@ -824,6 +823,7 @@ export default class OCPPService {
detailedMessages: { statusNotification, connector, lastTransaction }
});
}
+ }
// No extra inactivity
} else {
await Logging.logInfo({
@@ -838,6 +838,8 @@ 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);
}
}
// OCPI: Post the CDR
@@ -848,8 +850,6 @@ export default class OCPPService {
if (lastTransaction.oicpData?.session) {
await this.checkAndSendOICPTransactionCdr(tenant, lastTransaction, chargingStation, lastTransaction.tag);
}
- // Billing - We now know the extra inactivity - the invoice can be generated
- await OCPPUtils.processTransactionBilling(tenant, lastTransaction, TransactionAction.END);
// Save
await TransactionStorage.saveTransaction(tenant, lastTransaction);
} else if (!Utils.isNullOrUndefined(lastTransaction)) {

pricing/billing on end transaction