Additional backend changes
MODIFY
src/assets/server/rest/v1/schemas/billing/billing-setting-update.json
src/assets/server/rest/v1/schemas/billing/billing-setting-update.json
"type": "boolean",
"sanitize": "mongo"
},
- "taxID": {
+ "customerTaxID": {
+ "type": "string",
+ "sanitize": "mongo"
+ },
+ "billingAccountTaxID": {
"type": "string",
"sanitize": "mongo"
}

MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -4,6 +4,7 @@ import { BillingAccount, BillingDataTransactionStart, BillingDataTransactionStop
import { DimensionType, PricedConsumptionData, PricedDimensionData } from '../../../types/Pricing';
import FeatureToggles, { Feature } from '../../../utils/FeatureToggles';
import StripeHelpers, { StripeChargeOperationResult } from './StripeHelpers';
+import Tenant, { TenantComponents } from '../../../types/Tenant';
import Transaction, { StartTransactionErrorCode } from '../../../types/Transaction';
import AsyncTaskBuilder from '../../../async-task/AsyncTaskBuilder';
@@ -27,7 +28,6 @@ import { Request } from 'express';
import { ServerAction } from '../../../types/Server';
import SettingStorage from '../../../storage/mongodb/SettingStorage';
import Stripe from 'stripe';
-import Tenant from '../../../types/Tenant';
import TransactionStorage from '../../../storage/mongodb/TransactionStorage';
import User from '../../../types/User';
import UserStorage from '../../../storage/mongodb/UserStorage';
@@ -101,30 +101,54 @@ export default class StripeBillingIntegration extends BillingIntegration {
}
public async checkActivationPrerequisites(): Promise<void> {
- await this.checkTaxPrerequisites();
+ await this.checkCustomerTaxPrerequisites();
+ await this.checkBillingAccountTaxPrerequisites();
}
- public async checkTaxPrerequisites(): Promise<void> {
+ public async checkCustomerTaxPrerequisites(): Promise<void> {
// Check whether the taxID is set and still active
- const taxID = this.settings.billing?.taxID;
- if (taxID) {
- const billingTax: BillingTax = await this.getTaxRate(taxID);
+ const customerTaxID = this.settings.billing?.customerTaxID;
+ if (customerTaxID) {
+ const billingTax: BillingTax = await this.getTaxRate(customerTaxID);
if (!billingTax) {
throw new BackendError({
- module: MODULE_NAME, method: 'checkTaxPrerequisites',
+ module: MODULE_NAME, method: 'checkCustomerTaxPrerequisites',
action: ServerAction.BILLING_TAXES,
- message: `Billing prerequisites are not consistent - taxID is not found or inactive - taxID: '${taxID}'`
+ message: `Billing prerequisites are not consistent - Customer TaxID is not found or inactive - Customer TaxID: '${customerTaxID}'`
});
}
} else {
throw new BackendError({
- module: MODULE_NAME, method: 'checkTaxPrerequisites',
+ module: MODULE_NAME, method: 'checkCustomerTaxPrerequisites',
action: ServerAction.BILLING_TAXES,
- message: 'Billing prerequisites are not consistent - taxID is mandatory'
+ message: 'Billing prerequisites are not consistent - Customer TaxID is mandatory'
});
}
}
+ public async checkBillingAccountTaxPrerequisites(): Promise<void> {
+ // Check whether the taxID is set and still active
+ if (Utils.isTenantComponentActive(this.tenant, TenantComponents.BILLING_PLATFORM)) {
+ const billingAccountTaxID = this.settings.billing?.billingAccountTaxID;
+ if (billingAccountTaxID) {
+ const billingTax: BillingTax = await this.getTaxRate(billingAccountTaxID);
+ if (!billingTax) {
+ throw new BackendError({
+ module: MODULE_NAME, method: 'checkBillingAccountTaxPrerequisites',
+ action: ServerAction.BILLING_TAXES,
+ message: `Billing prerequisites are not consistent - Billing Account TaxID is not found or inactive - Billing Account TaxID: '${billingAccountTaxID}'`
+ });
+ }
+ } else {
+ throw new BackendError({
+ module: MODULE_NAME, method: 'checkBillingAccountTaxPrerequisites',
+ action: ServerAction.BILLING_TAXES,
+ message: 'Billing prerequisites are not consistent - Billing Account TaxID is mandatory'
+ });
+ }
+ }
+ }
+
public async checkTestDataCleanupPrerequisites(): Promise<void> {
// Make sure the STRIPE account is not live
let secretKey: string, publicKey: string;
@@ -150,7 +174,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
isTransactionBillingActivated: false,
immediateBillingAllowed: false,
periodicBillingAllowed: false,
- taxID: null
+ customerTaxID: null
};
newBillingsSettings.stripe = {
url: null,
@@ -356,9 +380,9 @@ export default class StripeBillingIntegration extends BillingIntegration {
return stripeInvoiceItem;
}
- private getTaxRateIds(): Array<string> {
- if (this.settings.billing.taxID) {
- return [this.settings.billing.taxID] ;
+ private getCustomerTaxRateIds(): Array<string> {
+ if (this.settings.billing.customerTaxID) {
+ return [this.settings.billing.customerTaxID] ;
}
return []; // No tax rates so far!
}
@@ -1140,7 +1164,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
// -------------------------------------------------------------------------------
// TODO - so far we use the same tax rates for all invoice items!
// -------------------------------------------------------------------------------
- const taxes = this.getTaxRateIds();
+ const taxes = this.getCustomerTaxRateIds();
// -------------------------------------------------------------------------------
// Enrich the consumption data with information required for billing it
// -------------------------------------------------------------------------------
@@ -1546,7 +1570,8 @@ export default class StripeBillingIntegration extends BillingIntegration {
}
// Check all settings that are necessary to bill a transaction
try {
- await this.checkTaxPrerequisites(); // Checks that the taxID is still valid
+ await this.checkCustomerTaxPrerequisites(); // Checks that the taxID is still valid
+ await this.checkBillingAccountTaxPrerequisites();
} catch (error) {
await Logging.logError({
tenantID: this.tenant.id,

MODIFY
src/storage/mongodb/SettingStorage.ts
src/storage/mongodb/SettingStorage.ts
@@ -447,9 +447,13 @@ export default class SettingStorage {
isTransactionBillingActivated: !!content.billing?.isTransactionBillingActivated,
immediateBillingAllowed: !!content.billing?.immediateBillingAllowed,
periodicBillingAllowed: !!content.billing?.periodicBillingAllowed,
- taxID: content.billing?.taxID,
+ customerTaxID: content.billing?.customerTaxID,
usersLastSynchronizedOn: content.billing?.usersLastSynchronizedOn,
};
+ // Insert billingAccountTaxID only if the billing platform is enabled
+ if (Utils.isTenantComponentActive(tenant, TenantComponents.BILLING_PLATFORM)) {
+ billing.billingAccountTaxID = content.billing?.billingAccountTaxID;
+ }
const billingSettings: BillingSettings = {
id,
identifier: TenantComponents.BILLING,

MODIFY
src/types/Setting.ts
src/types/Setting.ts
@@ -248,7 +248,7 @@ export interface BillingSetting {
immediateBillingAllowed: boolean;
periodicBillingAllowed: boolean;
customerTaxID: string;
- billingAccountTaxID: string;
+ billingAccountTaxID?: string;
usersLastSynchronizedOn?: Date;
}

MODIFY
test/api/StripeTestHelper.ts
test/api/StripeTestHelper.ts
@@ -474,7 +474,8 @@ export default class StripeTestHelper {
// Check the new billing settings
const newSettings: BillingSettings = response?.data?.internalData as BillingSettings;
assert(newSettings.billing.isTransactionBillingActivated === false, 'Transaction billing should be switched OFF');
- assert(!newSettings.billing.taxID, 'taxID should not be set anymore');
+ assert(!newSettings.billing.customerTaxID, 'Customer TaxID should not be set anymore');
+ assert(!newSettings.billing?.billingAccountTaxID, 'Billing Account TaxID should not be set anymore');
assert(!newSettings.stripe.url, 'URL should not be set anymore');
assert(!newSettings.stripe.publicKey, 'publicKey should not be set anymore');
assert(!newSettings.stripe.secretKey, 'secretKey should not be set anymore');

Additional backend changes