/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2007 ComPiere, Inc. All Rights Reserved. *
* This program is free software, you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY, without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program, if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package ar.com.ergio.print.fiscal.document;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import ar.com.ergio.print.fiscal.exception.DocumentException;
import ar.com.ergio.print.fiscal.msg.MsgRepository;
public class Invoice extends Document {
/**
*
*/
private static final long serialVersionUID = 1702265732103996574L;
private static BigDecimal maxAmountCF = new BigDecimal(1000);
/** Número del CAI*/
private String caiNumber;
/** Número del remito asociado a la factura */
private String packingSlipNumber;
/** Lista de pagos realizados */
private List<Payment> payments;
/** Indica si la factura a consumidor final no supera el monto
* máximo permitido sin identificación del cliente */
private boolean validCFInvoice;
public Invoice() {
super();
payments = new ArrayList<Payment>();
}
/**
* @return Returns the packingSlipNumber.
*/
public String getPackingSlipNumber() {
return packingSlipNumber;
}
/**
* @param packingSlipNumber The packingSlipNumber to set.
*/
public void setPackingSlipNumber(String packingSlipNumber) {
this.packingSlipNumber = packingSlipNumber;
}
/**
* @return Retorna verdadero si la factura tiene un
* número de remito asociado.
*/
public boolean hasPackingSlipNumber() {
return getPackingSlipNumber() != null && !getPackingSlipNumber().equals("");
}
/**
* @return Returns the caiNumber.
*/
public String getCAINumber() {
return caiNumber;
}
/**
* @param caiNumber The caiNumber to set.
*/
public void setCAINumber(String caiNumber) {
this.caiNumber = caiNumber;
}
/**
* @return Indica si la factura tiene asignado o no un número de CAI.
*/
public boolean hasCAINumber() {
return getCAINumber() != null && !getCAINumber().equals("");
}
@Override
public String getDocumentType() {
return DT_INVOICE;
}
@Override
public void validate() throws DocumentException {
super.validate();
// Validar cantidad de líneas mayor que 0.
if (getLines().isEmpty()) {
throw createDocumentException("InvalidDocumentLinesCount", this);
}
// Validar que si la factura es a CONSUMIDOR FINAL el monto acumulado
// de las lineas no supere el límite definido. Si lo supera, se deben
// ingresar los datos del comprador.
validateInvoiceCFLimit();
// Se validan los pagos.
for (Payment payment : getPayments()) {
payment.validate();
}
}
private void validateInvoiceCFLimit() throws DocumentException {
// Esta validación debe hacerse línea por línea y ni bien se detecte
// que el acumulado supera el máximo se debe disparar un error dado
// que es así como se ejecutan los comandos en la impresora fiscal
// y la misma no puede predecir si luego de una linea de X monto va a
// venir un descuento (el cual haría que el total de la factura
// sea válido).
Customer c = getCustomer();
boolean validName = c.getName() != null && !c.getName().trim().equals("");
boolean validLocation = c.getLocation() != null && !c.getLocation().trim().equals("");
boolean validIdNumber = c.getIdentificationNumber() != null && !c.getIdentificationNumber().trim().equals("");
boolean customerDataValid = validName && validLocation && validIdNumber;
// Se asume que la factura será válida.
setValidCFInvoice(true);
if(getCustomer().getIvaResponsibility() == Customer.CONSUMIDOR_FINAL && !customerDataValid) {
BigDecimal total = BigDecimal.ZERO;
boolean amountValid = true;
// Por cada línea...
for (DocumentLine docLine : getLines()) {
// Se suma al total (sin descuentos / recargos).
total = total.add(docLine.getSubtotal());
// Se pregunta si sigue siendo válido el monto.
if (total.compareTo(getMaxAmountCF()) > 0) {
amountValid = false;
// Si sigue siendo válido
} else {
// Se obtiene el monto del descuento / recargo.
BigDecimal discountAmt = (docLine.hasDiscount() ?
docLine.getDiscount().getAmount() : BigDecimal.ZERO);
total = total.add(discountAmt);
// Y se válida nuevamente el total.
if (total.compareTo(getMaxAmountCF()) > 0) {
amountValid = false;
}
}
// Si no fue válido en alguno de los casos, se dispara la excepcion
if(!amountValid) {
// Se arma el mensaje de respuesta.
StringBuffer msg = new StringBuffer();
msg.append(MsgRepository.get("InvalidCFInvoiceAmount"));
msg.append(" ($" + getMaxAmountCF() + "). ");
msg.append(MsgRepository.get("CompleteCustomerFields") + ": ");
if (!validName) {
msg.append(MsgRepository.get("Name") + (!validLocation ? "," : ""));
}
if (!validLocation) {
msg.append(MsgRepository.get("Location") + (!validIdNumber ? "," : ""));
}
if (!validIdNumber) {
msg.append(MsgRepository.get("IdentificationNumber"));
}
throw Document.createDocumentException(msg.toString(),this);
}
}
}
}
/**
* Agrega un pago al documento.
* @param payment Pago a agregar.
*/
public void addPayment(Payment payment) {
payments.add(payment);
}
/**
* Elimina un pago del documento en caso de existir.
* @param payment Pago a eliminar.
*/
public void removePayment(Payment payment) {
payments.remove(payment);
}
/**
* @return Returns the payments.
*/
public List<Payment> getPayments() {
return payments;
}
/**
* @return Retorna verdadero en caso de que el documento tenga asignado
* algun pago.
*/
public boolean hasPayments() {
return !getPayments().isEmpty();
}
/**
* @return Returns the maxAmountCF.
*/
public static BigDecimal getMaxAmountCF() {
return maxAmountCF;
}
/**
* @param maxAmountCF The maxAmountCF to set.
*/
public static void setMaxAmountCF(BigDecimal maxAmountCF) {
Invoice.maxAmountCF = maxAmountCF;
}
/**
* @return Returns the validCFInvoice.
*/
public boolean isValidCFInvoice() {
return validCFInvoice;
}
/**
* @param validCFInvoice The validCFInvoice to set.
*/
protected void setValidCFInvoice(boolean validCFInvoice) {
this.validCFInvoice = validCFInvoice;
}
}