stripe - compute unit price from total price
MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -9,6 +9,7 @@ import BillingIntegration from '../BillingIntegration';
import BillingStorage from '../../../storage/mongodb/BillingStorage';
import Constants from '../../../utils/Constants';
import Cypher from '../../../utils/Cypher';
+import Decimal from 'decimal.js';
import I18nManager from '../../../utils/I18nManager';
import Logging from '../../../utils/Logging';
import { Request } from 'express';
@@ -650,50 +651,28 @@ export default class StripeBillingIntegration extends BillingIntegration<StripeB
}
private _buildInvoiceItemParameters(customerID: string, billingInvoiceItem: BillingInvoiceItem, invoiceID?: string): Stripe.InvoiceItemCreateParams {
-
+ // Convert pricing information to STRIPE expected data
const { description, pricingData, taxes } = billingInvoiceItem;
-
+ const quantity = new Decimal(pricingData.quantity).dividedBy(1000).toNumber();
+ const unit_amount = new Decimal(pricingData.amount).times(100).dividedBy(quantity).round().toNumber();
+ const currency = pricingData.currency.toLowerCase();
+ // Build stripe parameters for the item
const parameters: Stripe.InvoiceItemCreateParams = {
customer: customerID,
- currency: this.settings.currency.toLocaleLowerCase(),
- amount: pricingData.amount,
- // quantity = pricingData.quantity,
+ quantity, // Energy consumed in kW.h
+ unit_amount, // price in cents
+ currency,
description,
tax_rates: taxes
};
-
// STRIPE throws an exception when invoice is set to null.
if (invoiceID) {
// Make sure to only add that property when updating an existing invoice
parameters.invoice = invoiceID;
}
-
return parameters;
}
- // private _buildInvoiceItemParameters(customerID: string, transaction: Transaction, invoiceID?: string): Stripe.InvoiceItemCreateParams {
-
- // const description = this.buildLineItemDescription(transaction);
- // const amount = this.convertTransactionPrice(transaction);
- // const tax_rates = this.getTaxRateIds();
-
- // const parameters: Stripe.InvoiceItemCreateParams = {
- // customer: customerID,
- // currency: this.settings.currency.toLocaleLowerCase(),
- // amount,
- // description,
- // tax_rates
- // };
-
- // // STRIPE throws an exception when invoice is set to null.
- // if (invoiceID) {
- // // Make sure to only add that property when updating an existing invoice
- // parameters.invoice = invoiceID;
- // }
-
- // return parameters;
- // }
-
public async stopTransaction(transaction: Transaction): Promise<BillingDataTransactionStop> {
// Check Stripe
await this.checkConnection();
@@ -742,10 +721,13 @@ export default class StripeBillingIntegration extends BillingIntegration<StripeB
private convertToBillingInvoiceItems(transaction: Transaction) : Array<BillingInvoiceItem> {
// TODO - make it more precise - Pricing transparency!
const description = this.buildLineItemDescription(transaction);
- // STRIPE expects the amount, in cents!!!
- const amount = Math.round(transaction.stop.roundedPrice * 100);
- const quantity = 1; // TODO - rethink that part
- const price = amount; // TODO - rethink that part
+ // -------------------------------------------------------------------------------
+ // ACHTUNG - STRIPE expects the amount and prices in CENTS!
+ // -------------------------------------------------------------------------------
+ const quantity = transaction.stop.totalConsumptionWh; // Total consumption in Wh
+ const amount = transaction.stop.price; // Total amount for the line item
+ const currency = transaction.stop.priceUnit;
+ // -------------------------------------------------------------------------------
const taxes = this.getTaxRateIds(); // TODO - take into account SITE settings
// Build a billing invoice item based on the transaction
const billingInvoiceItem: BillingInvoiceItem = {
@@ -753,7 +735,7 @@ export default class StripeBillingIntegration extends BillingIntegration<StripeB
pricingData: {
quantity,
amount,
- price,
+ currency
},
taxes
};

MODIFY
src/types/Billing.ts
src/types/Billing.ts
@@ -86,8 +86,8 @@ export interface BillingInvoiceItem {
description: string;
pricingData: {
quantity: number,
- price: number,
amount: number,
+ currency: string
}
taxes?: string[];
}

MODIFY
test/api/BillingStripeTestData.ts
test/api/BillingStripeTestData.ts
@@ -12,7 +12,6 @@ import Stripe from 'stripe';
import StripeBillingIntegration from '../../src/integration/billing/stripe/StripeBillingIntegration';
import TenantContext from './context/TenantContext';
import TestConstants from './client/utils/TestConstants';
-import Transaction from '../types/Transaction';
import User from '../../src/types/User';
import UserStorage from '../../src/storage/mongodb/UserStorage';
import chaiSubset from 'chai-subset';
@@ -172,10 +171,10 @@ export default class StripeIntegrationTestData {
}
await this.checkForDraftInvoices(this.dynamicUser.id, 0);
// Let's create an Invoice with a first Item
- const dynamicInvoice = await this.billInvoiceItem(777, taxId);
+ const dynamicInvoice = await this.billInvoiceItem(10 /* kW.h */, 4 /* EUR */, taxId);
assert(dynamicInvoice, 'Invoice should not be null');
// Let's add an second item to the same invoice
- const updatedInvoice = await this.billInvoiceItem(555, taxId);
+ const updatedInvoice = await this.billInvoiceItem(20 /* kW.h */, 8 /* EUR */, taxId);
assert(updatedInvoice, 'Invoice should not be null');
// User should have a DRAFT invoice
const draftInvoices = await this.getDraftInvoices(this.dynamicUser.id);
@@ -190,15 +189,17 @@ export default class StripeIntegrationTestData {
return nbDraftInvoice;
}
- public async billInvoiceItem(price: number, taxId?: string) : Promise<BillingInvoice> {
+ public async billInvoiceItem(quantity: number, amount: number, taxId?: string) : Promise<BillingInvoice> {
assert(this.billingUser, 'Billing user cannot be null');
+ const price = amount / quantity;
+
// array of tax ids to apply to the line item
const invoiceItem:BillingInvoiceItem = {
- description: `Stripe Integration - Item ${price}`,
+ description: `Stripe Integration - ${quantity} kWh * ${price} Eur`,
pricingData: {
- amount: price,
- quantity: 1,
- price: price
+ quantity: quantity * 1000, // kW.h ==> Wh
+ amount: amount, // STRIPE expects total amount in cents
+ currency: 'EUR'
}
};
if (taxId) {

MODIFY
test/api/BillingTest.ts
test/api/BillingTest.ts
@@ -99,7 +99,7 @@ class TestData {
assert((user.tags && user.tags.length), 'User must have a valid tag');
const tagId = user.tags[0].id;
const meterStart = 0;
- const meterStop = 1000;
+ const meterStop = 50000; // Unit: Wh
const startDate = moment().toDate();
const stopDate = moment(startDate).add(1, 'hour').toDate();
const startTransactionResponse = await this.chargingStationContext.startTransaction(connectorId, tagId, meterStart, startDate);

stripe - compute unit price from total price