# Monday, April 14, 2008

The math behind Electronic Document Management

One of the key ideals behind Electronic Document Management is that it's supposed to save you money. The idea is that by eliminating some of the paper requirements you can cut down on supply and maintenance costs. It's one of those arguments that I've heard a number of times and to be honest I'd mostly ignored it.

My thought was that KNOWING you had electronic copies of each service order was well worth the investment and that the ongoing management and filing of these documents had such a time savings that the financial ramifications weren't as big a deal. Turns out I was wrong...

 

So here's the premise...

Each work order written inside of a Dealer Management System typically consists of 6 copies.

1 x Hard Copy approving the work.
1 x Technician Copy, so the tech's can note their work.
2 x Closing Copy, one for the customer, one for the dealership.
1 x Warranty Copy for the the manufacturer (if applicable).
1 x Accounting Copy, for the accounting system.


So, a store with 12 technicians doing 5 service orders per day would generate 360 documents per day.

12 techs x 5 service orders x 6 documents per service order = 360 documents


The same store, over the course of a year would generate almost 100,000 service documents.

360 documents per day x 5 days per week x 52 weeks per year = 93,600


Based on our experience each of these documents costs around 4 cents to print. When you take into account paper, toner, and printer wear and tear this adds up pretty quickly.

4 cents per document x 93,600 documents = $3,744 per year.


And these numbers are for an average sized shop!

I still believe that alot of the benefit behind electronic documents is the ability to better manage and store your information, but these kinds of figures do make a compelling financial argument.

#    Comments [0] |
# Thursday, February 28, 2008

You call that Snow!

Next time anyone complains about weather in Calgary I gotta forward this picture of a snow pile outside a Canadian Tire in Quebec... it was probably 50 feet high...

#    Comments [0] |
# Tuesday, February 26, 2008

Unit Test / Data Generation

I’ll admit that I have a love/hate relationship with Unit Testing.  Unit Testing has absolutely saved my bacon a number of times where a seemingly inconsequential change would have crippled our software. The reality is that the only way you can verify that those tiny changes don’t wreck havoc is to script your testing for known results. By having your build process validate those results you add a very strong safety net to your development process.

But… in most software systems there’s this pesky layer that throws a real wrench into the entire thing – it’s called the database.

The problem is this… a Unit Test is meant to be autonomous. It should be free standing and require no external dependencies. In reality the code you’re executing typically interacts with an existing database and performs INSERTS/UPDATES/DELETES to verify that certain functions still work. What get’s awkward is that the “Unit Test” database is typically an external dependency for your Unit Tests – it just has to be there be in the correct state or the Unit Tests will crash hard. Things like database schema changes, new testing datasets, and changing database locations really screw the unit tests up.

I’m going to describe a solution to this problem that we’ve been using for the last couple weeks. It’s worked extremely well by streamlining issues we had with databast style unit tests and by increasing our code quality. Everything here is based on Visual Studio 2005, nUnit, and nAnt but it’s more the concept that’s interesting.

How It Works!

We started off by adding a special project as part of each module called the Schema. Basically this is a simple class library with a bunch of embedded SQL scripts. These SQL scripts are responsible for taking a database and putting it into a known state for the Unit Tests. Execution of these scripts is done by a class called the SchemaManager, it has three methods which will become obvious in a minute.

The Unit Tests now add a reference to the Schema project. As a nUnit Setup Method we'll call out to a special class called the TestConfiguration. This TestConfiguration will be responsible for triggering the SchemaManager. Here's what a typical Unit Test in our UnitTest project would look like.

The TestConfiguration is a little more interesting. It uses a singleton pattern to create a SchemaManager, tell it to Drop the current Schema, and then Create it fresh. This executes the Drop Table/Procedure commands to clear out our database, and then uses the Create Table commands to make a fresh database.

Perfect! Now the database schema is in a state that our Unit Tests can work with – table are there, stored procedures are there, life’s good.

Now we need to create some canned data before we start our tests. Things like maintenance objects, customer codes, etc. are all expected to be in the database before our Unit Tests run so we need to create scripts in our UnitTest database which setup this data. Something like this...

We’ll embed this scripts into the UnitTest project and then change our TestConfiguration so that it gets the SchemaManager to insert this data after calling CreateSchema. We'll simply use the ExecuteResourceSql call we defined above and call it from our TestConfiguration.

And that's pretty much it! I think the beauty of this SchemaManager is that is makes the database a source-controlled resource. Instead of having some unknown dependency that the unit tests must rely on, the unit tests actually create their environment using scripts generated by the developer. If the developer breaks the Schema or the Business Logic, the unit test will catch it right away and any failed unit tests are expected to be logic errors instead of logistical problems between the development and unit test environments.

If you have any comments or suggestions on this area please drop me a line - it's a very interesting (and often underused) development practice!

PS - The foundation for a lot of this stuff is from a 4guysfromrolla posting, check it out for more details...

http://aspnet.4guysfromrolla.com/articles/040605-1.2.aspx

