Cross Dictionary Customization – EXAMPLE


Objective: This post is intended to show a very simple but practical example of 3rd Party Dictionary Customization. The target product is Field Service Contract Administration.

Field Service Product Details:

1. Product Name: FieldService
2. Product ID: 949

Sample Customization Description: I am going to retrieve the Contract Header information, when an existing Contract is entered. I am using SanScript runtime code executions and Dex object Triggers.

Procedure: STARTUP
{
Procedure: Startup
Series: System (Not mandatory to select System)
Summary: This script registers all dex object triggers required for this customization product.
}

local integer l_nResult;

l_nResult = Trigger_RegisterFocusByName
(
949, {Product ID}
“‘Contract Number’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance”, {Object on which the trigger is registered}
TRIGGER_FOCUS_CHANGE, {execute this trigger on the CHANGE event of the object}
TRIGGER_AFTER_ORIGINAL, {execute this trigger after the original CHANGE event script is processed}
script FS_Get_Contract_Hdr_Info
);

if l_nResult <> SY_NOERR then
warning “Error registering the trigger: FS_Get_Contract_Hdr_Info. ” +
“Object: ‘Contract Number’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance, ” +
“Event: CHANGE, ” +
“Scope: AFTER_ORIGINAL.”;
end if;

Procedure: FS_Get_Contract_Hdr_Info
{
Procedure: FS_Get_Contract_Hdr_Info
Series: Sales (Not mandatory to select Sales)
Summary: This script retrieves the contract header information on Contract Entry/Update form once an existing Contract is entered.
If the Contract is new, then it is not touched.
}

{Local Variables Declaration}
local integer l_nResult;
local string l_sCompileMsg, l_sContractNo, l_sCustomerID, l_sAddressID, l_sContractType, l_sCurrencyID;
local integer l_nContractLength, l_nContractPeriod;
local datetime l_dtStartDate;
local text l_sCode;

{Construct the SanScript code to execute it inside Field Service and retrive the Contract values}
l_sCode = “”;
l_sCode = l_sCode + “out string O_sContractNo;”;
l_sCode = l_sCode + “out string O_sCustomerID;”;
l_sCode = l_sCode + “out string O_sAddressID;”;
l_sCode = l_sCode + “out string O_sContractType;”;
l_sCode = l_sCode + “out string O_sCurrencyID;”;
l_sCode = l_sCode + “out integer O_nContLength;”;
l_sCode = l_sCode + “out integer O_nContPeriod;”;
l_sCode = l_sCode + “out datetime O_dtStartDate;”;
l_sCode = l_sCode + “if ‘Customer Number’ of window SVC_Contract_Maintenance of form SVC_Maintenance <> “” then”;
l_sCode = l_sCode + ” O_sContractNo = ‘Contract Number’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance;”;
l_sCode = l_sCode + ” O_sCustomerID = ‘Customer Number’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance;”;

l_sCode = l_sCode + ” O_sAddressID = ‘Address Code’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance;”;

l_sCode = l_sCode + ” O_sContractType = ‘Contract Type’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance;”;

l_sCode = l_sCode + ” O_sCurrencyID = ‘Currency ID’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance;”;

l_sCode = l_sCode + ” O_nContLength = ‘Contract Length’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance;”;

l_sCode = l_sCode + ” O_sContPeriod = ‘Contract Period’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance;”;

l_sCode = l_sCode + ” O_dtStartDate = ‘Start Date’ of window SVC_Contract_Maintenance of form SVC_Contract_Maintenance;”;

l_sCode = l_sCode + “end if;”;
{Execute the Code segment inside Field Service}
l_nResult = execute
(
949, {Product ID}
l_sCode, {Constructed Code Segment}
l_sCompileMsg, {Store the Runtime Compilation errors, if any found}
{Parameters}
l_sContractNo,
l_sCustomerID,
l_sAddressID,
l_sContractType,
l_sCurrencyID,
l_nContractLength,
l_nContractPeriod,
l_dtStartDate
);


