Skip to content

Pricing Service Basic Concepts

inspiran edited this page Feb 17, 2011 · 13 revisions

We'll just start to an use case to explain more what the pricing service should be capable of and we envision its functionality and extensibility. We'll start with a simple use case and make it more complicated step by step.

An online paint store offers a can of five liter primer paint for 50 euro excluding VAT. Painting products require a packaging cost of 2 euro for each can. A handling fee is charged once, independent of how many paint products are bought. Currently there is a 5% discount promotion if at least two cans are bought. The customer is located in Belgium and orders two cans which should be delivered within 24 hours.

Price element

A price element is the basic piece of pricing information which can be associated in the context of pricing to a product or sales order. The primer paint can in our case would have following price elements at product level:

  • net_price : 50 euro for 5 liter
  • packaging_cost : 2 euro for 1 unit

Price configuration and price container

A price configuration defines a set of possible price elements and how price elements should be populated or calculated. Examples of pricing elements are total price, discount rate, discount value, handling fees, .. Actually the primer paint pricing elements (net_price and packaging_cost) are also part of a price configuration at product level. A sales order will have its own price configuration.

When performing prices determination on a subject (eg. product, sales order, ...) the processing will build a pricing context container which holds calculated price elements. During calculation price elements within this container can see each other. This is required because price elements can depend on eachother (eg. total price of a sales order depends on the discount applied). A price element can also reference external information such as the country of the customer in order to determine the tax rate. The customer should be injected into the pricing container before price calculation occurs.

Price actions and price sequences

Having pricing elements is not enough. We further need to define how prices are retrieved or calculated. A price action tells the pricing service what should be done. By executing a predefined set of price actions the final prices are determined. We'll call this predefined set and in which order they are executed the price action sequence.

Let's look back at our example and understand how the price sequence would be defined for the product and sales order. Results of executing a price action sequence are found in the pricing context container.

Example price action sequence for the product price configuration

  • Get attribute value 'list_net_price' of entity product and put it in pricing context container value container.net_price
  • Put value '5' to container.handling_fee

Example price action sequence for the sales order price configuration

  • Sum all net_price price elements of all sales order items into price element total_net_price
  • Sum all packaging_cost price elements of all items into price element total_packaging_cost
  • Set handling_fee element to 5 euro.
  • Apply active promotion and set price element discount_rate
  • Set discount_value to total_net_price * 100 / discount_rate
  • Calculate total_excl_vat as total_net_price + total_packaging_cost + handling_fee - discount_value
  • Lookup price element vat_rate using container value customer.country
  • Calculate total_vat as total_excl_vat * vat_rate
  • Calculate total_incl_vat as total_excl_vat + total_vat

Having the price sequence is enough to start calculating all required prices. However in our example we can execute the pricing determination only if the customer is known during execution. Hence the customer is injected in the pricing context container.

$pricingService = $this->getService('core.pricing_service');
$priceConfiguration = $pricingService->getPriceConfiguration('paint_product_price_configuration_for_sales_order');
$pricingContextContainer = $priceConfiguration->createPriceContextContainer();
$pricingContextContainer->setExternalElement('customer', $theCustomer);

Individual price elements can be easily extracted from the price context container.

$totalInclVat = $pricingContextContainer->getPricElement('total_incl_vat');

The pricing service can be used to retrieve pricing elements for a particular product.

//$paintCan5liter contains a Product instance
$productPricingContextContainer = new PricingContextContainer();
$priceConfiguration = $pricingService->getPriceConfiguration('paint_product');
$priceConfiguration->determinePrices($paintCan5liter, $productPricingContextContainer);

The product pricing context container now contains price elements net_value and handling_fee.

Internals of price actions execution

todo