We needed to inventory-close 18 months worth of transactions. This happened because a legacy system was the system of record for this period of time and no one was worrying about details like inventory close. When AX became the system of record, focus turned to reconciling accounts and the inventory close.
We chose not to:
We chose not to do the inventory close one month at a time because that would require opening old accounting periods.
Problem:
When we did the inventory close for 18 months (moderate number of transactions), the process would run for 24 hours or so and then we would get an "Out of memory" error.
Workaround Attempts:
- The machines were reasonably powerful...but, just in case, we restarted the AOS and client to make sure that they were in the best condition possible. No luck.
- We used "Calculation Help" to try to spread out the load of the closing process among several work stations. This shortened the 24 hours, but still ended in "Out of memory".
- We set the Maximum Throughputs and Minimum... parameters to favor speed over accuracy. For us, that was an option because this wasn't the system of record - we just need to get to a clean starting point.
- When the inventory close failed, the status of the Invent Closing record was "Ledger Posting".
- All of the inventory settlement records had been created (and didn't roll back) when the inventory close failed.
- In looking at the code, it became clear the the "Calculation Help" only applied to creating/processing the inventory settlement records. When it got to posting to the ledger, the original client was the only one doing the work.
- In looking at the code, it seemed that Posting with a specification of Total, Item Group, or Item didn't change the transaction size. We had a specification of 'Total'. (that's the only one we tried)
- Create InventSettlement records. We used the records created by one of our failed attempts, but you could also comment out the call to this.updateLedgerPosting(); towards the bottom of classes\InventCostHelp.run().
- Create several InventClosing records with status of "Ledger Posting". We created 3 total. You can make these by commenting out some code in classes\InventCostHelp.run() after the inventClosing record is inserted but before any work is done.
- Update InventSettlement.Voucher (in SQL Mgmt Studio) to match InventClosing.Voucher so that the InventSettlement records are assigned to the InventClosing records that you created in manageable chunks. Since we were posting with a specification of 'Total' we just split the records roughly in thirds. If you're posting by Item Group, you might want to take care to put all of the same item group in the same voucher.
- Post each InventClosing record. Normally, when an inventory close record has failed, all you can do is cancel it. We temporarily commented code so that when we clicked Close on a failed record, it would 'pick up where it left off' and run updateLedgerPosting(). I've included some snippets below on this.
Success!
Code related to step #4:
classes\InventCostClosing
static void main(Args args)
{
InventClosing inventClosing;
FormDataSource fd;
InventCostClosing closing = InventCostClosing::newParameters();
//NDP 9/24/10 - BEGIN temp change
if (args && args.caller() && args.dataset() == tablenum(InventClosing))
{
inventClosing = args.record();
}
InventCostHelp::newInventClosing(inventClosing,true).run();
/*
if (! closing.prompt())
return;
try
{
closing.run();
}
catch
{
exceptionTextFallThrough();
}
*/
//NDP 9/24/10 - END
if (args && args.caller() && args.dataset() == tablenum(InventClosing))
{
...
classes\InventCostHelp
public void run()
{
...
setprefix(InventCostClosing::prefixText(inventClosing.AdjustmentType));
try
{
this.progressInit(InventCostClosing::prefixText(inventClosing.AdjustmentType),inventClosing.CostNumOf,#AviUpdate);
//NDP 9/24/10 - comment out starting here
/*
if (! this.validate())
throw error("@SYS18447");
...
if (doMasterClient && !trueClient)
masterClient = true;
*/
//NDP 9/24/10 - end comment out here
if (! doStop && masterClient)
{
this.updateLedgerPosting();
if (inventClosing.RunRecalculation && systemdateget() > inventClosing.TransDate)
{
this.runRecalculation();
}
}
Hope that helps,Nate
No comments:
Post a Comment