Quantcast
Channel: Dynamics GP Land : forecaster
Viewing all 240 articles
Browse latest View live

Converting a DataTable to objects in C#

$
0
0
By Steve Endow

Let's say you have a C# Dynamics GP integration that retrieves Customer records from a staging table and you need to convert each row to a Customer object so that you can more easily work with the data.

You could loop through the rows in your DataTable, read every field in the row, and assign each field value to each corresponding object property.  But that would be tedious, particularly if your object has dozens of properties.  And it's very low value coding.

After having done this a few times, I got sick of all of the typing and figured there had to be a better way.  Of course there is.  Fortunately a very smart person posted some code that handles this task very well, using Reflection.

https://codereview.stackexchange.com/questions/30714/converting-datatable-to-list-of-class

It works incredibly well and requires all of 1 or 2 lines of code to use.

I made a few different variations, allowing me to use it with a DataTable, DataRow, and DataRow arrays.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;

namespace TSM.Integration.Library
{
    static class ObjectMapper
    {
        ///

        /// Converts a DataTable to a list with generic objects
        ///
        /// Generic object
        /// DataTable
        /// List with generic objects
        public static List DataTableToList(this DataTable table) where T : class, new()
        {
            //From: https://codereview.stackexchange.com/questions/30714/converting-datatable-to-list-of-class

            try
            {
                List list = new List();

                foreach (var row in table.AsEnumerable())
                {
                    T obj = new T();

                    foreach (var prop in obj.GetType().GetProperties())
                    {
                        try
                        {
                            PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
                            propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
                        }
                        catch
                        {
                            continue;
                        }
                    }

                    list.Add(obj);
                }

                return list;
            }
            catch
            {
                return null;
            }
        }


        public static T DataRowToList(this DataRow row) where T : class, new()
        {
            //Variant of DataTableToList code from: https://codereview.stackexchange.com/questions/30714/converting-datatable-to-list-of-class

            try
            {
                List list = new List();

                T obj = new T();

                foreach (var prop in obj.GetType().GetProperties())
                {
                    try
                    {
                        PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
                        propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
                    }
                    catch
                    {
                        continue;
                    }
                }

                return obj;
            }
            catch
            {
                return null;
            }
        }


        public static List DataRowArrayToList(this DataRow[] dataRowArray) where T : class, new()
        {
            //Variant of DataTableToList code from: https://codereview.stackexchange.com/questions/30714/converting-datatable-to-list-of-class

            try
            {
                List list = new List();

                foreach (var row in dataRowArray.AsEnumerable())
                {
                    T obj = new T();

                    foreach (var prop in obj.GetType().GetProperties())
                    {
                        try
                        {
                            PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
                            propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
                        }
                        catch
                        {
                            continue;
                        }
                    }

                    list.Add(obj);
                }

                return list;
            }
            catch
            {
                return null;
            }
        }

    } 
}



You can also find him on Twitter, YouTube, and Google+











SQL Script to verify Dynamics GP GL batch control totals

$
0
0
By Steve Endow

I have a customer who is importing GL batches into Dynamics GP, and they explained that they a bug in their integration that is causing the batch control totals to be incorrect. So they may import 50 transactions into GP, but the batch control total will show 85 transactions.  I believe that this discrepancy is causing some issues.

So I quickly threw together this SQL query to check the number of GL transactions and JE totals and compare those numbers to the batch control totals in SY00500.

There are probably several different ways to accomplish this, but I happened to pull this version together in a few minutes using a CTE.


WITH glTotals (BACHNUMB, BatchCount, BatchTotal)
AS (
SELECT glh.BACHNUMB, COUNT(glh.JRNENTRY) AS BatchCount, SUM(dtGLTotals.JEAmount) AS BatchTotal FROM GL10000 glh
JOIN (SELECT JRNENTRY, SUM(DEBITAMT + CRDTAMNT) AS JEAmount FROM GL10001 GROUP BY JRNENTRY) AS dtGLTotals ON dtGLTotals.JRNENTRY = glh.JRNENTRY
GROUP BY glh.BACHNUMB
)

SELECT b.BACHNUMB, b.NUMOFTRX, b.BCHTOTAL, glTotals.BatchCount, glTotals.BatchTotal, 
CASE WHEN b.NUMOFTRX <> glTotals.BatchCount THEN 'Count Diff' ELSE '' END AS CountDiff, 
CASE WHEN b.BCHTOTAL <> glTotals.BatchTotal THEN 'Amount Diff' ELSE '' END AS AmountDiff 
FROM TWO..SY00500 b 
JOIN glTotals ON glTotals.BACHNUMB = b.BACHNUMB
WHERE b.BCHSOURC = 'GL_Normal' AND b.BACHNUMB LIKE 'TEST%'


Here's what the results look like:


If there is a discrepancy in the transaction count or the total amount, it will display a note in the CountDiff or the AmountDiff columns.

Next, I will likely need to write a SQL script that will correct the control totals in SY00500.



You can also find him on Twitter, YouTube, and Google+





SQL Trivia: Leading spaces on string field

$
0
0
By Steve Endow

I think I've been writing SQL statements since 1996.  Maybe I encountered this scenario many years ago, but completely forgot about it.  But I am pretty sure that since I have been working with GP over the last 13 years, I can't remember ever encountering it.

During the SmartConnect training class that I attended this week, the trainer, Mark Anderson, pointed out a situation where an extra space could accidentally make its way into a SQL statement in a SmartConnect map.  He explained that the leading space in the WHERE clause value would cause the query to return zero records.

Somehow, I don't think I've run into this problem--I just haven't made that particular typo.

Here's an example of what that might look like.  The first query has no leading space in the WHERE clause, but does have trailing spaces, and it retrieves one customer record.  But the second query adds a few spaces in front of the customer ID value in the WHERE clause, and that query returns zero records.


Most Dynamics GP application fields do not seem to allow leading spaces--the only exception I could find is the Note field/window.  Given this, it is unlikely that you would have a situation where Dynamics GP data would have a leading space and cause this scenario.

However, if you have integrations or reporting with custom queries, or queries that are concatenated through script or code, it's possible for a space to creep in.  In SmartConnect, this can occur when you are inserting a pre-defined data field name into a SQL statement, like this:

SELECT * FROM RM00101 WHERE CUSTNMBR = ' _CUSTOMERID'

When you drag the _CUSTOMERID source data field name into your SQL script, it can result in an extra space before the field name, causing the SQL statement to return zero records.

Since I can't remember having ever encountered this scenario, it isn't something I would think to look for.  It makes sense, but it wouldn't have been obvious to me.  I've become almost indifferent to trailing spaces, because they have no consequence with a typical GP SQL install, but leading spaces are definitely a gotcha.

I thought it was interesting, and a neat reminder about the mechanics of SQL Server.


You can also find him on Twitter, YouTube, and Google+




Musical Tribute: I Want My MVP

$
0
0
By Steve Endow

My colleague Andrew Dean and I have come up with a few wild ideas, mostly related to Dynamics GP development and customization.  The other day, he came up with a really, really wild idea.

I mentioned that MVP submissions were due at the end of March, so I had to finish up a few things in the next few weeks.

He said, "Why don't you make a video to the song Money for Nothing, but make it 'I Want My MVP'?"

That was one wild idea.  After I got over the surprise, I didn't know where to begin.  How does one make a music video, and how would I create the song?

With a little ingenuity, a friend who has a rock band, and some low budget guerrilla film making with my daughter, we pulled it together in 3 days.

Enjoy!




Lyrics

I want my MVP

I want my MVP

Now look at them users
That’s the way you do it
Getting help from those MVPs
That ain’t workin’ that’s the way you do it
Knowledge for nothin’ and your help for free

Now that ain’t workin’ that’s the way you do it
Lemme tell ya them users ain’t dumb
Maybe get an answer from the GP forums
Maybe get an answer from a GP blog

We gotta install all the latest patches
ERP software deliveries
We gotta move these big databases
We gotta write these SQL queries

See the busy worker with Excel and tons of numbers
Yeah buddy, no need to despair
That busy worker calls on the MVPs
That busy worker, he don’t need to care

We gotta install all the latest patches
ERP software deliveries
We gotta move these big databases
We gotta write these SQL queries

I shoulda learned to post a couple o’ questions
I shoulda learned to read some blogs
Look at that accountant, she’s got all the answers
Man accounting is so much fun
And he’s up there, what’s that? Reconciliations?
Bangin’ out reports like SQL wizardry
That ain’t workin that’s the way you do it
Get your knowledge for nothin’ get your help for free

