Monday, 26 April 2010

Display Inventory onhand in Sales order line


Rquirement: to display inventory on- hand in sales line.

Solution:
-Add a new method into SalesLine datasource:
//BP Deviation documented
display inventQty availPhysical(SalesLine _SalesLine)
{
InventOnhand InventOnhand;
InventDimParm inventDimParm;
;
if (inventDim.configId != '')
inventDimParm.ConfigIdFlag = NoYes::Yes;
if (inventDim.inventBatchId != '')
inventDimParm.InventBatchIdFlag = NoYes::Yes;
if (inventDim.InventColorId != '')
inventDimParm.InventColorIdFlag = NoYes::Yes;
if (inventDim.InventLocationId != '')
inventDimParm.InventLocationIdFlag = NoYes::Yes;
if (inventDim.inventSerialId != '')
inventDimParm.InventSerialIdFlag = NoYes::Yes;
if (inventDim.InventSiteId != '')
inventDimParm.InventSiteIdFlag = NoYes::Yes;
if (inventDim.InventSizeId != '')
inventDimParm.InventSizeIdFlag = NoYes::Yes;
if (inventDim.wMSLocationId != '')
inventDimParm.WMSLocationIdFlag = NoYes::Yes;
if (inventDim.wMSPalletId != '')
inventDimParm.WMSPalletIdFlag = NoYes::Yes;
InventOnhand =
InventOnhand::newParameters(_salesLine.ItemId,
_salesLine.inventDim(),
inventDimParm);
return inventOnHand.availPhysical();
}

-Customize modified method of inventdim's fields datasource :
public void modified()
{
SalesLine salesLineFind;
super();

salesLine.modifyItemDim(inventDim,fieldnum(InventDim,InventBatchId),InventTable::find(salesLine.ItemId).DimGroupId);

if (salesLine.DeliveryDateControlType)
SalesCalcAvailableDlvDates::modifiedField(salesLine,0,false,false,inventDim);

// finds the current selected sales line
salesLineFind = SalesLine::find(salesLine.SalesId, salesLine.LineNum);
// syncs sales table with db
salesLine_ds.research();
// updates table ui
salesLine_DS.reread();
// finds the current selected sales line
salesLine_ds.findRecord(salesLineFind);
}
-Add a Real field into SaleLine grid with display method is set to the method created in step 1.

Enjoy!

Friday, 6 March 2009

Helpful Purchase Order and Sales order info

When working with a client, and doing data imports of their data into the new Ax instance you might have to bring in open purchase orders or sales orders. The great thing about this is that both of these are very similar in how they function, look, act, etc. One of the key things to understand when bringing in, for example, purchase orders is the Quantity tab and the data that lives there. The easiest peice about this is the actual Quantity or Purchase Quantity. The thing to keep in mind here when mapping and filling this field with data, is that in reality it's two fields: QtyOrdered, PurchQtyThis is a key peice of data that you must first fill to build everything in the Quantity tab from. The next field that needs to be explained and understood is the Deliver Remainder field on the Qty tab. This field specifys how much of the purchase qty is left to be delivered to the specified delivery address. As long as there is data in this field then the given purchase order is still marked as Open. This field, is actually two fields in the table: RemainInventPhysical, RemainPurchPhysicalOur next field to look at is the Invoice Remainder. This field tells you how much of the purchase qty, that has been recieved, but not yet been invoiced. This field is actually one field called: RemainPurchFinancial.The next two fields we are going to talk about is the Invoiced and Recieved fields in the tab. These fields are actual not fields in the PurchLine database, but rather are driven from Display methods off of the PurchLine Table itself. These display methods are called: Recieved = PurchLine.receivedInTotal(), Invoiced = PurchLine.invoicedInTotal(). What you need to keep in mind here is that these fields are acutally built off of the vendPackingSlipTrans table (Recieved) and the vendInvoiceTrans table (Invoiced). These tables must have values in them, as they represent actual receiving actions doen to the given purchase order line, and invoicing done. This is something that can be tricky, and must be done correctly, as if done wrong you can have incorrect data in these two tables that can cause reports to be off, etc. A lot of people / companies at this point decide to back out of the recieved and invoiced values and then for each open PO, redo these actions from within axapta in order to make sure all reporting and values are accurate and percise to maintain data integrity. The last field we will review, which happens to be the first field in the tab is the Recieve Now field. This field, when supplied with a value, can be used to mark a given qty for the specified line, during a packing slip update to be marked as recieved. Now we can go further into the details of this and how each field pertains to different actions, etc. What most important to understand is this base knowledge though and from there build upon that during your use of Ax. To Re-cap below is a list of these Field names, and then there actual field name in the table. Also I have included the logic for how Ax determines the status of a given PO or SO:1. Quantity = PurchLine.QtyOrdered, PurchLine.PurchQty2. Deliver Remainder = PurchLine.RemainInventPhysical, PurchLine.RemainPurchPhysical3. Invoice Remainder = PurchLine.RemainPurchFinancial4. Invoiced = PurchLine.invoicedinTotal() [Display Method]5. Recieved = PurchLine.recievedInTotal() [Display Method]Status Logic:If anything exists in the Deliver Remainder then the PO is open.If Nothing exsists in the Deliver Remainder, and all Qty Ordered exist in the Recieved then the PO is recievedIf all qty has been recieved, and all has been invoiced, then the PO is invoiced.