#    Comments [0] |
# Saturday, February 09, 2008

The Danger of Little Issues...

I came across a great article a couple weeks back about the danger of little issues... the foundation of this article was that every day we get interupted in ways that force us to change what we're focused on, deal with an emergency, and then re-focus back on the task at hand.

This articule suggested that these "shifts" cause us to lose more time then if we could just merrily work through one project at a time... makes sense, huh?  

What's really interesting is that this article suggested that the LITTLE things actually cause you more long-term grief than the big things. The reasoning was that when you come across a big issue you learn in a big way... and subconsciously take action to resolve it in the future. The problem with little issues is that they only take 1/2 an hour to resolve... and you become complacent in resolving them... twice a week... for a year.

 

Why is this worth mentioning? Today while setting up for our NADA trade show (www.nada.org) I ended up spending an hour trouble-shooting some file location issues on our demo server. It's a stupid virtual-drive issue that only occurs in certain environments and generally takes me about an hour to figure out.

The trouble is that we've grown complacent in spending an hour on this issue... instead of focusing on why we need a virtual-drive in the first place. If we'd reworked our pathing a year ago, I wouldn't get bothered by this every few weeks.

 

Once you identify the "Little Issue" it's all about committing yourself to resolving it... we're in mad-panic trade show mode right now so let's see what we can do after we get back from San Francisco...

To be continued...

#    Comments [0] |
# Monday, January 07, 2008

Cruise Control .Net / Queued Building

I just found an outstanding configuration element inside of cruise control which allows you to setup multiple projects to run in a queued environment. Basically it functions as a mutex so that while one project is building all other projects go into a queue until the first project is completed, and then another one is given control. The configuration element is really easy, here's our ccnet.config...

<cruisecontrol>

  <project name="Source Control" queue="ReleaseBuild">
    <workingDirectory>C:\Projects\dvt-root</workingDirectory>
    <triggers>
      <intervalTrigger seconds="180" />
    </triggers>
    <modificationDelaySeconds>10</modificationDelaySeconds>
    <sourcecontrol type="vault" autoGetSource="true" applyLabel="false">
      <executable>c:\program files\sourcegear\vault client\vault.exe</executable>
      <username>BuildUserName</username>
      <password>BuildPassword</password>
      <host>myDevtServer</host>
      <repository>Evolution</repository>
      <folder>$/Dvt-Root</folder>
      <useWorkingDirectory>false</useWorkingDirectory>
      <ssl>False</ssl>
      <setFileTime>current</setFileTime>
    </sourcecontrol>
  </project>

 

  <project name="Release Esenaar" queue="ReleaseBuild">
    <workingDirectory>C:\Projects\dvt-root</workingDirectory>
    <triggers>
      <intervalTrigger seconds="180" />
    </triggers>
    <tasks>
       <nant>
        <baseDirectory></baseDirectory>
        <buildArgs>-D:debug=False</buildArgs>
        <buildFile>Release.Esenaar.Build</buildFile>
        <buildTimeoutSeconds>1200</buildTimeoutSeconds>
        <targetList>
          <target>build</target>
        </targetList>
      </nant>
    </tasks>
  </project>
 
  <project name="Release Duvel" queue="ReleaseBuild">
    <workingDirectory>C:\Projects\dvt-root</workingDirectory>
    <triggers>
      <intervalTrigger seconds="180" />
    </triggers>
    <tasks>
       <nant>
        <baseDirectory></baseDirectory>
        <buildArgs>-D:debug=False</buildArgs>
        <buildFile>Release.Duvel.Build</buildFile>
        <buildTimeoutSeconds>1200</buildTimeoutSeconds>
        <targetList>
          <target>build</target>
        </targetList>
      </nant>
    </tasks>
  </project>

</cruisecontrol>

The first "project", called "Source Control" is actually responsible for downloading all our code from SourceGear Vault. You can see that every 180 seconds it downloads the source code from vault to a local folder called C:\Projects\dvt-root.

The second and third projects, called "Duvel" and "Esenaar" (maintenance release names), actually call out to our nant script and compile the appropriate release.

Now, our primary goal with all this is to make sure that we don't pull down source code while we're compiling a release (and vice versa) and that's where the queue property on the project comes into play. By setting the queue on all three projects to be the same thing, cruise control will not allow two projects to execute at the same time!

http://confluence.public.thoughtworks.org/display/CCNET/Project+Configuration+Block

#    Comments [0] |
# Monday, December 31, 2007

SigPlusNet Missing Module Exception

As part of our ongoing eSignature rollout we found that a smattering of client machines have issues when attempting to load the SigPlusNet.dll.

This dll is basically our interface to the signature pad itself and would fail with a FileNotFoundException. What was really strange was that the exception contained no information about the file it was trying to load. In addition, 95% of clients worked fine the first time. On the remaining 5% as soon as we started troubleshooting by installing Windows Updates or any other sample apps the error would simply go away.

