Every one of us has been guilty, or will be guilty, of creating a bad solution to a problem at some point in our career. If you have not done so yet, just be prepared, your day will come.
Most of the time, people do not start off trying to create a bad solution, it just ends up like that. The cause can be just about anything, but here are a few:
- Bad information (from research or the customer)
- Change in design of Dynamics CRM (i.e., they changed something and didn’t tell you)
- Over-thinking a problem
- Under-thinking a problem
- Unfamiliarity with the product, its features, and functionality points
One of the things that had been done was to modify the calculations of the Quote/Order/Invoice system in order to incorporate a customer-requested design change.
The main part of the customization was that custom total fields were added and the calculated values were stored in those fields while also updating the original total fields with the custom calculations.
The one thing that was different and extremely important was a custom field that allowed the user to enter a specific price per unit that would take the place of any system-calculated price.
So I upgraded everything, cleaned up the code a bit, and everything continued to work as designed/requested.
Then we upgraded to CRM 2015, and things started to NOT work as design. Specifically with the Opportunity Product. You would change a value and see before your eyes, the numbers change.
After spending about 3 hours one night tracing the actions of the system, I found this flow:
- User changes the quantity on the form
- Our custom Plugins fire
- [Possibly] Internal CRM plugins fire
The net result of this was that Dynamics CRM was overwriting our newly calculated values with their own, which was driving the users crazy.
Dynamics CRM Internals Notes
If you did not know, the Quote, Order, and Invoice entities are exactly the same, just in different buckets. Also, the Opportunity Product, Quote Product, Order Product, and Invoice Product entities also share the same structure.
Also, even though these entities are similar in layout and design, it would appear that do not all function exactly the same.
Also, everything is version-specific. With CRM 2015, only the Opportunity Product uses the new form design. Quote/Order/Invoice Products still use the Information form.
Any work that must be done on the create of one of these records must be accomplished using a plugin.
The main problem was the internal Dynamics CRM code was overwriting the results of our custom code – somewhere – and after reviewing the facts, I realized there was just no way I could circumvent the actions of the product.
Correcting the Problem
The solution to this problem was actually rather simple and I still wonder why this wasn’t tried before.
It turns out that there is a Manual Discount field which is actually used by the automatic calculation engine. After spending about 30 minutes with the customer, we were able to successfully test the use of the Manual Discount field as the basis for our custom per unit price.
I used that field to reduce the price per unit so that the calculation appeared to be using the manually entered price per unit, even though it was not. The code looks like this:
The only issue that remained was we had years worth of data in the wrong fields and many of the additional functionality points: Templates, reports, etc., were using these custom total fields.
So here are the results of this process:
As far as the users go, there was not change to the functionality they have been using for the past 7 years or so.
I decommissioned and removed five plugins because their function was either unnecessary or redundant. The plugins that currently exist perform addition functions but the only pricing-related things they do are to put the values from the standard total fields into the custom total fields because those are the fields that are being used throughout the entire system.
You’ve probably heard me say this many times but it is never a good idea to recreate Dynamics CRM built-in functionality. Sooner or later you will pay the price for that decision and it is never pretty.
So, don’t do it.