#35740
Javier Ader
Participante

Matias, vos decis que la pestaña “de cuotas” (vencimientos de pagos creo que es) es editable? (una pavada pero no lo pude chequiar ya que en la base actual que tengo no tengo ninguna factura con esquemas de pagos…); pense que no, por eso todo el tema de “automatico” vs “manual”. Si es editable (lo cual tiene todo el sentido ahora que lo pienso; esto es, siempre son manuales, al menos respecto a los montos y la fechas) entonces tiene cierto sentido que afterSave de MInvoicePaySchedule (de aca en mas IPS) revalide la factura y la guarde (pero solo bajo ciertas ciertas circunstancias que adelante explico).

Mire un poco el codigo de Adempiere, y es casi identico, en particular:
-MInvoice.IsPayScheduleValid es Y si y solo si la sumataria delos IPS.DueAmt es exctamente igual a MInvoice.GrandTotal.
-IPS.afterSave revalida la factura si se modifico DueAmt (is_ValueChanged(“DueAmt”), lo cual creo que es true incluso en instancias recien creadas); lo caul creo que tambien es un error aca, ya que se hace siempre.
-la utilización de los porcentajes y descuentos es igual (IPS.DueAmt = GranTotal * Porcentaje; IPS.DiscountAmt = IPS.DueAmt * Porcentaje de descuento )
-MPaymentTerm.applySchedule : tambien le agrega al ultimo IPS lo que resta si las totales no son exactamente igual (esto es, si uno tiene una 3 cuotas, de 30%, la ultima va ser tratada en la practica como de 40%), y tambien llama sobre el final a MInvoice.validatePaySchedule()
-Tambien se rendondean incorrectametne los montos de las cuotas (se uiliza la escala de la moneda para realizar la division necesaria para el porcentaje, pero no para redondear el resultado de la mutiplicación; por lo tanto el monto de la cuota va a tener mas decimales que lo que dice la precisión de la moneda….. el tema es que ellos almacenan los montos como numeric, esto es, con cualquier cantidad de decimales; libertya almacena todo con 2 decimales…. esto en libertya se va a producir un redondeo o trucado a nivel de base de datos sobre estos montos, se haga o no el redondeo desde java…)… en cualquier caso, la correccion posterior que hace MPaymentTerm creo que lo soluciona en ambos sistemas (el tema es que ellos pueden llegar a tener el monto de una cuota por ej con valor 33.1234 incluso cuando la precisión de la moneda sea 2; Libetya va a tener necesariamente 33.12, pero esto por que lo hace la base de datos…. )

Las diferencias:
-MInvoice cuando vueve a salvar los ips llama a un metodo saveEx, lo cual simplemente es un save() pero que dipsara una excepcion en caso de el save retorne false (esta buena la idea, ya que simplifica mucho el tipico codiogo “if o.save()! return “error o dispara una execpion”. Esto es, el prepareIt falla si falla el guadadado de los IPS (lo cual tieen sentido, si no puede darse el caso de que los IPS queden en estado inconsistente con respecto a MInvoice.IsPayScheduleValid)
-no se intenta saltear feriados del EC y cosas por el estilo; la fecha del pago es siempre la fecha de facturación mas la cantidad de dias netos datos en C_PaySchedule, lo mismo para la fecha “de descuento” (la cual no se entiende bien si es para un sobrecargo o descuento….)

En cualquier caso, lo que mas raro veo es el afterSave de los IPS; ya que no tienen en cuenta dos cosas: que la factura ya este paga (en ese caso seria un error, al menos conceptual, creo modificar el plan de pagos), en tal caso deberia disparar un error y si se esta invocando desde MPaymentTerm o MInvoice en estos dos casos es incorrecto la revalidación de la factura y su guardado (esto se va a hacer a posteriormente).
Dicho esto, pienso que el codigo de MInvoicePaySchedule deberia tener un flag para saltear la revalidación, y que este flag se seteado tanto de MPaymentTerm como Minvoce; algo asi

Code:
//MInvoicePaySchedule
public booelan afterSave(newRedord, sucess)
{
if (!sucess) return false;

if (m_skipInvoiceValidatePaySchedule)
return true;

if( is_ValueChanged( “DueAmt” )) {
log.fine( “afterSave” );
getParent();
m_parent.validatePaySchedule();
m_parent.save(); //IGUAL ESTO ES DUDOSO, tal vez deberia usarse un
//update directo sobre la factura para setear IsPayScheduleValid
//con el resultado de validatePaySchedule, asi se saltea toda la logica
//de after y beforeSave de MInvoice
}
return true;
}

public beforeSave(newRecord)
{
//opcional, agregar esto:
getParent();
if (m_parent.isPaid())
{
“error la factura ya esta paga”;
return false;

}

//lo que sigue igual
}

//finalmente el flag false por defecto; saltea la revalidación y guardado de la factura
boolean m_skipInvoiceValidatePaySchedule = false;
public booelan getSkipInvoiceValidatePaySchedule() { return m_skipInvoiceValidatePaySchedule;}
public void setSkipInvoiceValidatePaySchedule(booelan skip)
{ m_skipInvoiceValidatePaySchedule = skip}

Finalmente MPayementTerm.applySchedule y MInvoice.validatePaySchedule setean este flag a true en cada instancia de MInvoicePaySchedule a la que acceden (en ambos casos, el que determina si cada IPS y la factura es valida como un todo va a ser MInvoice; no es necesario que cada IPS invoque la revalidación)

En cuanto a que el AfterSave de Minvoice genere el esquema de pagos (y asi dejar de usar el callout) tiene sentido, pero me parece que trae otros problemas ya que este afterSave se puede llamar muchas veces… Todas estas cosas son necesidades visuales, ya que se van a pisar en el prepareIt…. Tal vez habria que agregar un boton para que el usuario puede regenrar el esquema de pagos cuando lo desee (esto tiene la contra de que se tiene que agregar una columnas mas en la base de datos… tampoco me gusta mucho… habria que encontrar una solucion generar para agregar este tipo de “acciones” a tablas pero sin modificarlas; en vez de esto agregar otras “tablas” de extensión, que generen menus de accciones en la ventanas, especificas para la tabla… hace rato que quiero hacer algo al respecto como una solución general a esta y otras cosas, algun dia tendré tiempo… igual, esto es otro tema)