pricing - bill FF only once
MODIFY
src/integration/pricing/PricingEngine.ts
src/integration/pricing/PricingEngine.ts
@@ -35,6 +35,7 @@ export default class PricingEngine {
pricingDefinitions.push(...await PricingEngine.getPricingDefinitions4Entity(tenant, transaction.companyID.toString()));
// TODO - No pricing definition? => Throw an exception ? or create dynamically a simple one based on the simple pricing settings?
const resolvedPricingModel: ResolvedPricingModel = {
+ flatFeeAlreadyPriced: false,
pricingDefinitions
};
return Promise.resolve(resolvedPricingModel);
@@ -133,6 +134,7 @@ export default class PricingEngine {
private static priceParkingTimeConsumption(pricingDefinitions: PricingDefinition[], consumptionData: Consumption): PricingDimensionData {
let pricingDimensionData: PricingDimensionData = null;
+ // TODO - This is wrong - totalInactivitySecs should not be used here!
const hours = Utils.createDecimal(consumptionData?.totalInactivitySecs).dividedBy(3600).toNumber();
pricingDimensionData = PricingEngine.PriceDimensionConsumption(pricingDefinitions, 'parkingTime', hours);
return pricingDimensionData;
@@ -140,6 +142,7 @@ export default class PricingEngine {
private static priceChargingTimeConsumption(pricingDefinitions: PricingDefinition[], consumptionData: Consumption): PricingDimensionData {
let pricingDimensionData: PricingDimensionData = null;
+ // TODO - This is wrong - totalDurationSecs should not be used here!
const hours = Utils.createDecimal(consumptionData?.totalDurationSecs).dividedBy(3600).toNumber();
pricingDimensionData = PricingEngine.PriceDimensionConsumption(pricingDefinitions, 'chargingTime', hours);
return pricingDimensionData;
@@ -218,8 +221,13 @@ export default class PricingEngine {
// TODO - POC - to be clarified - temporary solution
// - we shouldn't update the transaction object directly from this layer
// ----------------------------------------------------------------------------------------------
+ let flatFee: PricingDimensionData = null;
+ if (!transaction.pricingModel.flatFeeAlreadyPriced) {
+ // Flat fee must not be priced only once
+ flatFee = PricingEngine.priceFlatFeeConsumption(actualPricingDefinitions, consumptionData);
+ transaction.pricingModel.flatFeeAlreadyPriced = !!flatFee;
+ }
// Build the consumption data for each dimension
- const flatFee: PricingDimensionData = PricingEngine.priceFlatFeeConsumption(actualPricingDefinitions, consumptionData);
const energy: PricingDimensionData = PricingEngine.priceEnergyConsumption(actualPricingDefinitions, consumptionData);
const chargingTime: PricingDimensionData = PricingEngine.priceChargingTimeConsumption(actualPricingDefinitions, consumptionData);
const parkingTime: PricingDimensionData = PricingEngine.priceParkingTimeConsumption(actualPricingDefinitions, consumptionData);

MODIFY
src/integration/pricing/simple-pricing/BuiltInPricingIntegration.ts
src/integration/pricing/simple-pricing/BuiltInPricingIntegration.ts
+import FeatureToggles, { Feature } from '../../../utils/FeatureToggles';
import { PricedConsumption, PricingDefinition, PricingSource, ResolvedPricingModel } from '../../../types/Pricing';
import Consumption from '../../../types/Consumption';
@@ -54,7 +55,35 @@ export default class BuiltInPricingIntegration extends PricingIntegration<Simple
private async resolvePricingContext(tenant: Tenant, transaction: Transaction): Promise<ResolvedPricingModel> {
const resolvedPricingModel: ResolvedPricingModel = await PricingEngine.resolvePricingContext(tenant, transaction);
if (!resolvedPricingModel.pricingDefinitions?.length) {
- const simplePricingDefinition: PricingDefinition = {
+ resolvedPricingModel.pricingDefinitions = [ this.getDefaultPricingDefinition() ];
+ }
+ return resolvedPricingModel;
+ }
+
+ private getDefaultPricingDefinition(): PricingDefinition {
+ if (FeatureToggles.isFeatureActive(Feature.PRICING_TEST_PARKING_TIME)) {
+ // TODO - Should be removed - just for testing purposes!
+ return {
+ name: 'Tariff 3 Dimensions',
+ description: 'Tariff - FF + CT + PT',
+ dimensions: {
+ flatFee: {
+ active: true,
+ price: 3, // 3 EUR when connecting
+ },
+ chargingTime: {
+ active: true,
+ price: 5, // 5 EUR/hour
+ },
+ parkingTime: {
+ active: true,
+ price: 7, // 7 EUR/hour
+ },
+ }
+ };
+ }
+ // Defaults to the simple pricing settings
+ return {
name: 'Default Tariff',
description: 'Tariff based on simple pricing settings',
dimensions: {
@@ -64,9 +93,6 @@ export default class BuiltInPricingIntegration extends PricingIntegration<Simple
}
}
};
- resolvedPricingModel.pricingDefinitions = [ simplePricingDefinition ];
- }
- return resolvedPricingModel;
}
}

MODIFY
src/types/Pricing.ts
src/types/Pricing.ts
@@ -10,6 +10,7 @@ export default interface PricingModel extends CreatedUpdatedProps, Authorization
export interface ResolvedPricingModel {
// Put there only the information that is to be kept with the Transaction
pricingDefinitions: PricingDefinition[];
+ flatFeeAlreadyPriced: boolean
}
export interface PricingDefinition {

MODIFY
src/utils/FeatureToggles.ts
src/utils/FeatureToggles.ts
@@ -4,7 +4,8 @@ export enum Feature {
BILLING_SYNC_USERS,
BILLING_CHECK_THRESHOLD_ON_STOP,
BILLING_PREVENT_CUSTOMER_DELETION,
- PRICING_NEW_MODEL
+ PRICING_NEW_MODEL,
+ PRICING_TEST_PARKING_TIME
}
export default class FeatureToggles {
@@ -13,7 +14,8 @@ export default class FeatureToggles {
// 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.PRICING_NEW_MODEL
+ Feature.PRICING_NEW_MODEL,
+ // Feature.PRICING_TEST_PARKING_TIME
];
// Check whether the feature is active or not!

pricing - bill FF only once