Showing posts with label Business Process Improvement. Show all posts
Showing posts with label Business Process Improvement. Show all posts

02 March, 2011

Love, Hate and the ViewState

I was recently tasked with creating a SharePoint interface to Microsoft Dynamics GP Item Maintenance. As the client's business had grown, inconsistencies in theirItem Master became apparent. When new items were needed, a similar existing item was copied and the details updated to match the new item. If there were no similar items, a new item was created.

The problem was, many of the existing items were not properly categorized. There were people in the organization who knew bits of information about items, but nobody had all the information to correctly set up an item. Setting up an item properly required a combination of phone calls, emails and a little bit of luck. It could sometimes take weeks to get the item set up. This held up BOMs, Routings and pretty much everything else dependent on the new item.

As usual for a new project, we started with a discovery phase. We tried to identify the groups that knew the necessary bits of information about items and proceeded to schedule interviews. During the interviews we gathered a lot of information to help us get started. We also found several points that were unclear: i.e. Accounting said Billing provides this. Billing said it was Sales, Sales thought it was Purchasing, Purchasing pointed to Engineering and Engineering said it was Accounting. After a few round trips, we were able to pin most things down but in the end, there were still a few bits of information that nobody understood.

It was clear the Workflow would have to be very flexible. Adding to the complexity, some Items could bypass entire groups. For example, there's no need to set a price on an item if you don’t sell it. And why bother Purchasing if you are making this item in your own shop?

To solve this business problem, we needed to deliver a product with:
  • Flexible Workflow rules that could be adapted as the business changes (and as the users work with the system and discover steps that had been overlooked.)
  • Field-Level security to ensure each group can only edit their section.
  • The ability to assign some fields to multiple groups and users.
  • The ability to add new fields and groups as new requirements surface.
  • Audit Logging for accountability.
  • An intuitive User Interface.
  • The ability to open, edit and copy existing GP Items.
  • The ability to push the approved changes back to GP.
This was not a simple SharePoint WebPart with an ASP.NET Form you can throw on a Page and start using. The form had to be generated dynamically, with different sections editable by different users. Lookup Fields had to be populated dynamically. Some based on values stored in GP like Class Code, others with a Hard-Coded list of choices, like Item Type. Oh, and new lookup fields could be added at any time.

What's more, the fields and their rules were not known at design time. All the metadata describing the rules had to be parsed during form generation and postback.

While building this application I ran into a few challenges. One in particular had to do with updating posted values based on business rules and then rendering the fields, not as the user had posted, but as the rules dictated. Now that you know the background, how do we make this happen?

The ViewState is great! It makes your life as a web developer so much easier. Some action causes a postback and all the fields are repopulated with their values. You can handle events for a control without having to worry about the rest of the form. Controls get their IDs set automatically. What's not to love? Plenty.
  1. The ViewState is transmitted and parsed with every page post/load cycle using bandwidth, memory and CPU cycles for the server and the client.
  2. The ViewState, while encoded, is not encrypted. I've seen this argument and I don’t think it's really all that relevant. After all, you are sending the same information back and forth through the form fields. And if you need to keep a secret, use HTTPS.
  3. The ViewState is persistent insistent. If I take the users' submitted data and do some processing on the backend, I just might want to change some values on the form when it is sent back. Suppose they tried to order 100 widgets but you just sold some and you only have 75. Send the form back to the user with quantity set to 75 and display a nice alert telling them they are lucky to get that many. Thanks to ViewState, the quantity field gets set back to 100 automatically. I know, JavaScript could validate the page before the user submits. But what if the user is running without JavaScript? I know I do unless I'm on a trusted page. Add-ons like NoScript offer significant protection while surfing and after a whitelisting your common sites, they pretty much stay out of the way. But even with JavaScript, if I'm dealing with Dynamic Data, (what other kind is there?) the validation rules may have changed since the page was loaded. I suppose I could build some AJAXy validation JavaScript, but again, you can't count on JavaScript being there and you should never trust anything a user submits, even if you think your JavaScript has sanitized it.
So, lets say we want to prevent ViewState from running. Easy enough, just set the EnableViewState property of the control to false:

         TextBox t = new TextBox();
         t.EnableViewState = false;
         t.Text = this.ToString();
         return t;

And what if you want to disable ViewState on the whole page?

      private void Page_Init(object sender, System.EventArgs e)
      {
         this.EnableViewState = false;
         //do some other interesting stuff 

      }

So, you’ve defeated the ViewState on a couple of projects and now it's time to build a SharePoint Web Part. Create the Web Part, add some controls, disable ViewState, deploy the Web Part and life is good! And we still have time to make happy hour (the first one!)

