The Ninja plugin is doing wonders in bulk CSV import of model data such as for M_Product. However there is a protected AfterSave method that will generate Accounting Defaults and M_Cost detail. Those have to be done manually if we import data externally and not thru the MProduct.java.
To avoid redoing, or calling every core model Java method from my Ninja code, i have to externally invoke the afterSave() method of any model class during runtime dynamically. I faced an issue since last week as the methods are protected. After some long Googling and experimenting i finally made them work. Below is the very short snippet that can work on any core table:
- Code: Select all
if (tableHasSequence!=null){
int pk = DB.getSQLValue(trxName, "SELECT "+model+"_ID FROM "+model+WHERE);
if (pk>0){
PO po = tableHasSequence.getPO(pk, trxName);
Class<? extends PO> clazz = po.getClass();
try {
Method method = clazz.getDeclaredMethod("afterSave", boolean.class,boolean.class);
method.setAccessible(true);
method.invoke(po, true,true);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
As seen, there is no fixed model identity. TableHasSequence is the PO model of the core data i.e. M_Product or C_BPartner. All we need to do is to extract from the ModelFactory and pass it the primary key (PK) of the record just created from a CSV line.
The tricky part is to get the right POClass to expose its protected method. The hack is method.setAccessible(true). That is a good problem as it means we can hack into protected Java code!

Finally invoke must use the PO instance and passing the two args of (new record?, successful save?).
This snipper is part of the HandleCSVImport class and at the end of the everyLineUpdateInsert(). I will test if for the updateExisted method too. Then will try it for all the core models importing. Once OK will commit it.