P/S: There is a bug in Axapta which will be fixed if you know above useful information!!!

Sunday, 4 January 2009

New year, new HOPES

A new year is comming and our real works with Microsoft is come true!!!!
Last Friday, I sent an email to Dynamics Axapta Build team to ask them about our license in Axapta. And out of my supprise, the replied my email quickly. I really appreciate their helps and I also know that right now our new hard challenges is comming too. I like challenge!!!
Our main duties with Microsoft is Axapta bug fixing.

Wednesday, 17 September 2008

Windows Test Technicque For Axapta

Last weeks, I recevied some  resources from our Ukraine about Test Automation. It's called WTT. Unfortunately, we didn't understand what  it is about. We just read the document and we was really in a circle. Where could we start? What is the first step to deal with Axapta Test Automation?
It were hard questions for me because I never deal with test automation before. (I just know UniTest)
But, lucky me, my dear friend Danang sent us videos to demonstrate how to deal with WTT.
Right now, with all of our Celenia Vietnam mates, I think we are ready for implementing real testcase.
I also hope that we will deal with Axapta 2009 as much as possible.

Monday, 28 July 2008

Create an Axapta page on Facebook

Today, i have created an Axapta page on facebook. I hope this page will help us easier to share our knowledge.

Tuesday, 15 July 2008

10 tips for debugging in Dynamics Ax


Fixing bugs requires quite a bit of experience and knowledge of the modules involved, both on a technical and functional level. The first step to fix something is to find the cause of the problem, a.k.a. debugging.

You shouldn’t limit yourself to using the debugger when things go wrong. Debugging can help you understand the system. I often fire up the debugger just to see what happens in a standard application. This helps me to see how modifications can be implemented and what the consequences are. Dynamics is too big and too complex to be able to just dive in and change something.

Here are some tips to help you in the fine art of debugging. Some might be blatantly obvious to experienced developers. These are things I wish I had known when I first started working with Axapta.

Assume you broke it
This is probably the most important advice. We developers tend to think we write good code. Some of us do, some of us don’t. But nobody does it flawlessly. By default, assume anything you didn’t write yourself works perfectly. This narrows down the search considerably. After careful debugging you may come to a different conclusion. In which case you’ll have a good bug report to file.

If a system has been running fine for a while and it suddenly breaks down after importing new code, those changes are likely to be the root cause of the problem. Try reverting your changes and doing the exact same thing. If the problem remains, you have found an unrelated problem. If not, you know where to start looking for errors.

Get a clear description of the problem
Unless the error is clear enough and you immediately know how to fix it, you’ll need a detailed description how to trigger this error. Unfortunately this can be very hard. Getting users to tell you exactly what you need to understand a bug isn’t that simple. Keep in mind that users are generally not interested in the program they’re using. They just want to get their job done. They have been taught to use the system in a certain way and unexpected errors confuse them. They might not realize what’s different when things go wrong compared to when everything just works.

