billing - preserve stop transaction decision
MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -917,62 +917,38 @@ export default class StripeBillingIntegration extends BillingIntegration {
};
}
// Do not bill suspicious StopTransaction events
- 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
- 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,
- user: transaction.userID,
- action: ServerAction.BILLING_TRANSACTION,
- module: MODULE_NAME, method: 'stopTransaction',
- message: `Transaction data is suspicious - billing operation has been aborted - transaction ID: ${transaction.id}`,
- ...LoggingHelper.getTransactionProperties(transaction)
- });
+ if (!await this.checkBillingDataThreshold(transaction)) {
return {
status: BillingStatus.UNBILLED
};
}
- }
- // Inform the calling layer that the operation has been postponed
+ // Inform the calling layer that the billing operation has been postponed
return {
status: BillingStatus.PENDING
};
}
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 sessions with suspicious data
- if (FeatureToggles.isFeatureActive(Feature.BILLING_CHECK_THRESHOLD_ON_STOP) && !Utils.isDevelopmentEnv()) {
- // Suspicious data may occur after a 'Housing temperature approaching limit' error on some charging stations
- const timeSpent = this.computeTimeSpentInSeconds(transaction);
- if (timeSpent < 60 /* seconds */ || transaction.stop.totalConsumptionWh < 1000 /* 1kWh */) {
- await Logging.logWarning({
- tenantID: this.tenant.id,
- user: transaction.userID,
- action: ServerAction.BILLING_TRANSACTION,
- module: MODULE_NAME, method: 'endTransaction',
- message: `Transaction data is suspicious - billing operation has been aborted - transaction ID: ${transaction.id}`,
- ...LoggingHelper.getTransactionProperties(transaction)
- });
+ 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');
+ }
+ if (!transaction.stop?.extraInactivityComputed) {
+ // This should not happen
+ throw new Error('Operation aborted - unexpected situation - the extra inactivity is not yet known');
+ }
+ if (transaction.billingData?.stop?.status === BillingStatus.UNBILLED) {
+ // Make sure to preserve the decision made during the STOP transaction
return {
status: BillingStatus.UNBILLED
};
}
- }
// Create and Save async task
await AsyncTaskBuilder.createAndSaveAsyncTasks({
name: AsyncTasks.BILL_TRANSACTION,
@@ -992,6 +968,29 @@ export default class StripeBillingIntegration extends BillingIntegration {
};
}
+ private async checkBillingDataThreshold(transaction: Transaction): Promise<boolean> {
+ // Do not bill suspicious StopTransaction events
+ if (!Utils.isDevelopmentEnv()) {
+ // Suspicious StopTransaction 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,
+ user: transaction.userID,
+ action: ServerAction.BILLING_TRANSACTION,
+ module: MODULE_NAME, method: 'stopTransaction',
+ message: `Transaction data is suspicious - billing operation has been aborted - transaction ID: ${transaction.id}`,
+ ...LoggingHelper.getTransactionProperties(transaction)
+ });
+ // Abort the billing process - thresholds are not met!
+ return false;
+ }
+ }
+ // billing data sounds correct
+ return true;
+ }
+
public async billTransaction(transaction: Transaction): Promise<BillingDataTransactionStop> {
// Check Stripe
await this.checkConnection();

MODIFY
src/utils/FeatureToggles.ts
src/utils/FeatureToggles.ts
// Declare here the list of features
export enum Feature {
BILLING_SYNC_USERS,
- BILLING_CHECK_THRESHOLD_ON_STOP,
BILLING_PREVENT_CUSTOMER_DELETION,
BILLING_SHOW_PRICING_DETAIL,
}
@@ -11,7 +10,6 @@ export default class FeatureToggles {
// Comment out the features that you want to switch OFF
static activeFeatures: Feature[] = [
// Feature.BILLING_SYNC_USERS, - When switched OFF the sync of the user should be implicit (LAZY mode)
- Feature.BILLING_CHECK_THRESHOLD_ON_STOP,
Feature.BILLING_PREVENT_CUSTOMER_DELETION,
// Feature.BILLING_SHOW_PRICING_DETAIL,
];

billing - preserve stop transaction decision