/******************************************************************************
* 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.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import ar.com.ergio.print.fiscal.exception.DocumentException;
/**
* Clase que representa un documento fiscal/no fiscal a imprimir en una
* impresora fiscal. Cualquier documento que se deba imprimir en una
* <code>FiscalPrinter</code> debe estar conformado por una clase que
* especialice esta clase abstracta.
* @author Franco Bonafine
* @date 11/02/2008
* @contributor Emiliano Pereyra - http://www.ergio.com.ar
*/
public abstract class Document implements Serializable{
/**
*
*/
protected static final long serialVersionUID = 1L;
// Tipos de documento.
/** Tipo de documento: Factura */
public static final String DT_INVOICE = "I";
/** Tipo de documento: Nota de Crédito */
public static final String DT_CREDIT_NOTE = "CN";
/** Tipo de documento: Nota de Débito */
public static final String DT_DEBIT_NOTE = "DN";
/** Tipo de documento: Remito */
public static final String DT_SHIPMENT = "S";
// Letras de documento.
/** Letra de Documento: A */
public static final String DOC_LETTER_A = "A";
/** Letra de Documento: B */
public static final String DOC_LETTER_B = "B";
/** Letra de Documento: C */
public static final String DOC_LETTER_C = "C";
/** Ciente asociado al documento */
private Customer customer;
/** Número de documento/comprobante */
private String documentNo;
/** Líneas del documento */
private List<DocumentLine> lines;
/** Percepcion general (emmie) */
private PerceptionLine perceptionLine;
/** Descuento general */
private DiscountLine generalDiscount;
/** Observaciones o descripciónes del documento */
private List<String> observations;
/** Letra del documento. */
private String letter;
/** Descuentos a nivel documento */
private List<DiscountLine> documentDiscounts = null;
public Document() {
super();
customer = new Customer();
lines = new ArrayList<DocumentLine>();
observations = new ArrayList<String>();
documentDiscounts = new ArrayList<DiscountLine>();
}
/**
* @return Returns the customer.
*/
public Customer getCustomer() {
return customer;
}
/**
* @param customer The customer to set.
*/
public void setCustomer(Customer customer) {
this.customer = customer;
}
/**
* @return Returns the documentNo.
*/
public String getDocumentNo() {
return documentNo;
}
/**
* @param documentNo The documentNo to set.
*/
public void setDocumentNo(String documentNo) {
this.documentNo = documentNo;
}
/**
* Agrega una línea al documento.
* @param line Línea a agregar.
*/
public void addLine(DocumentLine line) {
getLines().add(line);
}
/**
* Elimina una línea del documento.
* @param line Línea a eliminar.
*/
public void removeLine(DocumentLine line) {
getLines().remove(line);
}
/**
* @return Returns the lines.
*/
public List<DocumentLine> getLines() {
return lines;
}
public void setPerceptionLine(PerceptionLine perceptionLine)
{
this.perceptionLine = perceptionLine;
}
public PerceptionLine getPerceptionLine()
{
return perceptionLine;
}
/**
* @return Returns the generalDiscount.
*/
public DiscountLine getGeneralDiscount() {
return generalDiscount;
}
/**
* @param generalDiscount The generalDiscount to set.
*/
public void setGeneralDiscount(DiscountLine generalDiscount) {
this.generalDiscount = generalDiscount;
}
/**
* @return Returns the observations.
*/
public List<String> getObservations() {
return observations;
}
/**
* Agrega una observación al documento.
* @param observation Texto de la observación.
*/
public void addObservation(String observation) {
observations.add(observation);
}
/**
* Elimina una observación del documento
* @param observation Observación a eliminar.
*/
public void removeObservation(Object observation) {
observations.remove(observation);
}
/**
* @return Indica si el documento tiene o no asignado un descuento general.
*/
public boolean hasGeneralDiscount() {
return getGeneralDiscount() != null;
}
/**
* @return Returns the letter.
*/
public String getLetter() {
if(letter == null)
letter = "";
return letter;
}
/**
* @param letter The letter to set.
*/
public void setLetter(String letter) {
this.letter = letter;
}
/**
* @return Retorna veraddero en caso de que el documento tenga una letra
* asignada.
*/
public boolean hasLetter() {
return getLetter() != null;
}
/**
* @return Retorna el tipo de documento.
*/
public abstract String getDocumentType();
/**
* Validación del documento.
* @throws DocumentException cuando el documento no puede enviarse
* a imprimir dado que esta acción produciría un estado de error en la
* impresora fiscal.
*/
public void validate() throws DocumentException {
try {
// Se validan los datos del cliente.
getCustomer().validate();
} catch (DocumentException e) {
// Se relanza la excepción agregando este documento como
// parámetro.
e.setDocument(this);
throw e;
}
// Validar total del documento distinto de 0.
validateNumber(getTotal(), "!=", BigDecimal.ZERO, "InvalidDocumentTotalAmount");
// Validar las líneas del documento.
for (DocumentLine docLine : getLines()) {
docLine.validate();
}
// Validar el descuento general.
if(hasGeneralDiscount())
getGeneralDiscount().validate();
// Validar descuentos / recargos del documento
for (DiscountLine discount : getDocumentDiscounts()) {
discount.validate();
}
}
/**
* @return Retorna el monto total del documento.
*/
public BigDecimal getTotal() {
BigDecimal sum = BigDecimal.ZERO;
// Se suma el total de cada línea.
for (DocumentLine docLine : getLines()) {
sum = sum.add(docLine.getLineTotal());
}
// Se suma el descuento en caso de existir.
if(hasGeneralDiscount())
sum = sum.add(getGeneralDiscount().getAmount());
return sum;
}
/**
* Validación de un texto. Valida que no sea null y que contenga al menos
* un caracter visible.
* @param text Texto a validar.
* @param errorMsg Mensaje de error a lanzar en caso de que no sea válido.
* @throws DocumentException cuando el texto no es válido.
*/
public static void validateText(String text, String errorMsg) throws DocumentException {
if(text == null || text.trim().length() == 0)
throw createDocumentException(errorMsg);
}
/**
* Validación de un número.
* @param number Número a validar.
* @param operand Operación a realizar con <code>otherNumber</code> (<code><=, <, >, >=, ==, !=</code>).
* @param otherNumber Número a comparar.
* @param errorMsg Mensaje de error a lanzar en caso de que no sea válido.
* @throws DocumentException cuando el número no cumple la condición.
*/
public static void validateNumber(BigDecimal number, String operand, BigDecimal otherNumber, String errorMsg) throws DocumentException {
boolean operResult = false;
if(operand.equals("<="))
operResult = number.compareTo(otherNumber) <= 0;
else if(operand.equals("<"))
operResult = number.compareTo(otherNumber) < 0;
else if(operand.equals(">"))
operResult = number.compareTo(otherNumber) > 0;
else if(operand.equals(">="))
operResult = number.compareTo(otherNumber) >= 0;
else if(operand.equals("=="))
operResult = number.compareTo(otherNumber) == 0;
else if(operand.equals("!="))
operResult = number.compareTo(otherNumber) != 0;
else
operResult = false;
if(number == null || !operResult)
throw createDocumentException(errorMsg);
}
/**
* Método factory de excepciones de documento.
* @param msg Mensaje de la excepción.
* @return La excepción.
*/
protected static DocumentException createDocumentException(String msg) {
return createDocumentException(msg, null);
}
/**
* Método factory de excepciones de documento.
* @param msg Mensaje de la excepción.
* @param document Documento origen de la excepción.
* @return La excepción.
*/
protected static DocumentException createDocumentException(String msg, Document document) {
return new DocumentException(msg, document);
}
/**
* @return el valor de documentDiscounts
*/
public List<DiscountLine> getDocumentDiscounts() {
return documentDiscounts;
}
/**
* @return Indica si ese documento tiene descuentos de encabezado asociados.
*/
public boolean hasDocumentDiscounts() {
return !getDocumentDiscounts().isEmpty();
}
/**
* Agrega un descuento a nivel documento a este documento
* @param discount Línea de descuento a agregar.
*/
public void addDocumentDiscount(DiscountLine discount) {
getDocumentDiscounts().add(discount);
}
}