You need to ask the right questions. If necessary sit next to them and watch them work. Take notes and try to notice special cases. And don’t forget to ask what the correct behaviour should be. There may be no error message and whatever happens may look correct but the user could be expecting a different result.

Without a good scenario it may be impossible to solve some bugs.

Don’t worry to much about errors that only occur once
If something goes wrong only once and it doesn’t happen again, don’t worry too much about it. Depending on the risk it may be better to fix the damage and move on. There’s probably a bug lurking somewhere but you have to decide if it’s worth chasing it.

Intercept error messages
Anything sent to the info log window passes through the add() method on the Info class. Put a breakpoint there if you want to know where a message is triggered. Using the stack trace in the debugger it’s usually not that hard to see which conditions cause it.

Often it turns out to be a missing setting in one of the basic tables.

Intercept data modifications
Not all bugs come with an easy to intercept error message. Sometimes all you get is bad data. It’s possible to see when and why records are created, modified or deleted by putting breakpoints in insert(), update() or delete() on a table. Create them if necessary. Just being able to look at the stack in the debugger when these are called can be very insightful.

Remember that it is possible to modify data without passing through these methods. Like using doInsert(), doUpdate() or doDelete(), or using direct SQL. It’s not very common but sometimes you can miss something.

Intercept queries
If you suspect a query is not correct you’ll want to verify its output. A way that doesn’t require much work is using the postLoad() method. It can be overridden on each table and is called for each selected record. It even works with complex joins. Putting an info() in the postLoad() of each table in a query can tell you a lot about what’s happening.

The cross-reference is your friend
The cross-reference is one of the most important tools when developing and debugging in Dynamics Ax. Always try to have an environment somewhere with an updated cross-reference (not the live environment). You can find the cross-reference in the development tools menu.

Need to know where a field gets its value? The cross-reference tells you where every read and write happens.
Want to know where an error message is used? Open the label editor and find the label, then click the Used By button.

Set up a separate environment
When dealing with complex problems it helps to have a separate environment for debugging. This allows you to freely modify code and data without affecting the live system. This is very important when you have to post invoices or do anything else that is basically irreversible.

It also prevents live users from being blocked if you have breakpoints in the middle of a transaction.

Dealing with large datasets
Sometimes a problem can only be reproduced in (a copy of) the live environment. You’re often stuck with a lot of data that doesn’t matter but gets in the way. Like when you need to debug the MRP. Using regular breakpoints doesn’t help because it takes too long before you get to the real issue.

In this case you need to have some more tricks up your sleeve to narrow down the search. One option is to work in several passes. Using the cross-reference determine places where something interesting happens and dump data with info() or Debug::printDebug(). This should narrow down the possible suspects. With a bit of luck just looking at the data can be enough to identify the problem.

Another way is implementing your own conditional breakpoints. The debugger doesn’t offer these out of the box but you can roll your own with an if-statement and the breakpoint statement. This is very effective if you have some more or less unique identifier of the problem, like a record ID or a customer account or even a date.

Clean up
Don’t forget to remove any modifications you made while debugging. You probably don’t want to leave a hardcoded breakpoint in a live system. Been there, done that, very annoying.

Good luck hunting for bugs.

Feel free to share your debugging techniques.

Install Axapta 3.0 SP5,SP6

Last week i tried to install Axapta 3.0 into my computer and it took me more than one day to finish. I was so tired but actually I got some good experience in setup Axapta. In my opinion, here are steps to install Axapta.
  1. Install SQL server. I just used SQL server 2005 version.
  2. Install Axapta 3.0.
  3. Update your Axapta client to kernel rollup 2.If you are planning to upgrade to SP6 you don't need to update to kernel rollup 2.
  4. Install SP5 or SP6 as needed.
  5. Setup Connection from Axapta server to SQL server by using ODBC connection or SQL server as needed