After using a great little tool called FileMon (www.sysinternals.com) I found that the SigPlusNet.dll was failing on an attempt to find and load msvcr71.dll. Apparently msvcr71.dll is basically a set of C style application methods that are somehow used internally by SigPlusNet. Since this dll is pretty common it appears that on most machines it's installed by something else and so that's why on 95% of machines we had no issues.

Once I modified the install to include this dll, life is wonderful. A very strange unexpected dependancy...

 

#    Comments [8] |
# Friday, November 09, 2007

Drivers License Scanner

In our most recent release of Aristo Contact Management we've added support for a USB Drivers License Scanner. The basis of this project is that we connect this scanner to the local pc, integrate it into our customer screen, and then use the scanner to read customer information.

We've tried to make this a very simple process... after the user selects the Scan button the reader will whir and buzz as it attempts to pull information from the license. The reader itself accomplishes this by taking a picture of the license and then using text recognition (OCR) to separate the license into different fields we can populate our customer record with.

Once we read this information it automatically updates into the appropriate fields on our screen. In addition, because we're taking a picture of the license, we can also attempt to save a picture of the customer IF the regional license supports it.

At this point we support Canadian and US licenses and pull Name, Address, License and expiry fields.

Now, as a promotion for the first 5 clients who email me (and use Aristo Accounting and Contact Management) we're going to send you a drivers license scanner free! Quantities are limited so drop me an email at freeScanner@pbssystems.com and we'll contact the winners.

 

#    Comments [1] |
# Friday, September 21, 2007

Customer Alerts

Every now and then a project comes up that really tests the foundation of Aristo, our DMS product, and exemplifies how this foundation can provide us some very powerful functionality.

 

Couple weeks back, while working on Aristo Prospecting, we had a wish-list item to have an automatic alert show a sales person whenever one of "their" customers was in the dealership. The idea is that if you make a point of tracking down a customer when they're in for service you'll help to build your relationship with that client and increase the likelihood of them returning to look at a new vehicle in the future.

 

After reviewing this concept for a couple hours we came to a startling conclusion... our application already allowed for this! The basis of this was the Customer History, a listing of all Open and Closed activity for this customer. You can see it here on the right side of the screen.

 

 

Well the idea of a Customer Alert leverages on this really well - instead of grabbing a customer and looking at all their activity, we just need to change our query and grab all Open items for the dealership, and only show them if I have a relationship with that customer! To accomplish this we add the idea of User Roles.

 

Each customer can have any number of Users associated with them as either a Sales Rep or an Account Manager. These users now need a simple gauge on their desktop to show them when this Open activity applies to them. Enter the Customer Alerts Gauge!

Again, you can click on these items to get right back into that customer activity. We now have a very simple and powerful tool to help our clients build customer relationships. And all this without a huge amount of development effort! Our Aristo Contact Management dealerships will get a general roll-out on this feature in the next few weeks, hopefully this blog entry will give them a sense as to what it can be used for.

#    Comments [0] |
# Tuesday, September 18, 2007

Enhanced eSignature Changes

With eSignature rolling into larger beta it was time to address some flexibility concerns that had come up at our second pilot store.

 

Their chief problem was that when they took a signature on a Hard Copy they wanted the software to automatically print two copies at two different printers - one at the Service Counter (for the customer to take home) and one at the back counter (for the technicians). With our first version of eSignature this was awkward because the user was given one prompting screen and would need to use the "print" dialog twice - pretty difficult in a fast paced retail environment.

 

So... while we were out at our annual dealer conference last week I bounced this idea around with a couple service managers. We came up with the idea of "Document Actions". The idea is that eSignature already managed the layout of the document, it's not that big a stretch to allow it to also manage WHAT we do with the document once we have it. If we allow our document management infrastructure to take care of this we can specify that this document should be printed on Printer A, then printed on Printer B, and finally reviewed with Printer C. The flexibility can all be managed in our Document Layout interface and tailored to the dealerships processes.

Finally it's worth noting that all this new Document Management is only kicked off if you "Enable Document Management" for that specific document type. Once that checkbox is enabled the background, signature capture, and printing is all handled by eSignature - the existing printing control in Service is totally ignored.

#    Comments [0] |
# Tuesday, August 14, 2007

Dot Net / COM Interop Issues

Just overcome an extremely challenging problem we've been having. Our COM application was calling out to a dot net assembly through COM Interop and when the dot net assembly returned a response the process would get terminated... no friendly output, error messages, or log entries - just dead.

The solution was to totally REMOVE the Dot Net 2.0 framework and re-install. We tried a REPAIR first but that didn't seem to do anything.

It's worth mentioning that the problem didn't occur when calling into the dot net assembly but rather when it returned something to VB6... very strange.

Anyway, strike another issue off the project wall. Time to move back on to Prospecting!

Addendum> Apparently this issue is caused by one of the Dot Net 2.0 Security Updates from Windows Update! For now we're avoiding this patch.

#    Comments [0] |