/************************************************************************************
 * Copyright (C) 2017-2018 Openbravo S.L.U.
 * Licensed under the Openbravo Commercial License version 1.0
 * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
 * or in the legal folder of this module distribution.
 ************************************************************************************/

package org.openbravo.module.sii.invoicefiles;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.criterion.Restrictions;
import org.openbravo.base.exception.OBException;
import org.openbravo.dal.service.OBCriteria;
import org.openbravo.dal.service.OBDal;
import org.openbravo.model.common.currency.Currency;
import org.openbravo.model.common.enterprise.DocumentType;
import org.openbravo.model.common.invoice.Invoice;
import org.openbravo.model.common.invoice.InvoiceTax;
import org.openbravo.model.financialmgmt.tax.TaxCategory;
import org.openbravo.model.financialmgmt.tax.TaxRate;
import org.openbravo.module.sii.data.AEATSIIConfig;
import org.openbravo.module.sii.utils.GenericTax;
import org.openbravo.module.sii.utils.SIICreator;
import org.openbravo.module.sii.utils.SIIUtils;

/**
 * Code developed by Opentix S.L.
 * 
 * @author imonferrer
 * @created 4 may. 2017
 */
public class FacturaExpedida extends SIICreator {

  protected String tipoFactura;
  protected String tipoRectificativa;
  protected String fechaOperacion;
  protected String claveRegimenEspecialTrascendencia;
  protected String claveRegimenEspecialTrascendencia2;
  protected String claveRegimenEspecialTrascendencia3;
  protected String numRegistroAcuerdoFacturacion;
  protected String importeTotal;
  protected String descripcionOperacion;
  protected String importeTransmision;

  protected String tipoOperacion = null;

  protected boolean rectificativa = false;
  protected boolean sujeta;
  protected boolean exenta;
  protected boolean tieneInmueble = false;
  protected boolean esTransmision = false;
  protected boolean noSujetaArticulos;
  protected boolean intracomunitaria = false;
  protected boolean isISP = false;
  protected boolean isREBU = false;

  protected int lineasImpuesto;

  protected List<GenericTax> listaImpuestosAgrupados = new ArrayList<GenericTax>();

  @Override
  public void validate() {

    List<String> wrongFields = new ArrayList<String>();

    if (tipoFactura == null || tipoFactura.equals("")) {

      wrongFields.add("Tipo Factura");
    }

    if (rectificativa) {

      if (tipoRectificativa == null || tipoRectificativa.equals("")) {

        wrongFields.add("Tipo factura rectificativa");
      }
    }

    if (claveRegimenEspecialTrascendencia == null || claveRegimenEspecialTrascendencia.equals("")) {

      wrongFields.add("Clave Regimen Especial o Trascendencia");
    }

    if (importeTotal == null || importeTotal.equals("")) {

      wrongFields.add("Importe total");
    }

    if (descripcionOperacion == null || descripcionOperacion.equals("")) {

      wrongFields.add("Descripción de la Operación");
    }

    String text = "";

    for (String s : wrongFields) {

      text += s + ", ";
    }

    if (!text.equals("")) {

      text = "Faltan los siguientes campos por rellenar de los datos de la factura expedida: "
          + text;

      text = text.substring(0, text.length() - 2) + ".";

      throw new OBException(text);
    }
  }

