The FSG-Data-Pricing data model has met FSG’s needs thus far. Currently the Recalculate Data Transform supports UNIT and VOLUME as values for the PricingModel property. FSG would like to see the tiered pricing model supported as well.
The following table provides the credentials you need to complete the exercise.
Design a solution where the FSG-Data-Pricing Recalculate Data Transform implements a different pricing strategy based on the value of the PricingModel property without using When/Other When/Otherwise logic. The solution should be able to support a tiered pricing strategy.
There are two ways to perform Volume pricing. One way is for the returned pricing to include the quantity. The unit price per item could be derived by dividing the returned pricing by the quantity. The second way to perform Volume pricing is for the lookup to return the unit price per item. In this situation, the total price is the identified unit price multiplied by the lookup quantity.
Tiered pricing always uses the unit price approach where there is a stated price per item. The unit price in the range associated to the quantity is multiplied against (quantity – range_start). Then each lower range is priced as: unit_price_in range * (range_end – range_start).
The table below shows that for an event with 12,000 attendees, FSG would be able to change an extra $10,000, plus an extra $1500 for hotel service. FSG’s cost does not change; only the amount that it charges has changed. As opposed to charging $6.67 per attendee within the 0-to-6000 attendees range, FSG would instead charge $8.33.
Your solution should include a brief design analysis followed by description of the recommended solution.
1 Solution Design Analysis
To eliminate the need to use When/Other When/Otherwise logic, some form of specialization based on the PricingModel property is required. For obvious reasons, ruleset specialization is not appropriate.
The FSG-Booking-Work-BookEvent case possesses a .Pricing Page List property that references D_PricingList using the case pzInsKey. FSG-Data-Pricing records are persisted to the database, they are not held in the BookEvent case’s BLOB (pzPvStream). The .Pricing Page List is not used by the Booking application as explained below.
Currently there are only two things that FSG charges for, event hosting and optional hotel service. When an Event is created, both items are initialized within the FSG-Booking-Work-BookEvent case’s InitPricing activity before being saved to the database. At this point, pricing has not calculated since the number of event attendees, and whether hotel service is desired, is not yet known.
Once the value of those two properties are known, FSG-Booking-Work-BookEvent calls a Recalculate activity. The Recalculate activity initializes TotalCost, TotalPrice, and Profit before calling RecalculateHotel. Afterward the Recalculate activity retrieves the FSG-Data-Pricing record for the Event that was originally persisted by the InitPricing activity. The Recalculate activity initializes the FSG-Data-Pricing “PricingSavable” page setting Quantity, DiscountFactor, and Bit, the latter indicating whether or not the record is selected. Since the Event must always be selected, the value for Bit is set to 1.
Currently the PricingModel for an FSG-Data-Pricing record is decided by the PricingModel Decision Table. In the future this could be moved to an FSG-Data-PricingModel data type. The Decision Table is called in the first step the FSG-Data-Pricing Recalculate Data Transform. In the future this step could be replaced by a D_PricingModel lookup.
How to specialize a pricing record based on the value of its .PricingModel property boils down to two approaches:
- Clas Specialization
At first the use of circumstancing seems the most appropriate since the number of different pricing models would never grow large. The same argument though can be made for using class specialization. Maintaining a small number of specialized classes would be easier than maintaining a large number.
An advantage that class specialization has over circumstancing is that a different number of rules can be leveraged to derive each PricingModel-specific solution. With circumstancing, everything that is specialized must have a base rule, even if that rule is never used. Circumstancing is ideal for situations where there is a single rule that is applicable to the majority of situations and where specializations of that rule rarely needed.
Class Specialization would best satisfy the Build for Change guardrail. From an ease-of-maintenance perspective, pattern-inheritance would be the best approach.
Tiered Pricing Solution
It is questionable whether computing a tiered price using an evaluate-all-rows Decision Table is possible. Even it were possible, itis questionable whether that approach would be easy to maintain over time or would it, instead, become cumbersome.
In the long run, it would be better to store price information in a database table. The information contained in the UnitPricing and VolumePricing Decision Tables belongs in a separate Data class. The obvious name for that Data type is FSG-Data-Price.
|ItemID||Unique ID for a priced item|
|Currency||Unit of currency associated to the price, e.g., USD|
|QtyFrom||Integer whole number start of a range|
|QtyTo||Integer whole number end of a range|
|PricingModel||UNIT, VOLUME, TIERED|
|IsUnitPrice||Whether the price applies to each item or is the final price|
The DerivePricing Data Transform defined in the FSG-Data-Pricing-Tiered class could ask the D_PriceList FSG-Data-Price List Data Page to fetch every row associated to an Item ID where PricingModel = TIERED. An ascending sort would be applied to the “QtyFrom” value. The DerivePricing Data Transform would then iterate the results accumulating a tiered price. The iteration would end after QtyTo value is either greater than Quantity or the QtyTo value is undefined.
2 Solution detail
Rather than the PricingModel Decision Table returning the value for the PricingModel property, it can set that value directly and, instead, return a pxObjClass value for the Recalculate Data Transform to set. The Recalculate Data Transform can subsequently apply a stubbed-out Data Transform named DerivePricing. The logic that currently exists within the Recalculate Data Transform for Unit and Volume pricing would be moved to FSG-Data-Pricing-Unit and FSG-Data-Pricing-Volume DerivePricing override transforms. The logic for the FSG-Data-Pricing-Tiered DerivePricing override transform would then need to be developed.
It becomes apparent once the new pattern-inheriting classes are created, that the opportunity to use encapsulation from the beginning had been missed. For example, the UnitPricing Decision Table belongs in the FSG-Data-Pricing-Unit class, and the VolumePricing Decision Table belongs in the FSG-Data-Pricing-Volume class. Similarly, The UnitPrice and UnitCost properties belong in FSG-Data-Pricing-Unit and VolumePrice, VolumeCost, and VolumnPriceIncludeQty belong in FSG-Data-Pricing-Volume.
3 Verify your work
- Create an Event case.
- Evaluate how pricing is calculated.
- Review the configuration.