Trapdoor In The Sun

Alan Shanahan, Technician & Consultant


3 Comments

Force.com: Apex Styleguide, Part 5

Click for Part 1, Part 2, Part 3, Part 4 in this series.

Arrays or Lists?

With this post I am, strictly speaking, stepping outside of the pure topic of style. It’s one of those grey areas.

It’s that whole idea of whether to use Array or List data structures in your code. If, like me, you come from a background of programming languages where the first element of an array is element # 1, rather than element # 0, then you may also find List structures a little more intuitive because you usually don’t have to worry about element numbers when you iterate.

From the Apex language viewpoint, arrays and lists are interchangeable; you can declare a list and treat it as an array and vice-versa. Try it yourself if you don’t believe me:

public class BlogStyleGuide5 {

  // -----------------------------------------------------
  // The first method declares and populates an Array,
  // then iterates through it as a List.
  // -----------------------------------------------------
  void iterateOLI1() {

    OpportunityLineItem[] arrOLI = [
      SELECT Id, Quantity
      FROM OpportunityLineItem
    ];

    for (OpportunityLineItem iOLI : arrOLI) {
      Id      wrkId  = iOLI.Id;
      Decimal wrkQty = iOLI.Quantity;
      // Do something
    }

  }

  // -----------------------------------------------------
  // The second method declares and populates a List,
  // then iterates through it as an Array.
  // -----------------------------------------------------
  void iterateOLI2() {

    List<OpportunityLineItem> lstOLI = [
      SELECT Id, Quantity
      FROM OpportunityLineItem
    ];

    for (
      Integer i = 0;
      i < lstOLI.size();
      i++
    ) {
      Id      wrkId  = lstOLI[i].Id;
      Decimal wrkQty = lstOLI[i].Quantity;
      // Do something
    }

  }

}

If you were to adopt my preference for List structures rather than Arrays, you might end up having to re-code. That’s why I mentioned that this topic steps a little outside the realm of style. Therefore, please use care if you take this route. Ensure you test your changes thoroughly according to standard “good practice”.

Any comments on the above?


3 Comments

Zuora Pricing: Tiered & Volume Pricing Explained

In the world of pricing, I have found that people tend to use the terms “volume pricing” and “tiered pricing” interchangeably. In the Zuora world, they have very specific meanings. The differences are subtle, but have a financial impact. So it’s important you understand what they both mean and make the right choices when setting up your product catalog.

I find that most things like this are best illustrated by example. Below, I will show both Volume and Tiered pricing setup for an item. The numbers on each line are identical, but the calculations arrive at different numbers.

Let’s assume a customer places an order of a quantity of 35 in both cases.

Volume Pricing:

01-10 = 100 per unit
11-20 =  90 per unit
21-30 =  80 per unit
31+   =  70 per unit

Cost Breakdown:
All units cost 70 each.

Calculation:
Total cost = 35 x 70 = 2450

Tiered Pricing:

01-10 = 100 per unit
11-20 =  90 per unit
21-30 =  80 per unit
31+   =  70 per unit

Cost Breakdown:
First  10 units cost 100 each 
Second 10 units cost  90 each
Third  10 units cost  80 each
Last    5 units cost  70 each

Calculation:
Total cost = (10 x 100) + (10 x 90) + (10 x 80) + (5 x 70) = 3050

As the examples above show, Volume and Tiered pricing are not always the same, especially in the Zuora world.


1 Comment

Preparing Your Discount Rules For The Subscription Economy

Introduction:
Are you preparing to move to another subscription billing and finance platform for your subscription business?

Here’s a question or two: do you know how your business gives sales discount to your customers? I mean really know? If you were asked to define the rules, would you be able to do so precisely? Is it possible your sales people are selling some goods or services at a loss in order to land a deal? Is your discounting “system” open to abuse? Are some customers benefitting from excessive discounts, based on old deals, to the detriment of the overall business?

In short, are you in control? Can you run a report to get an accurate, current picture of your discount situation?

You know that you certainly should have full control and visibility of this aspect of your selling. In reality though, your IT systems may very well be based on legacy code, with lots of history and undocumented revisions; with many twists and turns, rules and exceptions, some old, some newer; possibly more which only some of your IT or Sales people are aware of; maybe some that are no longer part of your business rules but are still active in your code base.

System Replacement:
What if you need to implement a new selling or billing system: how would you fare out? Would the transition be painless or would you likely incur a substantial cost to analyse or reverse-engineer your discount rules?

So far I’ve asked a good many questions; the aim is to give you an insight into the difficulties posed by those helping you with the transition from the old to the new. And, perhaps, to make you think about a neglected area of your business that is sitting in a mystical black box. You can use the lists and notes below as a checklist to help uncover the hidden depths of your discount business rules; rules that will be used by implementers/analysts/techies when you make that transition to a new system.

Types of discount:

The list below indicates several types of discount that I and my colleagues typically encounter during client discovery sessions:

  • Customer discount – based on special terms, often a percentage discount, applied “across the board”
  • Agent discount – given to entities who purchase on behalf of their client companies
  • Quantity discount – applied based on volume purchases; In the Zuora world, there are two flavours of this, Tiered and Volume pricing
  • Vouchers – offer codes, unique or public voucher codes; time limited; one per customer/order
  • Special Offer discounts – product introductions, promotions, final remaining stock, loss leaders, marked-down stock, etc.
  • Discretionary discounts (sales) – for example, a salesperson saying “thats 1050, let’s make it an even 1000”; another less common use case would be where discretionary discounts are given to effectively pro-rate discount for partial subscription periods e.g. “we normally charge for the full year regardless of when you start but we’ll make an exception this time”
  • Legacy discounts – discounts that were negotiated a long time ago, that “linger” and may need re-alignment or re-negotiation
  • Region discount – discount applicable to a geographical region or market
  • Package or Bundle discount – a discount may be applicable when a particular set or combination of products are bought
  • Complaint – perhaps you offer discounts to customers to “keep them sweet” when they encounter poor product or service quality; sometimes known as a rebate
  • Group – discounts applicable by virtue of belonging to a group of companies, or having a particular parent company

Which of the above apply to your business? Do you use other discount types not listed above?

Now ask yourself, in relation to all of these: do you use percentages or fixed amounts? Both? Either? What are the specific rules? Build examples in Excel or on a whiteboard to help deduce the rules.

Particularly in the case of discounts amounts, when applied to a specific customer order, how do you decide on apportionment of discount values between products or distinct line items on the order?

Your rules may start to look complex now but we’re not finished yet!

Considerations and questions:
Once you have taken the initial steps to enumerate your discount types, the next step is to understand how they all fit together. At some point, it may be necessary to define a formal algorithm for an all-in-one discount calculation. The following aspects need to be considered:

  • Sequence – usually, the sequence in which discounts are calculated is important; mathematically, the calculation may not be commutative
  • Dependency – in order to qualify for discount A, do you need to qualify for discount B?
  • Mutual-exclusivity – to qualify for discount A, you must not already qualify for discount B; OR if you qualify for discount X, you cannot have discount Y
  • Compounded or additive – if discount A is 10% and discount B is 15%, does this add up to 25% discount? Or is it 23.5%? If you need to know how I arrived at that last figure, see the example at the bottom of this article **.
  • Thresholds – what happens if you give someone a discount worth 500, but they order 200 worth of goods or services? Or if the sum of their discount percentages exceeds 100%? Rules to cover these situations should be considered as part of your algorithm.

Approvals:
In many cases, there is an approval step that must happen in order to allow the order to progress to billing, fulfilment or whatever the next stage in your sales process. Firstly, you should identify entry criteria for approval: there may be more than one set of entry criteria. For example: “if discretionary discount exceeds 10% on any line item, use Approval Process X; if any line item has 100% discount applied, use Approval Process Y”. And so on.

Each approval process has a defined set of steps and may have more than one possible path through it. The ultimate outcome will be either an Approved status or a Rejected status. Here are some questions to help drive out your approval rules, and you should consider these questions in light of each of your defined approval processes:

  • Who should approve?
  • Should more than one person approve?
  • Does approval require unanimous approval from two or more people?
  • Are the approvers specific people or specific roles? The latter is preferable; consider the absence of key persons.
  • What thresholds apply?
  • What conditions apply?
  • Can you flowchart your approval process(es)?

Downstream Systems – Additional Questions:
So far we have only thought about the mathematical rules around the discount calculation. You need to also consider the bigger picture, in the context of the full implementation and how discounts play into the full ordering business process.

  • How do your discounts appear on invoices and quotations? Are your customers aware of the discounts they have received or is everything rolled into a derived line total?
  • How do you report discounts? Do you have the granularity you require for all discount types? Are these reports accurate and always up to date?
  • How do you control and audit discounts? Is the business operating within business constraints without tying the hands of your sales staff?
  • Where, in the life-cycle of the customer sales order, does the discount calculation belong? How and when are discounts calculated? Is the calculation automated or manual? what triggers a discount calculation? Do your users have the benefit of being able to view “what if” scenarios?
  • If the order changes, what effect does it have on the discount calculation? Is it a repeatable process?
  • Do you supply some products or services to which discounts do not apply, ever? Top-selling items, low-margin products and fixed costs such as shipping may not qualify for discounts.
  • How do you test and verify your discount calculation process? During the development phase? After it’s in production and affecting your business? Can you see the full audit trail for a complex discount calculation? Read my post on Auditable Programming for more details on what I mean.
  • To what type of charges do discounts apply?
    • One time charges? Examples are: setup fees; hardware provision at the start of a service provision period (mobile phones, for example); non-refundable deposits.
    • Recurring charges: and for how long? X charge periods or indefinitely?
    • Usage charges: for pay-as-you-go or included unit selling scenarios.