  @Override
  public void create(Object object) {

    Invoice invoice = (Invoice) object;

    SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");

    this.fechaOperacion = sdf.format(invoice.getAeatsiiFechaOperacion());

    this.tipoFactura = invoice.getAeatsiiClaveTipo();

    if (invoice.getAeatsiiDescripcionSii() != null) {

      this.descripcionOperacion = SIIUtils.stringToFile(invoice.getAeatsiiDescripcionSii(), 500);
    }

    this.claveRegimenEspecialTrascendencia = "01";

    OBCriteria<InvoiceTax> cImpuestosFactura = OBDal.getInstance().createCriteria(InvoiceTax.class);
    cImpuestosFactura.add(Restrictions.eq(InvoiceTax.PROPERTY_INVOICE, invoice));

    List<InvoiceTax> listaImpuestosFactura = cImpuestosFactura.list();

    String nombreImp = "";

    boolean flagArrendamientos = false;

    BigDecimal impTrans = BigDecimal.ZERO;

    boolean isSalesInvoice = invoice.isSalesTransaction();
    boolean containsExportTax = false;

    for (InvoiceTax impFactura : listaImpuestosFactura) {

      TaxRate imp = impFactura.getTax();

      nombreImp = imp.getName().toLowerCase();

      if (imp.getId().equals("3ECEF933D8204EADA2558E5B00974396")
          || imp.getId().equals("F4B364332EE84B578E27343CB8FDA70F")
          || nombreImp.contains("Entregas sin IVA por ISP")) {

        this.isISP = true;
      }

      if (nombreImp.contains("transmis")) {

        this.esTransmision = true;

        impTrans = impTrans.add(impFactura.getTaxableAmount());
        impTrans = impTrans.add(impFactura.getTaxAmount());
      }

      if (imp.isObsptiIsexport()) {

        containsExportTax = true;
      }

      if (imp.isObsptiIslease()) {

        flagArrendamientos = true;
      }
    }

    boolean flagDesgloseOperacion = false;

    for (InvoiceTax impFactura : listaImpuestosFactura) {

      TaxRate imp = impFactura.getTax();

      if (imp.isOBSPTIIsintracommunity()) {

        flagDesgloseOperacion = true;
        break;
      }
    }

    if (!flagDesgloseOperacion) {

      if (invoice.getPartnerAddress().getLocationAddress().getCountry().isEucntryIseucountry()
          && !invoice.getPartnerAddress()
              .getLocationAddress()
              .getCountry()
              .getISOCountryCode()
              .equals("ES")) {

        flagDesgloseOperacion = true;
      }
    }

    if (!flagDesgloseOperacion) {
      int claveIdentificacion = Integer.valueOf(invoice.getBusinessPartner().getOBTIKTaxIDKey());
      if (claveIdentificacion == 1 && invoice.getBusinessPartner().getTaxID().startsWith("N")) {
        flagDesgloseOperacion = true;
      }
    }

    // check invoice currency
    Currency invCurrency = invoice.getCurrency();
    String curCode = invCurrency.getISOCode();
    BigDecimal rate = BigDecimal.ONE;

    if (!curCode.equals("EUR")) {

      rate = SIIUtils.getCurrencyConversionRate(invoice);
    }

    if (invoice.isAeatsiiIsauthorization()) {

      this.numRegistroAcuerdoFacturacion = invoice.getAeatsiiAuthorizationno();

    } else {

      this.numRegistroAcuerdoFacturacion = null;
    }

    this.importeTotal = SIIUtils.bigdecimalToFile(invoice.getGrandTotalAmount().multiply(rate), 12,
        2);

    if (esTransmision) {

      this.importeTransmision = SIIUtils.bigdecimalToFile(impTrans.multiply(rate), 12, 2);
    }

    // Facturas de venta por inversión de sujeto pasivo

    if (isISP) {

      this.tipoFactura = "F1";
      this.claveRegimenEspecialTrascendencia = "01";

      // Agrupación de impuestos

      for (InvoiceTax impFactura : listaImpuestosFactura) {

        TaxRate imp = impFactura.getTax();

        if (!imp.isWithholdingTax()) {

          GenericTax impuestoGenerico = new GenericTax();
          impuestoGenerico.setRate(imp.getRate());
          impuestoGenerico.setNotTaxable(imp.isNotTaxable());
          impuestoGenerico.setRealState(imp.isObsptiIsrealestate());
          impuestoGenerico.setReverseCharge(imp.isOBSPTIReverseCharge());
          impuestoGenerico.setTaxAmount(impFactura.getTaxAmount().multiply(rate));
          impuestoGenerico.setTaxableAmount(impFactura.getTaxableAmount().multiply(rate));
          impuestoGenerico.setTaxExempt(imp.isTaxExempt());
          impuestoGenerico.setLease(imp.isObsptiIslease());

          if (imp.isOBSPTIEquivalentCharge()) {

            impuestoGenerico.setEquivalentCharge(true);
            impuestoGenerico.setChargeRate(imp.getRate());
            impuestoGenerico.setChargeTaxAmount(impFactura.getTaxAmount().multiply(rate));

            impuestoGenerico.setRate(imp.getParentTaxRate().getRate().subtract(imp.getRate()));
            impuestoGenerico.setTaxableAmount(BigDecimal.ZERO);
            impuestoGenerico.setTaxAmount(BigDecimal.ZERO);
          }

          if (this.listaImpuestosAgrupados.size() < 1) {

            this.listaImpuestosAgrupados.add(impuestoGenerico);

          } else {

            boolean flagInList = false;

            for (GenericTax gr : listaImpuestosAgrupados) {

              if (impuestoGenerico.getRate().compareTo(gr.getRate()) == 0
                  && (impuestoGenerico.isNotTaxable() == gr.isNotTaxable())
                  && (impuestoGenerico.isTaxExempt() == gr.isTaxExempt())
                  && (impuestoGenerico.isReverseCharge() == gr.isReverseCharge())
                  && impuestoGenerico.isLease() == gr.isLease()) {

                gr.setTaxableAmount(gr.getTaxableAmount().add(impuestoGenerico.getTaxableAmount()));
                gr.setTaxAmount(gr.getTaxAmount().add(impuestoGenerico.getTaxAmount()));

                if (impuestoGenerico.isEquivalentCharge()) {

                  gr.setEquivalentCharge(true);

                  if (gr.getChargeRate() == null) {

                    gr.setChargeRate(impuestoGenerico.getChargeRate());
                  }

                  if (gr.getChargeTaxAmount() == null) {

                    gr.setChargeTaxAmount(impuestoGenerico.getChargeTaxAmount());

                  } else {

                    gr.setChargeTaxAmount(
                        gr.getChargeTaxAmount().add(impuestoGenerico.getChargeTaxAmount()));
                  }
                }

                flagInList = true;
                break;
              }
            }

            if (!flagInList) {

              listaImpuestosAgrupados.add(impuestoGenerico);
            }
          }
        }
      }

      this.lineasImpuesto = listaImpuestosAgrupados.size();

      // Ventas a Canarias - Ceuta - Melilla // IPSI-IGIC

    } else if (SIIUtils.someTaxIsIpsiOrIgic(listaImpuestosFactura)) {

      boolean flagIpsiIgic = false;

      for (InvoiceTax impFactura : listaImpuestosFactura) {

        TaxRate imp = impFactura.getTax();
        TaxCategory grupoImpuesto = imp.getTaxCategory();
        String nombreGrupoImpuesto = grupoImpuesto.getName().toLowerCase();

        if (nombreGrupoImpuesto.contains("ipsi") || nombreGrupoImpuesto.contains("igic")) {

          flagIpsiIgic = true;
          break;
        }
      }

      // Operaciones sujetas a IPSI / IGIC --> no sujeta --> reglas localizacion
      if (flagIpsiIgic) {

        this.claveRegimenEspecialTrascendencia = "08";

        // Comprobar si hay arrendamientos

        // comprobar si es retencion / sin retencion / ambos
        boolean conRet = false;
        boolean sinRet = false;

        for (InvoiceTax impFact : listaImpuestosFactura) {

          TaxRate imp = impFact.getTax();

          if (imp.isObsptiIslease()) {

            org.openbravo.model.common.businesspartner.TaxCategory grupoImp = imp
                .getBusinessPartnerTaxCategory();
            String nombreGrupoImp = grupoImp.getName().toLowerCase();

            if (nombreGrupoImp.contains("arrendamientos con ret")) {

              conRet = true;
            }

            if (nombreGrupoImp.contains("arrendamientos sin ret")) {

              sinRet = true;
            }
          }
        }

        // con retencion
        if (conRet && !sinRet) {

          this.claveRegimenEspecialTrascendencia = "11";
          this.claveRegimenEspecialTrascendencia2 = "08";

          // sin retencion
        } else if (sinRet && !conRet) {

          this.claveRegimenEspecialTrascendencia = "12";
          this.claveRegimenEspecialTrascendencia2 = "08";

          // ambos
        } else if (conRet && sinRet) {

          this.claveRegimenEspecialTrascendencia = "13";
          this.claveRegimenEspecialTrascendencia2 = "08";
        }

        if (this.claveRegimenEspecialTrascendencia.equals("12")
            || this.claveRegimenEspecialTrascendencia.equals("13")) {

          this.tieneInmueble = true;
        }

        // Agrupación de impuestos

        for (InvoiceTax impFactura : listaImpuestosFactura) {

          TaxRate imp = impFactura.getTax();

          if (!imp.isWithholdingTax()) {

            GenericTax impuestoGenerico = new GenericTax();
            impuestoGenerico.setRate(imp.getRate());
            impuestoGenerico.setTaxableAmount(impFactura.getTaxableAmount().multiply(rate));

            if (this.listaImpuestosAgrupados.size() < 1) {

              this.listaImpuestosAgrupados.add(impuestoGenerico);

            } else {

              this.listaImpuestosAgrupados.get(0)
                  .setTaxableAmount(this.listaImpuestosAgrupados.get(0)
                      .getTaxableAmount()
                      .add(impuestoGenerico.getTaxableAmount()));
            }
          }
        }

        this.lineasImpuesto = listaImpuestosAgrupados.size();

        // Ventas a Canarias, Ceuta y Melilla
      } else {

        boolean tieneBienes = false;
        boolean tieneServicios = false;

        for (InvoiceTax impFactura : listaImpuestosFactura) {

          TaxRate imp = impFactura.getTax();
          TaxCategory grupoImp = imp.getTaxCategory();
          String nombreGrupoImp = grupoImp.getName().toLowerCase();

          if (tieneBienes && tieneServicios) {

            break;
          }

          // Prestacion servicios
          if (nombreGrupoImp.contains("servic")) {

            tieneServicios = true;

            // Bienes
          } else {

            tieneBienes = true;
          }
        }

        // Tiene bienes
        if (tieneBienes) {

          this.claveRegimenEspecialTrascendencia = "02";

          // Solo servicios
        } else {

          this.claveRegimenEspecialTrascendencia = "01";
        }

        // Check tax "Entregas no sujetas con derecho a deducción" --> id =
        // 643B40AED45A47F79E52D68ADAF0EA21

        boolean flagEntregasDeduc = true;

        for (InvoiceTax impFact : listaImpuestosFactura) {

          TaxRate imp = impFact.getTax();

          if (!imp.getId().equals("643B40AED45A47F79E52D68ADAF0EA21")) {

            flagEntregasDeduc = false;
            break;
          }
        }

        if (flagEntregasDeduc) {

          this.claveRegimenEspecialTrascendencia = "01";
        }

        // Agrupación de impuestos

        for (InvoiceTax impFactura : listaImpuestosFactura) {

          TaxRate imp = impFactura.getTax();
          TaxCategory grupoImp = imp.getTaxCategory();
          String nombreGrupoImp = grupoImp.getName().toLowerCase();

          if (!imp.isWithholdingTax()) {

            GenericTax impuestoGenerico = new GenericTax();
            impuestoGenerico.setRate(imp.getRate());
            impuestoGenerico.setNotTaxable(imp.isNotTaxable());
            impuestoGenerico.setRealState(imp.isObsptiIsrealestate());
            impuestoGenerico.setReverseCharge(imp.isOBSPTIReverseCharge());
            impuestoGenerico.setTaxableAmount(impFactura.getTaxableAmount().multiply(rate));
            impuestoGenerico.setTaxAmount(impFactura.getTaxAmount().multiply(rate));
            impuestoGenerico.setTaxExempt(imp.isTaxExempt());

            if (nombreGrupoImp.contains("servic")) {

              impuestoGenerico.setService(true);

            } else {

              impuestoGenerico.setService(false);
            }

            if (imp.isOBSPTIEquivalentCharge()) {

              impuestoGenerico.setEquivalentCharge(true);
              impuestoGenerico.setChargeRate(imp.getRate());
              impuestoGenerico.setChargeTaxAmount(impFactura.getTaxAmount().multiply(rate));
            }

            if (this.listaImpuestosAgrupados.size() < 1) {

              this.listaImpuestosAgrupados.add(impuestoGenerico);

            } else {

              boolean flagInList = false;

              for (GenericTax gr : listaImpuestosAgrupados) {

                if (impuestoGenerico.getRate().compareTo(gr.getRate()) == 0
                    && (impuestoGenerico.isNotTaxable() == gr.isNotTaxable())
                    && (impuestoGenerico.isTaxExempt() == gr.isTaxExempt())
                    && (impuestoGenerico.isReverseCharge() == gr.isReverseCharge())
                    && (impuestoGenerico.isService() == gr.isService())) {

                  gr.setTaxableAmount(
                      gr.getTaxableAmount().add(impuestoGenerico.getTaxableAmount()));
                  gr.setTaxAmount(gr.getTaxAmount().add(impuestoGenerico.getTaxAmount()));

                  if (impuestoGenerico.isEquivalentCharge()) {

                    gr.setEquivalentCharge(true);

                    if (gr.getChargeRate() == null) {

                      gr.setChargeRate(impuestoGenerico.getChargeRate());
                    }

                    if (gr.getChargeTaxAmount() == null) {

                      gr.setChargeTaxAmount(impuestoGenerico.getChargeTaxAmount());

                    } else {

                      gr.setChargeTaxAmount(
                          gr.getChargeTaxAmount().add(impuestoGenerico.getChargeTaxAmount()));
                    }
                  }

                  flagInList = true;
                  break;
                }
              }

              if (!flagInList) {

                listaImpuestosAgrupados.add(impuestoGenerico);
              }
            }
          }
        }

        this.lineasImpuesto = listaImpuestosAgrupados.size();
      }

      // Exportación (destino país no comunitario) --> sujeta --> exenta "E2"
    } else if (!invoice.getPartnerAddress()
        .getLocationAddress()
        .getCountry()
        .isEucntryIseucountry()) {

      this.claveRegimenEspecialTrascendencia = "02";

      boolean tieneBienes = false;
      boolean tieneServicios = false;

      for (InvoiceTax impFactura : listaImpuestosFactura) {

        TaxRate imp = impFactura.getTax();
        TaxCategory grupoImp = imp.getTaxCategory();
        String nombreGrupoImp = grupoImp.getName().toLowerCase();

        if (tieneBienes && tieneServicios) {

          break;
        }

        // Prestacion servicios
        if (nombreGrupoImp.contains("servic")) {

          tieneServicios = true;

          // Bienes
        } else {

          tieneBienes = true;
        }
      }

      // solo servicios
      if (!tieneBienes && tieneServicios) {

        this.claveRegimenEspecialTrascendencia = "01";
      }

      // Check tax "Entregas no sujetas con derecho a deducción" --> id =
      // 643B40AED45A47F79E52D68ADAF0EA21

      boolean flagEntregasDeduc = true;

      for (InvoiceTax impFact : listaImpuestosFactura) {

        TaxRate imp = impFact.getTax();

        if (!imp.getId().equals("643B40AED45A47F79E52D68ADAF0EA21")) {

          flagEntregasDeduc = false;
          break;
        }
      }

      if (flagEntregasDeduc) {

        this.claveRegimenEspecialTrascendencia = "01";
      }

      // Check Spanish taxes

      boolean flagOnlySpanishTaxes = true;

      for (InvoiceTax impFact : listaImpuestosFactura) {

        TaxRate imp = impFact.getTax();

        if (imp.getCountry() != null && imp.getCountry().getISOCountryCode() != null
            && !imp.getCountry().getISOCountryCode().equals("ES")) {

          flagOnlySpanishTaxes = false;
          break;
        }

        if (imp.getDestinationCountry() != null
            && imp.getDestinationCountry().getISOCountryCode() != null
            && !imp.getDestinationCountry().getISOCountryCode().equals("ES")) {

          flagOnlySpanishTaxes = false;
          break;
        }
      }

      if (flagOnlySpanishTaxes) {

        this.claveRegimenEspecialTrascendencia = "01";
      }

      // Check leasing

      // comprobar si es retencion / sin retencion / ambos
      boolean conRet = false;
      boolean sinRet = false;

      for (InvoiceTax impFact : listaImpuestosFactura) {

        TaxRate imp = impFact.getTax();
        org.openbravo.model.common.businesspartner.TaxCategory grupoImp = imp
            .getBusinessPartnerTaxCategory();
        String nombreGrupoImp = "";

        if (grupoImp != null && grupoImp.getName() != null) {

          nombreGrupoImp = grupoImp.getName().toLowerCase();
        }

        if (nombreGrupoImp.contains("arrendamientos con ret")) {

          conRet = true;
        }

        if (nombreGrupoImp.contains("arrendamientos sin ret")) {

          sinRet = true;
        }
      }

      // con retencion
      if (conRet && !sinRet) {

        this.claveRegimenEspecialTrascendencia = "11";

        // sin retencion
      } else if (sinRet && !conRet) {

        this.claveRegimenEspecialTrascendencia = "12";

        // ambos
      } else if (conRet && sinRet) {

        this.claveRegimenEspecialTrascendencia = "13";
      }

      if (this.claveRegimenEspecialTrascendencia.equals("12")
          || this.claveRegimenEspecialTrascendencia.equals("13")) {

        this.tieneInmueble = true;
      }

      // Agrupación de impuestos

      for (InvoiceTax impFactura : listaImpuestosFactura) {

        TaxRate imp = impFactura.getTax();

        if (!imp.isWithholdingTax()) {

          TaxCategory grupoImp = imp.getTaxCategory();
          String nombreGrupoImp = grupoImp.getName().toLowerCase();

          GenericTax impuestoGenerico = new GenericTax();
          impuestoGenerico.setRate(imp.getRate());
          impuestoGenerico.setNotTaxable(imp.isNotTaxable());
          impuestoGenerico.setRealState(imp.isObsptiIsrealestate());
          impuestoGenerico.setReverseCharge(imp.isOBSPTIReverseCharge());
          impuestoGenerico.setTaxableAmount(impFactura.getTaxableAmount().multiply(rate));
          impuestoGenerico.setTaxAmount(impFactura.getTaxAmount().multiply(rate));
          impuestoGenerico.setTaxExempt(imp.isTaxExempt());

          if (impuestoGenerico.isReverseCharge()) {

            impuestoGenerico.setTaxAmount(BigDecimal.ZERO);
          }

          if (nombreGrupoImp.contains("servic")) {

            impuestoGenerico.setService(true);

          } else {

            impuestoGenerico.setService(false);
          }

          if (imp.isOBSPTIEquivalentCharge()) {

            impuestoGenerico.setEquivalentCharge(true);
            impuestoGenerico.setChargeRate(imp.getRate());
            impuestoGenerico.setChargeTaxAmount(impFactura.getTaxAmount().multiply(rate));
          }

          if (this.listaImpuestosAgrupados.size() < 1) {

            this.listaImpuestosAgrupados.add(impuestoGenerico);

          } else {

            boolean flagInList = false;

            for (GenericTax gr : listaImpuestosAgrupados) {

              if (impuestoGenerico.getRate().compareTo(gr.getRate()) == 0
                  && (impuestoGenerico.isNotTaxable() == gr.isNotTaxable())
                  && (impuestoGenerico.isTaxExempt() == gr.isTaxExempt())
                  && (impuestoGenerico.isReverseCharge() == gr.isReverseCharge())
                  && (impuestoGenerico.isService() == gr.isService())) {

                gr.setTaxableAmount(gr.getTaxableAmount().add(impuestoGenerico.getTaxableAmount()));
                gr.setTaxAmount(gr.getTaxAmount().add(impuestoGenerico.getTaxAmount()));

                if (impuestoGenerico.isEquivalentCharge()) {

                  gr.setEquivalentCharge(true);

                  if (gr.getChargeRate() == null) {

                    gr.setChargeRate(impuestoGenerico.getChargeRate());
                  }

                  if (gr.getChargeTaxAmount() == null) {

                    gr.setChargeTaxAmount(impuestoGenerico.getChargeTaxAmount());

                  } else {

                    gr.setChargeTaxAmount(
                        gr.getChargeTaxAmount().add(impuestoGenerico.getChargeTaxAmount()));
                  }
                }

                flagInList = true;
                break;
              }
            }

            if (!flagInList) {

              listaImpuestosAgrupados.add(impuestoGenerico);
            }
          }
        }
      }

      this.lineasImpuesto = listaImpuestosAgrupados.size();

      // Intracomunitarias
    } else if (flagDesgloseOperacion) {

      this.intracomunitaria = true;
      this.claveRegimenEspecialTrascendencia = "01";

      // Check leasing

      // comprobar si es retencion / sin retencion / ambos
      boolean conRet = false;
      boolean sinRet = false;

      for (InvoiceTax impFact : listaImpuestosFactura) {

        TaxRate imp = impFact.getTax();
        org.openbravo.model.common.businesspartner.TaxCategory grupoImp = imp
            .getBusinessPartnerTaxCategory();
        String nombreGrupoImp = "";

        if (grupoImp != null && grupoImp.getName() != null) {

          nombreGrupoImp = grupoImp.getName().toLowerCase();
        }

        if (nombreGrupoImp.contains("arrendamientos con ret")) {

          conRet = true;
        }

        if (nombreGrupoImp.contains("arrendamientos sin ret")) {

          sinRet = true;
        }
      }

      // con retencion
      if (conRet && !sinRet) {

        this.claveRegimenEspecialTrascendencia = "11";

        // sin retencion
      } else if (sinRet && !conRet) {

        this.claveRegimenEspecialTrascendencia = "12";

        // ambos
      } else if (conRet && sinRet) {

        this.claveRegimenEspecialTrascendencia = "13";
      }

      if (this.claveRegimenEspecialTrascendencia.equals("12")
          || this.claveRegimenEspecialTrascendencia.equals("13")) {

        this.tieneInmueble = true;
      }

      // Agrupación de impuestos

      for (InvoiceTax impFactura : listaImpuestosFactura) {

        TaxRate imp = impFactura.getTax();
        TaxCategory grupoImp = imp.getTaxCategory();
        String nombreGrupoImp = grupoImp.getName().toLowerCase();

        if (!imp.isWithholdingTax()) {

          GenericTax impuestoGenerico = new GenericTax();
          impuestoGenerico.setRate(imp.getRate());
          impuestoGenerico.setNotTaxable(imp.isNotTaxable());
          impuestoGenerico.setRealState(imp.isObsptiIsrealestate());
          impuestoGenerico.setReverseCharge(imp.isOBSPTIReverseCharge());
          impuestoGenerico.setTaxableAmount(impFactura.getTaxableAmount().multiply(rate));
          impuestoGenerico.setTaxAmount(impFactura.getTaxAmount().multiply(rate));
          impuestoGenerico.setTaxExempt(imp.isTaxExempt());
          impuestoGenerico.setIntracom(imp.isOBSPTIIsintracommunity());
          impuestoGenerico.setLocalization(imp.isOBSPTIReverseCharge());

          if (nombreGrupoImp.contains("servic")) {

            impuestoGenerico.setService(true);

          } else {

            impuestoGenerico.setService(false);
          }

          if (imp.isOBSPTIEquivalentCharge()) {

            impuestoGenerico.setEquivalentCharge(true);
            impuestoGenerico.setChargeRate(imp.getRate());
            impuestoGenerico.setChargeTaxAmount(impFactura.getTaxAmount().multiply(rate));
          }

          if (this.listaImpuestosAgrupados.size() < 1) {

            this.listaImpuestosAgrupados.add(impuestoGenerico);

          } else {

            boolean flagInList = false;

            for (GenericTax gr : listaImpuestosAgrupados) {

              if (impuestoGenerico.getRate().compareTo(gr.getRate()) == 0
                  && (impuestoGenerico.isNotTaxable() == gr.isNotTaxable())
                  && (impuestoGenerico.isTaxExempt() == gr.isTaxExempt())
                  && (impuestoGenerico.isIntracom() == gr.isIntracom())
                  && (impuestoGenerico.isReverseCharge() == gr.isReverseCharge())
                  && (impuestoGenerico.isService() == gr.isService())
                  && (impuestoGenerico.isLocalization() == gr.isLocalization())) {

                gr.setTaxableAmount(gr.getTaxableAmount().add(impuestoGenerico.getTaxableAmount()));
                gr.setTaxAmount(gr.getTaxAmount().add(impuestoGenerico.getTaxAmount()));

                if (impuestoGenerico.isEquivalentCharge()) {

                  gr.setEquivalentCharge(true);

                  if (gr.getChargeRate() == null) {

                    gr.setChargeRate(impuestoGenerico.getChargeRate());
                  }

                  if (gr.getChargeTaxAmount() == null) {

                    gr.setChargeTaxAmount(impuestoGenerico.getChargeTaxAmount());

                  } else {

                    gr.setChargeTaxAmount(
                        gr.getChargeTaxAmount().add(impuestoGenerico.getChargeTaxAmount()));
                  }
                }

                flagInList = true;
                break;
              }
            }

            if (!flagInList) {

              listaImpuestosAgrupados.add(impuestoGenerico);
            }
          }
        }
      }

      int countNotTaxableLoc = 0;
      int countNotTaxableArt = 0;
      int countNotTaxableServLoc = 0;
      int countNotTaxableServArt = 0;

      for (GenericTax gr : listaImpuestosAgrupados) {

        if (gr.isNotTaxable()) {

          if (gr.isService()) {

            if (gr.isLocalization()) {

              countNotTaxableServLoc += 1;

            } else {

              countNotTaxableServArt += 1;
            }

          } else {

            if (gr.isLocalization()) {

              countNotTaxableLoc += 1;

            } else {

              countNotTaxableArt += 1;
            }
          }
        }
      }

      if (countNotTaxableLoc > 1) {

        GenericTax noSujTax = new GenericTax();
        noSujTax.setNotTaxable(true);
        noSujTax.setReverseCharge(true);
        noSujTax.setTaxExempt(false);
        noSujTax.setService(false);
        noSujTax.setLocalization(true);
        noSujTax.setTaxableAmount(BigDecimal.ZERO);
        noSujTax.setTaxAmount(BigDecimal.ZERO);

        int countTaxList = listaImpuestosAgrupados.size() - 1;

        for (int i = countTaxList; i >= 0; i--) {

          GenericTax gr = listaImpuestosAgrupados.get(i);

          if (gr.isNotTaxable() && !gr.isService() && gr.isLocalization()) {

            noSujTax.setTaxableAmount(noSujTax.getTaxableAmount().add(gr.getTaxableAmount()));
            noSujTax.setTaxAmount(noSujTax.getTaxAmount().add(gr.getTaxAmount()));

            listaImpuestosAgrupados.remove(i);
          }
        }

        listaImpuestosAgrupados.add(noSujTax);
      }

      if (countNotTaxableArt > 1) {

        GenericTax noSujTax = new GenericTax();
        noSujTax.setNotTaxable(true);
        noSujTax.setReverseCharge(true);
        noSujTax.setTaxExempt(false);
        noSujTax.setService(false);
        noSujTax.setLocalization(false);
        noSujTax.setTaxableAmount(BigDecimal.ZERO);
        noSujTax.setTaxAmount(BigDecimal.ZERO);

        int countTaxList = listaImpuestosAgrupados.size() - 1;

        for (int i = countTaxList; i >= 0; i--) {

          GenericTax gr = listaImpuestosAgrupados.get(i);

          if (gr.isNotTaxable() && !gr.isService() && !gr.isLocalization()) {

            noSujTax.setTaxableAmount(noSujTax.getTaxableAmount().add(gr.getTaxableAmount()));
            noSujTax.setTaxAmount(noSujTax.getTaxAmount().add(gr.getTaxAmount()));

            listaImpuestosAgrupados.remove(i);
          }
        }

        listaImpuestosAgrupados.add(noSujTax);
      }

      if (countNotTaxableServLoc > 1) {

        GenericTax noSujTax = new GenericTax();
        noSujTax.setNotTaxable(true);
        noSujTax.setReverseCharge(true);
        noSujTax.setTaxExempt(false);
        noSujTax.setService(true);
        noSujTax.setLocalization(true);
        noSujTax.setTaxableAmount(BigDecimal.ZERO);
        noSujTax.setTaxAmount(BigDecimal.ZERO);

        int countTaxList = listaImpuestosAgrupados.size() - 1;

        for (int i = countTaxList; i >= 0; i--) {

          GenericTax gr = listaImpuestosAgrupados.get(i);

          if (gr.isNotTaxable() && gr.isService() && gr.isLocalization()) {

            noSujTax.setTaxableAmount(noSujTax.getTaxableAmount().add(gr.getTaxableAmount()));
            noSujTax.setTaxAmount(noSujTax.getTaxAmount().add(gr.getTaxAmount()));

            listaImpuestosAgrupados.remove(i);
          }
        }

        listaImpuestosAgrupados.add(noSujTax);
      }

      if (countNotTaxableServArt > 1) {

        GenericTax noSujTax = new GenericTax();
        noSujTax.setNotTaxable(true);
        noSujTax.setReverseCharge(true);
        noSujTax.setTaxExempt(false);
        noSujTax.setService(true);
        noSujTax.setLocalization(false);
        noSujTax.setTaxableAmount(BigDecimal.ZERO);
        noSujTax.setTaxAmount(BigDecimal.ZERO);

        int countTaxList = listaImpuestosAgrupados.size() - 1;

        for (int i = countTaxList; i >= 0; i--) {

          GenericTax gr = listaImpuestosAgrupados.get(i);

          if (gr.isNotTaxable() && gr.isService() && !gr.isLocalization()) {

            noSujTax.setTaxableAmount(noSujTax.getTaxableAmount().add(gr.getTaxableAmount()));
            noSujTax.setTaxAmount(noSujTax.getTaxAmount().add(gr.getTaxAmount()));

            listaImpuestosAgrupados.remove(i);
          }
        }

        listaImpuestosAgrupados.add(noSujTax);
      }

      this.lineasImpuesto = listaImpuestosAgrupados.size();

      // arrendamientos
    } else if (flagArrendamientos) {

      // intracom client
      if (invoice.getPartnerAddress().getLocationAddress().getCountry().isEucntryIseucountry()
          && !invoice.getPartnerAddress()
              .getLocationAddress()
              .getCountry()
              .getISOCountryCode()
              .equals("ES")) {

        this.intracomunitaria = true;
      }

      // comprobar si es retencion / sin retencion / ambos
      boolean conRet = false;
      boolean sinRet = false;

      for (InvoiceTax impFact : listaImpuestosFactura) {

        TaxRate imp = impFact.getTax();
        org.openbravo.model.common.businesspartner.TaxCategory grupoImp = imp
            .getBusinessPartnerTaxCategory();
        String nombreGrupoImp = "";

        if (grupoImp != null && grupoImp.getName() != null) {

          nombreGrupoImp = grupoImp.getName().toLowerCase();
        }

        if (nombreGrupoImp.contains("arrendamientos con ret")) {

          conRet = true;
        }

        if (nombreGrupoImp.contains("arrendamientos sin ret")) {

          sinRet = true;
        }
      }

      // con retencion
      if (conRet && !sinRet) {

        this.claveRegimenEspecialTrascendencia = "11";

        // sin retencion
      } else if (sinRet && !conRet) {

        this.claveRegimenEspecialTrascendencia = "12";

        // ambos
      } else if (conRet && sinRet) {

        this.claveRegimenEspecialTrascendencia = "13";
      }

      if (this.claveRegimenEspecialTrascendencia.equals("12")
          || this.claveRegimenEspecialTrascendencia.equals("13")) {

        this.tieneInmueble = true;
      }

      // Agrupación de impuestos

      for (InvoiceTax impFactura : listaImpuestosFactura) {

        TaxRate imp = impFactura.getTax();
        org.openbravo.model.common.businesspartner.TaxCategory grupoImp = imp
            .getBusinessPartnerTaxCategory();
        String nombreGrupoImp = "";

        if (grupoImp != null && grupoImp.getName() != null) {

          nombreGrupoImp = grupoImp.getName().toLowerCase();
        }

        // Arrendamiento sin retencion o arrendamiento con retencion si NO es impuesto de
        // retencion
        if ((nombreGrupoImp.contains("arrendamientos sin ret")
            || (nombreGrupoImp.contains("arrendamientos con ret") && !imp.isWithholdingTax()))
            || !nombreGrupoImp.contains("arrendamientos")) {

          GenericTax impuestoGenerico = new GenericTax();
          impuestoGenerico.setRate(imp.getRate());
          impuestoGenerico.setTaxableAmount(impFactura.getTaxableAmount().multiply(rate));
          impuestoGenerico.setTaxAmount(impFactura.getTaxAmount().multiply(rate));
          impuestoGenerico.setLease(true);
          impuestoGenerico.setNotTaxable(imp.isNotTaxable());
          impuestoGenerico.setTaxExempt(imp.isTaxExempt());
          impuestoGenerico.setReverseCharge(imp.isOBSPTIReverseCharge());

          if (this.listaImpuestosAgrupados.size() < 1) {

            this.listaImpuestosAgrupados.add(impuestoGenerico);

          } else {

            boolean flagInList = false;

            for (GenericTax gr : listaImpuestosAgrupados) {

              if (impuestoGenerico.getRate().compareTo(gr.getRate()) == 0
                  && impuestoGenerico.isNotTaxable() == gr.isNotTaxable()
                  && impuestoGenerico.isTaxExempt() == gr.isTaxExempt()
                  && impuestoGenerico.isReverseCharge() == gr.isReverseCharge()) {

                gr.setTaxableAmount(gr.getTaxableAmount().add(impuestoGenerico.getTaxableAmount()));
                gr.setTaxAmount(gr.getTaxAmount().add(impuestoGenerico.getTaxAmount()));

                flagInList = true;
                break;
              }
            }

            if (!flagInList) {

              listaImpuestosAgrupados.add(impuestoGenerico);
            }
          }
        }
      }

      // comprobar criterio de caja

      if (invoice.isCashVAT()) {

        String claveAux = this.claveRegimenEspecialTrascendencia;

        this.claveRegimenEspecialTrascendencia2 = claveAux;
        this.claveRegimenEspecialTrascendencia = "07";
      }

      this.lineasImpuesto = listaImpuestosAgrupados.size();

      // Resto

    } else {

      this.claveRegimenEspecialTrascendencia = "01";

      // criterio de caja

      boolean flagIsCashvat = false;

      for (InvoiceTax impFactura : listaImpuestosFactura) {

        TaxRate imp = impFactura.getTax();

        if (imp.isCashVAT()) {

          flagIsCashvat = true;
          break;
        }
      }

      if (flagIsCashvat) {

        this.claveRegimenEspecialTrascendencia = "07";

        // Comprobar si hay arrendamientos

        // comprobar si es retencion / sin retencion / ambos
        boolean conRet = false;
        boolean sinRet = false;

        for (InvoiceTax impFact : listaImpuestosFactura) {

          TaxRate imp = impFact.getTax();

          if (imp.isObsptiIslease()) {

            org.openbravo.model.common.businesspartner.TaxCategory grupoImp = imp
                .getBusinessPartnerTaxCategory();
            String nombreGrupoImp = "";

            if (grupoImp != null && grupoImp.getName() != null) {

              nombreGrupoImp = grupoImp.getName().toLowerCase();
            }

            if (nombreGrupoImp.contains("arrendamientos con ret")) {

              conRet = true;
            }

            if (nombreGrupoImp.contains("arrendamientos sin ret")) {

              sinRet = true;
            }
          }
        }

        // con retencion
        if (conRet && !sinRet) {

          this.claveRegimenEspecialTrascendencia2 = "11";

          // sin retencion
        } else if (sinRet && !conRet) {

          this.claveRegimenEspecialTrascendencia2 = "12";

          // ambos
        } else if (conRet && sinRet) {

          this.claveRegimenEspecialTrascendencia2 = "13";
        }

        if (this.claveRegimenEspecialTrascendencia2 != null
            && (this.claveRegimenEspecialTrascendencia2.equals("12")
                || this.claveRegimenEspecialTrascendencia2.equals("13"))) {

          this.tieneInmueble = true;
        }
      }

      // Agrupación de impuestos

      for (InvoiceTax impFactura : listaImpuestosFactura) {

        TaxRate imp = impFactura.getTax();

        if (!imp.isWithholdingTax()) {

          GenericTax impuestoGenerico = new GenericTax();
          impuestoGenerico.setRate(imp.getRate());
          impuestoGenerico.setNotTaxable(imp.isNotTaxable());
          impuestoGenerico.setRealState(imp.isObsptiIsrealestate());
          impuestoGenerico.setReverseCharge(imp.isOBSPTIReverseCharge());
          impuestoGenerico.setTaxAmount(impFactura.getTaxAmount().multiply(rate));
          impuestoGenerico.setTaxableAmount(impFactura.getTaxableAmount().multiply(rate));
          impuestoGenerico.setTaxExempt(imp.isTaxExempt());
          impuestoGenerico.setLease(imp.isObsptiIslease());

          if (imp.isOBSPTIEquivalentCharge()) {

            impuestoGenerico.setEquivalentCharge(true);
            impuestoGenerico.setChargeRate(imp.getRate());
            impuestoGenerico.setChargeTaxAmount(impFactura.getTaxAmount().multiply(rate));

            impuestoGenerico.setRate(imp.getParentTaxRate().getRate().subtract(imp.getRate()));
            impuestoGenerico.setTaxableAmount(BigDecimal.ZERO);
            impuestoGenerico.setTaxAmount(BigDecimal.ZERO);
          }

          if (this.listaImpuestosAgrupados.size() < 1) {

            this.listaImpuestosAgrupados.add(impuestoGenerico);

          } else {

            boolean flagInList = false;

            for (GenericTax gr : listaImpuestosAgrupados) {

              if (impuestoGenerico.getRate().compareTo(gr.getRate()) == 0
                  && (impuestoGenerico.isNotTaxable() == gr.isNotTaxable())
                  && (impuestoGenerico.isTaxExempt() == gr.isTaxExempt())
                  && (impuestoGenerico.isReverseCharge() == gr.isReverseCharge())
                  && impuestoGenerico.isLease() == gr.isLease()) {

                gr.setTaxableAmount(gr.getTaxableAmount().add(impuestoGenerico.getTaxableAmount()));
                gr.setTaxAmount(gr.getTaxAmount().add(impuestoGenerico.getTaxAmount()));

                if (impuestoGenerico.isEquivalentCharge()) {

                  gr.setEquivalentCharge(true);

                  if (gr.getChargeRate() == null) {

                    gr.setChargeRate(impuestoGenerico.getChargeRate());
                  }

                  if (gr.getChargeTaxAmount() == null) {

                    gr.setChargeTaxAmount(impuestoGenerico.getChargeTaxAmount());

                  } else {

                    gr.setChargeTaxAmount(
                        gr.getChargeTaxAmount().add(impuestoGenerico.getChargeTaxAmount()));
                  }
                }

                flagInList = true;
                break;
              }
            }

            if (!flagInList) {

              listaImpuestosAgrupados.add(impuestoGenerico);
            }
          }
        }
      }

      this.lineasImpuesto = listaImpuestosAgrupados.size();

      // Comprobar si se trata de exportación aunque el tercero sea nacional

      for (InvoiceTax impFactura : listaImpuestosFactura) {

        TaxRate imp = impFactura.getTax();
        String nameTax = imp.getName().toLowerCase();

        if (nameTax.contains("export") || nameTax.contains("entregas a canarias")
            || nameTax.contains("entrega a canarias")) {

          this.claveRegimenEspecialTrascendencia = "02";
          break;
        }
      }
    }

    if (invoice.getAeatsiiClaveTipo() != null && invoice.getAeatsiiClaveTipo().equals("R")) {

      this.rectificativa = true;
      this.tipoFactura = invoice.getAeatsiiMotivoRectif();
      this.tipoRectificativa = invoice.getAeatsiiTipoRectif();
    }

    // The invoice contains an export tax
    if (isSalesInvoice && containsExportTax) {

      this.claveRegimenEspecialTrascendencia = "02";
    }

    // Facturas primer semestre

    if (SIIUtils.isFromFirstSemester(invoice)) {

      if (this.tipoFactura == null || this.tipoFactura.equals("")) {

        DocumentType tipoDocumento = OBDal.getInstance()
            .get(DocumentType.class, invoice.getDocumentType());

        if (tipoDocumento.getName().equals("Reversed Sales Invoice")) {

          this.tipoFactura = "R1";
          this.tipoRectificativa = "I";

        } else if (invoice.getGrandTotalAmount().compareTo(BigDecimal.ZERO) >= 0) {

          this.tipoFactura = "F1";
        }
      }

      this.claveRegimenEspecialTrascendencia = "16";
    }
  }

