billing/pricing - reorg, refactoring, cleanup
MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
import { AsyncTaskType, AsyncTasks } from '../../../types/AsyncTask';
/* eslint-disable @typescript-eslint/member-ordering */
-import { BillingDataTransactionStart, BillingDataTransactionStop, BillingDataTransactionUpdate, BillingInvoice, BillingInvoiceItem, BillingInvoiceStatus, BillingOperationResult, BillingPaymentMethod, BillingStatus, BillingTax, BillingUser, BillingUserData } from '../../../types/Billing';
+import { BillingDataTransactionStart, BillingDataTransactionStop, BillingDataTransactionUpdate, BillingInvoice, BillingInvoiceItem, BillingInvoiceStatus, BillingOperationResult, BillingPaymentMethod, BillingStatus, BillingTax, BillingUser, BillingUserData, DimensionPricingData } from '../../../types/Billing';
import FeatureToggles, { Feature } from '../../../utils/FeatureToggles';
import StripeHelpers, { StripeChargeOperationResult } from './StripeHelpers';
import Transaction, { StartTransactionErrorCode } from '../../../types/Transaction';
@@ -14,7 +14,6 @@ import { BillingSettings } from '../../../types/Setting';
import BillingStorage from '../../../storage/mongodb/BillingStorage';
import Constants from '../../../utils/Constants';
import Cypher from '../../../utils/Cypher';
-import { EffectivePricingData } from '../../../types/Pricing';
import I18nManager from '../../../utils/I18nManager';
import Logging from '../../../utils/Logging';
import { Request } from 'express';
@@ -876,34 +875,34 @@ export default class StripeBillingIntegration extends BillingIntegration {
await this._createStripeInvoiceItem4Dimension(customerID, 'parkingTime', billingInvoiceItem, invoiceID);
}
- private async _createStripeInvoiceItem4Dimension(customerID: string, pricingDimension: string,
+ private async _createStripeInvoiceItem4Dimension(customerID: string, dimension: string,
billingInvoiceItem: BillingInvoiceItem, invoiceID?: string): Promise<Stripe.InvoiceItemCreateParams> {
- const effectivePricing = billingInvoiceItem.effectivePricing;
+ const pricingData = billingInvoiceItem.pricingData;
// data for the current dimension (energy | parkingTime, etc)
- const effectivePricingData: EffectivePricingData = effectivePricing[pricingDimension];
- if (!effectivePricingData || !effectivePricingData.amount || !effectivePricingData.quantity) {
+ const dimensionData: DimensionPricingData = pricingData[dimension];
+ if (!dimensionData || !dimensionData.amount || !dimensionData.quantity) {
// Do not bill that dimension
return null;
}
const currency = billingInvoiceItem.currency.toLowerCase();
// Tax rates
- const tax_rates = effectivePricing[pricingDimension].taxes || [];
+ const tax_rates = pricingData[dimension].taxes || [];
// Build stripe parameters for the parking time
const parameters: Stripe.InvoiceItemCreateParams = {
invoice: invoiceID,
customer: customerID,
currency,
- description: effectivePricingData.itemDescription,
+ description: dimensionData.itemDescription,
tax_rates,
// quantity: 1, //Cannot be set separately
- amount: Utils.createDecimal(effectivePricing[pricingDimension].amount).times(100).round().toNumber(),
+ amount: Utils.createDecimal(pricingData[dimension].amount).times(100).round().toNumber(),
metadata: { ...billingInvoiceItem?.metadata }
};
if (!parameters.invoice) {
// STRIPE throws an exception when invoice is set to null.
delete parameters.invoice;
}
- await this._createStripeInvoiceItem(parameters, this.buildIdemPotencyKey(billingInvoiceItem.transactionID, 'invoice', pricingDimension));
+ await this._createStripeInvoiceItem(parameters, this.buildIdemPotencyKey(billingInvoiceItem.transactionID, 'invoice', dimension));
return parameters;
}
@@ -1024,12 +1023,12 @@ export default class StripeBillingIntegration extends BillingIntegration {
private shrinkInvoiceItem(fatInvoiceItem: BillingInvoiceItem): BillingInvoiceItem {
// The initial invoice item includes redundant transaction data
- const { transactionID, currency, effectivePricing } = fatInvoiceItem;
+ const { transactionID, currency, pricingData: effectivePricing } = fatInvoiceItem;
// Let's return only essential information
const lightInvoiceItem: BillingInvoiceItem = {
transactionID,
currency,
- effectivePricing
+ pricingData: effectivePricing
};
return lightInvoiceItem;
}
@@ -1054,7 +1053,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
const billingInvoiceItem: BillingInvoiceItem = {
transactionID,
currency,
- effectivePricing: {
+ pricingData: {
energy: {
itemDescription,
amount,

MODIFY
src/integration/billing/stripe/StripeHelpers.ts
src/integration/billing/stripe/StripeHelpers.ts
@@ -32,7 +32,7 @@ export default class StripeHelpers {
if (billingInvoiceItem) {
session = {
transactionID: billingInvoiceItem.transactionID,
- effectivePricing: billingInvoiceItem.effectivePricing,
+ pricingData: billingInvoiceItem.pricingData,
};
}
// Is there anything to update?

MODIFY
src/types/Billing.ts
src/types/Billing.ts
import { ActionsResponse } from './GlobalType';
-import { EffectivePricing } from './Pricing';
import User from './User';
export interface TransactionBillingData {
@@ -84,7 +83,7 @@ export interface BillingInvoice {
export interface BillingInvoiceItem {
transactionID: number;
currency: string;
- effectivePricing: EffectivePricing
+ pricingData: BillingPricingData
metadata?: {
// Just a flat list of key/value pairs!
[name: string]: string | number | null;
@@ -94,14 +93,14 @@ export interface BillingInvoiceItem {
export interface BillingSessionData {
transactionID: number;
// pricingData: BillingPricingData;
- effectivePricing: EffectivePricing;
+ pricingData: BillingPricingData;
}
-export interface BillingPricingData {
- quantity: number;
- amount: number;
- currency: string;
-}
+// export interface BillingPricingData {
+// quantity: number;
+// amount: number;
+// currency: string;
+// }
export enum BillingInvoiceStatus {
PAID = 'paid',
@@ -155,3 +154,21 @@ export interface BillingAdditionalData {
session?: BillingSessionData,
lastError?: BillingError,
}
+
+export interface BillingPricingData {
+ flatFee?: DimensionPricingData,
+ energy?: DimensionPricingData,
+ parkingTime?: DimensionPricingData,
+ chargingTime?: DimensionPricingData,
+}
+
+export interface DimensionPricingData {
+ itemDescription: string,
+ amount: number;
+ quantity: number;
+ cumulatedAmount?: number;
+ roundedAmount?: number;
+ // Each invoice item may have a different tax rate
+ // And STRIPE allows more than one for each of them, so this is an array!
+ taxes?: string[];
+}

MODIFY
src/types/Pricing.ts
src/types/Pricing.ts
@@ -15,7 +15,6 @@ export interface Pricing {
}
export interface PricingComponent {
- // type: PricingDimensionType, // Type of dimension
price: number, // Price per unit (excluding VAT) for this tariff dimension
stepSize?: number, // Minimum amount to be billed. This unit will be billed in this step_size blocks. For example: if type is time and step_size is 300, then time will be billed in blocks of 5 minutes, so if 6 minutes is used, 10 minutes (2 blocks of step_size) will be billed.
}
@@ -51,24 +50,6 @@ export enum DayOfWeek {
// TIME = 'T', // Time charging: defined in hours, step_size multiplier: 1 second
// }
-export interface EffectivePricing {
- flatFee?: EffectivePricingData,
- energy?: EffectivePricingData,
- parkingTime?: EffectivePricingData,
- chargingTime?: EffectivePricingData,
-}
-
-export interface EffectivePricingData {
- itemDescription: string,
- amount: number;
- quantity: number;
- cumulatedAmount?: number;
- roundedAmount?: number;
- // Each invoice item may have a different tax rate
- // And STRIPE allows more than one for each of them, so this is an array!
- taxes?: string[];
-}
-
// Interface exposed by the pricing integration layer
export interface PricedConsumption {
amount: number;

MODIFY
test/api/BillingStripeTestData.ts
test/api/BillingStripeTestData.ts
-import { BillingInvoice, BillingInvoiceItem, BillingInvoiceStatus, BillingOperationResult, BillingUser, BillingUserData } from '../../src/types/Billing';
+import { BillingInvoice, BillingInvoiceItem, BillingInvoiceStatus, BillingOperationResult, BillingPricingData, BillingUser, BillingUserData } from '../../src/types/Billing';
import { BillingSettings, BillingSettingsType, SettingDB } from '../../src/types/Setting';
import FeatureToggles, { Feature } from '../../src/utils/FeatureToggles';
import chai, { assert, expect } from 'chai';
@@ -8,7 +8,6 @@ import CentralServerService from './client/CentralServerService';
import ContextDefinition from './context/ContextDefinition';
import ContextProvider from './context/ContextProvider';
import Cypher from '../../src/utils/Cypher';
-import { EffectivePricing } from '../../src/types/Pricing';
import Factory from '../factories/Factory';
import Stripe from 'stripe';
import StripeBillingIntegration from '../../src/integration/billing/stripe/StripeBillingIntegration';
@@ -278,7 +277,7 @@ export default class StripeIntegrationTestData {
// array of tax ids to apply to the line item
const taxes = (consumptionTestData.taxId) ? [ consumptionTestData.taxId ] : [];
// Princing/Consumption Data
- const effectivePricing: EffectivePricing = {
+ const effectivePricing: BillingPricingData = {
energy: {
itemDescription: `Energy consumption - ${consumptionTestData.energyConsumptionkWh} kWh * ${consumptionTestData.energyAmount / consumptionTestData.energyConsumptionkWh} Eur`,
amount: consumptionTestData.energyAmount, // total amount to bill - not yet in cents
@@ -296,7 +295,7 @@ export default class StripeIntegrationTestData {
const invoiceItem:BillingInvoiceItem = {
currency: 'EUR',
transactionID: Utils.getRandomIntSafe(),
- effectivePricing
+ pricingData: effectivePricing
};
// Let's attempt to bill the line item
const billingInvoice: BillingInvoice = await this.billingImpl.billInvoiceItem(this.dynamicUser, invoiceItem);

billing/pricing - reorg, refactoring, cleanup