Enhancing the pricing Data Model
3 タスク
1時間
シナリオ
The Delivery Service application initially used Declare Expressions to calculate the cost of priceable items. These items included business partner membership fees, membership renewals, truck vendor payments, and shipment delivery costs. As the application expanded, the number of Declare Expressions increased significantly. This growth made maintenance difficult, especially when introducing new priceable items such as varied truck sizes, moving services, and tiered membership types.
To address this complexity, the Delivery Service team adopted a pricing model approach similar to e-commerce pricing structures. This design introduced a Pricing data type to encapsulate the core properties required for price computation. Two foundational pricing models were implemented:
- Unit pricing
- Volume pricing
The team implemented Rule-Declare-OnChange rules to respond to changes in the input properties of the Pricing data type. This eliminated the need for Rule-Declare-Expressions. The solution continued to use Decision tables for pricing logic.
During the redesign, the team identified an issue: pricing model-specific rules were placed at the MDC-Data-Pricing class level, which created unnecessary coupling. To resolve this, the team applied pattern inheritance and polymorphism. Pricing model-specific rules were moved into their respective derived classes, such as MDC-Data-Pricing-Volume, resulting in a cleaner and more extensible architecture.
The team evaluated circumstancing as a specialization approach based on the pricing model but decided against it for this use case. However, circumstancing remains an option for finer-grained differentiation at the MDC-Data-Pricing class level. For example, it can be used to compute price and cost differently based on business context.
Several challenges emerged during the redesign:
- Existing Decision tables required modification whenever a new priceable item was added. This violated the Open/Closed Principle, which states that software entities should be open for extension but closed for modification.
- There was no mechanism to specify a different pricing model for cost versus price.
- The team wanted to avoid adding additional Decision tables.
- Inputs needed to be passed to the MDC-Data-Pricing recalculate Data Transform, which set display property values and maintained running totals for total price and cost to project potential profit.
The MDC center of excellence (COE) established a clear goal: to remove Decision tables entirely while maintaining extensibility and correctness. This objective initiated the analysis required to transition the pricing engine toward an Open/Closed, extensible architecture.
The following table provides the credentials you need to complete the challenge:
| Role | User name | Password |
|---|---|---|
| Admin | Admin@deliveryservice | rules |
詳細なタスク
1 Transition to Pega Live Data
The MDC COE recognized early on that managing complexity requires disciplined simplicity: every additional variable increases overall complexity, so each part of the solution must be kept as simple as possible.
The Pricing table records historical data. Each column is historical in nature and records what Case owns the record (Reference), what the Priceable item is, the computed Price, and the inputs used to compute the Price: Quantity, Discount, and PricingModel.
Existing Pricing table structure
|
ItemID (key) |
Reference (key) |
Price |
Quantity |
Discount |
PricingModel |
|---|
The Pricing Decision table was decomposed into a UnitPricing Decision table in the MDC-Data-Pricing-Unit class and a VolumePricing Decision table in the MDC-Data-Pricing-Value class. Polymorphism applies to a Data Transform called CalculatePricing, which the MDC COE team stubs out in MDC-Data-Pricing, and then overrides in each derived class.
The first step is to move the columns in both Decision tables to a live data table. The name of the live data table cannot be Pricing because that name is already in the system. A better name for the table is Price because that is the information that it contains.
New Price table structure
|
ItemID |
Quantity From |
Quantity To |
PricingModel |
Price |
|---|
It is possible to say that a Price record has four keys, namely the four columns on the left. If the application uses only two keys (ItemID and PricingModel), it says, Every priceable can have only one row per PricingModel. That does not make sense because Volume pricing requires multiple rows, one for each from/to quantity range. It is impossible to enforce that the system defines only one non-overlapping, contiguous set of volume quantity range rows. Adding an AsOfDate column to this table might allow prices to transition smoothly to new values over time. Because of the complexity of unique key enforcement, the decision is made to auto-generate pyGUID as the primary key by selecting the checkbox on the class Rule of the MDC-Data-Price Data Type.
2 Devise an Open/Closed solution
In Stage 1, devising an Open/Closed solution is straightforward: convert two Decision tables into one live data table. The next stage is more challenging.
The InitializeInvoice Data Transform currently runs at the beginning of the invoicing stage to pre-populate a set of Pricing records. One might ask: why pre-populate at all? Why not allow the user to build the list of Pricing records manually using a Table layout? The answer is rooted in user experience and accuracy:
- Pre-initialization reduces the risk of user error: salespersons must focus on communicating with customers rather than recalling which priceable items apply.
- The analogy is clear: ordering from a menu is far more efficient and less error-prone than asking a server to recite the entire menu from memory.
- Initialization does not restrict extensibility; any application component can initialize a Pricing record for its own context.
The Discount property of a Pricing record is initialized to 0 (no discount) via the pyDefault Data Transform of MDC-Data-Pricing. This approach provides a clean separation of concerns: the Data Type itself defines the default state of a Pricing record, not the invoicing process.
3 Generate invoice UI configuration
When the Item ID, Transaction type, Pricing model, Quantity, and Discount are known, the application initializes and persists the Invoice in the database, then links it to the appropriate Case. A standard Invoice UI is common across all transactions (Debit/Credit) and all Personas.