We gotta install all the latest patches
ERP software deliveries
We gotta move these big databases
We gotta write these SQL queries

Now that ain’t workin’ that’s the way you do it
You get your help from an MVP
Now that ain’t workin’ that’s the way you do it
Knowledge for nothin’ and your help for free
Knowledge for nothin’ and help for free


Dynamics 365 Financials Training - Day 1

$
0
0
By Steve Endow

Today I attended the first day of the Dynamics 365 Financials training class organized by Liberty Grove.

http://libertygrove.com/services/training/dynamics-365-for-financials-training-ndpm/


Each day I'll try and share a few observations from the training, primarily from the perspective of Dynamics 365 Financials vs. Dynamics GP.

Overall, the training was excellent.  There was a lot of content covered in four hours, but the trainer, Kerry Rosvold, was able to get through all of the content while answering dozens of questions along the way.



Here are my observations from Day 1:

1. Beautiful user interface.  The Dynamics 365 user interface just looks fantastic.  The look, feel and visual cues are really impressive.  There are definitely elements to the UI design that aren't obvious or intuitive, and have some complexity that you have to figure out (like any complex application), but I think the design is gorgeous, and it's really amazing how much functionality they were able to put into a web client.

So much functionality is at your fingertips right on the home page, which is highly configurable.



Color bars tell you which activities need your attention.



There are some really nice charts and graphs available as KPIs.


You can press the Esc key to exit out of windows as an alternative to clicking the X button, and when you drill several levels down, I think you will find this very useful to get back out of windows.



2. Integrated global window search and list search. As a long time Dynamics GP user, the lack of global search has been a big gap that most people don't realize they need.  In Dynamics 365 Financials, you don't click through 5 menus and sub-menus and option buttons to open a window--you just type something into the search box to find it and then click once.  The Dynamics GP Web Client does have a global window and report search feature, but since most customers are still using the full GP client, they aren't able to use it.

Once you search for something and get a result list, you can click on a list of "facets" or categories based on object type to narrow down the results.


When you are viewing a list, you can also use a search box on those windows to find or filter results.


And some wildcard searches are case sensitive.



3. Lots of potential complexity managed behind the scenes.  When you create a new company in Financials, you can use a very simple wizard that will ask you just a few questions, and then setup the new company for you, creating lots of default options.  It looks really easy and simple.  But behind the scenes, there are hundreds of options being configured and defaulted.  This is good for customers who can get up and running with the default options.  But if you were to create a blank company and configure it from scratch, we saw a very brief glimpse of the dozens of windows that you would need to review and configure, and as a new user it looked a bit overwhelming.  Perhaps those very familiar with NAV can navigate through all of those windows manually, but it looks like the wizard is a great way to get up and running quickly.


4. All grids have native sorting and filtering.  This seems obvious in the context of Excel, but with Dynamics GP scrolling windows, this functionality is like science fiction.  The only current limitation with the grids is that you can't change the order of the columns.  It isn't known whether column sorting will be added in the future.



5. Default reports. You cannot currently modify or customize the default reports, like AP Aging, Purchase Order, etc.  Some reports let you specify options to control content, but apparently no options for layout changes at this time.  I don't know if there are plans for any type of Report Writer tool to customize reports, or if 3rd party reporting tools would be required.


6. Security.  Security appears to be pretty comprehensive, with Permission Sets that roll up into Roles.  This appears similar in concept to GP security, and has the same challenges that exist with any complex application.  Security will likely be a hassle, just like GP and other ERP apps, so I suspect FastPath will be offering solutions and services to assist.


7. Automatic save at the field level.  This is a big difference from GP.  In D365 Financials, after you tab off of a field, any changes are saved.  There are generally no "Save" buttons--you simply exit the window, which performs a "Save and Close".  If you make changes on a window, you can't cancel the changes or exit without saving.  There are pros and cons to this approach, but that's the design.


8. Intercompany.  At this time, Dynamics 365 Financials does not support Intercompany transactions.  This will be a critical limitation for Dynamics GP customers who have dozens of companies.


9. User and company licensing.  During training, we were told that a user can have (or have access to?) up to 10 companies.  I have many Dynamics GP customers with dozens of companies, and have a few customers with several hundred companies.  I don't know how the D365 Financials licensing will handle such customers.


10.  Number Series.  You can define multiple "Number Series" records with start dates, start numbers, and end numbers.  I thought this was really cool.  While it may not be heavily used by many customers, I think such flexibility is nice, and makes the system more powerful than GP.



11. Posting Groups. This functionality, by far, is one of the biggest differences in core functionality between Dynamics 365 Financials and Dynamics GP that we covered in the first day of training.  I suspect it's 80% wrapping your brain around how Posting Groups work and adjusting to how they are used, and 20% actual changes in how users will need to use the system.  In short, Posting Groups dictate which GL accounts are used for all transactions.  Users cannot open a transaction Distributions window and change GL accounts during transaction entry.  All GL posting accounts must be defined in advance as part a posting group.  Overall, I think this is a good feature, as it should reduce incorrect or invalid GL account postings.  But it does require a little more planning and setup than what we are used to in Dynamics GP.



12. Timeout.  The D365 Financials web site will "time out" after a period of inactivity, displaying a dialog to ask you if you want to resume.  This is reasonable and a best practice for several reasons, but for those who are used to leaving GP open and running all day, this will be very annoying.  Every time you come back from a meeting or get off of a 20 minute call, you'll need to "Resume" and potentially log back in and 'relaunch' the web application.


Overall, I think Dynamics 365 Financials is very impressive.  At the moment, there are some missing features that might prevent some customers from migrating to D365, but I think the product is looking very good.



You can also find him on Twitter, YouTube, and Google+





Dynamics GP vs. Dynamics 365 Financials: Do users really need access to transaction distributions?

$
0
0
By Steve Endow

In my last post on Dynamics 365 Financials training, I mentioned that in the first day, one difference I noticed was that D365 Financials does not allow access to transaction distributions during transaction entry, and that users cannot change distribution accounts directly on a transaction.  Dynamics 365 Financials (NAV) uses a different design involving "Posting Groups" that control the GL account assignments for transactions.

As someone who has worked with Dynamics GP for a long time, this seemed like a big difference to me.  In the GP world, Distributions are a pretty big deal.  When certain transactions are entered in GP, you often have to verify the distributions.  And some customers have processes that require users to change the distributions.

For example, some customers may manually code revenue accounts on a sales invoice, while other customers may code expense accounts on a vendor invoice.  In the GP world, Distributions are a thing, and they're an important thing.  When transactions fail to post, we sometimes ask customers to check the posting journal or Edit List to see if the distributions might have an issue.  When importing transactions using eConnect, I have to make sure that the correct distributions are imported.  We're so used to dealing with Distributions that it's second nature for us in the GP world.

After reading my blog post, Mariano Gomez asked a reasonable question:


I had the same reaction when the trainer explained the D365 Posting Groups and how they needed to be setup for all customers, vendors, and items so that accounts could flow through to transactions.  It sounded complicated.  This is the actual question I asked the trainer:

Is the setup of posting groups tedious & time consuming for customers? It seems like a lot more work to setup in advance than what a GP customer would be used to.

She explained that for most customers, the setup is not too difficult or complex.  As long as the customer doesn't have a ton of revenue or expense accounts, and as long as they don't have many different AR and AP accounts, the setup of Posting Groups not difficult.  She really knows her stuff, so I trust her.

So perhaps addressing the underlying point of both Mariano's question and my question: What is the benefit of the Posting Groups, which appear more complex?

After just one day of training on D365 Financials, I'm far from an expert, but my interpretation is that the Posting Groups allow you to configure the system to default the posting accounts, similar to GP, but for every situation and scenario.  The design of the Posting Groups apparently allows the system to handle different scenarios that could not otherwise be handled by a single default account.

For some companies, GP account defaults may easily handle all scenarios, but for other companies with more complex business models, GP default accounts don't cover every situation with a vendor or customer, and a user must manually enter or change a transaction distribution.

So why are Posting Groups beneficial rather than a complex hassle?  My interpretation is that it is beneficial for a system to automate the GL account assignment for transactions 100% of the time.  If the system can fully automate the process, why would you ever want a user to have to do it?  If that takes a few more hours during implementation, I'd say it's worth it if you can eliminate the Distribution window.  Stop wasting a single second selecting GL accounts at the transaction level while avoiding incorrect posting accounts on transactions.

Let go of distributions completely.  Think of Distributions as a burden rather than a benefit.