{If any runtime compilation errors occurred, throw the corresponding error message}
if l_nResult <> 0 then
warning “Error executing the constructed code. Error Message: ” + l_sCompileMsg;
abort script;
end if;

{Do some Planned Process}
———

Vaidy

Cross Dictionary Customizations – Contd…



The second point in the list (Cross Dictionary Customizations – An Insight) is Writing 3rd Party Triggers. Triggers are classified as 3rd Party triggers, if we use the keyword “ByName”. I hope all of us know what exactly is a trigger and how it is written, when we read this post.

The following are the Triggers available for writing triggers on 3rd Pary products:
1. Trigger_RegisterFormByName
2. Trigger_RegisterFocusByName
3. Trigger_RegisterProcedureByName
4. Trigger_RegisterFunctionByName
5. Trigger_RegisterDatabaseByName

Syntaxes and explanations are best provided in Dex Manual, which can be referred. But let me tell you some of the complications involved in this.

First and foremost: 3rd Party triggers are comparitively less reliable. Maintaining our code with respect to each and every version release of the Parent 3rd Party product is mandatory. This can be experienced best by writing Procedure Triggers. For some reason, if the procedure is either amended with Parameters or worst case its been scrapped, our life will become miserable. That’s the sole reason, always, the dependency towards a 3rd Party product should be minimal.

We won’t be having any kind of release notes for the resources that are being either amended or removed or added. It is our QA’s responsibility to test our customization against each version release of the parent 3rd party and fix our customization, if needed.

Using #1 and #2 (SanScript Code & 3rd Party Triggers), we can achieve almost all kinds of requirements from the customers.

Customizing a UI resource (Form, Report, etc) will be the worst way of customizing. At any cost, we should try avoid doing such customizations, as this would cost us too much at the time of maintenance. I had faced this in one of my projects. I had to customize a 3rd party product’s screen to some extent and after all efforts put in and maintained it for number of version releases, one fine day, that screen was scrapped from the parent product itself, leaving me to grudge in frustration. I cannot keep this form, as the core dependency of that particular form is no more available in the parent product. I cannot scrap this functionality from my customization as it is somewhat critical to the client. The only way out for me then, was to redesign that form in my customization and establish all the missing dependencies. By then, we had skipped several deadlines.

One more thing, which is interesting as well as challenging, is the access of Table Buffers of the Parent Product from our customizations. You may want to access the Table Buffers for various reasons, such as Creating Records from your product, Retrieving records which may form a basis for your product, Populating records in a lookup designed by you specifically for your requirements, etc.

Among all these reasons, the most tricky scope of accessing buffers is, any Process-Oriented access. For instance, if a Sales Invoice is posted from the Parent Product and a subsequent GL Journal is created from that product, and if your customization require this new piece of information, then you will have to be very very careful in placing your code so that you get the correct table buffer values. Most of the Cross Dictionary customizations face issues on accessing the table buffers and almost always when they try to access in between a critical process.

More to come…

Vaidy

Regarding to GL table


What is the main difference between GL00100 and GL10105?

(both are contain mostly same records)

Intention of "Itemcode" in SOP_LINE_WORK ?


Any one knows, what is the purpose of having “itemcode” in SOP Line Work table.
I have gone through SDK but i am getting only below statement,
Item Code: Field similar to UPC Code – is not unique for each item.

But i am not getting exactly what it means. Please any one let me know, intention of itemcode in SOP Line work, and its usage.

-Prabu

A much improved VSTools For Dynamics GP



I was a bit pessimistic about using VSTools for Dynamics GP for various reasons, which I had posted some days back. You can refer that from my previous post: Major roadblocks involving VSTools for Dynamics GP.

Now, there seems to be a major improvement which will certainly bring smiles to our Developers. MS is working towards releasing an Addon for VSTools, using which, we can add forms created from VSTools to Standard GP Menus. I am not kidding, you can trust me.

I was involved in testing the Beta version of this Addon and it was really quite good and addresses the major issue which involved the Standard GP Menu integrations. While I am awaiting the release soon from MS, I will keep you all posted with the experience I had with the Addon testing.

Vaidy

Cross Dictionary Customizations – An Insight



