(SOLVED) Dynamics AX 2009 – Receive Purchase Order Line using x++ & .Net Business Connector

By ckane at January 17, 2010 08:14
Filed Under: Microsoft Axapta 2009
We needed to expose a WCF service so that our logistics vendors could execute a purchase order
line receipt. There were a lot of results returned from a google & yahoo search but a good portion
of them weren’t very specific. After hours of trial and error I came up with the x++ code below
that includes a serial number update through the Inventory Dimension.
public static void receivePurchLine(PackingSlipId _packSlipId, PurchId _purchId,
                                  Qty _qty, ItemId _itemId, LineNum _lineNum, str _inventLocation)
{
    PurchFormLetter purchFormLetter;
    ParmId parmId;
    PurchParmTable purchParmTable;
    PurchParmLine purchParmLine;
    PurchTable purchTable;
    PurchLine purchLine;
    InventDim currentInventDim;
    InventDim updatedInventDim;
    ;

    purchTable = PurchTable::find(_purchId);
    purchFormLetter = PurchFormLetter::construct(DocumentStatus::PackingSlip);
    purchFormLetter.createParmUpdate();
    purchFormLetter.createParmTable(purchParmTable, purchTable);
    purchParmTable.Num = _packSlipId;
    purchParmTable.insert();
    while select purchLine
        where purchLine.PurchId == purchTable.PurchId
    {
        purchParmLine.InitFromPurchLine(purchLine);
        purchParmLine.ParmId = purchParmTable.ParmId;
        purchParmLine.TableRefId = purchParmTable.TableRefId;
        if (purchLine.ItemId == _itemId && purchLine.LineNum == _lineNum)
        {
            currentInventDim = InventDim::find(purchLine.InventDimId);
            if (currentInventDim.RecId)
            {
                updatedInventDim = 
InventDim::findOrCreateOwnCondDispSiteLocation(currentInventDim.configId, currentInventDim.InventSizeId, currentInventDim.InventColorId, currentInventDim.InventSiteId, _inventLocation); if (!updatedInventDim.RecId) { throw error('Unable to find or create destination inventory dimension'); } } purchParmLine.ReceiveNow = _qty; purchParmLine.RemainAfter = purchLine.QtyOrdered - _qty; purchParmLine.InventDimId = updatedInventDim.inventDimId; } else { purchParmLine.ReceiveNow = 0; purchParmLine.RemainAfter = purchLine.QtyOrdered; } purchParmLine.setQty(DocumentStatus::PackingSlip, false, true); purchParmLine.setLineAmount(); purchParmLine.insert(); } purchFormLetter.proforma (false); // proforma ? purchFormLetter.printFormLetter(false); // print ? purchFormLetter.specQty (PurchUpdate::All); // what to update? purchFormLetter.transDate (today()); // update date purchFormLetter.run(); }

Axapta Business Connector To Import Address and Performance

By ckane at August 03, 2009 13:14
Filed Under: Microsoft Axapta 2009

So, importing addresses the correct way, according to professionals we have talked to, is to import by using the DirParty and PartyId values to do the inserts. Let me tell you this is DOG slow and performance is horrible. If you bypass and just use the AddrTableId from say the CustTable performance is a huge improvement.

I don’t know what Microsoft (or it’s previous developers were thinking) but the DirParty and DirPartyRelationships need some SERIOUS improvement in performance or just get rid of them all together.

Imports using the Business Connector for any other data other than Addresses FLY!

AOS Server Service Fault

By ckane at July 11, 2009 02:14
Filed Under: Microsoft Axapta 2009

Discovered a problem with the Axapta AOS Server service stopping and faulting:

Faulting application Ax32Serv.exe, version 5.0.1000.52, time stamp 0x490c68d8, faulting module Ax32Serv.exe, version 5.0.1000.52, time stamp 0x490c68d8, exception code 0xc0000005, fault offset 0x00000000004be844, process id 0x3a0, application start time 0x01c992a34fef6bbc.

The error was discovered when attempting to run the Label Editor. We deleted all the .ali .alc .ald files and restarted the service.

Dealing with lists in .Net Business Connector and how to get around it

By ckane at July 11, 2009 02:10
Filed Under: Microsoft Axapta 2009

So I had the pleasure of having to deal with Lists and Containers in the .Net Business Connector and it was NOT a pleasurable experience. Axapta uses lists and containers and trying to use them in C# was a complete nightmare because using either type always generated a ‘Bad Container’ error.

The Axapta SDK states that a List is equivalent  to a generic list in C#….this is incorrect Axapta doesn’t support generics. The real c# array to use is the ArrayList because it is not of generic type. When you go to pass the ArrayList into the method you must use the following code to do so: list.ToArray(typeof(string)). Otherwise you will get an invalid parameter exception but this still generated a ‘Bad Container’ exception.

The Axapta SDK states that you can use a AxaptaContainer to pass into a method where the container object is being used but unfortunately COM interop doesn’t translate it correctly and once again throws a ‘Bad Container’ exception.

The solution? I ended up using a comma separated  string to pass into a new method and used the Axapta ‘strSplit’ Global method to split the string into an Axapta List.

Below is the x++ method that I created

server static void finishMultiMDSi(str _pickListIds)
{
    List list = new List(Types::String);
    ;
    if (_pickListIds)
    {
        // We pass in a comma sep string, we split the string into a list
        list = strSplit(_pickListIds, ',');
        // Pass the list into the finishMulti method to post the pick list
        WMSPickingRoute::finishMulti(list.pack());
    }
}

Getting values from another table to wire up into a form’s fields

By ckane at July 11, 2009 02:10
Filed Under: Microsoft Axapta 2009

I had to develop a unique situation where a table in axapta needed to be populated using some fields from a newly created table. The problem was that the table ‘ConfigTable’ and it’s associated form allowed the user to enter in information via a textbox/string and we wanted the form to populate this data from another table. We were worried that people won’t do the due diligence to check and see if the ‘ConfigId’ already existed nor would the follow formatting rules. So what we did is was created a new “OwnerMasterTable” table that contained all the unique “ConfigId” and “Name” fields we then changed the form to do a lookup.

We hid the first two fields in the ConfigTable form (ConfigId and Name) and added a new field to the form: OwnerId. Using this field, we were able to lookup the values from the “OwnerMasterTable” and populate the “hidden” values in the form that would then be used to populate the "ConfigTable”. We did it by overwriting the textChange event on the OwnerId so that we could wireup the hidden fields and not break the existing “ConfigTable” schema.

public void textChange()
{
    super();
    // We know what the text is that was selected so lets wire up the configTable's ConfigId value
    configtable.ConfigId = this.text();
    // We need to do a quick lookup of the ownerMasterTable so we can
    // can get the correct Name to wireup to the ConfigTable Name property using the text from above.
    select ownerMasterTable where ownerMasterTable.OwnerId == this.text();
    configtable.Name = ownerMasterTable.Name;
}

Executing Pick List Registration in code

By ckane at July 11, 2009 02:06
Filed Under: Microsoft Axapta 2009

So I needed to post the pick list registration outside of Axapta. After quite a bit of time I found out exactly where it is done and it’s very simple.

WMSPickingRoute::finishMulti() is the method that is used to post the pick list registration and all the method takes is a container of PickingRouteId’s. You simply pass in all the PickingRouteId’s that you need to be Registered and the logic in this method takes care of it.