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();
}
1e3c76cb-e807-4d6b-aa07-da1b6290e257|1|5.0
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!
0a11050b-29b2-4706-a588-9bf7703b0102|0|.0
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.
42348ad5-7d15-4d21-8a48-b58e41cfbf7f|0|.0
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());
}
}
27253823-fbc0-46c1-a87f-0383807dd1ae|0|.0
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;
}
ef66d856-39ce-4e8d-a786-239f176ce820|0|.0
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.
def9e30c-69dc-4707-af5f-013af66ced43|0|.0