Wait a minute. Didn't you disable ViewState? Why aren't your backend changes sticking? Because SharePoint Web Parts love ViewState so much, they insist on using it. Disable it on the control? Doesn't matter. It happens anyway. Control.ClearChildViewState() doesn't even help. How about firing up SharePoint Designer and disabling it for the entire Page that hosts the Web Part? Congratulations, you've done it, and you’ve disabled pretty much all the SharePoint functionality too. No, there has to be way around this.

Actually, there are two:
  1. Create a LiteralControl and build it's Text property with the HTML you need to create your form field. Now you can render the LiteralControl and IIS will never even see the field. Remember, you will have to inspect the Post Variables yourself to find out how many widgets you just sold. Unfortunately, I tend to make the occasional mistake dynamically building HTML from within a C Sharp app. Leave off a quote or miss a closing tag and your form starts acting really strange. That brings us to the other option.
  2. Create your controls like normal and add them to parent controls if you like. No need to worry about the HTML, IIS will get it right. But instead of adding the controls to the page (or a page element) render them into the Text property of our friend the LiteralControl. Using a StringBuilder, a StringWriter and an HTMLTextWriter, it all falls into place
             //...Build your textbox as you like. 
             //Don't forget a unique ID. 
             TextBox tbQuantity = new TextBox();
             LiteralControl LControl = new LiteralControl();
             LControl.Text = this.RenderControlToString(tbQuantity);
             this.Controls.Add(LControl);
    

          public string RenderControlToString(WebControl Control)
          {
             StringBuilder sb = new StringBuilder();
             using (StringWriter sw = new StringWriter(sb))
             {
                using (HtmlTextWriter textWriter = new HtmlTextWriter(sw))
                {
                   Control.RenderControl(textWriter);
                }
             } return sb.ToString();
          }
Using the HtmlTextWriter, we have well-formed HTML without having to worry about ViewState moving our cheese. Even in a SharePoint Web Part. And as a bonus, the ID you assigned to the Control is the ID that will be returned. No prepending all the parent control IDs by IIS. This, too helps to reduce the page size and load time.

13 January, 2011

5 Reasons to Re-Implement your Dynamics ERP

Are you frustrated with your Dynamics ERP system and starting to consider other options?  Maybe you feel like you have outgrown your Dynamics ERP system and need to move on to something like SAP.  Maybe it's just time to take a fresh look at your ERP strategy to take it to the next level.

Over the past few years we have completed several re-implementations of Dynamics GP for our clients while several others are considering the same in favor or moving on to something else.  Here are some reasons why they are choosing to re-implement.

1. Enable new revenue streams and growth strategies:

After completing a Dynamics GP implementation for a client in the early 2000s they recently changed their distribution strategy to include direct sale retail stores and have expanded the number of customer service centers.  During the initial implementation, neither was part of their strategy or a design consideration.  Their Dynamics GP workflow and integration customizations were not designed specifically to handle some of these new requirements.

We are now in the process of planning the re-design and implementation of some of their customizations.  With this new design, as they continue to expand their retail and service operations, on boarding these entities will be as simple as populating some setup screens on which their workflow, subledger to general ledger integration, and other system features will rely.  Long-term, as they continue their expansion, this will save them consulting services costs and make them more nimble.

2. Automate standardized business processes:

We spent a significant portion of last year re-implementing Dynamics GP for a client that was originally implemented in the early 2000s.  Since, they had further evolved and standardized their business processes as business process improvement and SOX compliance projects had been executed.  They evaluated their options and considered replacing Dynamics GP with a "Tier 1" system.  Through that evaluation they found that Dynamics GP could handle their requirements just as well for a fraction of the cost.

The result was a complete re-implementation of an integrated Dynamics CRM/GP system with a new custom application in between to handle product configuration.  The project was completed for considerably less than the estimate to do the same with a common "Tier 1" system with the same or better results.  They now operate their business free of disparate Excel spreadsheets, countless hours of redundant and unnecessary data entry, or years worth of hard coding implemented to quickly deliver on new or changing requirements.

3. Hodge Podge Syndrome:


ERP systems are "evolutionary" not "revolutionary".  They grow, mature, and evolve over time as existing requirements are refined or more clearly understood and new requirements become known.  As this happens new functionality in the form of 3rd Party ISV Products, new modules or integrated technology, and custom developed solutions is implemented.  This is a common best practice that most often produces very good results.

