This code is posted for educational and discussion purposes only. You should not run this code on a production environment. Use at your own risk. Having said that, here is what I tried to accomplish with this sample code. First and most importantly, attempting to settle all open transactions should not impact the customer balance, and I've included some checks to try to guarantee that. Two of the Accounts receivable parameters should be set to zero, "Maximum penny difference" and "Maximum overpayment or underpayment", otherwise the system may automatically post write-off amounts if the debit and credit transactions happen to be close enough in their amounts. I have some concerns that the Account receivable parameter "Cash discount administration" should be set to Specific, but it didn't seem to matter in my light testing. I'm setting the Use cash discount on both transactions to Never to prevent any cash discount posting. Finally, I capture the open balance amount and check it before the transaction is committed, in an attempt to trap unforeseen scenarios. To facilitate testing, this code aborts after one customer, and it reports which customer it settled and the before/after balances. You should inspect the before and after states closely to see if its doing what you need. I can't stress enough that this is only for discussion purposes and anything you do with it is at your own risk. static void CustOpenMassSettle(Args _args) { CustVendOpenTransManager manager; CustTable custTable; CustTransOpen custTransOpenDbExist; CustTransOpen custtransOpenCrExist; CustTransOpen custTransOpenDb; CustTransOpen custTransOpenCr; AmountMST openBalanceMST; ; setPrefix(strFmt("Automatic settlement")); if (CustParameters::find().MaxMSTDiff || // maximum penny difference not 0 CustParameters::find().MaxMSTOverUnder) // maximum overpayment or underpayment not 0 { throw error(error::wrongUseOfFunction(funcName())); // fail } while select custTable order AccountNum exists join custTransOpenDbExist where custTransOpenDbExist.AccountNum == custTable.AccountNum && custTransOpenDbExist.AmountMST > 0 // debit amount exists join custTransOpenCrExist where custTransOpenCrExist.AccountNum == custTable.AccountNum && custtransOpenCrExist.AmountMST 0; // debit amount select firstOnly forUpdate custTransOpenCr order TransDate // oldest first where custTransOpenCr.AccountNum == custTable.AccountNum && custTransOpenCr.AmountMST < 0; // credit amount if (!custTransOpenDb.RecId || !custTransOpenCr.RecId) break; if (custTransOpenDb.UseCashDisc != UseCashDisc::Never) { custTransOpenDb.UseCashDisc = UseCashDisc::Never; // prevent cash discount posting custTransOpenDb.update(); } if (custTransOpenCr.UseCashDisc != UseCashDisc::Never) { custTransOpenCr.UseCashDisc = UseCashDisc::Never; // prevent cash discount posting custTransOpenCr.update(); } manager = CustVendOpenTransManager::construct(custTable); manager.updateTransMarked(custTransOpenDb, true); // add debit transaction manager.updateTransMarked(custTransOpenCr, true); // add credit transaction manager.updateSpecTransWithSelectedDate(); manager.settleMarkedTrans(); } info(strFmt("Customer balance before: %1, after: %2", openBalanceMST, custTable.openBalanceMST())); if (openBalanceMST != custTable.openBalanceMST()) // check for change in customer balance { ttsAbort; throw error(strFmt("@SYS138340")); // Operation failed } ttsCommit; break; // exit after one customer } info(strFmt("@SYS9265")); // Operation completed }
↧