pricing - amountAsDecimal persisted
MODIFY
src/integration/pricing/ConsumptionChunkPricer.ts
src/integration/pricing/ConsumptionChunkPricer.ts
@@ -273,7 +273,8 @@ export default class ConsumptionChunkPricer {
// throw new Error('Unexpected situation - priceFlatFeeDimension should be called only once per session');
return {
unitPrice: 0,
- amount: Utils.createDecimal(0),
+ amountAsDecimal: Utils.createDecimal(0),
+ amount: 0,
roundedAmount: 0,
quantity: 0 // Session
};
@@ -281,7 +282,8 @@ export default class ConsumptionChunkPricer {
// First call for this dimension
pricingDimension.pricedData = {
unitPrice: unitPrice,
- amount: Utils.createDecimal(unitPrice),
+ amountAsDecimal: Utils.createDecimal(unitPrice),
+ amount: unitPrice,
roundedAmount: Utils.truncTo(unitPrice, 2),
quantity: 1 // Session
};
@@ -291,12 +293,13 @@ export default class ConsumptionChunkPricer {
private priceConsumptionStep(pricingDimension: PricingDimension, steps: number): PricedDimensionData {
const unitPrice = pricingDimension.price || 0; // Eur/wWh
const quantity = Utils.createDecimal(steps).times(pricingDimension.stepSize).toNumber(); // Wh
- const amount = Utils.createDecimal(unitPrice).times(quantity).div(1000); // Eur
+ const amountAsDecimal = Utils.createDecimal(unitPrice).times(quantity).div(1000); // Eur
// Price the consumption
const pricedData: PricedDimensionData = {
unitPrice: unitPrice,
- amount,
- roundedAmount: Utils.truncTo(amount, 2),
+ amountAsDecimal,
+ amount: amountAsDecimal.toNumber(),
+ roundedAmount: Utils.truncTo(amountAsDecimal, 2),
quantity,
stepSize: pricingDimension.stepSize,
};
@@ -309,13 +312,14 @@ export default class ConsumptionChunkPricer {
private priceConsumptionWh(pricingDimension: PricingDimension, consumptionWh: number): PricedDimensionData {
const unitPrice = pricingDimension.price || 0; // Eur/kWh
const quantity = Utils.createDecimal(consumptionWh).toNumber(); // Wh
- const amount = Utils.createDecimal(unitPrice).times(consumptionWh).div(1000); // Eur
+ const amountAsDecimal = Utils.createDecimal(unitPrice).times(consumptionWh).div(1000); // Eur
// const consumptionkWh = Utils.createDecimal(consumptionWh).div(1000).toNumber();
// Price the consumption
const pricedData: PricedDimensionData = {
unitPrice: unitPrice,
- amount,
- roundedAmount: Utils.truncTo(amount, 2),
+ amountAsDecimal,
+ amount: amountAsDecimal.toNumber(),
+ roundedAmount: Utils.truncTo(amountAsDecimal, 2),
quantity
};
// Add the consumption to the previous data (if any) - for the billing
@@ -344,12 +348,13 @@ export default class ConsumptionChunkPricer {
private priceTimeSteps(pricingDimension: PricingDimension, steps: number): PricedDimensionData {
const unitPrice = pricingDimension.price || 0; // Eur/hour
const quantity = Utils.createDecimal(steps).times(pricingDimension.stepSize).toNumber(); // seconds
- const amount = Utils.createDecimal(unitPrice).times(quantity).div(3600); // Eur
+ const amountAsDecimal = Utils.createDecimal(unitPrice).times(quantity).div(3600); // Eur
// Price the consumption
const pricedData: PricedDimensionData = {
unitPrice: unitPrice,
- amount,
- roundedAmount: Utils.truncTo(amount, 2),
+ amountAsDecimal,
+ amount: amountAsDecimal.toNumber(),
+ roundedAmount: Utils.truncTo(amountAsDecimal, 2),
quantity,
stepSize: pricingDimension.stepSize
};
@@ -361,12 +366,13 @@ export default class ConsumptionChunkPricer {
private priceTimeSpent(pricingDimension: PricingDimension, seconds: number): PricedDimensionData {
const unitPrice = pricingDimension.price || 0; // Eur/hour
- const amount = Utils.createDecimal(unitPrice).times(seconds).div(3600); // Eur
+ const amountAsDecimal = Utils.createDecimal(unitPrice).times(seconds).div(3600); // Eur
// Price the consumption
const pricedData: PricedDimensionData = {
unitPrice: unitPrice,
- amount,
- roundedAmount: Utils.truncTo(amount, 2),
+ amountAsDecimal,
+ amount: amountAsDecimal.toNumber(),
+ roundedAmount: Utils.truncTo(amountAsDecimal, 2),
quantity: seconds
};
// Add the consumption to the previous data (if any) - for the billing
@@ -379,7 +385,8 @@ export default class ConsumptionChunkPricer {
// Add the consumption to the previous data (if any) - for the billing
const previousData = pricingDimension.pricedData;
if (previousData) {
- previousData.amount = Utils.createDecimal(previousData.amount).plus(pricedData.amount);
+ previousData.amountAsDecimal = Utils.createDecimal(previousData.amountAsDecimal).plus(pricedData.amountAsDecimal);
+ previousData.amount = previousData.amountAsDecimal.toNumber();
previousData.quantity = Utils.createDecimal(previousData.quantity).plus(pricedData.quantity).toNumber();
previousData.roundedAmount = Utils.truncTo(previousData.amount, 2);
} else {

MODIFY
src/integration/pricing/PricingHelper.ts
src/integration/pricing/PricingHelper.ts
@@ -51,13 +51,15 @@ export default class PricingHelper {
if (!accumulatedData[dimensionType]) {
const emptyDimensionData: PricedDimensionData = {
quantity:0,
- amount: Utils.createDecimal(0),
+ amountAsDecimal: Utils.createDecimal(0),
+ amount: 0,
roundedAmount: 0
};
accumulatedData[dimensionType] = emptyDimensionData;
}
accumulatedData[dimensionType].quantity = Utils.createDecimal(accumulatedData[dimensionType].quantity).plus(pricedData[dimensionType].quantity).toNumber();
- accumulatedData[dimensionType].amount = Utils.createDecimal(accumulatedData[dimensionType].amount).plus(pricedData[dimensionType].amount);
+ accumulatedData[dimensionType].amountAsDecimal = Utils.createDecimal(accumulatedData[dimensionType].amountAsDecimal).plus(pricedData[dimensionType].amountAsDecimal);
+ accumulatedData[dimensionType].amount = Utils.createDecimal(accumulatedData[dimensionType].amountAsDecimal).toNumber();
// accumulatedData[dimensionType].roundedAmount = Utils.createDecimal(accumulatedData[dimensionType].roundedAmount).plus(pricedData[dimensionType].roundedAmount).toNumber();
accumulatedData[dimensionType].roundedAmount = Utils.truncTo(accumulatedData[dimensionType].amount, 2);
}

MODIFY
src/types/Pricing.ts
src/types/Pricing.ts
@@ -125,7 +125,8 @@ export interface PricedConsumptionData {
export interface PricedDimensionData {
unitPrice?: number;
- amount: number | Decimal; // Very important - switch to Decimal as soon as possible to preserve precision
+ amountAsDecimal: number | Decimal // Very important - preserve maximal precision
+ amount: number;
roundedAmount: number;
quantity: number;
stepSize?: number;

MODIFY
test/api/StripeTestHelper.ts
test/api/StripeTestHelper.ts
@@ -279,6 +279,7 @@ export default class StripeTestHelper {
energy: {
itemDescription: `Energy consumption - ${consumptionTestData.energyConsumptionkWh} kWh * ${consumptionTestData.energyAmount / consumptionTestData.energyConsumptionkWh} Eur`,
unitPrice: Utils.createDecimal(consumptionTestData.energyAmount).div(consumptionTestData.energyConsumptionkWh).toNumber(),
+ amountAsDecimal: Utils.createDecimal(consumptionTestData.energyAmount), // total amount to bill - not yet in cents
amount: consumptionTestData.energyAmount, // total amount to bill - not yet in cents
roundedAmount: Utils.truncTo(consumptionTestData.energyAmount, 2),
quantity: Utils.createDecimal(consumptionTestData.energyConsumptionkWh).div(1000).toNumber(), // Wh
@@ -287,6 +288,7 @@ export default class StripeTestHelper {
parkingTime: {
itemDescription: `Parking time - ${consumptionTestData.parkingTime} minutes`,
unitPrice: Utils.createDecimal(consumptionTestData.parkingAmount).div(consumptionTestData.parkingTime).toNumber(),
+ amountAsDecimal: Utils.createDecimal(consumptionTestData.parkingAmount),
amount: consumptionTestData.parkingAmount, // Euros
roundedAmount: Utils.truncTo(consumptionTestData.parkingAmount, 2),
quantity: Utils.createDecimal(consumptionTestData.parkingTime).div(60).toNumber(), // seconds

pricing - amountAsDecimal persisted