Over time, if continuously reacting to an ever changing environment by implementing the first solution that appears to plug a GAP as quickly as possible, at the lowest possible cost you may end up with a variety of heterogeneous systems that don't integrate well or truly fit your requirements.  Common results of this approach include business rules hard coded into queries serving reports and a myriad of patches that have turned your off the shelf solution into a custom solution.

Taking the time to carefully and proactively consider new requirements and match them to the best available solution with consideration for how it interacts with the existing environment will prevent this problem.  If you don't, you may be sacrificing long-term continuity for short-term results.

4. The "vanilla", "out-of-the-box" approach left you with an incomplete system:


While "vanilla", "out-of-the-box" implementations are less costly and completed more rapidly than full scale deployments they are often incomplete.  This is more commonly true for larger organizations.  Typically, customers assume that they can simply follow-up Phase I with future phases to layer on additional functionality.  This is not only true but is considered a best practice approach.  However, if you don't plan for future phases while designing your initial implementation you could be left with many GAPS to fill later.

If those GAPS are not few and far between you might be left with a square peg/round hole scenario in which you are consistently working around design decisions made without consideration of the future functionality required.  This is another situation where the software, if designed and configured around all of your business processes and requirements, will likely fit well.  If you do take this rapid approach with your implementation make sure to consider any known future requirements in your design to ease the implementation of that functionality later.


5. Your initial implementation just wasn't successful:

There are many reasons why ERP system implementations fail.  Inadequate requirements definition, inadequate customer and/or consulting resources, and unrealistic timelines or expectations are among some of the common reasons.  Typically, the primary driver of an unsuccessful implementation is not the software itself.

Often, unsuccessful implementations can be salvaged.  However, if the foundation is bad then you might be better served starting over.  Of course, now you would have the luxury of hindsight to determine why the initial implementation failed and correct that before starting over.  I would recommend you start by discussing this with your partner who has obtained the institutional knowledge to best ensure your success.  Of course, if they were the problem you might consider a change.

In summary, don't assume that changing ERP systems will solve your problems or get you where you need to go next.  You could very well have already purchased, many years ago, the ERP system that is best suited to run your business for many years to come.  Whether you are experiencing some sort of pain or simply have a new ERP strategy to implement I recommend you consider all of the factors involved in delivering a world class ERP solution and take the steps necessary to prevent the problems you might have to react to later.

04 November, 2010

Business Process Improvement with Conditional Process Holds in Dynamics GP Sales Order Processing

I was presented with a business process problem by a client related to managing Credit Limit overrides in Dynamics GP Sales Transaction Entry.  This company does not supply Order Entry users with the Credit Limit override password.  It's the Credit Manager's responsibility to decide whether or not to allow that override.

This client has been working for some time to generally route information to the right person that needs to make the decision and eliminate waste in their business processes.  During the normal course of business when users are presented with the "Please enter the credit limit override password:" prompt the Credit Manager is called to the user's workstation to make the decision on the fly.


This is a very inefficient process.  What a great opportunity for improvement!

To resolve this issue and get the information to the person responsible for making the decision while maintaining the system controls required we got creative with Process Holds, eConnect, and VBA with ADO.  Here's what we did:

First, we removed the "Exceed Credit Limit" password from Receivables Management Setup:


Now, users would have been presented with the more friendly prompt that would allow them to proceed without a password.


I don't claim to be a SOX expert but I'm guessing that wouldn't pass a SOX audit.  So, we added some VBA Code to the BeforeModalDialog Event behind the Sales Transaction Entry Window.  Of course, to make this work you would need to add that window plus the DocumentNo and the SOPTypeDatabase fields to your project.



The code calls the taSopUpdateCreateProcessHold eConnect stored procedure and adds the "CREDIT" Process Hold to the Document when the credit limit prompt appears and closes the dialog box by answering Continue to the prompt automatically.


Now, instead of stopping the user in their tracks to make this decision on the fly the Credit Manager can manage this Process Hold separate from the Order Entry Process.  To do this, we used SmartList Builder to build a SmartList that displayed SOP Documents On Hold.  Then, we added a Favorite with a Reminder to the SmartList to show only SOP Documents with the "CREDIT" Process Hold applied.


Now, when the Credit Manager logs into GP and periodically throughout the day he can quickly and easily analyze the Sales Orders for Customers that had exceeded their Credit Limit and manage them accordingly.


Get the right information into the hands of the person who is responsible for making the decision and you too can improve your business processes and efficiency.  It doesn't take much work or creativity to increase the ROI on your GP implementation using techniques such as this.

If you like this let me know.  If enough people do, maybe we'll produce a new freebie for Dynamics GP!

Don't accept what you're given, make it into what you need it to be.