Most of my posts have been around how to do things. Typically they are small scripts. Today I’ll discuss one of the projects I have been working on to demonstrate that scripting isn’t just for the quick and easy tasks but can also solve complex issues.
IFL need to get imported product and caught product in to M3, they also have a 3rd Party Logistics Coolstore operation which they also want to keep track of within M3.
The process that has been designed is using Purchase Orders to get stock in to M3. 3rd Party stock goes in at zero cost, imported and caught products have prices against them to reflect the costs.
IFL uses lot control extensively which determines what product can be exported to which parts of the world, each import, each landing will have multiple products in a single lot – so we need to create lots for each product and populate some of the attributes.
And finally we have to receipt the product.
In standard M3 we do something like this:
- Create the PO Header (PPS200)
Create the PO Lines for each item
- Create lot numbers for each item (MMS235/B1)
- Populate some of the lot details (MMS235/E)
Receipt the Purchase Order
- Set the lot attribute values (MMS235/B1)
This involves working through quite a lot of panels and even for a proficient operator, it takes a fair amount of time. Unfortunately we don’t always know the specifics of products before we receive them (don’t ask), so creating purchase orders in advance doesn’t always work. Typically we know almost all of the required information at the time of stocking in to M3. Wouldn’t it be nice if we could just enter the products and attributes on a single panel and it would go out and create the purchase order, populate the lines, create the lots, receipt the purchase order and then assign the attribute values in a single step?
The correct answer is, no, it wouldn’t be nice, it would be utterly fantastic!
The solution is to use APIs and thankfully Infor have been progressively adding API calls to make it possible to avoid any webservices. And this is the situation where having access to Alistair from JBC – an undeniable M3 guru with extensive knowledge of the APIs and the processes above (which he designed for us) – becomes invaluable J
And this is what it looks like:
Warehouse, Supplier and Order Type all relate back to our purchase order creation.
Lot Ref 1, Lot Ref 2, Suppl/Manf No are common values stored against the Lot record in MMS235 which we will populate for each item/lot combination for this lot. Our lot number is comprised of and is automatically padded.
Then we have the attributes – these are the ATS101 attributes that we will be populating which again will be common for all items on this PO Receipt. As you can see some of these have lookups behind them.
We have the list and finally the line entry. Item code, Qty, UoM and Location are pretty clear. But for 3rd party product we bill some customers on a pallet basis, so we need to keep track of the number of pallets. The remaining fields relate to attributes (ATS101) that can be unique per line. Elgbty is the Eligibility – this determines what parts of the world we can send product to. Latin Name is the latin name of the product, and package number is the M3 container if we don’t want the default – which in the case of some 3rd party product we actually have labelled pallets so need to use their identifier rather than an auto-generated number from M3 and finally EU Catch Cert which is used to flag certain document requirements.
When a user hits the add button, we will do some basic checks – ensuring that the item and location exists, and that the quantity is evenly divisible by the number of pallets. We could do more, but we don’t want the operator to be waiting on a multitude of API calls before they can enter in the next line.
Once the operator has entered in all of the product they want to receipt, they hit Next and we go out and start our calls to our APIs. And it works something like this:
- Is the Warehouse Valid? (MMS005MI)
- Is the Supplier Valid? (CRS620MI)
- Is the Order Type Valid? (PPS095MI)
- Start PO Batch Entry (PPS370MI)
- Create PO Header (PPS370MI)
- Add each PO Line (PPS370MI)
- Finish PO Batch Entry (PPS370MI)
Get unique item codes (we need to create our lot number for each item)
- Create Lot for each item (MMS235MI)
- Poll M3 checking to see if each of our batch lines has gone to status 90 or 23 (CRS990MI)
Receipt each line in to its final location
- Receipt (Quantity / Pallets), pallets times – so quantity of 100, 5 pallets will receipt 20 cartons 5 times creating a unique container for each receipt (PPS001MI)
Set the attribute values for each line
- Validate attribute model attribute IDs available for product (MMS235MI)
- Set attribute value (ATS101MI)
If attribute type 4 (Text)
Set Line Text
- Create Text ID (CRS980MI)
- Add Text Header (CRS980MI)
- Add Text Line (CRS980MI)
- Set Text ID against lot/item (CRS980MI)
In all, there are 27 unique M3 API calls – and for line entry and attribute entry we may have to call these APIs multiple times.
The biggest challenge around this project came down to some timing issues between the finish of the batch entry and when we could start receipting product. As the transfer from a batch PO to a real PO is not done live, then I have to wait for the M3 batch or autojob to complete before I can receipt product. This came down to checking for a status 90 for the lines or status 23 which indicated there was an error on the line. We had initially wanted to set this up so the Batch POs would delete automatically, but this became more involved than we wanted to deal with. Oh, and then having to work out the relatively new SetTextID API call…
So if we actually enter some data.
Add a single line where there is 100 cartons on 5 pallets. Hit Next
We get a completed message with the Purchase Order Number.
Now if we take a look at what has happened with the actual M3 programs…
The Purchase Order
The Lot itself where we have prepopulated three of the fields.
And we’ve set some of the lot attributes aswell, including those of type 4 (text)
And the actual MWS070 line receipts where we can see the 5 lines of 20 cartons, representing 5 pallets with 20 cartons on each pallet. We can see the outer pack is different for each line.
And that’s it…
The solution is written in C# and is deployed as a standalone script and took around 20 hours to complete – this is longer than it should have been but I ended up regigging the UI and there was some scope creep that required restructuring some of the code.
I hope this demonstrates that you can unify and improve processes and workflows, adding in your own business logic with relative ease.