That's my positive spin on what I saw today.  If you eliminate the Distribution window that we're used to in GP, the ERP system needs to have a comprehensive process of defaulting GL accounts on transactions.  Dynamics 365 Financials adopted NAV, which uses the concept of Posting Groups to address that need.

If it seems complex or burdensome or like it will be a hassle or restrictive, I then consider the estimated number of NAV customers.  My thought is that if it works okay for over 110,000 companies with a far broader geographic distribution than Dynamics GP, it must be a viable solution.  With training and some experience implementing D365 and configuring Posting Groups, I expect it to be no more complex than setting up all of the default GL accounts that are scattered throughout GP.

Is it different than GP?  Absolutely.  Is that a bad thing?  Not necessarily.  I think that the little bit of extra setup time up front can provide significant benefits long term.  And I would personally be perfectly happy if I never had to directly interact with Distribution records ever again.

Before I get beat up for this Dynamics GP heresy, nay, this GP blasphemy!, I will preemptively offer the counterpoint: Are there some downsides to not having a Distribution window?

ABSOLUTELY.  Not having access to transaction distributions can be a royal pain in the butt for some unique businesses and some unusual business processes.

I know this because it was a nightmare for me to develop a customization for a NetSuite customer that needed to automatically change GL accounts at the transaction level.  That cannot be done in NetSuite, because there are no distributions.  And that is frustrating and limiting and annoying.  So I've been in the trenches in that scenario as well.

Once I learn a lot more about D365 Posting Groups and GL account assignments on transactions, I will be happy to wage war on the anti-Distribution argument in support of the Dynamics GP Distribution window.  Until then, I'm giving D365 the benefit of the doubt.


Steve Endow is a Microsoft MVP for Dynamics GP and a Dynamics GP Certified IT Professional in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter, YouTube, and Google+





Dynamics 365 Financials Training - Day 2

$
0
0
By Steve Endow

Today I attended day 2 of the Dynamics 365 Financials training class organized by Liberty Grove.

http://libertygrove.com/services/training/dynamics-365-for-financials-training-ndpm/


Training day 2 summary: Brain overload

Here are my observations from Day 2:

1.  UI updates.  The user interface is nice, but the web interface does have a few minor quirks.  Sometimes the web site is very responsive, sometimes it pauses or lags when you perform an action, and other times there are multi-second delays.  And the responsiveness varies by user.  My UI was generally very responsive, but the instructor has had several 10-15 second delays on steps where I had no delay.  The inconsistency is strange, but I'm guessing Microsoft is doing tuning on the back end.

A few additional UI observations.

When you have multiple 'windows' open, you can only see the one on top.  You can click the X in the upper right to close the top window, or you can press the Esc key to close it.  Today I found that you can click anywhere on the gray bar on the left to close the top window.  So if you are a keyboard person, you can use Esc. If you are a mouse person, it's quicker and easier to click the gray bar than click on the X.  I am finding the gray bar to be the most convenient, as you can easily click multiple times to close several windows.


As I mentioned in my Day 1 notes, Dynamics 365 Financials saves data at the field level as soon as you tab off of a field.  When it is performing the save, you will sometimes see two arrows next to the field, indicating that the save is in progress.  Sometimes it saves so quickly you never see this symbol, while other times it takes a few seconds, and you will clearly see the arrows.  Sometimes you can move on to other fields during the save, while on other windows you may have to wait for it to save and refresh before you can move on.



2. Dimensions.  This is a big one.  Perhaps even bigger than posting groups.  For those in the GP world, you will have to open your mind, clear your thoughts about how GP works, and be receptive to a completely different design philosophy around how a chart of accounts and GL is designed.

With only a few hours of exposure to Dimensions so far, I am still trying to fully understand it, and I can't possibly cover it completely, but I'll try and describe it as best I can.  I intentionally don't want to compare the Dynamics 365 Financials Dimension feature to any GP features because I don't want you to make assumptions about how they work or what they are "like" in GP.  There are two obvious features in GP that you will likely compare this to, but for the time being, just assume there is no equivalent in GP and don't try and compare it directly to any GP features.

Imagine a pretty typical Dynamics GP "segmented" GL account structure.  The sample accounts aren't the best, but for convenience, let's use Fabrikam as an example: Division - Natural Account - Department with 3-4-2 account segment sizes.  This is a fairly conventional GL account design used by many systems.

Dynamics 365 Financials (NAV) takes a different approach to GL accounts.  The GL account is only the natural account segment.  Period.  The other segments are handled through Dimensions. So rather than using a full account string of 200-6170-00 for Repairs & Maintenance - Accounting, you would just have a natural account of 6170 in your GL COA.  That's it.  No segmented account string--just a single natural GL account.

This means that you can simplify your COA, as it only contains the natural account list, and you do not have to worry about all of the division and department permutations in the account list.

