
Bueno, aporto unas modificaciones que hice para manejar el tema del último TotalTender permitido; básicamente agregue tres métodos (yo los agregue a un driver que aún no termino completamte; despues lo subo; en el código de 10.09 o 10.03 debería ir en HasarFiscalPrinter.printInvoice, posiblemente modificando la forma en que se llama a cmdTotaTender):
/**
* Detemina si el CF soporta la cancelación de documentos despues de la emisión
* de un TotalTender; todas las tiqueadoras no soportan la cancelación leugos
* de la emisión de un TotalTender “excepto en los modelos SMH/P-PR5F (versión 2.01),
* SMH/P-715F (versiones 3.02 y posteriores), y SMH/P-441F.” (Sic. 3.4.10 TotalTender, Doc Hasar
* PubTick.pdf); todas las facturadoras parecen no permitir esto (Sic. 3.7.1. Cancel , Doc Hasar
* PubFact). Implemtanción default retonra false.
* @return
*/
protected boolean allowCancelAfterTotalTender()
{
return false;
}
/**
* Dada una respuesta a un TotalTender retorna el valor del campo que representa
* el faltante para saldar el total de la factura según el CF. Un valor
* positivo supone un faltante; cero saldado exactamente; y un némero negativo
* reqpresenta “cambio”.
* NOTA: este metodo retorna null si encuentra algún problema (por ej, el rspTotalTender
* no tiene el formado requerido); esto es asi porque propagar una excepcion en este
* punto puede llegar a dejar a varios CF en un estado de bloqueo (los documetnos abiertos
* no se pueden cancelar luego de emitido un TotalTender en mucho modelos/versiones).
* NOTA2: esta implementación siempre retorna un BigDeciaml redondeado a dos decimales
* con redondeo DOWN (hacia cero); esto no deberia afectar ya que todos CF Hasar retorna 2 decimales
* en esta respueta.
* @param rspTotalTender
* @return
*/
protected BigDecimal getRemainingAmount(FiscalPacket rspTotalTender)
{
BigDecimal remAmount = null;
if (rspTotalTender == null)
return null;
try{
//el monto esta en 3er campo
String remAmoutString = rspTotalTender.getString(3);
//se asume que que el CF no retorna cosas raras como “+.00” o “-0.”
remAmount = new BigDecimal(remAmoutString);
remAmount = remAmount.setScale(2, RoundingMode.DOWN);
}catch(Exception ex){}
return remAmount;
}
//FIN de soporte para printPayments
/**
* Ref C++ Hasar: ver ImpresorFiscal::ImprimirPago
* NOTA Maxima cantidad de pagos permitidos: Este metodo emite a los sumo
* getAllowedPaymentQty() de TotalTenders
* NOTA Tiqueadoras: Para los modelos SMH/P-715F -versiones 3.02 y posteriores-,
* SMH/P-PR5F -versión 2.01- y SMH/P-441F puede emitirse 5 veces; 4 en el resto.
*
* NOTA Cancelacion luego de pagos: esta implementación invoca a setCancellowed(false) luego
* de la emisión de un TotalTender solo si allowCancelAfterTotalTender() retonra false. Esto último
* es el comportamiento por defecto, ya que todas los CF Hasar no permiten la cancelación
* de docuemtnos luego de la emisión de un TotalTender, salvo las tiqueadoras
* SMH/P-715F -versiones 3.02 y posteriores-, SMH/P-PR5F -versión 2.01- y SMH/P-441F en
* las cuales la cancelación SIEMPRE es posible; los drivers de estos modelos deberían redefinir
* allowCancelAfterTotalTender() para que retorne true.
*
*
* Comentario acerda del último pago: El Comando TotalTender asociado puede
* fallar (es rechazado) si el pago adeudado es 0, o, mas importante, si se esta emitiendo
* el ultimo TotalTender permitido (el quinto o el cuarto, dep. del modelo/version) y este no
* alcanza a saldar totalmente el monto a saldar. Aca hay dos posibles soluciones: siempre emitir
* una cantidad menor de TotalTenders (4 o 3 maximo, dep. del modeolo/version) o en usar el valor
* de la respuesta Monto Faltante del anterior TotalTender usar este monto como el
* monto del ulimto TotalTender en caso de que Payment.getAmount sea menor.
* NOTA modificación 20 oct 2010 :
* MODIFICACION DE MANJEJO DE ULITMO TOTAL TENDER:
* 1) Por cada Payment
* -SI, monto faltante según el CF es menor o igual que cero; finaliza la impresión de pagos
* -SI no, si estamos estamos en el ultimo pago y este es menor al faltante, CAMBIAR MONTO de pago
* al faltante y posiblemente su descripción
* 2) ejecución normal de un TotalTender, chequear si se deben prohibir cancelaciones,
* actualización del total faltante a partir de la respueta del TotalTender.
*
* @param payments
*/
protected void printPayments(List
{
if (payments == null || payments.size()<=0)
return;
int maxTotalTenders = getAllowedPaymentQty();
BigDecimal remAmount = null;
for (int i = 0; i < payments.size(); i++)
{
Payment pay = payments.get(i);
BigDecimal payAmount = pay.getAmount();
String payDesc = pay.getDescription();
int numPayment = i + 1; //1,2,3....
if (numPayment > maxTotalTenders)
{
//NO debeira pasar, significa que se agregar mas payments que los
//permitidos a por getAllowedPaymentQty
break;
}
//assert(numPayment<= maxTotalTenders)
if (remAmount != null)
{
if (remAmount.compareTo(BigDecimal.ZERO)<=0)
{
//se saldo completamente y aún quedan pagos! aca podria ir
//un warning o mensaje, ya que no deberia pasar en general
break;
}
//assert(remAmount != null && remAmount > 0)-> esto es, hay faltante
//estamos por emitir el ulitmo TotalTender permitido, hay que chequear
//redondeos o modifaciones de la descripción del pago y del monto
//a pagar eviando remAmount para que no genere error (obligadamente se debe saldar
//completamente el documento con este TotalTender).
//Estas modificaiones solo son necesarias cuando el monto del pago es menor a
//el faltante; si es mayor o igual no se genera error nunca.
if (numPayment == maxTotalTenders && payAmount.compareTo(remAmount)< 0)
{
//el monto que le falta a payAmount para saldar completamente el documento
BigDecimal difCredito = remAmount.subtract(payAmount);
//modificación de la descripción original:
//por simplicidad SIEMPRE se agrega a la descipción
//"CC: difCredito, Resto:
//esto es, se supone que no hay error de redondeo; otra forma
//seria simplemente poner “Otro Pagos” y no usar el prefijo.
payDesc = “CC:” + difCredito.toPlainString()
+”, Resto:” + payDesc;
//finalmente, el monto a pagar realmente se pone a remAmount, asi
//el TotalTender salda exactametne el total de la factura. Este
//es el unico punto en que se cambia el monto a enviar.
payAmount = remAmount;
}
}
//se ejecuta el TotalTender
FiscalPacket rspTotalTender = execute(
cmdTotalTender( payDesc,payAmount,””));
//solo setea cancelAllowed a false, si el CF NO permite la cancelación de documentos
//luego de un TotalTender.
if (!allowCancelAfterTotalTender())
setCancelAllowed(false);
//se atualiza el totalFaltante o cambio
remAmount = getRemainingAmount(rspTotalTender);
//assert(remAmount != null) si no seria un error de formato en la respuesta
}
}
Esta bastante comentado, supongo que se entiende; básicamente opte por implementar la solución mas complicada (esto es permite la emisión de pagos máxima, pero si se llega al último pago permitido y se ve que no va saldar completamente la factura, se cambiar el valor a emitir en el pago, pero cambiándole la descripción).
OBS: mi versión de printDocument(Invoice) no llama directamente cmdTotalTender si no que lo delega a printPayments; es decir las lineas
// Se ingresan los pagos realizados por el comprador.
// Comando: @TotalTender
for (Payment payment : invoice.getPayments()) {
execute(cmdTotalTender(
payment.getDescription(),
payment.getAmount(),
false,
null)
);
setCancelAllowed(false);
}
se cambian por
// Se ingresan los pagos realizados por el comprador.
// varios @TotalTender
printPayments(invoice.getPayments());
Testeo:
lo testie forzando a llegar al limite te pagos y no saldar:
Total a pagar:
A PAGAR: 363,00
-50 efectivo
-100 tarjeta 1234, cupon 1
-100 tarjeta 1234, cupon 2
-100 tarteta 1234, cupon 3
-Resto a Credito desde el TPV: 13.00
Esto genera 4 TotalTenders (y por el efectivo y 3 por los pagos con tarjeta), pero el ulimto que emite de las tarjeta los hace por 113.00 , con la descripcion de la forma “CC:13.00, Resto:Visa 1”. Esto es, salda completamte la factura con el ultimo pago, pero le cambia la descripción reflejando este hecho.
EL otro teste que hice fue por el mismo monto y cantidad de pagos reales, pero de tal manera que no sea necesario una parte a crédito:
A PAGAR: 363,00
-50 efectivo
-110 tarjeta 1234, cupon 1001
-90 tarjeta 1234, cupon 1002
-113 tarteta 1234, cupon 1003
El último pago salda exactamente la factura, asi que al emitir el úttimo TotalTender, no le cambia la descripción.