Trapdoor In The Sun

Alan Shanahan, Technician & Consultant

Leave a comment

Social Perils: Are Naivety Levels At A Record High?

To tell the truth, I’m worried. Worried because I see grown men and women falling for obvious social engineering scams. Grown men and women that, I feel, should know better. But more than this, I am seeing a pattern emerge; there seems to be an inherent willingness in us all to believe what we read, simply because it is written. Some have been trained out of this urge or have simply grown or matured out of it. But too many haven’t. I’m sure I risk scorn from some who might say I’m a smartarse. I’ll risk it.

Facebook – the tool of choice for those who like to interact with their world or just lurk watching others live – is where I see much of this behaviour manifest itself. Facebook gives us two innocuous little clicky things: Like and Share. But, like the proverbial iceberg, there’s a lot more under the surface. They carry responsibilities that many are unaware of.

And here is why: when you click Like or Share you cause something to happen: that something is called publishing. That action has legalities all over it. The fact that it is, technically, “re-publishing” carries no weight from a legal standpoint.

Examples of the types of posts I’ve seen shared recently are:

  • picture of a male in late teens holding a beer bottle; there’s a warning to watch out for him in animal rescue shelters – he’s looking for dogs to use in dogfights.
  • picture of a middle-aged man, warning that he’s living in a certain locality and he is a convicted rapist and murderer.
  • missing person reports with accompanying messages begging everyone to share
  • Share-ing and Like-ing of competition links, willy-nilly
  • Instant noodles are coated with wax and cause cancer

Properly researched and checked, I have no problem with any of these things. But when it becomes indiscriminate, it then starts to gnaw at me. I note that many have taken to automatically re-publishing most of what flows in front of them with no filter whatsoever. Don’t they know they’re opening themselves up to libel suits? Or that they’re annoying their (more enlightened) friends?

It’s the willingness to publish potentially libellous material without any source checks that is most worrying. If it’s written down, it must be true; after all, it is on the internet

Are gullibility levels high or are they now visible to everyone because of Facebook’s popularity?

Related articles:
5 Easy Ways To Get Sued On Facebook
You Can Be Sued For Libel For What You Write On Facebook
Warning: You Can Get Sued For Libel For Your Facebook/Twitter/MySpace Posts


The Verb “To Unfriend”

We’re in new territory.

It’s hard to remember the days when we didn’t have Facebook. There’s about a billion+ of us who use it. Many are addicted. It’s possible I’m borderline addicted; maybe that’s self-denial. If I really wasn’t addicted I could give it up in the morning. Seriously, I could. If I sound like I’m trying to convince myself, it’s probably because I am. Trying to convince myself, that is.

There are many who measure themselves on that magic number – the number of “friends” they have. Doesn’t matter if it’s Tesco, the dry cleaner down the road, the woman who does my nails, that famous comedian; they all count. I’ll bet most of you know (to within 10 or so) exactly how many FB friends you have right now. Be honest.

Having a lot of friends also has its downside – they all like to share. Whether directly or indirectly, you will see quite a lot of “material” flow up through your Timeline. Some will interest you; more will not. There are filters available; filters for apps, for pages, for stories, for people and more. If someone is constantly spewing and you don’t want to know any more, you can block them. They won’t know about it and it’s easy to do (and to undo). Or you may choose to “unfriend” them. This is slightly more drastic. Again, they won’t know they are no longer on your list, at least not at first, but when you start to appear as a friend suggestion on their page, they will soon work it out.

Please don't unfriend me!

Which brings me to my point. Five years ago it was a safe bet that the word “unfriend” was never heard by human ears. Now it’s a real thing. A thing in the virtual world, but a very real thing. It has a damaging payload – an insult with a real world analogue. What you’re saying (whether or not you want to) is “I’m closing the door on you.” It’s a definitive, perceptible statement to the other person; unlike saying to yourself “I won’t bother with him anymore” which is far more passive.

I’ve had some Unfriend experiences and been on both sides of the fence. My first was when I worked out that one of my FB acquaintances (word chosen for accuracy) was stirring it up between me and a real-world ex-friend, based on some thinly-veiled comments I had made. I made a conscious decision to unfriend that person. I was happy with the consequence of their knowing I did that; I hoped it made a statement. You might argue it was a little cowardly of me and maybe there’s some truth in that; but there was nothing positive to be gained from a confrontation; there were still many connections between me and my new Unfriend, and others I cared about would have been directly and adversely affected.

A more recent experience I had was when another in my circle (apologies to Google+), who was responsible for some awful output and had been blocked my me, decided to add a snide comment to one of my pearls of wisdom. My own curt response (again, words chosen carefully for impact) more or less challenged that person to make a choice. Without using the words, I was saying “well, there are easy ways to stop seeing what I have to say”. About a week later, I saw their photo in my suggestion list. Wow! I was unfriended. Deliberately and definitively. I was a little unsettled, for a short while anyway, but I got over it quickly. I suppose I was surprised that my comment (which you could certainly call a challenge) had a direct consequence. Surprised too that they didn’t just block me, they Unfriended me.

I had seen, prior to that, that one person I knew a long time ago had done the same thing but that was something I shrugged off in a moment. I guess the degree of closeness to your Unfriender (or Unfriendee) is proportional to the degree of Hurt felt. I’m sure I could call this Alan’s Law and become famous. But I’ll leave that.

Another Unfriending I beheld as an observer. Someone close to me, whom I’ve known since babyhood, decided to unfriend all five of her grandchildren. I don’t know why. It caused quite a hubbub amongst them; mostly disbelief, heaps of scorn, topped with more than a little disdain. And at the back of it all, I’m sure, a generous helping of hurt. I have no idea what the actual intent was; I don’t know why it happened; I do know that other observers who are closer than me to the Culprit will take sides (against them) and that some real and lasting damage was done. Regardless of the intention.

Is it simply down to a choice: Block or Unfriend? Scary new territory with new rules and new consequences. And what impact to those in the business world introducing social to the game?

Your thoughts and comments on this topic are most welcome.

This post was prompted, in part, by this Mashable post on the same topic.

3 Comments 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();
    ) {
      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?


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.

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

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

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.

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 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?