Now that you have your simple and clean COA, you can then separately define Dimensions to handle your Divisions and Departments, and anything else you need to track.  And when you define the Dimensions and Dimension Values, you can use alphanumeric labels instead of just the traditional numbers.  (Yes, GP can have alpha characters in the GL, but let's not go there...)


So I can create a dimension called Division, with Dimension Values of Administration, Accounting, Sales, Service, Consulting, etc.  And I can create a dimension called Department with whatever label values I want.


Once I have my Dimensions setup, I can then assign the Dimensions to customers, vendors, and items, and also specify a default value for each master record if desired.  Here I have assigned a Customer Group and Department to a customer record.


The idea is that when I enter a sales order, the order header can have one or more Dimensions default based on the Customer, while the order lines can have other Dimensions default based on the item.

I can also go into my GL accounts, and for each natural account, I can specify whether dimensions are required when that GL account is used.

This is a very fundamental feature of D365 Financials that will require quite a bit more time for me to learn and understand, but hopefully that at least described the concept.


3. Financial, Sales, and Purchasing Setup.  This was relatively straightforward, but there were a few things of note.

First, the GL setup window is where you control the valid posting dates.  Unlike Dynamics GP, where you open and close pre-defined fiscal periods, D365 Financials allows you to specify a date range that can be used for posting.



This seems like an interesting idea, as it lets you specify a range that might be slightly different than your fiscal period.  Say you wanted to allow posting to the last day of the prior month during closing.  Rather than keep the entire prior period open, you could set a date range of 2/28 to 3/31.  I suppose you could even set it from 2/28 to 3/15 to limit incorrect postings to future days of the month.

In addition to this flexibility, you can apparently specify different allowed posting dates at the USER level.  So the main GL Setup window could have allowed posting dates of 3/1 to 3/31 to limit most users, while just 2 people in accounting could have allowed posting dates of 2/26 - 3/31 so that they can post some final entries to the prior period during closing.  Seems like a neat idea.


Payment terms were surprisingly simple.  Given some of the other features of the application, I expected it to have a few of the fancier payment terms options or more configurability, but it's very basic.  I've had customers with odd payment terms, such as paying by the 5th of the month, and the current D365 terms won't handle those scenarios.



The Inventory Setup window raised some red flags for me.  There are only four options on the main Inventory Setup window, and not very many options at the Item level.


At the moment, D365 Financials apparently only supports FIFO valuation.  According to this forum post, average costing should be coming next, and BOMs were recently added.


4.  Financial Reporting.  D365 Financials has a relatively new financial reporting tool called "Account Schedules".  I don't know where the name came from, but it looks like a basic standard Row / Column style financial reporting tool.


Because it is new in NAV as well, adoption may be limited at this point.  I was told that the predominant financial reporting tool in NAV is JetReports, with the Account Schedules potentially being a distant second, and PowerBI having a small role.

I suspect that the Account Schedules reports may have some limitations, but the benefit appears to be the full integration of the reporting tool throughout D365.  You can easily modify, view, print, schedule, and drill down in the reports in D365.  It appears very seamless.


And those are the highlights from Day 2.



You can also find him on Twitter, YouTube, and Google+





Dynamics 365 Financials Training - Day 3 - Payables and Inventory

$
0
0
By Steve Endow

Today I attended day 3 of the Dynamics 365 Financials training class organized by Liberty Grove.

http://libertygrove.com/services/training/dynamics-365-for-financials-training-ndpm/


While I'm starting to get a little more familiar with the UI and navigation, there are a lot of nooks and crannies in Dynamics 365 Financials and very different names and concepts, so the training still seems very fast paced as I try and digest all of the new material.

Here are some observations from Day 3.

1. UI updates.

Menus are dead. Other than the few 'area page' links/buttons you can access from your Role Center (home page), there aren't really any menus in the application.  You interact with actions on your Role Center, the Ribbon above a window, or use the Global Search feature to locate things.




The Save button is dead.  I don't think I've seen a Save button anywhere. Maybe there are a few hidden on an option window, but for nearly all windows, there is no save button.  It is WEIRD.  My entire life, I have been trained to click a button to save my work as I go, to save before I close, to save before I exit a window to work on something else.  I constantly find myself trying to find and click a save button before I close a window--it feels very unnatural.  But it's also a demonstration of a better software design--why should I have to constantly save to avoid losing my work?  The only minor downside is that sometimes you may want to check something, and you can't exit a window without saving changes.  So if you accidentally make a change without realizing it, it gets committed.

In the grids, you cannot currently resize the columns.  Several times today I found this annoying.  Sometimes the columns are too narrow for the data value, and sometimes they are too narrow for the column header label, and it's a hassle to try and figure out what is in the cell or what the label says.

Column label is not fully visible:


Data in a row is truncated:


On many grids, there are often columns that are not displayed.  Many times these are important or required fields, but unless you know that you need to populate them, you won't even realize they are hidden.  Once you change the displayed columns, I believe that the grid will save your preferred fields and display them the next time you open the window, but there are a lot of grids, so you have to constantly check the available columns to see if you are missing anything.



In Dynamics GP, the scrolling window columns can't be resized, and you can't even pick which fields are displayed, but GP always displays the key fields and also has multi-line rows.  And in GP, you often times have a line detail window that gives you a full window for entering additional information on a line.

If you have a grid with many rows and you need to delete several of the rows, it's fairly tedious.  You have to click on the row, click on the "..." button, wait for the context menu to appear, click Delete, and then wait for the operation to complete and the window to refresh.  For 1 or 2 lines, it's okay, but deleting 10 or more rows is painfully tedious.  I think some grids could benefit from a multi-select feature.


In many windows, there is a "Show More" / "Show Less" link that expands or hides extra fields that were apparently deemed less important or less used.  This can be frustrating for new users like me, as I don't realize that the fields are hidden, and I spend 30 seconds trying to figure out why I can't see the fields.  I eventually realize they are hidden and click on Show More.



I suppose this is similar to GP detail windows or expansion windows.  You need to know that the field exists and know to click on the blue arrow to enter the additional information or change a field value.


2. Reports.

It was noted during the training that D365 Financials does not currently have the ability to print a report directly to a printer.  Apparently they are working on that.  I recently saw a blog post indicating that the NAV web client has the same limitation, and people are trying to work around it by using cloud based printing services (which makes me wary--sending your financial reports over the internet to a third party service to send it to your internal printer?).

I personally didn't expect the web based ERP system to be able to print to printer.  Displaying the report as a PDF first, and then having the user print the PDF seems pretty straightforward to me, but I can imagine this might be annoying for some customers who are used to different methods.


Note that with these file output options, there is no option to view these reports directly in the browser as an "on screen" report.  You currently always have to open a file to view a report.

The report generation is usually pretty fast, with the browser prompting you to open or save the file.



2. Payables

Templates. When you create a new vendor, you are prompted to choose a vendor template, which can default values for you and make the vendor setup more consistent.  This is similar to a Dynamics GP Vendor Class.  The templates can be setup for vendors, customers, and items.




No equivalent to Dynamics GP PM Vouchers.   This is kind of weird with D365 Financials.  It may change in the future, but at the moment, there is apparently no equivalent to a Dynamics GP PM Voucher.  Full NAV apparently does have a voucher-like entry process, but D365 Financials doesn't at the moment.

In D365, you either enter a full purchase invoice, with line items (or base a purchase invoice on a PO), or you enter a strange transaction called a "Purchase Journal".

Some customers may be fine entering line items for AP invoices, but every line must use a pre-defined Item. You can't enter a free form one-time item like "Pizza Delivery".  The Items must be setup as inventory items or service items in advance, and must be tied to posting groups (GL accounts and dimensions, etc.).  So we discussed during class that this will likely not work too well with many AP departments, as it would require them to potentially setup and maintain dozens of Item records.

The alternative is the Purchase Journal, which I can only describe as a sub-ledger journal entry.


It is a very sparse window with only a grid where you enter a journal entry like transaction.  The transaction can be tied to vendors, so it does hit the sub-ledger, and it also has posting groups / GL accounts, so it hits the GL as well.  But it just seems odd, and I personally have a harder time performing data entry in such a large grid than a traditional window--in part because I just don't know the fields well enough to know what I'm entering.  And each line of the Posting Journal can do very different things, so it seems like a much less controlled entry process.  With my current limited knowledge of Purchase Journals, I would have a hard time recommending it to customers that are used to a more formal transaction entry window like the Payables Transaction Entry window in GP.


3. Inventory.

We only briefly touched on Inventory today by looking at what are supposedly called "Inventory Adjustments" in Dynamics 365 Financials.  Those quotation marks are there for a reason, as I can only assume that this is a very temporary measure until the Inventory module is more fully developed in D365.

Here's the process, which I think you'll see is a bit lacking.

Open an item.


Click on the arrow next to the Quantity On Hand field.


And just start changing numbers.


No transaction window.  No notes, no descriptions, nada.  Just change numbers, click OK, and viola, your inventory quantities have changed, and the GL has been updated with the inventory valuation adjustment.

The changes are tracked as "Ledger Entries" that you can view, but there is no visibility of who made the changes or why.


Like I said, I assume that this is just a temporary process until the Inventory module is more fully developed and proper transactions can be entered in dedicated windows.


Inventory Items. Based on a quick glance at the current Item Card (shown above), I don't see any fields for bins or lot or serial tracking.  There is support for "Item Attributes", such as dimensions, color, size, etc., but those are at the Item Card level, so I don't think they could be used to support bins, lots, or serial numbers.



And that's a wrap for Day 3!


You can also find him on Twitter, YouTube, and Google+







Dynamics 365 Financials vs. Dynamics GP: Payment Terms

$
0
0
By Steve Endow

In my post yesterday summarizing my Day 2 training, I said that the D365 Financials Payment Terms window looked disappointingly simple, as I expected it to be more configurable.

Well, it turns out that it is quite a bit more configurable than I thought based on my first glance, but you wouldn't realize it unless you knew about the Secret Codes.


What are the Secret Codes, and why exactly are they secret?  Good questions.

First, they are secret because they are apparently not documented yet.  The D365 Financials help web pages do not currently have any reference to Payment Terms.  And they are Secret Codes because unless you know what they are and how to use them, you would never know that they exist, or that you could wield their power in the Payment Terms window.

So...



At first glance, the Payment Terms window looks really basic.  Code, Due Date code, Discount Date code, Discount Percent, and Description.  Very simple and standard looking.

But notice the column headers:  "Due Date Calculation" and "Discount Date Calculation"

Instead of just having "30D" for 30 Days, there are codes you can use to setup some unusual payment terms.

Let's say you need to pay 3 days before the end of each month.  You would use a Due Date Calculation of CM-3D.  CM means Current Month, and -3D means subtract 3 days.  So CM-3D means 3 days before the end of the current month.

CM+1D apparently means the beginning of the next month.

10D means 10 days from today, while D10 means the 10th day of the month.

D = Days
W = Weeks
M = Months
Q = Quarters
Y = Years
CW = Current Week
CM = Current Month


It's an unusual type of date math, so it will take some new thinking to use it properly, but it looks pretty powerful and flexible.

It is apparently based on the NAV "Date Formulas" feature, which is discussed on this MSDN page.

So how does this compare to Dynamics GP payment terms?  It looks like the current GP Payment Terms window is fairly good, but is different.


GP seems to have a few more options, such as calculating due date based on Transaction Date or Discount Date, and having a separate configuration for Discounts.  Very few (maybe one?) of the customers I have worked with actually use terms discounts, but for customers that take advantage of discounts, this may be valuable.  I'm pretty sure most of the customers I have worked with just ignore vendor terms and pay Net 60, Net 90, or Net 120 for cash flow purposes.

Dynamics GP also has options to calculate the discount on Sale/Purchase, Discount, Freight, Misc and Tax, which I am not seeing in D365.

It's been years since I helped a customer setup anything other than the typical Net 30 / Net 45 / Net 60 payment terms, so I don't have any unusual scenarios to offer.  If you have come across any weird ones, let me know if either the D365 or GP Payment Terms window will handle them.


Steve Endow is a Microsoft MVP for Dynamics GP and a Dynamics GP Certified IT Professional in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter, YouTube, and Google+





Updating Email File Formats in SQL

$
0
0
The best laid plans...  Word templates are not my favorite thing.  There I said it.  It is not because I don't think are pretty and functional and allow for more flexibility than report writer reports.  It's just that they can be time consuming in a way that clients don't expect.  Modifications that might be worth 1-2 hours of effort end up taking double or triple due to the quirks of word templates. 


I have found that this disconnect happens most frequently with clients who already have modified report writer reports.  The process to recreate a word template that looks like the report writer report can be challenging and time consuming.  So in those cases, I try to use HTML for email delivery.  That way clients can keep using the report writer report, and the cost to implement email delivery can be quite low.


Sometimes, though, you get stuck.  HTML doesn't work well with complicated layouts, and can be unpredictable in terms of how it displays for different recipients.  So then we have to use the word templates and send in PDF.  This is fine, except if you have already set up customers for emailing.  So now you have to change the format in Cards-Sales-Customer-Email Settings.

For that purpose, you can use the script below.  Keep in mind that EmailDocumentID (in this case it is set to Sales Invoice) and EmailSeriesID (in this case it is set to Sales)  would vary for different modules and documents.  The EmailDocumentFormat is the field you want to update.  It is the same as the dropdown (1-docx, 2-html, 3-pdf, 4-xps).

--Update sales invoice email settings for all customers to use PDF
update SY04905 set EmailDocumentFormat=3 where EMAILSeriesID=3 and EmailDocumentID=3 and MODULE1=11 and EmailDocumentEnabled=1

As always, test first and always back up your data!

Christina Phillips is a Microsoft Certified Trainer and Dynamics GP Certified Professional. She is a director with BKD Technologies, providing training, support, and project management services to new and existing Microsoft Dynamics customers. This blog represents her views only, not those of her employer.

Back to Basics: Purchase Order Posting Flow

$
0
0
Sometimes it helps to just get back to the basics of how things flow in GP.  And a client question this week gave me an opportunity this week to do just that.  To understand how purchase order processing works in Dynamics GP, a basic posting flow is helpful to illustrate where accounts come from.


It lays out the source of transactions and the corresponding default account locations. Hope you all find this useful!

Christina Phillips is a Microsoft Certified Trainer and Dynamics GP Certified Professional. She is a director with BKD Technologies, providing training, support, and project management services to new and existing Microsoft Dynamics customers. This blog represents her views only, not those of her employer.

Dynamics 365 Financials Training - Day 4: Sales, Bank Rec, and GL

$
0
0
By Steve Endow

Today I attended day 4 of the Dynamics 365 Financials training class organized by Liberty Grove.

http://libertygrove.com/services/training/dynamics-365-for-financials-training-ndpm/


Here are links to my summaries of the prior days of the class:

Day 1 - Navigation, Company Setup, and Posting Groups

Day 2 - Dimensions, more Setup, and Financial Reporting

Day 3 - Payables and Inventory


Day 4 covered a lot of content and I found several items that I think are important to note, so this will be a long one.

And on a side note, I think I'm going to organize a contest to come up with some good abbreviations for the D365 products, since constantly typing out Dynamics 365 Financials gets old.  And I'm obviously not the only one with this issue:


I may use D365Fin or D3Fin or maybe even D3F eventually, but for now I've setup a keyboard shortcut in my FastKeys app that will automatically replace "d3" with "D365 Financials" as I type it.

And with that, let's get started.




1. UI Updates.

As we worked through more exercises and were exposed to more windows and record types, I sensed the navigation in D365 Financials can sometimes get long, a little winding, and even circular.  This is noticeable for me probably 90% due to the fact that the user interface and functionality is all new, making it seem more complex than it is.  But I do think there are some valid navigation paths where you may want a compass and breadcrumbs to keep from getting lost.

I suspect that there are a few places in GP where drilling into inquiry windows and GoTo windows can have a similar result, but in GP, you usually hit a dead end after 3-4 windows.

Here is a small example of what I would consider a 'longer' D365 Financials navigation.  There may be a more direct way to do this, but I believe this example actually came up during the class.

Let's say I'm currently logged in under the Accountant role.  Notice the word "Accountant" above the company name.


Notice that the home page for this role doesn't list anything related to Inventory or Items.  So I need to search for Items.  Easy enough.


Once you open an Inventory Item, click on the Navigate "ribbon group" -> Entries -> Ledger Entries.


You can then select an Item Ledger Entry and click Navigate.


You are then presented with a list of "Related Entries".


You can then click on the G/L Entry row and click on Show Related Entries in the ribbon, which takes you to GL Entries for account 50100 Cost of Materials.


From the GP user perspective, this is quite a bit of drilling around to see a GL entry.  As always, there are likely one or two completely different paths that may be shorter, but I think this is an interesting demonstration of the different terms used by D365 Financials navigation and how it may seem more complex to a GP user who first encounters the software.

But wait! If you want to entertain yourself, you can click on the Navigate button again.  Which brings you to right back to Document PS-CR104001.  Where you can click on G/L Entry again! Then click on Show Related Entries again!  Which takes you to the GL Entries yet again!  It's an interesting user interface where it seems you can go in an infinite loop of Navigation and Related Entities.

Seriously though, it's great to have the ability to drill into and through records and activity, but from a GP user perspective, the amount of information available through the navigation will likely be a bit confusing and overwhelming at first.

And if you were to throw in a really tight security policy, I suppose that could complicate things.  Suppose my role let me navigate half way through this process, but then prevented me from seeing some windows.  I might call IT or my D365 Financials partner and ask "Why can't I see X?"  That scenario might be tedious to figure out.


2. Cool Lookups.  I officially dub this feature:  "Cool Lookups"

I think this is a great feature of D365 Financials.  It will take some initial setup to populate the lookup tables, but hopefully it is possible to create lists of valid data (USPS zip code lists?) that can be imported.

Let's say that you're entering a customer.  Instead of having to type in the city, state, and zip, what if you skipped entering the city and state, and were to just type the first 2 or 3 numbers of the zip code?  Like, say, "606".


A window appears showing you a list of valid zip codes for Chicago IL.  And when you select the zip code, the City, State, and Zip code fields are populated.


Boom. Mic drop.

Those in the GP world should be familiar with Rockton SmartFill.  This is kinda-sorta similar, but D365 Financials kicks it up a notch by making both City and Zip code lookup fields, and then having the user selection populate all three fields: City, State, and Zip.

You can do the same with the City field, where you are presented with a list of Zip codes in that city.


I think this is a great feature--it makes address data entry faster and more accurate.


3. Master records and Contact records.  The concept of D365 Financials master records and related contact records makes sense in theory, but in practice, setting up contact records correctly is confusing at first, and somewhat tedious and cumbersome.  I, and a few other students, got tripped up on this feature, so it's worth spending some time making sure you understand how D365 Financials behaves when you assign a Contact to a master record.

Let's start by discussing how Dynamics GP stores master records and contact records.  In GP, you have a Customer record, and then you have a 'main' Address IDs associated with the customer record.  The address ID consists of an alpha ID, such as the word PRIMARY, and contact info, such as contact name, address, phone, etc.  The main address ID, or different address Customer Address IDs can be designated as the Primary Ship To, Bill To, and Statement addresses.

The object model would look something like this.



D365 Financials has a different model.

A Customer record has an address, but it does not appear to be a separate object or record--the address is just the main customer address--fields for the Customer record.

You then create a Company Contact record type that is associated with the Customer.  Once you have a Company Contact setup for the Customer, you then create Person Contact records that are children of the Company Contact record.  I believe the object model looks something like this.


While I think I understand this object model, I don't have enough experience with D365 Financials to know how it works or is really used in practice.  For example, what is the value of having separate Company and Person contact types associated with a customer?  Are those contact types used in different ways throughout the system?  Are there specific benefits of separate Person contacts, instead of just having a "Contact" name field on an address ID?

I could see the potential benefit if D365 Financials eventually gets a Common Data Model with D365 CRM--this model might be a better fit for sharing data between those two systems.  But I don't know how CRM stores such records, so I don't know if such a benefit exists.

For now, I'll just note that the D365 Financials design is different than GP, and that you'll want to be aware of that difference.

In terms of creating the Contact records, that is a bit confusing for new users.  When you create a new customer in D365 Financials, you'll get to the Primary Contact Code.  You'll want to be careful at this point.


You'll click on the ellipsis button and a Contact List lookup window will appear.


Note that a new Contact number will be displayed in this lookup window, and that the Contact Number is in bold text.  This is a key distinction.

When you create a new Customer record and click on the Primary Contact Code lookup button, D365 Financials automatically creates a Company Contact record, and Company Contacts will show up in bold text.  But, by default, the Company Contact record is completely empty.  Even though you just entered the company address on the Customer window, this new Company Contact record is blank.  Nothing is copied to the Company Contact. Hopefully a future version will let you copy or default the values from the Customer record.

Because the Company Contact record is blank, you'll want to first edit it to enter the customer address information.  So you will click on the Edit button in the ribbon.  This is where I got confused.


It assigns a Contact Card number to the record, and you see that value in both the "No." field and the "Company No." field.

Wait a minute, didn't we already have a Customer Number of C00070 assigned to our customer?  Why is this Contact Card saying the Company Number is CT000044?

Well, look back at my diagram of the D365 Financials Customer object model.  Note that a Customer is different than a Company Contact.  Those are two different objects.

So I now have to re-enter the Customer address & contact information on the Company Contact card.  A Copy button on this window would be nice.


Now that I have my CT000044 Company Contact record setup, I can close the contact card and return to the Contact List lookup window.


Notice that the bold Company Contact record now displays the customer information.  You can now click on OK to assign that Company Contact record to the Customer.


But notice that right below Primary Contact Code, there is a Contact Name field.  That Contact Name field is a link to a Person Contact record.  If I click on the lookup button next to the Contact Name field, I get the same Contact List window.


Since I only have one record listed, and it's a bold Company Contact, I now have to create a Person Contact record.  So I make sure that the Company Contact record is selected, then click on the New button.

Wait, that's not right.  Hmmm, that just creates a new Company Contact record.  Let me pull up my notes from class.  Ah, yes, I see that there is a 7 step process for creating a Person Contact that is associated with a Company Contact that is associated with a Customer.  Hey, only 7 steps!  I don't think it's just me--I think this process could be simplified.

So, getting back on track, to create a Person Contact, you actually have to edit the existing Company Contact.  So from the Contact List lookup window, you highlight the Company Contact record and click on Edit.


Once I'm editing the Company Contact record, I need to click on Navigate, then click on Related Contacts.  Pretty obvious, right?

Now I get a Contact List window that looks pretty much exactly the same as the Contact List window I just came from.  But apparently it's different. Somehow. I can't tell how, but just trust me.


Now that you are in this Contact List window, NOW you can click on the New button.  Yes, I promise.  When the new Contact window opens and you tab past the No field, a new Contact Number will be populated, and the Company No field will be filled with the "parent" Company Contact number value.  If this is a bit confusing, you are not alone.  It took me at least 3 tries to understand this process, and even then, I just got it wrong and had to review my notes.


The key fields to watch here are No, Type, and Company No.  The Company No field value must automatically populate with the Company Contact number value, and the Type here should be person.  If the values are different, you've done something wrong.

And notice that finally, an address is populated automatically for the Person Contact record.  Small victories.  Once you are done with the Person Contact, you can close that window and you'll see the new Person Contact under the Company Contact.


That's great, but remember you are still a few windows deep in the UI and need to crawl back to your Customer record so that you can actually assign your Person Contact record to your Customer.

So you then close the Related Contacts list, which takes you back to the Company Contact window, which you then close.  This takes you back to an identical looking Contact List, which will now show your Person Contact, which you can then select, and click OK.

You'll know you're getting close when you see the Customer record and Contact Name field behind your Contact List.


So after all of that work, you have finally populated the second Contact field with a name.


 This seems a bit overwrought just for a Contact Name, so I'm hoping that there is some simpler process for this.

I'm okay with the concept of the D365 Financials customer / contact object model, but unless I'm missing something, I am not a fan of how a Customer and the associated Contact records are entered.  It seems too cumbersome, and I would guess that a majority of the Contact records could simply be copied based on the data on the Customer record.  In the GP world, I don't see too many customers really utilizing the separate Company Contact and multiple Person Contacts for a customer, so I'm interested in learning more about how these records are used elsewhere in D365 Financials.


Lots of Other Items to Discuss

There are several other things I'd like to cover, but since this post is so long, I'm going to end Day 4 here and will write separate posts for the other D365 Financials topics I'd like to cover.

I hope you found this post interesting, educational, or useful.


Steve Endow is a Microsoft MVP for Dynamics GP and a Dynamics GP Certified IT Professional in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter, YouTube, and Google+








Bug in GP ribbon buttons when AA is installed

$
0
0
By Steve Endow

Today I was doing some testing in GP 2016 R2, where I have Analytical Accounting installed, reviewing some imported AP Invoices.  I opened the invoice, clicked on Distributions, and then moved my mouse up to the ribbon to click on the Default button.

But...the Default button wasn't in the ribbon.


I only had View, Additional, File, and Tools buttons in the ribbon.  I was puzzled for a few seconds until I noticed the Delete and Default buttons were at the bottom of the window.



I could have sworn that I've clicked on the Default button in the ribbon, so this seemed odd.  I thought that maybe the buttons were different depending on the "Window Command Display" option selected in User Preferences.


So I changed from Action Pane to Action Pane Strip, closed GP, and then relaunched GP.

Well look at that--the buttons are now in the "Action Pane Strip".


Curious, I then switched back to the Action Pane and closed and relaunched GP.  And behold, the Delete and Default buttons were now visible in the ribbon.  Starting to look like a bug.


I thought that maybe the setting had gone wacky and resetting it under User Preferences resolved the issue.

But then 5 minutes later, the issue came back again.


I can now reproduce the issue on demand.  After launching GP, the first time I open the Payables Transaction Entry Distribution window, the buttons are all present on the ribbon.  But the next time the Distribution window is opened, the Delete and Default buttons move down to the bottom of the window.  If I close and relaunch GP, it fixes it again only the first time the Distribution window is opened.

I wasn't sure if this was a bug in 2016 R2, or if it was related to having Analytical Accounting installed.  But I also have GP 2015 R2 installed on my AA server, and sure enough, the same issue occurs in GP 2015 with AA.

This is GP 2015 R2 with AA installed, and you can see the issue occurs with the "Action Pane Strip" option, so it isn't just with the full size Action Pane option.


This isn't a big deal, but it is a bit confusing when you first encounter it.



You can also find him on Twitter, YouTube, and Google+









Importing Paid AP Invoices into Dynamics GP: Payment Numbers and Distributions

$
0
0
By Steve Endow

I recently developed a Dynamics GP import that created AP Invoices for employee expenses.  One thing that was different with this integration was that some of the employee expenses had already been reimbursed or paid, either with cash or by credit card.

It seemed pretty straightforward at first, but while designing the integration, I learned two interesting things.  When importing Paid AP Invoices into Dynamics GP using eConnect, you'll want to pay attention to the Payment Numbers and Distributions, as they will vary depending on whether the invoice was paid with Cash, Check, or Credit Card.

When importing an AP Invoice paid via Credit Card, on the Payables Credit Card Entry window, the Payment Number field should be populated with the next AP Voucher Number, not the next AP Payment Number.  And the Credit distribution for an invoice paid with a Credit Card should be Type of Cash, with the GL account being the AP account from the Credit Card vendor (my customer uses a different AP account for their Credit Card vendor).

Here's a video sharing what I learned about the proper values for Payment Numbers and Distributions when importing the paid invoices using eConnect:

https://www.youtube.com/watch?v=_DTK_jdzT1Y



Steve Endow is a Microsoft MVP for Dynamics GP and a Dynamics GP Certified IT Professional in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter, YouTube, and Google+

http://www.precipioservices.com



Enhancing the reliability of complex Dynamics GP integrations

$
0
0
By Steve Endow

I had a call today with a customer who is implementing several complex Dynamics GP integrations.  One of the integrations involves the following steps:

1. A SmartConnect map imports a large AP Invoice batch once per day
2. Once the batch is fully imported, SmartConnect inserts a database record telling Post Master Enterprise that the batch is ready to post
3. Post Master Enterprise posts the AP Invoice batch
4. Once the batch is finished posting, Post Master Enterprise automatically fires a stored procedure where the customer will have custom SQL script
5. The stored procedure will verify the batch posted successfully and then call a SQL command to trigger a second SmartConnect map
6. SmartConnect will then import AP Manual Payments and apply the payments to the posted AP Invoice batch
7. Once SmartConnect is done importing the Payments and Applications, it will then insert another database record telling Post Master to post the AP Manual Payment batch

In theory, this process will work just fine, as both SmartConnect and Post Master can be configured to work together to coordinate in this manner.

But...

In any system integration with many steps or processes, there is a chance that one of the steps may not work properly, may encounter an error, may fail, may not fire, etc.

And in any system integration that is synchronous and tightly coupled like this one, any such problem in the chain of events can prevent the rest of the process from completing.  What if in Step 2, the SmartConnect map has a problem telling Post Master that the batch is ready to post?  What if in Step 3, Post Master finds that the Fiscal Period in Dynamics GP is closed, and it is unable to post the batch?  What if the batch fails to post due to a data error?  What if 682 out of 700 Invoices post successfully, but 18 fail to post due to invalid distributions? What if the custom SQL script in Step 4 encounters an error or table lock that prevents it from completing successfully?  What if SmartConnect encounters an error applying the Manual Payments to the posted Invoices?

In isolation, each of these issues is relatively small, but collectively, there are probably at least a dozen such minor problems that could potentially prevent the entire sequence from completing successfully.  Between the 7 plus different steps in this system integration and the dozen plus potential errors that can cause a failure, I would anticipate that this integration will have some reliability issues over time.

But that's okay.  That's what happens with complex systems--you often have equally complex failures and reliability challenges.

So how do you deal with this?  How do you manage such a complex integration?  And how do you increase reliability?

While speaking with the customer, a few things came to mind.

1. Error notifications.  Both SmartConnect and Post Master Enterprise can be configured to send notifications in case of an error.  As soon as a problem occurs, an email should be sent to a power user or administrator that has the tools to resolve the problem.

2. Proactive monitoring.  Sometimes problems occur, but notifications don't get sent or received, or are simply missed in the torrent of email that we all receive daily.  To supplement the error notifications, a monitoring job can be created that independently checks the status of the process.  Did the Invoices get imported by 1pm?  Did the Invoices get posted by 2pm?  Did the Manual Payments get imported and applied by 3pm?  Did the Manual Payments get posted by 4pm?  Each of these checks is just a simple SQL query against the Dynamics GP company database, and these checks serve as a second layer of notification in case there is a problem or delay.

3. Asynchronous design.  In my experience, synchronous, tightly coupled system integrations tend to be less reliable than asynchronous, loosely coupled integration.  So an integration could potentially be modified or redesigned to decouple one or more tasks in the chain, adopting more of a queue based integration rather than a real time integration.  In this particular integration, that would likely be challenging and would require a redesign.

4. Integration "Supervisor".  Rather than SmartConnect and Post Master working independently and simply handing off messages to each other, a "Supervisor" process or solution could be utilized that manages, or supervises, the entire process.  The Supervisor asks SmartConnect to run a map, monitoring that task until the import is complete.  It then hands a request to Post Master, monitoring that task until the posting is complete.  Rather than having to monitor two different applications and get notifications from each, this central supervisor service could potentially reduce the administration and monitoring of the overall process.

While these steps may help manage the process, they won't directly resolve the issues that cause failures or reliability issues in each step.  To increase reliability, I think you have to target the specific failures and eliminate the causes.  Increase data validation, add error handling, design each step to be able to proceed if some errors occur, and also utilize diagnostics to quickly track down the causes of errors.

There isn't a single answer for managing complex system integrations or improving reliability, but I think it is always a good idea to approach such complex integrations with an understanding of the potential errors and failures and an expectation that some additional measures may be required to increase reliability.

What have you done to make your complex system integrations easier to manage?  Have you used any techniques to increase overall reliability?


You can also find him on Twitter, YouTube, and Google+







Automatically generate and create batch IDs in Dynamics GP using VBA

$
0
0
By Steve Endow

This has probably been done a few thousand times by a few hundred people over the years, but I don't recall ever doing it before.

A customer wants to automatically generate batch IDs in Dynamics GP.  They don't want to have to type the batch ID or create batches when entering transactions.  They want to be able to open the Payables Transaction Entry window, have the Batch ID automatically generated and just starting entering a transaction.

Here is a link to a Word document with the instructions and the script.

           https://1drv.ms/w/s!Au567Fd0af9Tmh3tbpX2qrAXYfuY


Once the code is installed, if you open the Payables Transaction Entry window, a new batch is automatically created and the batch ID value is populated in the Batch ID field.


The customer didn't want to use the date, but wanted a sequential numeric batch ID that would be unique.  I used the username, plus the two digit year, plus the day of the year.  This ensures a unique batch for each day, and it's a way of using the date in the batch ID without using the full date.


Make sure to following the instructions in the Word doc and add a VBA Reference to Microsoft ActiveX Data Objects 2.8 Library in the VBA Editor.


Option Explicit

Dim conn As ADODB.Connection
Dim cmd As New ADODB.Command

Private Sub Window_BeforeOpen(OpenVisible As Boolean)
  Set conn = UserInfoGet.CreateADOConnection
  conn.DefaultDatabase = UserInfoGet.IntercompanyID
  cmd.ActiveConnection = conn
  cmd.CommandType = 1  'adCmdText
End Sub

Private Sub Window_AfterOpen()

    Dim interID As String
    Dim userID As String
    Dim shortYear As String
    Dim dayNumber As String
    
    Dim currentDate As Date
    Dim sqlDate As String
    Dim batch As String
    
    Dim sql As String
    
    interID = UserInfoGet.IntercompanyID  'Get the database name (INTERID)
    userID = UCase(UserInfoGet.userID)  'Get the GP user ID
    
    currentDate = DateTime.Now
    sqlDate = Format(currentDate, "yyyy-MM-dd")

    shortYear = Right(DateTime.year(currentDate), 2) '2 digit year
    dayNumber = DatePart("y", currentDate) 'Get day number (out of 365 / 366)
    batch = userID & "-" & shortYear & dayNumber  'Ex:  jdoe-17134
    
    'Create the batch if it does not already exist
    sql = "EXEC " & interID & "..taCreateUpdateBatchHeaderRcd '" & batch & "', '', 4, '" & sqlDate & "', 'PM_Trxent', 0, 1, 0, '', 0, 0, 1, 0, 0, 0, 0, '" & userID & "', 1, 0, 0, 0, '1900-01-01', '', '', '', '', '', '', '', 0, ''"
    cmd.CommandText = sql
    cmd.Execute
    
    'MsgBox (sql)
    
    'Assign the new batch ID to the batch field on the window
    batchID.Value = batch
    
End Sub



You can also find him on Twitter, YouTube, and Google+








Updating .NET apps to support Authorize.net TLS 1.2 for Credit Card and ACH integrations

$
0
0
By Steve Endow

Authorize.net is disabling support for TLS 1.0 and 1.1 in production as of September 18, 2017.  As of that date, they will only support TLS 1.2.  You can read more here:

http://app.payment.authorize.net/e/es.aspx?s=986383348&e=1411090


I have a customer using a .NET integration with Authorize.net, so I reviewed my code and did some research on which protocols .NET supports and uses.

I reviewed my code and confirmed that I was not explicitly setting the TLS protocol version.  So I researched which versions of TLS were supported by which .NET versions, and how the version was chosen.

After reading a few posts on StackOverflow, I confirmed that .NET 4.5 does support TLS 1.2.  So that was good news.  After reading a few more posts, my understanding was that .NET auto negotiates the protocol with the server, so if Authorize.net requires TLS 1.2, I thought that my .NET app should work fine.

So I tested against the Authorize.net developer sandbox, which has already been set to require TLS 1.2, and to my surprise, I received a connection error.  I researched the error and confirmed that it was due to the TLS 1.2 requirement.  But if .NET 4.5 supports TLS 1.2 and is able to negotiate the protocol version, why would my connection fail?

My only guess is that Authorize.net, in addition to requiring TLS 1.2, Authorize.net have configured their systems to detect protocol negotiation requests and deny those connections.  My assumption is that this may be a measure to prevent surreptitious protocol downgrades, such as the POODLE vulnerability, which makes sense.

So I updated my application to include the following line of code:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

(You will need a "using System.Net" reference as well in your class)

This explicitly tells System.Net to only use TLS 1.2.  After I added this line, my connections to the Authorize.net developer sandbox started working again.

Given this finding, I will need to prepare a new release and will have to work with the customer to deploy the new application before September 2017.

And one other small downside to this approach is that my application is now hard coded to TLS 1.2.  But in practical terms, I am not concerned about this, as TLS 1.2 is the latest version available in .NET 4.5.  If a new version of TLS is released, Authorize.net will probably require that specific protocol, and I'll need to update the .NET version of my application anyway, so I'll have to prepare a new release regardless.

So I learned a few things from this process, and fortunately the fix turned out to be very easy.



You can also find him on Twitter, YouTube, and Google+








Extract Dynamics GP Document Attach Files From SQL Server and Save To Disk

$
0
0
By Steve Endow

Today I was asked if there was a way to read an image file from the Dynamics GP Document Attach table so that the image can be added to a report.  For instance, suppose a customer wants to display item images on an invoice.

I have done very little work with the blob / varbinary field type in SQL Server, so I didn't know how difficult it would be to do this.  I quickly did some research and testing, and while I don't have a complete solution for inserting images onto a report, I did test one method for extracting files from the Dynamics GP Document Attach table and saving them to disk.

From what I could tell, there are at least three standard SQL Server tools/commands that you can use to extract an image or file from a varbinary field.

1.OLE Automation Query– This looks pretty sketchy and appears to be very poorly documented.  I tried some samples and couldn’t get it to work.

2.CLR (.NET) inside of SQL – Appears to be a viable option, but requires enabling CLR on SQL, which I personally would try to avoid on a GP SQL Server if possible, so I didn't try this one yet

3.BCP – I was able to get this to work and it was surprisingly easy, but I don’t know how easy it will be to integrate into a report process


Since I was able to quickly get the BCP option to work, here are the commands I used.  If you are able to shell out to run BCP as part of a report or other process, this should work.  


For my testing, I attached a text file and a JPG image to a customer record, and was able to use these BCP commands to successfully extract both files and save them to disk.  

When I ran the BCP command, it asked me four questions, and then prompted me to save those settings to a format file.  I accepted all of the default options except for the header length—that needs to be set to 0, and then saved the file as the default bcp.fmt.



BCP "SELECT BinaryBlob FROM TWO..coAttachmentItems WHERE Attachment_ID = '88d9e324-4d52-41fe-a3ff-6b3753aee6b4'" queryout "C:\Temp\DocAttach\TestAttach.txt" -T -f bcp.fmt

BCP "SELECT BinaryBlob FROM TWO..coAttachmentItems WHERE Attachment_ID = '43e1099f-4e2b-46c7-9f1c-a155ece489fa'" queryout "C:\Temp\DocAttach\TestImage.jpg" -T -f bcp.fmt


I found that BCP was able to extract the files from the Document Attach table and save them, and I was able to then immediately open and view the files.  Dynamics GP does not appear to be compressing or otherwise modifying the files before saving them to the varbinary field, so no additional decoding is required.

Given how simple BCP is and how well it seems to work, I would probably opt for this approach over using .NET, either inside SQL or outside of SQL.  But if you are already developing a .NET app, then it's probably better to use .NET code to perform this extraction.


Steve Endow is a Microsoft MVP for Dynamics GP and a Dynamics GP Certified IT Professional in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter, YouTube, and Google+



Very impressive SQL script for running multi-company Dynamics GP queries

$
0
0
By Steve Endow

I've previously posted some queries for retrieving values from multiple company databases.  I tried a few query designs, but ended up settling with cursors to loop through the different company databases and assemble the results.  Here are two examples:

https://dynamicsgpland.blogspot.com/2016/03/query-functional-currency-for-all.html

https://dynamicsgpland.blogspot.com/2015/10/finding-batches-with-errors-across-all.html


Given the importance of the queries and how infrequently I used them, I didn't worry about the cursor or spend much additional time trying to figure out an alternative.

While these ad hoc, one-time queries are probably just fine using cursors, many SQL folks (myself included) are not fans of cursors, and it's often a fun challenge to figure out a way to use a proper set-based query to replace an iterating cursor in a query.

Well, Ian Grieve has come up with a very clever technique for assembling a query that can run against multiple Dynamics GP company databases.  Rather than executing a query multiple times and storing the results each time, he's figured out an intriguing method for dynamically assembling the queries for multiple companies, and then running that entire dynamic query string using sp_executesql.

Here is his blog post:


http://www.azurecurve.co.uk/2017/05/sql-script-to-return-functional-currencies-for-all-companies-without-a-cursor/


While I understand the general technique, I am not familiar with some of the commands and syntax--particularly the STUFF and FOR XMLPATH statements--so it is going to take me a while to deconstruct and fully understand the entire query.

But hats off to Ian for the creativity!  I think he's come up with a new standard template for multi-company Dynamics GP queries!



You can also find him on Twitter, YouTube, and Google+



Extract and Save Dynamics GP Document Attach Files Using .NET

$
0
0
By Steve Endow

In a prior post, I showed how to use BCP to extract and save Dynamics GP Document Attach files.  I decided to explore this further and use .NET to extract the GP Doc Attach files.

It is very easy to export the file attachments from SQL using .NET, but because you need some data access commands to read the data from the VarBinary field and separate write the data to a file using a stream, it's quite a few more lines than the very simple single-line BCP statement.

This MSDN forum post has the basic code sample, which is 9 lines.  So in theory you could have something that simple.  But in reality any .NET application of value is going to have a fair amount of additional code for a data access layer and other plumbing, allowing for parameters, processing multiple records, error handling, etc.



To start, I have an ExecuteScalar data access method that returns a byte array.

publicstaticbyte[] ExecuteScalarBinary(stringdatabase, CommandType commandType, string commandText, SqlParameter[] sqlParameters)
{
    byte[] scalarResult;
    SqlConnection gpConn = newSqlConnection();

    try
    {
        gpConn = Connection(database);
        SqlCommand gpCommand = newSqlCommand(commandText);
        gpCommand.Connection = gpConn;
        gpCommand.CommandType = commandType;
               
        if ((commandType == CommandType.StoredProcedure) || (commandType == CommandType.Text))
        {
            if (sqlParameters != null)
            {
                foreach (SqlParameter sqlParameter in sqlParameters)
                {
                    gpCommand.Parameters.Add(sqlParameter);
                }
            }
        }

        object result = gpCommand.ExecuteScalar();
        if (result != null)
        {
            scalarResult = (byte[])result;
        }
        else
        {
            scalarResult = null;
        }

        return scalarResult;

    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        gpConn.Close();
    }
}



Next, I have a method that selects the BinaryBlob field value from the coAttachmentItems table and uses a FileStream to save the file to disk.


publicstaticboolSaveAttachment(stringdatabase, string attachmentID, string fullFilePath)
{
    try
    {
        string sqlCommand = "SELECT BinaryBlob FROM coAttachmentItems WHERE Attachment_ID = @Attachment_ID";

        SqlParameter[] sqlParameters = newSqlParameter[1];
        sqlParameters[0] = newSqlParameter("@Attachment_ID", System.Data.SqlDbType.VarChar, 37);
        sqlParameters[0].Value = attachmentID;

        byte[] binary = ExecuteScalarBinary(database, CommandType.Text, sqlCommand, sqlParameters);

        FileStream fs = newFileStream(fullFilePath, FileMode.Create);
        fs.Write(binary, 0, binary.Length);
        fs.Close();
               
        returntrue;  
    }
    catch (Exception ex)
    {
        throw ex;
    }

}



Finally, I have a method that retrieves the list of attachments and calls the SaveAttachment method for each file.  This is where you could have additional parameters and logic, like maximum number of files, filter by file extension, filter by GP record type, of filter by customer, vendor, etc.


publicbool ExportAttachments(string database, int maxFiles, string directory)
{
    try
    {
        DataTable fileList = newDataTable();
        bool success = DataAccess.GetAttachmentList("TWO", ref fileList);

        int fileCount = fileList.Rows.Count;

        if (fileCount < maxFiles)
        {
            maxFiles = fileCount;
        }

        string attachmentID = string.Empty;
        string fileName = string.Empty;
        string fullPath = string.Empty;

        for (int loop = 1; loop <= maxFiles; loop++)
        {
            attachmentID = fileList.Rows[loop - 1]["Attachment_ID"].ToString().Trim();
            fileName = fileList.Rows[loop - 1]["fileName"].ToString().Trim();
            fullPath = Path.Combine(directory, fileName);

            success = DataAccess.SaveAttachment(database, attachmentID, fullPath);
        }

        returntrue;

    }
    catch (Exception ex)
    {
        throw ex;
    }

}


This prototype code is relatively simple and works well, writing out my two sample attachments, a text file and a JPG.


So, if you have a .NET application or integration, or perhaps even a reporting platform that can utilize .NET, you could use this approach.

One consideration is that this sample writes the attachment to disk as a file.  This would probably be less than ideal for a dynamically generated report, so I would look into whether it is possible to retrieve an in-memory representation of the image file and embed it in the report.  I've never done anything like that, so I don't know if that is possible.

Anyway, that's a second method.  If I have time, I'll see if I can use VBA in GP Report Writer to extract image files from Doc Attach and embed them on a report.

Steve Endow is a Microsoft MVP for Dynamics GP and a Dynamics GP Certified IT Professional in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter, YouTube, and Google+




Viewing all 240 articles
Browse latest View live




Latest Images