#35267
Javier Ader
Participante

Y si… ademas de por el bug que te comente, una misma linea de pedido es ingresada mas de una vez; en realidad una vez por cada beforeSave y afterSave() de MorderLine…. (la razón: el select count(*) se hace sobre transaccion “null”; pero la creacion de las entradas en la tabla se hace sobre la transacción que esta usando la linea….).
Ahora, seguro que comentado estas invocaciones (yo ya lo hice y no vi nada raro) se mejora la performace el tpv…. cada linea del pedido es salada cerca de 10 veces; estas 10 veces generan 4 accesos a estas tablas (dos en el before, 2 en el after)… Es decir; 40 accesos adicionales por linea de pedido que no tienen mucho sentido.

Fijate también en MOrder.afterSave (creo…); que llama a un método “afterSaveSync” la primer parte de este método tiene que ver con esta tabla; también la comente… Después de eso te tira un error, porque el código que sigue actualiza codigo que realmente “deberia” estar sincronizado entre el pedido y sus lineas… el tema es que el afterSync es llamado con “DocStatus”; una columna que no existe en las lineas; por lo tanto tambien comente la invocacion afterSaveSync( “DocStatus” ). (las demas invocaciones “parecen” estar bien…)

Ok, ahi con esto la ganancia es minima (un sql update por cada save en una Morder) pero bueno… es lo correcto.

Un tema relacionado: si estas con la optimización del TPV (algo en lo que tambien estoy…) mira por los afterSave de MorderLine (iba a hacer un thread sobre esto, pero bueno, lo pongo aca…). Ahi se actualiza los C_OrderTax del pedido y el total (en 10.09 se hace de una manera un poco distinta a 10.03, pero termina sineod lo mismo). Ese codigo no solo ralenta mucho el TPV si no que es ….. incorrecto.
Por que? y bueno, uno modifica una linea, no se deberia tocar NADA de la cabecera, principalmente porque la cabecera puede estar completa (si uno recalcula los impuestos, va a estar modificando un pedido que NO deberia modificarse, ya que esta completo y posiblemente contabilizado; y el resulta puede ser distinto, si por ej, algun producto cambio de cat. iva ). Es decir, se viola el “pricipio” de que los documentos completos no se modifican. Se puede dar esto? Y si….. se da todo el tiempo; el punto mas evidente es cuando se completa un remito o una factura asociada a un pedido (sus lineas son modificadas, pero solo ciertas partes como la cantidad entregada y facturada; eso esta bien; el tema es que el after save no mira para nada esto….
De donde viene este actualizacion de un header por parte de una linea? Y… no se, pero debe venir de que sirve a la gui, ya que te mantiene actualizados los totales cuando uno modifica o agrega una linea….
Que solucion veo? Que esto solo se lleve a cabo cuando el pedido que contitne a la linea este en estado drafted… En realidad es una situación tan común modificar un documento cuando NO esta en drafted (externamente via el codigo de otro documento, por ej, de un remito, sobre las lineas de un pedido), que pienso que habria que poner un metodo directametne en PO, que sirva para todos estos casos; algo como

Code:
public boolean isHeaderDrafted(String TableHeader, int IdHeader)
{
if (idHeader <= 0) false; //igual , se supune que es llamado desde el afterSave //o del beforeSave pero cuanod no "isNew"; asi que no deberia darse ya que se deberia haber setedo en la linea String sqlST = "SELECT DocStatus FROM " + TableHeader + " WHERE " + TableHeader+"_ID = " + getId(); PreparedStatement pstmt = DB.preparedStatement(sqlST,getTrx_Name()); String ST = null; //try.... y toda la bola ResultSet rs = pstmt.executeQuery(); if (rs.next()) ST = rs.getString(1); else //se loguea algun error, return "DR".equals(ST); }

(fijate que el el preparedStatement corre sobre la transacción que esta usado el objeto actual… si no, se rompe todo; va a pasar los mismo que el select que te dije antes…)
Entonces, el codigo del afterSave, no puede hacerse mas eficiente:

Code:
afterSave…. sobre el final
….
if (isHeaderDrafted(“C_Order”,getC_Order_ID())
{

//SOLO ahora actualizo los totales y los impuestos…
//si esto es necesario claro; SI NO, no se toca nada del
//header, ya que no esta en estado Drafted

}

Lo ultimo, como te dije, no solo es por eficiencia, si no también por correctitud, y pienso que se debería aplicar a MInvoceLine y MInOutLine (bueno , en realidad , a casi cualquier cosa que se una “linea” de un documento; incluso tal vez a otras cosa relacionadas, como COrderTax, o CInvoiceTax).

Incluso mas… en el beforeSave o afterSave se podria llegar a dispara un error si se descubre que se esta modificando algo que no deberia poder ser modificado sobre un pedido/remito/factura no drafted. Por ej, desde la linea del pedido se deberia chequear que cosas como la cantidad o el producto NO estan siendo modificadas en un pedido NO drafted (en el caso del pedido creo que hay solo 2 o 3 columnas que deberias ser permitidas modicadas desde codigo: la cantidades ordernadas, entregadas y facturadas; todo lo demas, SOLO si el pedido esta en DR). También por ej, en el before o afterSave de registro nuevos se debería poder evitar la inserción sobre no documento no DR (algo similar en before o after delete).

La ganancia que tenes ahi de efincia es de 2 o 3 accesos por cada modificación de linea de pedido luego de que este esta en estado completo (hay que contar que el chequeo te come 1 acceso, asi que la ganancia no es tan grande).

Finalmente, esto no afecta la correctitud (en realidad, el código que afecta a la cabecera puede ser elminado completamente; salvo que desde la gui no se va a tener los resultados calculados hasta que hasta que uno lo complete), ya que el prepareIt de Morder, recalcula todo de nuevo, asi que las COrderTax y los totales van a estar ok.