  public void create(Invoice invoice, String taxType) {

    if (taxType == null || taxType.equals(SIIUtils.getIvaTaxType())) {

      create(invoice);

    } else {

      SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");

      this.fechaOperacion = sdf.format(invoice.getAeatsiiFechaOperacion());
      this.tipoFactura = invoice.getAeatsiiClaveTipo();

      if (invoice.getAeatsiiDescripcionSii() != null) {
        this.descripcionOperacion = SIIUtils.stringToFile(invoice.getAeatsiiDescripcionSii(), 500);
      }

      // Default
      this.claveRegimenEspecialTrascendencia = SIIUtils.getClaveTrascendenciaSiiIgicEmitidasRG();

      OBCriteria<InvoiceTax> cInvoiceTax = OBDal.getInstance().createCriteria(InvoiceTax.class);
      cInvoiceTax.add(Restrictions.eq(InvoiceTax.PROPERTY_INVOICE, invoice));

      List<InvoiceTax> invoiceTaxList = cInvoiceTax.list();

      boolean containsExportTax = false;
      boolean containsLeaseTax = false;
      boolean containsNotIgicTax = false;

      BigDecimal transmissionAmount = BigDecimal.ZERO;

      for (InvoiceTax invoiceTax : invoiceTaxList) {

        TaxRate tax = invoiceTax.getTax();
        TaxCategory tc = tax.getTaxCategory();

        if (tc.getObsptiTaxtype().equals(SIIUtils.getIgicTaxType())) {

          if (tax.isObsptiIsexport()) {

            containsExportTax = true;
          }

          if (tax.isObsptiIslease()) {

            containsLeaseTax = true;
          }

          if (tax.getName().toLowerCase().contains("transmis")) {

            this.esTransmision = true;
            transmissionAmount = transmissionAmount.add(invoiceTax.getTaxableAmount());
            transmissionAmount = transmissionAmount.add(invoiceTax.getTaxAmount());
          }

        } else {

          containsNotIgicTax = true;
        }
      }

      if (containsNotIgicTax) {

        this.claveRegimenEspecialTrascendencia = SIIUtils
            .getClaveTrascendenciaSiiIgicEmitidasIpsiIva();

      } else if (containsExportTax) {

        this.claveRegimenEspecialTrascendencia = SIIUtils
            .getClaveTrascendenciaSiiIgicEmitidasExport();

      } else if (containsLeaseTax) {

        this.claveRegimenEspecialTrascendencia = SIIUtils
            .getClaveTrascendenciaSiiIgicEmitidasArrendamiento();
        this.tieneInmueble = true;
      }

      if (invoice.isAeatsiiIsauthorization()) {

        this.numRegistroAcuerdoFacturacion = invoice.getAeatsiiAuthorizationno();

      } else {

        this.numRegistroAcuerdoFacturacion = null;
      }

      // check invoice currency
      Currency invCurrency = invoice.getCurrency();
      String curCode = invCurrency.getISOCode();
      BigDecimal rate = BigDecimal.ONE;

      if (!curCode.equals("EUR")) {

        rate = SIIUtils.getCurrencyConversionRate(invoice);
      }

      this.importeTotal = SIIUtils.bigdecimalToFile(invoice.getGrandTotalAmount().multiply(rate),
          12, 2);

      if (this.esTransmision) {

        this.importeTransmision = SIIUtils.bigdecimalToFile(transmissionAmount.multiply(rate), 12,
            2);
      }

      // Grouping taxes

      for (InvoiceTax invoiceTax : invoiceTaxList) {

        TaxRate tax = invoiceTax.getTax();

        if (!tax.isWithholdingTax()) {

          TaxCategory taxCategory = tax.getTaxCategory();
          String taxCategoryName = taxCategory.getName().toLowerCase();

          GenericTax genericTax = new GenericTax();
          genericTax.setRate(tax.getRate());
          genericTax.setNotTaxable(containsNotIgicTax ? true : tax.isNotTaxable());
          genericTax.setRealState(tax.isObsptiIsrealestate());
          genericTax.setReverseCharge(containsNotIgicTax ? true : tax.isOBSPTIReverseCharge());
          genericTax.setTaxableAmount(invoiceTax.getTaxableAmount().multiply(rate));
          genericTax.setTaxAmount(invoiceTax.getTaxAmount().multiply(rate));
          genericTax.setTaxExempt(tax.isTaxExempt());
          genericTax.setLease(tax.isObsptiIslease());

          if (genericTax.isReverseCharge()) {

            genericTax.setTaxAmount(BigDecimal.ZERO);
          }

          if (taxCategoryName.contains("servic")) {

            genericTax.setService(true);

          } else {

            genericTax.setService(false);
          }

          if (tax.isOBSPTIEquivalentCharge()) {

            genericTax.setEquivalentCharge(true);
            genericTax.setChargeRate(tax.getRate());
            genericTax.setChargeTaxAmount(invoiceTax.getTaxAmount().multiply(rate));
          }

          if (this.listaImpuestosAgrupados.size() < 1) {

            this.listaImpuestosAgrupados.add(genericTax);

          } else {

            boolean flagInList = false;

            for (GenericTax gr : this.listaImpuestosAgrupados) {

              if (genericTax.getRate().compareTo(gr.getRate()) == 0
                  && (genericTax.isNotTaxable() == gr.isNotTaxable())
                  && (genericTax.isTaxExempt() == gr.isTaxExempt())
                  && (genericTax.isReverseCharge() == gr.isReverseCharge())
                  && (genericTax.isLease() == gr.isLease())) {

                gr.setTaxableAmount(gr.getTaxableAmount().add(genericTax.getTaxableAmount()));
                gr.setTaxAmount(gr.getTaxAmount().add(genericTax.getTaxAmount()));

                if (genericTax.isEquivalentCharge()) {

                  gr.setEquivalentCharge(true);

                  if (gr.getChargeRate() == null) {

                    gr.setChargeRate(genericTax.getChargeRate());
                  }

                  if (gr.getChargeTaxAmount() == null) {

                    gr.setChargeTaxAmount(genericTax.getChargeTaxAmount());

                  } else {

                    gr.setChargeTaxAmount(
                        gr.getChargeTaxAmount().add(genericTax.getChargeTaxAmount()));
                  }
                }

                flagInList = true;
                break;
              }
            }

            if (!flagInList) {

              this.listaImpuestosAgrupados.add(genericTax);
            }
          }
        }
      }

      this.lineasImpuesto = this.listaImpuestosAgrupados.size();

      if (invoice.getAeatsiiClaveTipo() != null && invoice.getAeatsiiClaveTipo().equals("R")) {

        this.rectificativa = true;
        this.tipoFactura = invoice.getAeatsiiMotivoRectif();
        this.tipoRectificativa = invoice.getAeatsiiTipoRectif();
      }

      // Before "In SII date"
      AEATSIIConfig config = SIIUtils.getSiiConfigFromOrg(invoice.getOrganization());

      if (invoice.getInvoiceDate().before(config.getFechaAcogidaSII())) {

        this.claveRegimenEspecialTrascendencia = SIIUtils
            .getClaveTrascendenciaSiiIgicEmitidasAnterioresSii();
      }

      // First semester invoice
      if (SIIUtils.isFromFirstSemester(invoice)) {

        if (this.tipoFactura == null || this.tipoFactura.equals("")) {

          DocumentType tipoDocumento = OBDal.getInstance()
              .get(DocumentType.class, invoice.getDocumentType());

          if (tipoDocumento.getName().equals("Reversed Sales Invoice")) {

            this.tipoFactura = "R1";
            this.tipoRectificativa = "I";

          } else if (invoice.getGrandTotalAmount().compareTo(BigDecimal.ZERO) >= 0) {

            this.tipoFactura = "F1";
          }
        }

        this.claveRegimenEspecialTrascendencia = SIIUtils
            .getClaveTrascendenciaSiiIgicEmitidasAnterioresSii();
      }
    }
  }