One of the biggest advantages in Dexterity is the Cross Dictionary access. There are so many 3rd party verticals being developed for Dynamics GP to meet the requirements of various Customers around the globe. And each one can be customized again to meet a very specific requirement from a Customer. The best way to achieve this is by Cross Dictionary Coding.

What exactly is a Cross Dictionary Customization? Any addition / change of functionality in a 3rd Party product involve a dictionary which is other than Dynamics.dic. Technically, we have direct access only to Dynamics.dic and its resources. Any customizations can be done directly on Dynamics.dic and the same is not true for dictionaries (or products) other than Dynamics. A change/addition to any dictionary (or product) which is other than Dynamics GP (Dynamics.dic) is considered to be Cross Dictionary Customization.

Why this is so difficult compared to Standard GP Customization? Simple reason, we do not have direct access to the other dictionary (product) resources at runtime. For instance, I cannot access a table from Project Accounting directly by referring to its Technical Name in my custom dictionary. It is the same for Forms, Reports and other resources. That makes the life of a developer miserable most of the times.

What is needed for a Developer to carry out such Customizations? Thorough idea of 3rd Party product on which he/she is going to do the customization. For instance, if I need to write an additional validation on HR Card functionality, I should know better about this form and its scope. I should be able to foresee the impact which my code is going to make on this form and the subsequent processes. This is a real tough challenge for any GP developer, since not everyone knows everything about all the 3rd Party products and its’ functionalities. Also, a developer should possess tremendous analysis and troubleshooting skills, such as the ability to take and study thru’ the Script Logs, Profiles, etc. These will be the base for most of the Cross Dictionary Customizations.

What are the methods with which we can develop Cross Dictionary Customizations? We do not have definite methods defined, but thru’ experience and the technical feasibility, we can confine the methods to the following three:

  1. Construct SanScript code and pass the code to get it executed on the target 3rd Party Product.
  2. Write 3rd Party Object and/or Event Triggers, just as we write on Standard GP objects or events.
  3. Do a Developer Update of the target 3rd Party product with Dynamics and start customizing the screens and/or reports, depending on the actual requirements.

While all the above 3 points sound very simple, there are so many complications involved in using these methods and succeeding on our tasks.

Complications lie in finding the scope of our task in and around the 3rd Party functionality. Code needs to be written in such a way that the parent functionality should not be compromised (unless needed).

Coming back to the points listed above. The first point is widely used to retrieve any data from either window fields or tables of that particular product. This is used along with the 2nd point, to do some extensive customizations.

For instance if I need to fetch the “Employee Name” from the HR Employee Maintenance form, the following code piece will solve the purpose:

local string l_sEmployeeID, l_sCompileMsg;
local text l_sDexCode;
local integer l_nResult;

l_sDexCode = “”;
l_sDexCode = l_sDexCode + “out string O_sEmployeeID;”;
l_sDexCode = l_sDexCode + “O_sEmployeeID = ‘Employee ID’ of window UPR_Employee_MNT of form UPR_Employee_MNT;”;
l_nResult = execute(414, l_sDexCode, l_sCompileMsg, l_sEmployeeID);
if l_nResult 0 then
warning l_sCompileMsg;
end if;

The function execute() is used to compile and execute any SanScript code at runtime on any dictionary, either Dynamics or 3rd party. Syntax and prototype explanations can be referenced from the Dex Developer Compiled Help Manual.

It is very simple to construct such code pieces. But the most important thing is the Product ID (first parameter passed to execute() function). We should make sure that we have entered the correct product ID so that it gets executed correctly on the target product.

To be continued…

Vaidy

Major Roadblocks involving VSTools for Dyn GP


There are quite a few major issues which prevent VSTools from being the 1st priority to develop Customizations for Dynamics GP.