Conclusions: Why Would You Bother To Explore The Above?
That’s a lot to take in. It begs the question: why would I spend time and money to analyse my discount rules?

  • To understand how your business operates more completely
  • To understand how your discounts are (or are not) audited
  • To prepare for system change
  • To plan how to improve your business by simplifying processes and rules
  • To understand how you can have better visibility into your discounting strategy
  • To quantify whether it makes sense to retire some of your discount baggage; reduce your build, testing and maintenance costs as a result
  • When building a new system, understanding when the system will work as standard and when it needs customisation

Some final words of advice: when you’re moving house, you don’t have to take all your old furniture with you. Prepare your business for system transformation by making it leaner so that you can adopt new technology more easily.

** Example: Calculation of compound discount; think of it like this: “you can have 15% discount on the price that was already discounted by 10%”. In our example, discount A = 10%, discount B = 15%.

Discount A = 90% of the list price = 0.9 times list price
Discount B = 85% of the list price = 0.85 times list price
0.9 x 0.85 = 0.765 times list price = 76.5% of list price = 23.5% discount


3 Comments

Force.com: Apex Styleguide, Part 4

Click here for Part 1 of this series.
Click here for Part 2 of this series.
Click here for Part 3 of this series.

This one is a little easier on the brain.

From time to time, you will come across a scenario where one structure will need to be copied to another, and there’s no option but to do it “the hard way”, as in the example below. But do you want it to look good?

// Copy temporary record to database object structure
if (copyToRecord) {
  recordObject.Name = tempObject.Name;
  recordObject.Custom_Field_String_13 = tempObject.Custom_Field_String_13
  recordObject.Address_Line_1__c = tempObject.Address_Line_1__c;
  recordObject.Address_Line_2__c = tempObject.Name;
  recordObject.City__c = tempObject.Name;
  recordObject.Country_Code__c = tempObject.Name;
  recordObject.Postcode__c = tempObject.Name;
  recordObject.Contact_1_First_Name__c = tempObject.Name;
  recordObject.Contact_1_Last_Name__c = tempObject.Name;
  recordObject.Contact_2_First_Name__c = tempObject.Name;
  recordObject.Contact_2_Last_Name__c = tempObject.Name;
}

Figure 1, above, shows the raw code as many people would write it. Nothing wrong with that.

// Copy temporary record to database object structure
if (copyToRecord) {
  recordObject.Name                    = tempObject.Name;
  recordObject.Custom_Field_String_13  = tempObject.Custom_Field_String_13
  recordObject.Address_Line_1__c       = tempObject.Address_Line_1__c;
  recordObject.Address_Line_2__c       = tempObject.Address_Line_2__c;
  recordObject.City__c                 = tempObject.City__c;
  recordObject.Country_Code__c         = tempObject.Country_Code__c;
  recordObject.Postcode__c             = tempObject.Postcode__c;
  recordObject.Contact_1_First_Name__c = tempObject.Contact_1_First_Name__c;
  recordObject.Contact_1_Last_Name__c  = tempObject.Contact_1_Last_Name__c;
  recordObject.Contact_2_First_Name__c = tempObject.Contact_2_First_Name__c;
  recordObject.Contact_2_Last_Name__c  = tempObject.Contact_2_Last_Name__c;
}

Figure 2, above, is a “cleaned-up”, column-aligned version of the same code. It took very little effort, but suddenly there’s more clarity.

OK, call me petty, but what do you want your code to say about you?


2 Comments

Force.com: Apex Styleguide, Part 3

Click here for Part 1 of this series.
Click here for Part 2 of this series.

Here, I’m going to take a look at the condition part of the if statement. In particular, how best to write a complex condition to allow for readability and easy code maintenance. Sometimes even just a small number of ANDs and ORs can be easy to write but difficult to untangle later. Add in some brackets for changes in operator priority and the picture becomes even worse. I will refrain from filling up this post with words because I think the example below will provide most of the colour and information I’m trying to impart on the topic.

if (conditionA || (conditionB && conditionC) || (conditionD || conditionE)) {
  doSomething();
}

Figure 1, above, equates to the following:

if A OR (B AND C) OR (D OR E) then do something

When you substitute the conditions for real-world variables, function/method calls or complex structure sub-fields, the results can be less than legible. But, apply a little indentation and split your conditions up and you suddenly have some clarity.

if (
       conditionA
       ||
       (
           conditionB
           &&
           conditionC
       )
       ||
       (
           conditionD
           ||
           conditionE
       )
   ) {
  doSomething();
}

Figure 2, above, is functionally identical to Figure 1. Do you think it’s more readable? Easier to maintain?

A little tip for those engaged in writing complex Force.com custom formula fields with if statements: try using the same method .