  public String getTipoFactura() {

    return tipoFactura;
  }

  public String getTipoRectificativa() {

    return tipoRectificativa;
  }

  public String getFechaOperacion() {

    return fechaOperacion;
  }

  public String getClaveRegimenEspecialTrascendencia() {

    return claveRegimenEspecialTrascendencia;
  }

  public String getClaveRegimenEspecialTrascendencia2() {

    return claveRegimenEspecialTrascendencia2;
  }

  public String getClaveRegimenEspecialTrascendencia3() {

    return claveRegimenEspecialTrascendencia3;
  }

  public String getNumRegistroAcuerdoFacturacion() {

    return numRegistroAcuerdoFacturacion;
  }

  public String getImporteTotal() {

    return importeTotal;
  }

  public String getImporteTransmision() {

    return importeTransmision;
  }

  public String getDescripcionOperacion() {

    return descripcionOperacion;
  }

  public String getTipoOperacion() {

    return tipoOperacion;
  }

  public boolean getRectificativa() {

    return rectificativa;
  }

  public boolean getSujeta() {

    return sujeta;
  }

  public boolean getExenta() {

    return exenta;
  }

  public boolean getTieneInmueble() {

    return tieneInmueble;
  }

  public boolean getEsTransmision() {

    return esTransmision;
  }

  public boolean getNoSujetaArticulos() {

    return noSujetaArticulos;
  }

  public boolean getIntracomunitaria() {

    return intracomunitaria;
  }

  public boolean getIsISP() {

    return isISP;
  }

  public int getNumLineasImpuesto() {

    return lineasImpuesto;
  }

  public List<GenericTax> getGenericTaxList() {

    return listaImpuestosAgrupados;
  }

}