The below are the list, to my knowledge:

  1. Menu Integrity issue – We cannot add the VS forms to the Standard GP Menus.
  2. Scrolling Window – Most of the developers do not agree with this point, but I would still add this. Scrolling window is one of the best control we have in Dex, considering the functionality of the same. The very idea of embedding a Table on a grid and performing the operations, is a true delight for developers. VSTools certainly miss this rare control.
  3. Table Integrity and DB Connectivity – Since we use Table Buffers in Dex, we are assured that we perform our operations safely. That will be a drawback in VSTools, as we have to deal with SQL tables directly. We would certainly miss “copy from … to …” statements.
  4. Cannot perform critical processes such as Posting. We can write a code to create GJ or an Invoice or a PO etc. But we cannot rely on VSTools to post any Trx. Such critical routines would still be called from Dex, which limits the scope of VSTools.

All said, VSTools is still a HOT favorite among developers, as they do not have to learn Dex (I have heard fresh GP Developers cursing the syntaxes and the way the code is written, especially the Scrolling Window… Can’t help it…).

.NET is going to be the core framework for all MS applications. Having said that, I am pretty sure, things will be the same for GP and related technologies as well.

BUT, if anyone ask me DEX or .NET, then I would certainly declare DEX.

How about you guys?

A Serious Error during VBA Event


This was asked by Shankar, one of my colleagues in ZSL. He has been struggling with this error and has not yet been successful in even finding the cause. I am briefing the issue below (Original Post Link: http://www.microsoft.com/Businesssolutions/Community/Newsgroups/dgbrowser/en-us/default.mspx?dg=microsoft.public.dynamics.gp.developer&mid=69071664-24fd-4be3-8bd6-bcc45849075b):

There is a VBA customization done on Project Accounting Vendor Maintenance screen. Coded on the local machine, OS of which is Windows XP Pro SP2. Created a package and deployed it on a GP Server, OS of which is Windows Server 2003 Standard. Now, first time it worked merrily. Something happened (I mean it, some damn thing happened) and CRAP. It throws this message “A serious error occurred during a VBA event.”. That’s it. Nothing else. When I tried debugging this, it is not even entering into any of the Events on which he had written the code. Like, on VendorID CHANGE, there is a code, but it does not even enter this code. No idea, why and from where this error message is popping up.

Well, it’s eluding me as well. Constantly checking the forums, googling the sites. Anyone who crack this issue, they deserve a special appreciation (and a cup of Champagne).

So why don’t you guys start doing some exercise?

Tables Resource Description – Issue


I was facing a weird (really weird) situation.
I had 2 Custom Tables and both these tables were LIVE on Client's Company DB. There was a feature change
and I had to ALTER the table structure. I did that and since the Dex Table Names (Technical, Display & Physical)
did not match the standards, I changed those as well. Now these two tables are looking like new tables.
I created these tables thru' SQL Maintenance and pulled in all the existing records onto these new tables thru'
a SQL INSERT...SELECT FROM query. Now, when I check these tables in Tools -> Resource Descriptions -> Tables,
it still shows the old Resource Names (Technical, Display & Physical).
I did SYNCHRONIZE from Dex, but still the same. But the most weirder thing is, it is NOT THE CASE in my
machine. It is the case with the Client's machine. What in this world would have caused this and how can
I address this?
I posted this on MS Forum, and got the below response from Robert Cavill:
If the table definitions have changed in the dexterity dictionary, you need to delete the existing
OLFD0001.IDX and OLFD0001.DAT files in the application folder.
When you access the Table Resources,
it uses these files and does not refresh them.
By deleting those files , your table resouces display
within Dynamics GP will be refreshed based on the newly installed dictionary.
And yes, it indeed did the trick and I am quite happy with the results.
One more to learn for the day: OLFD001.DAT & OLFD001.IDX will store the Resource Description details in Dynamics GP.
Vaidy

Why can’t I discard changes on a Transaction? – Good Article by David Musgrave


I was going thru’ David’s blog for some other information. I somehow ended up reading this article. It reflected my way of thinking (quite honestly). But the article is a typical David’s article I would say, since it explains the reason with as much simpler terms as possible, so even a Functional Guy can understand.

Below is the direct link to that article. Read it, you will agree with me.

http://blogs.msdn.com/developingfordynamicsgp/archive/2008/08/18/why-can-t-i-discard-changes-on-a-transaction.aspx

Vaidy