/*
 * Copyright 2014 - LAit SpA Realizzato da Icona Management srl su commessa LAit SpA Copyright 2015-
 * LAit SpA Aggiornato da LAit SpA
 *
 * Concesso in licenza a norma dell'EUPL, versione 1.1 o successive dell'EUPL (la "Licenza") non
 * appena saranno approvate dalla Commissione europea; Non è possibile utilizzare l'opera salvo nel
 * rispetto della Licenza. possibile ottenere una copia della Licenza al seguente indirizzo:
 *
 * http://ec.europa.eu/idabc/eupl
 *
 * Salvo diversamente indicato dalla legge applicabile o concordato per iscritto, il software
 * distribuito secondo i termini della Licenza è distribuito "TAL QUALE", SENZA GARANZIE O
 * CONDIZIONI DI ALCUN TIPO, esplicite o implicite. Si veda la Licenza per la lingua specifica che
 * disciplina le autorizzazioni e le limitazioni secondo i termini della Licenza.
 */
/**
 *
 */
package it.laitspa.cpf.faces.sogei.invoice;

import it.gov.fatturapa.sdi.fatturapa.v1.*;
import it.laitspa.cpf.faces.BeanModel;
import it.laitspa.cpf.faces.utils.FacesUtils;
import it.laitspa.cpf.model.sogei.condizionepagamento.TipoCondizioniPagamentoSogei;
import it.laitspa.cpf.model.sogei.condizionepagamento.TipoModalitaPagamentoSogei;
import it.laitspa.cpf.model.sogei.fattura.FatturaSogei;
import it.laitspa.cpf.model.sogei.regimefiscale.TipoRegimeFiscaleSogei;
import it.laitspa.cpf.model.sogei.soggetto.SoggettoSogei;
import it.laitspa.cpf.model.sogei.tipocassaprevidenziale.TipoCassaPrevidenzialeSogei;
import it.laitspa.cpf.model.sogei.tipofattura.TipoFatturaSogei;
import it.laitspa.cpf.model.sogei.tiponatura.TipoNaturaSogei;
import it.laitspa.cpf.model.sogei.tipoprestazione.TipoPrestazioneSogei;
import it.laitspa.cpf.model.sogei.tiporitenuta.TipoRitenutaSogei;
import it.laitspa.cpf.model.sogei.tiposconto.TipoScontoSogei;
import it.laitspa.cpf.model.sogei.unitamisura.UnitaMisura;
import it.laitspa.cpf.spring.lut.LUTFacade;
import it.laitspa.cpf.spring.sogei.SogeiFacade;
import it.laitspa.cpf.util.log.LogUtils;
import it.laitspa.cpf.util.misc.DateUtils;
import it.laitspa.cpf.util.misc.FormUtils;
import org.richfaces.event.UploadEvent;
import org.richfaces.model.UploadItem;

import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import static java.math.RoundingMode.HALF_UP;
/**
 * @author andrea
 *
 */
public class InvBean extends BeanModel {

  public class OpenedAndSaved implements Serializable {
    private static final long serialVersionUID = 1L;

    private Date whenOpened;
    private Date whenSaved;

    public OpenedAndSaved() {
      whenOpened = new Date();
    }

    public Date getWhenOpened() {
      return whenOpened;
    }

    public void setWhenOpened(Date whenOpened) {
      this.whenOpened = whenOpened;
    }

    public Date getWhenSaved() {
      return whenSaved;
    }

    public void setWhenSaved(Date whenSaved) {
      this.whenSaved = whenSaved;
    }

    public boolean isStateSaved() {
      if (whenSaved == null) {
        return false;
      }

      return whenSaved.after(whenOpened);
    }

    public void save() {
      whenSaved = new Date();
    }
  }

  private static final long serialVersionUID = 1L;

  private FatturaElettronicaType invio;
  private FatturaElettronicaBodyType fattura;
  DatiCassaPrevidenzialeType c_type;
  ScontoMaggiorazioneType s_type;

  DatiDocumentiCorrelatiType o_doc_type;
  DatiDocumentiCorrelatiType c_doc_type;
  DatiDocumentiCorrelatiType cn_doc_type;
  DatiDocumentiCorrelatiType r_doc_type;
  DatiDocumentiCorrelatiType f_doc_type;
  Integer numeroLinea;
  DatiSALType sal_type;
  DatiDDTType ddt_type;

  private final ObjectFactory obj;
  private SoggettoSogei soggetto;
  private String wizard;

  private List<SelectItem> listRegimiFiscali;
  private List<SelectItem> listTipoDocumento;
  private List<SelectItem> listTipoRitenuta;
  private List<SelectItem> listTipoSocio;
  private List<SelectItem> listStatoLiquidazione;
  private List<SelectItem> listArt73;

  private List<SelectItem> listTipoCassa;
  private List<SelectItem> listTipoNatura;
  private List<SelectItem> listRitenuta;
  private List<SelectItem> listTipoSconto;
  private List<SelectItem> listCausaliPagamento;

  DettaglioLineeType riga;
  AltriDatiGestionaliType g_type;
  CodiceArticoloType cod_type;
  private List<SelectItem> listTipoPrestazione;

  DatiPagamentoType dati_pagamento;
  DettaglioPagamentoType dettaglio_pagamento;
  private List<SelectItem> listTipoCondizioniPagamento;
  private List<SelectItem> listModalitaPagamento;
  private List<SelectItem> listEsigibilitaIVA;

  AllegatiType allegato;
  protected UploadItem file;

  private Boolean[] menu;
  private HashMap<String, OpenedAndSaved> openMap;

  private Integer codiceFlusso;

  private final Map<Integer, String> causali = new HashMap<Integer, String>();


  private List<SelectItem> listTipoUnitaMisura;

  public InvBean() {
    // Retrieve SoggettoSogei and instance new invoice.
    //
    obj = new ObjectFactory();
    invio = obj.createFatturaElettronicaType();
    final FatturaElettronicaHeaderType header = obj.createFatturaElettronicaHeaderType();
    invio.setFatturaElettronicaHeader(header);
    FormatoTrasmissioneType versione = FormatoTrasmissioneType.FPA_12;
    invio.setVersione(versione);

    // TODO: Testing purpose: TRUE replace with FALSE!!!
    //
    menu = new Boolean[10];
    for (int i = 0; i < menu.length; i++) {
      menu[i] = Boolean.FALSE;
    }

    menu[0] = Boolean.TRUE;
    menu[1] = Boolean.TRUE;

    // ISogei
    //
    final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");

    soggetto = (SoggettoSogei) ldao.getItem("SoggettoSogei", SoggettoSogei.SOGGETTO_UNICO);
    if (soggetto != null) {
      // Create <DatiTrasmissione>
      //
      final DatiTrasmissioneType d_t = obj.createDatiTrasmissioneType();
      final ContattiTrasmittenteType contatti = obj.createContattiTrasmittenteType();
      d_t.setContattiTrasmittente(contatti);
      final IdFiscaleType id_t = obj.createIdFiscaleType();
      id_t.setIdPaese(soggetto.getNazione());
      if (soggetto.getCodiceFiscale() != null) {
        id_t.setIdCodice(soggetto.getCodiceFiscale());
      } else {
        id_t.setIdCodice(soggetto.getCodiceIdentificativoFiscale());
      }

      d_t.setIdTrasmittente(id_t);
      d_t.setFormatoTrasmissione(FormatoTrasmissioneType.FPA_12);

      header.setDatiTrasmissione(d_t);

      // Create <CedentePrestatore>
      //
      final CedentePrestatoreType cedente = obj.createCedentePrestatoreType();
      header.setCedentePrestatore(cedente);

      // Create <CedentePrestatore>//<DatiAnagrafici>
      //
      final DatiAnagraficiCedenteType anagrafica_cedente = obj.createDatiAnagraficiCedenteType();
      cedente.setDatiAnagrafici(anagrafica_cedente);

      // Trasmittente and cedente is the same
      //
      final IdFiscaleType id_c = obj.createIdFiscaleType();
      id_c.setIdPaese(soggetto.getNazione());
      id_c.setIdCodice(soggetto.getCodiceIdentificativoFiscale());

      anagrafica_cedente.setIdFiscaleIVA(id_c);
      anagrafica_cedente.setCodiceFiscale(soggetto.getCodiceFiscale());

      AnagraficaType anagrafica = obj.createAnagraficaType();
      anagrafica_cedente.setAnagrafica(anagrafica);
      anagrafica.setDenominazione(soggetto.getDenominazione());
      anagrafica.setCodEORI(soggetto.getDescrizioneCodiceEori());
      anagrafica.setTitolo(soggetto.getDescrizioneTitolare());
      anagrafica.setCognome(soggetto.getCognome());
      anagrafica.setNome(soggetto.getNome());


      // Create <CedentePrestatore>//<Sede>
      //
      IndirizzoType sede = obj.createIndirizzoType();
      cedente.setSede(sede);

      // Create <CessionarioCommittente>
      //
      final CessionarioCommittenteType cessionario = obj.createCessionarioCommittenteType();
      header.setCessionarioCommittente(cessionario);

      // Create <CessionarioCommittente>//<DatiAnagrafici>
      //
      final DatiAnagraficiCessionarioType a_cessionario = obj.createDatiAnagraficiCessionarioType();
      cessionario.setDatiAnagrafici(a_cessionario);

      anagrafica = obj.createAnagraficaType();
      a_cessionario.setAnagrafica(anagrafica);

      // Create <CessionarioCommittente>//<Sede>
      //
      sede = obj.createIndirizzoType();
      cessionario.setSede(sede);

      // Store what i done.
      //
      openMap = new HashMap<String, InvBean.OpenedAndSaved>();
    }
  }

  public SoggettoSogei getSoggetto() {
    return soggetto;
  }

  public void setSoggetto(SoggettoSogei soggetto) {
    this.soggetto = soggetto;
  }

  public Integer getCodiceFlusso() {
    return codiceFlusso;
  }

  public void setCodiceFlusso(Integer codiceFlusso) {
    this.codiceFlusso = codiceFlusso;
  }

  public List<SelectItem> getListTipoSconto() {
    if (listTipoSconto == null) {
      // ILut
      //
      final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");
      @SuppressWarnings("unchecked")
      final List<TipoScontoSogei> l_regimi = ldao.retrieve("TipoScontoSogei", "codice");
      listTipoSconto = new ArrayList<SelectItem>();
      for (final TipoScontoSogei tipo : l_regimi) {
        final SelectItem item =
            new SelectItem(TipoScontoMaggiorazioneType.fromValue(tipo.getLabel()),
                tipo.getDescrizione());
        listTipoSconto.add(item);
      }
    }
    return listTipoSconto;
  }

  public void setListTipoSconto(List<SelectItem> listTipoSconto) {
    this.listTipoSconto = listTipoSconto;
  }

  public List<SelectItem> getListCausaliPagamento() {
    if (listCausaliPagamento == null) {
      listCausaliPagamento = new ArrayList<SelectItem>();

      for (final CausalePagamentoType cp : CausalePagamentoType.values()) {
        listCausaliPagamento.add(new SelectItem(cp, cp.value()));
      }
    }
    return listCausaliPagamento;
  }

  public void setListCausaliPagamento(List<SelectItem> listCausaliPagamento) {
    this.listCausaliPagamento = listCausaliPagamento;
  }

  public List<SelectItem> getListTipoCassa() {
    if (listTipoCassa == null) {
      // ILut
      //
      final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");
      @SuppressWarnings("unchecked")
      final List<TipoCassaPrevidenzialeSogei> l_regimi =
          ldao.retrieve("TipoCassaPrevidenzialeSogei", "codice");
      listTipoCassa = new ArrayList<SelectItem>();
      for (final TipoCassaPrevidenzialeSogei tipo : l_regimi) {
        final SelectItem item =
            new SelectItem(TipoCassaType.fromValue(tipo.getLabel()), tipo.getDescrizione());
        listTipoCassa.add(item);
      }
    }
    return listTipoCassa;
  }

  public void setListTipoCassa(List<SelectItem> listTipoCassa) {
    this.listTipoCassa = listTipoCassa;
  }

  public List<SelectItem> getListTipoNatura() {
    if (listTipoNatura == null) {
      // ILut
      //
      final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");
      @SuppressWarnings("unchecked")
      final List<TipoNaturaSogei> l_regimi = ldao.retrieve("TipoNaturaSogei", "codice");
      listTipoNatura = new ArrayList<SelectItem>();
      for (final TipoNaturaSogei tipo : l_regimi) {
        final SelectItem item =
            new SelectItem(NaturaType.fromValue(tipo.getLabel()), tipo.getDescrizione());
        listTipoNatura.add(item);
      }
    }
    return listTipoNatura;
  }

  public void setListTipoNatura(List<SelectItem> listTipoNatura) {
    this.listTipoNatura = listTipoNatura;
  }

  public List<SelectItem> getListRitenuta() {
    if (listRitenuta == null) {
      listRitenuta = new ArrayList<SelectItem>();
      listRitenuta.add(new SelectItem(null, "NO"));
      listRitenuta.add(new SelectItem(RitenutaType.SI, RitenutaType.SI.toString()));
    }
    return listRitenuta;
  }

  public void setListRitenuta(List<SelectItem> listRitenuta) {
    this.listRitenuta = listRitenuta;
  }

  public List<SelectItem> getListEsigibilitaIVA() {
    if (listEsigibilitaIVA == null) {
      listEsigibilitaIVA = new ArrayList<SelectItem>();
      listEsigibilitaIVA.add(new SelectItem(EsigibilitaIVAType.I, "Immediata"));
      listEsigibilitaIVA.add(new SelectItem(EsigibilitaIVAType.D, "Differita"));
      listEsigibilitaIVA.add(new SelectItem(EsigibilitaIVAType.S, "Scissione dei Pagamenti"));
    }
    return listEsigibilitaIVA;
  }

  public void setListEsigibilitaIVA(List<SelectItem> listEsigibilitaIVA) {
    this.listEsigibilitaIVA = listEsigibilitaIVA;
  }

  public List<SelectItem> getListTipoPrestazione() {
    if (listTipoPrestazione == null) {
      // ILut
      //
      final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");
      @SuppressWarnings("unchecked")
      final List<TipoPrestazioneSogei> l_regimi = ldao.retrieve("TipoPrestazioneSogei", "codice");
      listTipoPrestazione = new ArrayList<SelectItem>();
      for (final TipoPrestazioneSogei tipo : l_regimi) {
        final SelectItem item =
            new SelectItem(TipoCessionePrestazioneType.fromValue(tipo.getLabel()),
                tipo.getDescrizione());
        listTipoPrestazione.add(item);
      }
    }
    return listTipoPrestazione;
  }

  public void setListTipoPrestazione(List<SelectItem> listTipoPrestazione) {
    this.listTipoPrestazione = listTipoPrestazione;
  }

  public List<SelectItem> getListRegimiFiscali() {
    if (listRegimiFiscali == null) {
      // ILut
      //
      final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");
      @SuppressWarnings("unchecked")
      final List<TipoRegimeFiscaleSogei> l_regimi =
      ldao.retrieve("TipoRegimeFiscaleSogei", "codice");
      listRegimiFiscali = new ArrayList<SelectItem>();
      for (final TipoRegimeFiscaleSogei tipo : l_regimi) {
        final SelectItem item =
            new SelectItem(RegimeFiscaleType.fromValue(tipo.getLabel()), tipo.getDescrizione());
        listRegimiFiscali.add(item);
      }
    }
    return listRegimiFiscali;
  }

  public void setListRegimiFiscali(List<SelectItem> listRegimiFiscali) {
    this.listRegimiFiscali = listRegimiFiscali;
  }

  public List<SelectItem> getListTipoRitenuta() {
    if (listTipoRitenuta == null) {
      // ILut
      //
      final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");
      @SuppressWarnings("unchecked")
      final List<TipoRitenutaSogei> l_regimi = ldao.retrieve("TipoRitenutaSogei", "codice");
      listTipoRitenuta = new ArrayList<SelectItem>();
      for (final TipoRitenutaSogei tipo : l_regimi) {
        final SelectItem item =
            new SelectItem(TipoRitenutaType.fromValue(tipo.getLabel()), tipo.getDescrizione());
        listTipoRitenuta.add(item);
      }
    }
    return listTipoRitenuta;
  }

  public void setListTipoRitenuta(List<SelectItem> listTipoRitenuta) {
    this.listTipoRitenuta = listTipoRitenuta;
  }

  public List<SelectItem> getListTipoSocio() {
    if (listTipoSocio == null) {
      listTipoSocio = new ArrayList<SelectItem>();
      listTipoSocio.add(new SelectItem(SocioUnicoType.SU, SocioUnicoType.SU.toString()));
      listTipoSocio.add(new SelectItem(SocioUnicoType.SM, SocioUnicoType.SM.toString()));
    }
    return listTipoSocio;
  }

  public void setListTipoSocio(List<SelectItem> listTipoSocio) {
    this.listTipoSocio = listTipoSocio;
  }

  public List<SelectItem> getListStatoLiquidazione() {
    if (listStatoLiquidazione == null) {
      listStatoLiquidazione = new ArrayList<SelectItem>();
      listStatoLiquidazione.add(new SelectItem(StatoLiquidazioneType.LN, StatoLiquidazioneType.LN
          .toString()));
      listStatoLiquidazione.add(new SelectItem(StatoLiquidazioneType.LS, StatoLiquidazioneType.LS
          .toString()));
    }
    return listStatoLiquidazione;
  }

  public void setListStatoLiquidazione(List<SelectItem> listStatoLiquidazione) {
    this.listStatoLiquidazione = listStatoLiquidazione;
  }

  public List<SelectItem> getListTipoDocumento() {
    if (listTipoDocumento == null) {
      // ILut
      //
      final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");
      @SuppressWarnings("unchecked")
      final List<TipoFatturaSogei> l_regimi = ldao.retrieve("TipoFatturaSogei", "codice");
      listTipoDocumento = new ArrayList<SelectItem>();
      for (final TipoFatturaSogei tipo : l_regimi) {
        final SelectItem item =
            new SelectItem(TipoDocumentoType.fromValue(tipo.getLabel()), tipo.getDescrizione());
        listTipoDocumento.add(item);
      }
    }
    return listTipoDocumento;
  }

  public void setListTipoDocumento(List<SelectItem> listTipoDocumento) {
    this.listTipoDocumento = listTipoDocumento;
  }

  public List<SelectItem> getListArt73() {
    if (listArt73 == null) {
      listArt73 = new ArrayList<SelectItem>();
      listArt73.add(new SelectItem(null, "NO"));
      listArt73.add(new SelectItem(Art73Type.SI, Art73Type.SI.toString()));
    }
    return listArt73;
  }

  public void setListArt73(List<SelectItem> listArt73) {
    this.listArt73 = listArt73;
  }

  public FatturaElettronicaType getInvio() {
    return invio;
  }

  public void setInvio(FatturaElettronicaType invio) {
    this.invio = invio;
  }

  public FatturaElettronicaBodyType getFattura() {
    return fattura;
  }

  public void setFattura(FatturaElettronicaBodyType fattura) {
    this.fattura = fattura;
  }

  public String getWizard() {
    return wizard;
  }

  public void setWizard(String wizard) {
    this.wizard = wizard;
  }

  public void doUpdateWizard(ActionEvent e) {
    final String wizard = (String) FacesUtils.getRequestParameter("wizard");
    this.wizard = wizard;

    final String s_menu = (String) FacesUtils.getRequestParameter("menu");
    final Integer m = Integer.parseInt(s_menu);
    menu[m] = Boolean.TRUE;
    menu[m + 1] = Boolean.TRUE;
    for (int i = menu.length - 1; i > m + 1; i--) {
      menu[i] = Boolean.FALSE;
    }
  }

  public void doAddFatturaWizard(ActionEvent e) {
    final String wizard = (String) FacesUtils.getRequestParameter("wizard");
    this.wizard = wizard;

    final String s_menu = (String) FacesUtils.getRequestParameter("menu");
    final Integer m = Integer.parseInt(s_menu);
    menu[m] = Boolean.TRUE;
    menu[m + 1] = Boolean.TRUE;


    // <Body>
    //
    fattura = obj.createFatturaElettronicaBodyType();
    final DatiGeneraliType dgt = obj.createDatiGeneraliType();
    fattura.setDatiGenerali(dgt);
    final DatiGeneraliDocumentoType dt = obj.createDatiGeneraliDocumentoType();
    dgt.setDatiGeneraliDocumento(dt);

    // <DatiBeniServizi>
    //
    final DatiBeniServiziType beni = obj.createDatiBeniServiziType();
    fattura.setDatiBeniServizi(beni);
    openMap.put(fattura.getId(), new OpenedAndSaved());
  }

  public void doEditFatturaWizard(ActionEvent e) {
    final String wizard = (String) FacesUtils.getRequestParameter("wizard");
    this.wizard = wizard;

    final String id = (String) FacesUtils.getRequestParameter("id");

    final List<FatturaElettronicaBodyType> l_fatture = invio.getFatturaElettronicaBody();
    final Iterator<FatturaElettronicaBodyType> i_fatture = l_fatture.iterator();
    fattura = null;
    while (i_fatture.hasNext() && fattura == null) {
      final FatturaElettronicaBodyType invoice = i_fatture.next();
      if (invoice.getId().equals(id)) {
        fattura = invoice;
      }
    }

    // Store invoice.
    //
    openMap.put(fattura.getId(), new OpenedAndSaved());
  }

  public void doSaveFatturaWizard(ActionEvent e) {
    // Check if current fattura is completed!
    //
    final String wizard = (String) FacesUtils.getRequestParameter("wizard");
    if (fattura != null) {
      addCausaliToFattura();

      if (fattura.getDatiGenerali().getDatiGeneraliDocumento().getDatiBollo() != null) {
        fattura.getDatiGenerali().getDatiGeneraliDocumento().getDatiBollo()
        .setBolloVirtuale(BolloVirtualeType.SI);
      }

      // Saving riepilogo State.
      //
      final List<DatiRiepilogoType> l_riep = fattura.getDatiBeniServizi().getDatiRiepilogo();
      final Iterator<DatiRiepilogoType> i_riep = l_riep.iterator();
      while (i_riep.hasNext()) {
        final DatiRiepilogoType riepilogo = i_riep.next();
        final OpenedAndSaved op = openMap.get(riepilogo.getId());
        if (op != null) {
          op.save();
        }
      }

      // Check if row is ok!
      //
      final String error = isFatturaOK(fattura);
      if (error != null) {
        FacesUtils.addContextErrorMessage(getClass(), error, new Object[] {fattura
          .getDatiGenerali().getDatiGeneraliDocumento().getNumero()});
        return;
      }

      final List<FatturaElettronicaBodyType> l_fatture = invio.getFatturaElettronicaBody();
      final Iterator<FatturaElettronicaBodyType> i_fatture = l_fatture.iterator();
      boolean founded = false;
      while (i_fatture.hasNext() && !founded) {
        final FatturaElettronicaBodyType invoice = i_fatture.next();
        founded = invoice.getId().equals(fattura.getId());
      }

      if (!founded) {
        l_fatture.add(fattura);
        LogUtils.info(getClass(), "Added new invoice to flux.");
      }

      final OpenedAndSaved op = openMap.get(fattura.getId());
      if (op != null) {
        op.save();
      }

      this.wizard = wizard;
    }
  }

  private void addCausaliToFattura() {
    for (final String causale : causali.values()) {
      if (!causale.isEmpty()) {
        fattura.getDatiGenerali().getDatiGeneraliDocumento().getCausale().add(causale);
      }
    }
  }

  public String doSaveFlux() {
    final String error = isFlussoOK(invio);
    if (error != null) {
      FacesUtils.addContextErrorMessage(getClass(), error);
      return null;
    }

    // ISogei
    //
    final SogeiFacade sdao = (SogeiFacade) FacesUtils.findBean("SogeiFacade");
    sdao.serializeCaricamentoFlusso(codiceFlusso, soggetto.getCodice(), invio);

    return "success";
  }

  public void doManageStabile(ActionEvent e) {
    // Create <CedentePrestatore>//<StabileOrganizzazione>
    //
    final CedentePrestatoreType cedente =
        invio.getFatturaElettronicaHeader().getCedentePrestatore();
    IndirizzoType stabileOrganizzazione = cedente.getStabileOrganizzazione();
    if (stabileOrganizzazione == null) {
      stabileOrganizzazione = obj.createIndirizzoType();
      cedente.setStabileOrganizzazione(stabileOrganizzazione);
    }
  }

  public void doEliminaStabile(ActionEvent e) {
    System.out.println("Elimino stabile");
    // Create <CedentePrestatore>//<StabileOrganizzazione>
    //
    final CedentePrestatoreType cedente =
        invio.getFatturaElettronicaHeader().getCedentePrestatore();
    cedente.setStabileOrganizzazione(null);
  }

  public void doManageContattiCedente(ActionEvent e) {
    System.out.println("ManageContatti");
    // Create <CedentePrestatore>//<Contatti>
    //
    final CedentePrestatoreType cedente =
        invio.getFatturaElettronicaHeader().getCedentePrestatore();
    ContattiType contatti = cedente.getContatti();
    if (contatti == null) {
      contatti = obj.createContattiType();
      cedente.setContatti(contatti);
    }
  }

  public void doEliminaContattiCedente(ActionEvent e) {
    System.out.println("Elimino contatti");
    // Create <CedentePrestatore>//<StabileOrganizzazione>
    //
    final CedentePrestatoreType cedente =
        invio.getFatturaElettronicaHeader().getCedentePrestatore();
    cedente.setContatti(null);
  }

  public void doManageIscrizioneRea(ActionEvent e) {
    System.out.println("doManageIscrizioneRea");
    // Create <CedentePrestatore>//<IscrizioneRea>
    //
    final CedentePrestatoreType cedente =
        invio.getFatturaElettronicaHeader().getCedentePrestatore();
    IscrizioneREAType rea = cedente.getIscrizioneREA();
    if (rea == null) {
      rea = obj.createIscrizioneREAType();
      cedente.setIscrizioneREA(rea);
    }
  }

  public void doEliminaIscrizioneRea(ActionEvent e) {
    System.out.println("Elimino rea");
    // Create <CedentePrestatore>//<StabileOrganizzazione>
    //
    final CedentePrestatoreType cedente =
        invio.getFatturaElettronicaHeader().getCedentePrestatore();
    cedente.setIscrizioneREA(null);
  }

  public void doManageRappresentante(ActionEvent e) {
    // Create <RappresentanteFiscale>
    //
    RappresentanteFiscaleType rap = invio.getFatturaElettronicaHeader().getRappresentanteFiscale();
    if (rap == null) {
      rap = obj.createRappresentanteFiscaleType();
      invio.getFatturaElettronicaHeader().setRappresentanteFiscale(rap);

      // Create <RappresentanteFiscale>//<DatiAnagrafici>
      //
      final DatiAnagraficiRappresentanteType anagrafica_cedente =
          obj.createDatiAnagraficiRappresentanteType();
      rap.setDatiAnagrafici(anagrafica_cedente);
      final IdFiscaleType id_t = obj.createIdFiscaleType();
      anagrafica_cedente.setIdFiscaleIVA(id_t);

      final AnagraficaType anagrafica = obj.createAnagraficaType();
      anagrafica_cedente.setAnagrafica(anagrafica);
    }
  }

  public void doEliminaRappresentante(ActionEvent e) {
    invio.getFatturaElettronicaHeader().setRappresentanteFiscale(null);
  }

  public void doManageRiferimentiFiscali(ActionEvent e) {
    // Create <CessionarioCommittente>//<IdFiscaleIVA>
    //
    final CessionarioCommittenteType cessionario =
        invio.getFatturaElettronicaHeader().getCessionarioCommittente();
    final DatiAnagraficiCessionarioType anag = cessionario.getDatiAnagrafici();
    IdFiscaleType id = anag.getIdFiscaleIVA();
    if (id == null) {
      id = obj.createIdFiscaleType();
      anag.setIdFiscaleIVA(id);
    }
  }

  public void doEliminaRiferimentiFiscali(ActionEvent e) {
    final CessionarioCommittenteType cessionario =
        invio.getFatturaElettronicaHeader().getCessionarioCommittente();
    final DatiAnagraficiCessionarioType anag = cessionario.getDatiAnagrafici();
    anag.setIdFiscaleIVA(null);
  }

  public void doManageDatiRitenuta(ActionEvent e) {
    final DatiGeneraliDocumentoType g_type = fattura.getDatiGenerali().getDatiGeneraliDocumento();
    DatiRitenutaType r_type = g_type.getDatiRitenuta();
    if (r_type == null) {
      r_type = obj.createDatiRitenutaType();
      g_type.setDatiRitenuta(r_type);
    }
    doRebuildRiepilogoFattura(fattura);
  }

  public void doEliminaDatiRitenuta(ActionEvent e) {
    final DatiGeneraliDocumentoType g_type = fattura.getDatiGenerali().getDatiGeneraliDocumento();
    g_type.setDatiRitenuta(null);
    doRebuildRiepilogoFattura(fattura);
  }

  public void doManageDatiBollo(ActionEvent e) {
    final DatiGeneraliDocumentoType g_type = fattura.getDatiGenerali().getDatiGeneraliDocumento();
    DatiBolloType r_type = g_type.getDatiBollo();
    if (r_type == null) {
      r_type = obj.createDatiBolloType();
      g_type.setDatiBollo(r_type);
    }
    doRebuildRiepilogoFattura(fattura);
  }

  public void doEliminaDatiBollo(ActionEvent e) {
    final DatiGeneraliDocumentoType g_type = fattura.getDatiGenerali().getDatiGeneraliDocumento();
    g_type.setDatiBollo(null);
  }

  public void doManageDatiCassaPrevidenziale(ActionEvent e) {
    c_type = obj.createDatiCassaPrevidenzialeType();
  }

  public void doEliminaDatiCassaPrevidenziale(ActionEvent e) {
    c_type = null;
  }

  public void doSaveDatiCassaPrevidenziale(ActionEvent e) {
    final DatiGeneraliDocumentoType g_type = fattura.getDatiGenerali().getDatiGeneraliDocumento();
    final List<DatiCassaPrevidenzialeType> c_list = g_type.getDatiCassaPrevidenziale();
    c_list.add(c_type);
    c_type = obj.createDatiCassaPrevidenzialeType();
  }

  public void doEliminaDatiCassaPrevidenzialeItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final DatiGeneraliDocumentoType g_type = fattura.getDatiGenerali().getDatiGeneraliDocumento();
    final List<DatiCassaPrevidenzialeType> c_list = g_type.getDatiCassaPrevidenziale();
    final Iterator<DatiCassaPrevidenzialeType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DatiCassaPrevidenzialeType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        //return;
      }
    }
    doRebuildRiepilogoFattura(fattura);
  }

  public void doManageScontiFattura(ActionEvent e) {
    s_type = obj.createScontoMaggiorazioneType();
  }

  public void doEliminaScontiFattura(ActionEvent e) {
    s_type = null;
  }

  public void doSaveScontiFattura(ActionEvent e) {
    final DatiGeneraliDocumentoType g_type = fattura.getDatiGenerali().getDatiGeneraliDocumento();
    final List<ScontoMaggiorazioneType> c_list = g_type.getScontoMaggiorazione();
    c_list.add(s_type);
    s_type = obj.createScontoMaggiorazioneType();
    doRebuildRiepilogoFattura(fattura);
  }

  public void doEliminaScontiFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final DatiGeneraliDocumentoType g_type = fattura.getDatiGenerali().getDatiGeneraliDocumento();
    final List<ScontoMaggiorazioneType> c_list = g_type.getScontoMaggiorazione();
    final Iterator<ScontoMaggiorazioneType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final ScontoMaggiorazioneType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        //return;
      }
    }
    doRebuildRiepilogoFattura(fattura);
  }

  public Integer getNumeroLinea() {
    return numeroLinea;
  }

  public void setNumeroLinea(Integer numeroLinea) {
    this.numeroLinea = numeroLinea;
  }

  public void doManageOrdiniFattura(ActionEvent e) {
    o_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaOrdiniFattura(ActionEvent e) {
    o_doc_type = null;
  }

  public void doSaveOrdiniFattura(ActionEvent e) {
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiOrdineAcquisto();
    c_list.add(o_doc_type);
    o_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaOrdiniFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiOrdineAcquisto();
    final Iterator<DatiDocumentiCorrelatiType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DatiDocumentiCorrelatiType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void doAddLineaOrdiniFatturaItem(ActionEvent e) {
    if (numeroLinea != null) {
      o_doc_type.getRiferimentoNumeroLinea().add(numeroLinea);
    }
  }

  public void doManageContrattiFattura(ActionEvent e) {
    c_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaContrattiFattura(ActionEvent e) {
    c_doc_type = null;
  }

  public void doSaveContrattiFattura(ActionEvent e) {
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiContratto();
    c_list.add(c_doc_type);
    c_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaContrattiFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiContratto();
    final Iterator<DatiDocumentiCorrelatiType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DatiDocumentiCorrelatiType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void doAddLineaContrattiFatturaItem(ActionEvent e) {
    if (numeroLinea != null) {
      c_doc_type.getRiferimentoNumeroLinea().add(numeroLinea);
    }
  }

  public void doManageDDTFattura(ActionEvent e) {
    ddt_type = obj.createDatiDDTType();
  }

  public void doEliminaDDTFattura(ActionEvent e) {
    ddt_type = null;
  }

  public void doSaveDDTFattura(ActionEvent e) {
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDDTType> c_list = g_type.getDatiDDT();
    c_list.add(ddt_type);
    ddt_type = obj.createDatiDDTType();
  }

  public void doEliminaDDTFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDDTType> c_list = g_type.getDatiDDT();
    final Iterator<DatiDDTType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DatiDDTType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void doAddLineaDDTFatturaItem(ActionEvent e) {
    if (numeroLinea != null) {
      ddt_type.getRiferimentoNumeroLinea().add(numeroLinea);
    }
  }

  public void doManageFattureCollegateFattura(ActionEvent e) {
    f_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaFattureCollegateFattura(ActionEvent e) {
    f_doc_type = null;
  }

  public void doSaveFattureCollegateFattura(ActionEvent e) {
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiFattureCollegate();
    c_list.add(f_doc_type);
    f_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaFattureCollegateFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiFattureCollegate();
    final Iterator<DatiDocumentiCorrelatiType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DatiDocumentiCorrelatiType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void doAddLineaFattureCollegateFatturaItem(ActionEvent e) {
    if (numeroLinea != null) {
      f_doc_type.getRiferimentoNumeroLinea().add(numeroLinea);
    }
  }

  public void doManageConvenzioniFattura(ActionEvent e) {
    cn_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaConvenzioniFattura(ActionEvent e) {
    cn_doc_type = null;
  }

  public void doSaveConvenzioniFattura(ActionEvent e) {
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiConvenzione();
    c_list.add(cn_doc_type);
    cn_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaConvenzioniFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiConvenzione();
    final Iterator<DatiDocumentiCorrelatiType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DatiDocumentiCorrelatiType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void doAddLineaConvenzioniFatturaItem(ActionEvent e) {
    if (numeroLinea != null) {
      cn_doc_type.getRiferimentoNumeroLinea().add(numeroLinea);
    }
  }

  public void doManageDocumentiRicezioneFattura(ActionEvent e) {
    r_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaDocumentiRicezioneFattura(ActionEvent e) {
    r_doc_type = null;
  }

  public void doSaveDocumentiRicezioneFattura(ActionEvent e) {
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiRicezione();
    c_list.add(r_doc_type);
    r_doc_type = obj.createDatiDocumentiCorrelatiType();
  }

  public void doEliminaDocumentiRicezioneFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiDocumentiCorrelatiType> c_list = g_type.getDatiRicezione();
    final Iterator<DatiDocumentiCorrelatiType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DatiDocumentiCorrelatiType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void doAddLineaDocumentiRicezioneFatturaItem(ActionEvent e) {
    if (numeroLinea != null) {
      r_doc_type.getRiferimentoNumeroLinea().add(numeroLinea);
    }
  }

  public void doManageSALFattura(ActionEvent e) {
    sal_type = obj.createDatiSALType();
  }

  public void doEliminaSALFattura(ActionEvent e) {
    sal_type = null;
  }

  public void doSaveSALFattura(ActionEvent e) {
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiSALType> c_list = g_type.getDatiSAL();
    c_list.add(sal_type);
    sal_type = obj.createDatiSALType();
  }

  public void doEliminaSALFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final DatiGeneraliType g_type = fattura.getDatiGenerali();
    final List<DatiSALType> c_list = g_type.getDatiSAL();
    final Iterator<DatiSALType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DatiSALType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void doManageDatiGestionaliRiga(ActionEvent e) {
    g_type = obj.createAltriDatiGestionaliType();
  }

  public void doEliminaDatiGestionaliRiga(ActionEvent e) {
    g_type = null;
  }

  public void doSaveDatiGestionaliRiga(ActionEvent e) {
    final List<AltriDatiGestionaliType> c_list = riga.getAltriDatiGestionali();
    c_list.add(g_type);
    g_type = obj.createAltriDatiGestionaliType();

  }

  public void doEliminaDatiGestionaliRigaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final List<AltriDatiGestionaliType> c_list = riga.getAltriDatiGestionali();
    final Iterator<AltriDatiGestionaliType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final AltriDatiGestionaliType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }

  }

  public AltriDatiGestionaliType getG_type() {
    return g_type;
  }

  public void setG_type(AltriDatiGestionaliType g_type) {
    this.g_type = g_type;
  }

  public DatiDocumentiCorrelatiType getO_doc_type() {
    return o_doc_type;
  }

  public void setO_doc_type(DatiDocumentiCorrelatiType o_doc_type) {
    this.o_doc_type = o_doc_type;
  }

  public DatiDocumentiCorrelatiType getC_doc_type() {
    return c_doc_type;
  }

  public void setC_doc_type(DatiDocumentiCorrelatiType c_doc_type) {
    this.c_doc_type = c_doc_type;
  }

  public DatiDocumentiCorrelatiType getCn_doc_type() {
    return cn_doc_type;
  }

  public void setCn_doc_type(DatiDocumentiCorrelatiType cn_doc_type) {
    this.cn_doc_type = cn_doc_type;
  }

  public DatiDocumentiCorrelatiType getR_doc_type() {
    return r_doc_type;
  }

  public void setR_doc_type(DatiDocumentiCorrelatiType r_doc_type) {
    this.r_doc_type = r_doc_type;
  }

  public DatiDocumentiCorrelatiType getF_doc_type() {
    return f_doc_type;
  }

  public void setF_doc_type(DatiDocumentiCorrelatiType f_doc_type) {
    this.f_doc_type = f_doc_type;
  }

  public ScontoMaggiorazioneType getS_type() {
    return s_type;
  }

  public void setS_type(ScontoMaggiorazioneType s_type) {
    this.s_type = s_type;
  }

  public DatiSALType getSal_type() {
    return sal_type;
  }

  public void setSal_type(DatiSALType sal_type) {
    this.sal_type = sal_type;
  }

  public DatiDDTType getDdt_type() {
    return ddt_type;
  }

  public void setDdt_type(DatiDDTType ddt_type) {
    this.ddt_type = ddt_type;
  }

  public DatiCassaPrevidenzialeType getC_type() {
    return c_type;
  }

  public void setC_type(DatiCassaPrevidenzialeType c_type) {
    this.c_type = c_type;
  }

  public Boolean[] getMenu() {
    return menu;
  }

  public void setMenu(Boolean[] menu) {
    this.menu = menu;
  }

  public void doAddDatiTrasporto(ActionEvent e) {
    // <DatiTrasporto>
    //
    DatiTrasportoType tr_type = fattura.getDatiGenerali().getDatiTrasporto();
    if (tr_type == null) {
      tr_type = obj.createDatiTrasportoType();
      fattura.getDatiGenerali().setDatiTrasporto(tr_type);
    }
  }

  public void doEliminaDatiTrasporto(ActionEvent e) {
    // <DatiTrasporto>
    //
    fattura.getDatiGenerali().setDatiTrasporto(null);
  }

  public void doAddAnagraficaDatiTrasporto(ActionEvent e) {
    // <DatiTrasporto>
    //
    final DatiTrasportoType tr_type = fattura.getDatiGenerali().getDatiTrasporto();
    if (tr_type != null) {
      DatiAnagraficiVettoreType anag = tr_type.getDatiAnagraficiVettore();
      if (anag == null) {
        anag = obj.createDatiAnagraficiVettoreType();
        tr_type.setDatiAnagraficiVettore(anag);
        final IdFiscaleType id_fiscale = obj.createIdFiscaleType();
        anag.setIdFiscaleIVA(id_fiscale);
        final AnagraficaType a_anag = obj.createAnagraficaType();
        anag.setAnagrafica(a_anag);
      }
    }
  }

  public void doEliminaAnagraficaDatiTrasporto(ActionEvent e) {
    // <DatiTrasporto>
    //
    final DatiTrasportoType tr_type = fattura.getDatiGenerali().getDatiTrasporto();
    if (tr_type != null) {
      tr_type.setDatiAnagraficiVettore(null);
    }
  }

  public void doAddIndirizzoResaDatiTrasporto(ActionEvent e) {
    // <DatiTrasporto>
    //
    final DatiTrasportoType tr_type = fattura.getDatiGenerali().getDatiTrasporto();
    if (tr_type != null) {
      final IndirizzoType indirizzo = obj.createIndirizzoType();
      tr_type.setIndirizzoResa(indirizzo);
    }
  }

  public void doEliminaIndirizzoResaDatiTrasporto(ActionEvent e) {
    // <DatiTrasporto>
    //
    final DatiTrasportoType tr_type = fattura.getDatiGenerali().getDatiTrasporto();
    if (tr_type != null) {
      tr_type.setIndirizzoResa(null);
    }
  }

  public void doAddDatiVeicolo(ActionEvent e) {
    // <DatiVeicolo>
    //
    DatiVeicoliType tr_type = fattura.getDatiVeicoli();
    if (tr_type == null) {
      tr_type = obj.createDatiVeicoliType();
      fattura.setDatiVeicoli(tr_type);
    }
  }

  public void doEliminaDatiVeicolo(ActionEvent e) {
    fattura.setDatiVeicoli(null);
  }

  public DettaglioLineeType getRiga() {
    return riga;
  }

  public void setRiga(DettaglioLineeType riga) {
    this.riga = riga;
  }

  public void doAddRigaWizard(ActionEvent e) {
    final String wizard = (String) FacesUtils.getRequestParameter("wizard");
    this.wizard = wizard;

    final String s_menu = (String) FacesUtils.getRequestParameter("menu");
    final Integer m = Integer.parseInt(s_menu);
    menu[m] = Boolean.TRUE;

    // <DettaglioLinee>
    //
    riga = obj.createDettaglioLineeType();

    int progressivo = 0;
    final Iterator<DettaglioLineeType> ir =
        fattura.getDatiBeniServizi().getDettaglioLinee().iterator();
    while (ir.hasNext()) {
      final DettaglioLineeType l = ir.next();
      if (l.getNumeroLinea() > progressivo) {
        progressivo = l.getNumeroLinea();
      }
    }
    riga.setNumeroLinea(++progressivo);

    // Store riga.
    //
    openMap.put(riga.getId(), new OpenedAndSaved());
  }

  public void doEditRigaWizard(ActionEvent e) {
    final String wizard = (String) FacesUtils.getRequestParameter("wizard");
    this.wizard = wizard;

    final String id = (String) FacesUtils.getRequestParameter("id");

    // <DettaglioLinee>
    //
    riga = null;
    final List<DettaglioLineeType> l_list = fattura.getDatiBeniServizi().getDettaglioLinee();
    final Iterator<DettaglioLineeType> l_it = l_list.iterator();
    while (l_it.hasNext() && riga == null) {
      final DettaglioLineeType linea = l_it.next();
      if (linea.getId().equals(id)) {
        riga = linea;
      }
    }

    // Store riga.
    //
    openMap.put(riga.getId(), new OpenedAndSaved());
  }

  public void doSaveRigaWizard(ActionEvent e) {
    final String wizard = (String) FacesUtils.getRequestParameter("wizard");

    final String s_menu = (String) FacesUtils.getRequestParameter("menu");
    final Integer m = Integer.parseInt(s_menu);
    menu[m] = Boolean.TRUE;

    // Check if row is ok!
    //
    final String error = isRigaOK(riga);
    if (error != null) {
      FacesUtils.addContextErrorMessage(getClass(), error);
      return;
    }

    final List<DettaglioLineeType> linee = fattura.getDatiBeniServizi().getDettaglioLinee();
    final Iterator<DettaglioLineeType> i_linee = linee.iterator();
    boolean founded = false;
    while (i_linee.hasNext() && !founded) {
      final DettaglioLineeType linea = i_linee.next();
      founded = linea.getId().equals(riga.getId());
    }

    if (!founded) {
      linee.add(riga);
      LogUtils.info(getClass(), "Added new row to invoice.");
    }

    // Rebuild riepilogo!
    //
    final OpenedAndSaved opened = openMap.get(riga.getId());
    opened.save();

    doRebuildRiepilogoFattura(fattura);
    this.wizard = wizard;
  }

  public void doManageScontiRiga(ActionEvent e) {
    s_type = obj.createScontoMaggiorazioneType();
  }

  public void doEliminaScontiRiga(ActionEvent e) {
    s_type = null;
  }

  public void doSaveScontiRiga(ActionEvent e) {
    final List<ScontoMaggiorazioneType> c_list = riga.getScontoMaggiorazione();
    c_list.add(s_type);
    s_type = obj.createScontoMaggiorazioneType();

    doUpdateImportoRiga(e);
  }

  public void doEliminaScontiRigaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final List<ScontoMaggiorazioneType> c_list = riga.getScontoMaggiorazione();
    final Iterator<ScontoMaggiorazioneType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final ScontoMaggiorazioneType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        //return;
      }
    }

    doUpdateImportoRiga(e);
  }

  public void doUpdateImportoRiga(ActionEvent e) {
      final BigDecimal importoUnitario = riga.getPrezzoUnitario();
      BigDecimal prezzoTotale = riga.getPrezzoTotale() != null ? riga.getPrezzoTotale() : new BigDecimal("0.0");
      if (importoUnitario != null) {
          BigDecimal quantita = riga.getQuantita();
          BigDecimal qm = quantita;
          if (quantita == null || quantita.compareTo(BigDecimal.ZERO) == 0) {
              quantita = BigDecimal.ZERO;
              qm = new BigDecimal("1.0");
          }

          prezzoTotale = importoUnitario.multiply(qm);

          // Ietarate on Sconto
          //
          final Iterator<ScontoMaggiorazioneType> sconti = riga.getScontoMaggiorazione().iterator();
          BigDecimal maggiorazione = new BigDecimal("0.0");
          BigDecimal currentTotale = prezzoTotale;

          while (sconti.hasNext()) {
              final ScontoMaggiorazioneType sconto = sconti.next();
              BigDecimal sign = new BigDecimal("1.0");
              if (sconto.getTipo().equals(TipoScontoMaggiorazioneType.SC)) {
                  sign = new BigDecimal("-1.0");
              }

              BigDecimal to_add = BigDecimal.ZERO;
              if (sconto.getPercentuale() != null && (!sconto.getPercentuale().equals(BigDecimal.ZERO))) {
                  to_add = currentTotale.multiply(sconto.getPercentuale()).divide(new BigDecimal("100.00")).setScale(2, HALF_UP);;
              }
              if (sconto.getImporto() != null && (!sconto.getImporto().equals(BigDecimal.ZERO))) {
                  BigDecimal q = riga.getQuantita();
                  if ((q==null)|| BigDecimal.ZERO.equals(q)){
                      q=BigDecimal.ONE;
                  }
                  to_add = (sconto.getImporto().multiply(q));
              }

              to_add = to_add.multiply(sign);
              maggiorazione = maggiorazione.add(to_add);
              currentTotale = prezzoTotale.add(maggiorazione);
          }

          prezzoTotale = prezzoTotale.add(maggiorazione);
          riga.setPrezzoTotale(prezzoTotale);

          // Rebuild riepilogo!
          //
          doRebuildRiepilogoFattura(fattura);
      }
      LogUtils.info(getClass(),  "Updated amount for row n. " + riga.getNumeroLinea());
  }

  public void doManageCodiciRiga(ActionEvent e) {
    cod_type = obj.createCodiceArticoloType();
  }

  public void doEliminaCodiciRiga(ActionEvent e) {
    cod_type = null;
  }

  public void doSaveCodiciRiga(ActionEvent e) {
    final List<CodiceArticoloType> c_list = riga.getCodiceArticolo();
    c_list.add(cod_type);
    cod_type = obj.createCodiceArticoloType();
  }

  public void doEliminaCodiciRigaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final List<CodiceArticoloType> c_list = riga.getCodiceArticolo();
    final Iterator<CodiceArticoloType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final CodiceArticoloType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public CodiceArticoloType getCod_type() {
    return cod_type;
  }

  public void setCod_type(CodiceArticoloType cod_type) {
    this.cod_type = cod_type;
  }

  public DatiPagamentoType getDati_pagamento() {
    return dati_pagamento;
  }

  public void setDati_pagamento(DatiPagamentoType dati_pagamento) {
    this.dati_pagamento = dati_pagamento;
  }

  public DettaglioPagamentoType getDettaglio_pagamento() {
    return dettaglio_pagamento;
  }

  public void setDettaglio_pagamento(DettaglioPagamentoType dettaglio_pagamento) {
    this.dettaglio_pagamento = dettaglio_pagamento;
  }

  public List<SelectItem> getListTipoCondizioniPagamento() {
    if (listTipoCondizioniPagamento == null) {
      final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");
      @SuppressWarnings("unchecked")
      final List<TipoCondizioniPagamentoSogei> list =
          ldao.retrieve("TipoCondizioniPagamentoSogei", "codice");
      listTipoCondizioniPagamento = new ArrayList<SelectItem>();
      for (final TipoCondizioniPagamentoSogei l : list) {
          listTipoCondizioniPagamento.add(new SelectItem(CondizioniPagamentoType.fromValue(l.getLabel()), l.getDescrizione()));
      }
    }
    return listTipoCondizioniPagamento;

  }

  public void setListTipoCondizioniPagamento(List<SelectItem> listTipoCondizioniPagamento) {
    this.listTipoCondizioniPagamento = listTipoCondizioniPagamento;
  }

  public List<SelectItem> getListModalitaPagamento() {
    if (listModalitaPagamento == null) {
      final LUTFacade ldao = (LUTFacade) FacesUtils.findBean("LUTFacade");
      @SuppressWarnings("unchecked")
      final List<TipoModalitaPagamentoSogei> list = ldao.retrieve("TipoModalitaPagamentoSogei", "codice");
      listModalitaPagamento = new ArrayList<SelectItem>();
      for (final TipoModalitaPagamentoSogei l : list) {
        listModalitaPagamento.add(new SelectItem(ModalitaPagamentoType.fromValue(l.getLabel()), l
            .getDescrizione()));
      }
    }
    return listModalitaPagamento;
  }

  public void setListModalitaPagamento(List<SelectItem> listModalitaPagamento) {
    this.listModalitaPagamento = listModalitaPagamento;
  }

  public void doManageDatiPagamentoFattura(ActionEvent e) {
    dati_pagamento = obj.createDatiPagamentoType();
    dettaglio_pagamento = obj.createDettaglioPagamentoType();
  }

  public void doEliminaDatiPagamentoFattura(ActionEvent e) {
    dati_pagamento = null;
  }

  public void doSaveDatiPagamentoFattura(ActionEvent e) {
    final List<DatiPagamentoType> c_list = fattura.getDatiPagamento();
    c_list.add(dati_pagamento);

    dati_pagamento = null;
    dettaglio_pagamento = null;
  }

  public void doEliminaDatiPagamentoFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final List<DatiPagamentoType> c_list = fattura.getDatiPagamento();
    final Iterator<DatiPagamentoType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DatiPagamentoType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void doManageDettaglioPagamentoFattura(ActionEvent e) {
    dettaglio_pagamento = obj.createDettaglioPagamentoType();
  }

  public void doEliminaDettaglioPagamentoFattura(ActionEvent e) {
    dettaglio_pagamento = null;
  }

  public void doSaveDettaglioPagamentoFattura(ActionEvent e) {
    final List<DettaglioPagamentoType> c_list = dati_pagamento.getDettaglioPagamento();
    c_list.add(dettaglio_pagamento);

    dettaglio_pagamento = null;
  }

  public void doEliminaDettaglioPagamentoFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final List<DettaglioPagamentoType> c_list = dati_pagamento.getDettaglioPagamento();
    final Iterator<DettaglioPagamentoType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DettaglioPagamentoType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public AllegatiType getAllegato() {
    return allegato;
  }

  public void setAllegato(AllegatiType allegato) {
    this.allegato = allegato;
  }

  public UploadItem getFile() {
    return file;
  }

  public void setFile(UploadItem file) {
    this.file = file;
  }

  public void doManageAllegatoFattura(ActionEvent e) {
    allegato = obj.createAllegatiType();
    file = null;
  }

  public void doEliminaAllegatoFattura(ActionEvent e) {
    allegato = null;
    file = null;
  }

  public void doSaveAllegatoFattura(ActionEvent e) {
    final List<AllegatiType> a_list = fattura.getAllegati();
    allegato.setNomeAttachment(FacesUtils.getNormalizedFileName(allegato.getNomeAttachment()));
    a_list.add(allegato);
    allegato = null;
    file = null;
  }

  public void doEliminaAllegatoFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");
    final List<AllegatiType> c_list = fattura.getAllegati();
    final Iterator<AllegatiType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final AllegatiType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void listener(UploadEvent event) throws Exception {
    final UploadItem item = event.getUploadItem();
    file = item;

    // Insert into AllegatoType.
    //
    final byte[] data = FacesUtils.getDataFromFile(item);
    allegato.setAttachment(data);
  }

  public void clearFile(ActionEvent e) {
    file = null;
    allegato.setAttachment(null);
    allegato.setNomeAttachment(null);
  }



  private String isFlussoOK(FatturaElettronicaType invio) {
    final long start_time = System.currentTimeMillis();
    String error = null;

    if (invio != null) {
      final CedentePrestatoreType cedente =
          invio.getFatturaElettronicaHeader().getCedentePrestatore();
      final DatiAnagraficiCedenteType anag_cede = cedente.getDatiAnagrafici();
      final AnagraficaType ced_anagrafica = anag_cede.getAnagrafica();
      if (ced_anagrafica == null) {
        error = "error_cedente_mustbecompleted";
      } else if (FormUtils.isEmpty(ced_anagrafica.getDenominazione())
          && (FormUtils.isEmpty(ced_anagrafica.getNome()) || FormUtils.isEmpty(ced_anagrafica
              .getCognome()))) {
        error = "error_cedente_mustbecompleted";
      } else if (!FormUtils.isEmpty(ced_anagrafica.getDenominazione())
          && (!FormUtils.isEmpty(ced_anagrafica.getNome()) || !FormUtils.isEmpty(ced_anagrafica
              .getCognome()))) {
        error = "error_cedente_mustbecompleted";
      }

      final CessionarioCommittenteType cessionario =
          invio.getFatturaElettronicaHeader().getCessionarioCommittente();
      final DatiAnagraficiCessionarioType anag_cess = cessionario.getDatiAnagrafici();
      final AnagraficaType cess_anagrafica = anag_cess.getAnagrafica();

      if (error == null
          && cessionario.getDatiAnagrafici().getIdFiscaleIVA() == null
          && (cessionario.getDatiAnagrafici().getCodiceFiscale() == null || cessionario
          .getDatiAnagrafici().getCodiceFiscale().trim().length() < 1)) {
        error = "error_cessionario_mustbecompleted";
      }

      if (error == null && cess_anagrafica == null) {
        error = "error_cessionarioanagrafica_mustbecompleted";
      } else if (error == null
          && FormUtils.isEmpty(cess_anagrafica.getDenominazione())
          && (FormUtils.isEmpty(cess_anagrafica.getNome()) || FormUtils.isEmpty(cess_anagrafica
              .getCognome()))) {
        error = "error_cessionarioanagrafica_mustbecompleted";
      } else if (error == null
          && !FormUtils.isEmpty(cess_anagrafica.getDenominazione())
          && (!FormUtils.isEmpty(cess_anagrafica.getNome()) || !FormUtils.isEmpty(cess_anagrafica
              .getCognome()))) {
        error = "error_cessionarioanagrafica_mustbecompleted";
      }

      final RappresentanteFiscaleType rappresentante =
          invio.getFatturaElettronicaHeader().getRappresentanteFiscale();
      if (rappresentante != null) {
        final DatiAnagraficiRappresentanteType anag_rappresentante =
            rappresentante.getDatiAnagrafici();
        final AnagraficaType rappresentante_anagrafica = anag_rappresentante.getAnagrafica();

        if (error == null
            && rappresentante.getDatiAnagrafici().getIdFiscaleIVA() == null
            && (rappresentante.getDatiAnagrafici().getCodiceFiscale() == null || rappresentante
                .getDatiAnagrafici().getCodiceFiscale().trim().length() < 1)) {
          error = "error_rappresentante_mustbecompleted";
        }

        if (error == null && rappresentante_anagrafica == null) {
          error = "error_rappresentanteanagrafica_mustbecompleted";
        } else if (error == null
            && FormUtils.isEmpty(rappresentante_anagrafica.getDenominazione())
            && (FormUtils.isEmpty(rappresentante_anagrafica.getNome()) || FormUtils
                .isEmpty(rappresentante_anagrafica.getCognome()))) {
          error = "error_rappresentanteanagrafica_mustbecompleted";
        } else if (error == null
            && !FormUtils.isEmpty(rappresentante_anagrafica.getDenominazione())
            && (!FormUtils.isEmpty(rappresentante_anagrafica.getNome()) || !FormUtils
                .isEmpty(rappresentante_anagrafica.getCognome()))) {
          error = "error_rappresentanteanagrafica_mustbecompleted";
        }
      }


      // Must have one or more invoice.
      //
      if (error == null && invio.getFatturaElettronicaBody().isEmpty()) {
        error = "error_flux_isempty";
      } else {
        final Iterator<FatturaElettronicaBodyType> i_bodies =
            invio.getFatturaElettronicaBody().iterator();
        final HashMap<String, Object[]> invoices = new HashMap<String, Object[]>();
        while (i_bodies.hasNext() && error == null) {
          final FatturaElettronicaBodyType fattura = i_bodies.next();
          final DatiGeneraliDocumentoType generali =
              fattura.getDatiGenerali().getDatiGeneraliDocumento();
          Object[] types = invoices.get(generali.getNumero());
          if (types == null) {
            types =
                new Object[] {DateUtils.toDate(generali.getData()), generali.getTipoDocumento()};
            invoices.put(generali.getNumero(), types);
          } else {
            // Check for double.
            //
            final Date a_data = (Date) types[0];
            final TipoDocumentoType a_tipo = (TipoDocumentoType) types[1];
            if (a_data.equals(DateUtils.toDate(generali.getData()))
                && a_tipo.equals(generali.getTipoDocumento())) {
              error = "error_duplicate_invoice";
            }
          }

          // if row was opened check it!
          //
          final OpenedAndSaved op = openMap.get(fattura.getId());
          if (op != null && !op.isStateSaved() && error == null) {
            error = isFatturaOK(fattura);
          }
        }
      }


    }

    final long end_time = System.currentTimeMillis();
    LogUtils.info(getClass(), "isFlussoOK returned " + error + " for riga n." + invio.getId()
        + " in " + (end_time - start_time) + " ms.");
    return error;
  }

  public boolean isRigaOK() {
    return isRigaOK(riga) == null;
  }

  private String isRigaOK(DettaglioLineeType riga) {
    final long start_time = System.currentTimeMillis();
    String insertable = null;

    if (riga != null) {
      if (riga.getAliquotaIVA() == null) {
        insertable = "error_aliquota_required";
      } else {
        if (riga.getAliquotaIVA().compareTo(BigDecimal.ZERO) == 0 && riga.getNatura() == null) {
          insertable = "error_natura_required";
        } else if (riga.getAliquotaIVA().compareTo(BigDecimal.ZERO) != 0
            && riga.getNatura() != null) {
          insertable = "error_natura_exceed";
        }
      }
    }

    final long end_time = System.currentTimeMillis();
    LogUtils.info(getClass(),
        "isRigaOK returned " + insertable + " for riga n." + riga.getNumeroLinea() + " in "
            + (end_time - start_time) + " ms.");
    return insertable;
  }

  public boolean isFatturaOK() {
    return isFatturaOK(fattura) != null;
  }

  private String isFatturaOK(FatturaElettronicaBodyType fattura) {
    final long start_time = System.currentTimeMillis();
    final Date now = new Date();
    String error = null;
    if (fattura != null) {
      boolean insertable = true;
      insertable &= fattura.getDatiGenerali() != null;
      insertable &= fattura.getDatiGenerali().getDatiGeneraliDocumento() != null;
      insertable &= fattura.getDatiGenerali().getDatiGeneraliDocumento().getTipoDocumento() != null;
      insertable &= fattura.getDatiGenerali().getDatiGeneraliDocumento().getNumero() != null;
      insertable &= fattura.getDatiGenerali().getDatiGeneraliDocumento().getData() != null;

      if (!insertable) {
        error = "error_fatturadatigenerali_required.";
      } else {
        final Date i_date =
            DateUtils.toDate(fattura.getDatiGenerali().getDatiGeneraliDocumento().getData());
        if (i_date.after(now)) {
          error = "error_fatturadatigenerali_isafternow";
        }
      }


      if (error == null) {
        // Iterate on DatiCassaPrevidenziale.
        //
        boolean hasRitenutaCassa = false;
        final Iterator<DatiCassaPrevidenzialeType> i_cas =
            fattura.getDatiGenerali().getDatiGeneraliDocumento().getDatiCassaPrevidenziale()
            .iterator();
        while (i_cas.hasNext()) {
          final DatiCassaPrevidenzialeType cassa = i_cas.next();

          if (cassa.getAliquotaIVA() == null) {
            error = "error_cassaaliquota_required";
          } else {
            if (cassa.getAliquotaIVA().compareTo(BigDecimal.ZERO) == 0 && cassa.getNatura() == null) {
              error = "error_cassanatura_required";
            } else if (cassa.getAliquotaIVA().compareTo(BigDecimal.ZERO) != 0
                && cassa.getNatura() != null) {
              error = "error_cassanatura_exceed";
            }
          }

          if (!hasRitenutaCassa) {
            hasRitenutaCassa = cassa.getRitenuta() != null;
          }
        }

        if (error == null && hasRitenutaCassa
            && fattura.getDatiGenerali().getDatiGeneraliDocumento().getDatiRitenuta() == null) {
          error = "error_ritenutaforcassa_required";
        }
      }


      if (error == null) {
        if (fattura.getDatiBeniServizi().getDettaglioLinee().size() < 1) {
          error = "error_fatturalinee_required";
        } else {

          // Check Dati Riepilogo.
          //
          if (fattura.getDatiBeniServizi().getDatiRiepilogo().size() < 1) {
            error = "error_fatturariepilogo_required";
          } else {
            final Iterator<DatiRiepilogoType> i_riep =
                fattura.getDatiBeniServizi().getDatiRiepilogo().iterator();
            while (i_riep.hasNext() && error == null) {
              // Check for rebuilt something!
              //
              final DatiRiepilogoType riep = i_riep.next();
              final OpenedAndSaved op = openMap.get(riep.getId());
              if (op != null && !op.isStateSaved()) {
                error = "error_riepilogo_mustbevalidated";
              }
            }
          }

          // Iterate on rows.
          //
          final Iterator<DettaglioLineeType> i_linee =
              fattura.getDatiBeniServizi().getDettaglioLinee().iterator();
          boolean hasRitenuta = false;
          while (i_linee.hasNext() && error == null) {
            final DettaglioLineeType linea = i_linee.next();

            // if row was opened check it!
            //
            final OpenedAndSaved op = openMap.get(linea.getId());
            if (op != null && !op.isStateSaved()) {
              error = isRigaOK(linea);
            }

            if (!hasRitenuta) {
              hasRitenuta = linea.getRitenuta() != null;
            }
          }

          // Check 1. Ritenuta
          //
          if (error == null) {
            if (hasRitenuta
                && fattura.getDatiGenerali().getDatiGeneraliDocumento().getDatiRitenuta() == null) {
              error = "error_datiritenura_required";
            }
          }

        }
      }
        if(error == null){
            try {

                TipoDocumentoType tipoDocumento = fattura.getDatiGenerali().getDatiGeneraliDocumento().getTipoDocumento();
                if (TipoDocumentoType.TD_04.equals(tipoDocumento)) {
                    Date dataNotaDiCredito = fattura.getDatiGenerali().getDatiGeneraliDocumento().getData().toGregorianCalendar().getTime();

                    SogeiFacade facadeSogei = (SogeiFacade)FacesUtils.findBean("SogeiFacade");
                    FatturaSogei fatturaSogei = null;

                    List<DatiDocumentiCorrelatiType> fattureCollegate = fattura.getDatiGenerali().getDatiFattureCollegate();

                    if(fattureCollegate != null && fattureCollegate.size() > 0) {
                        for (DatiDocumentiCorrelatiType fattColl : fattureCollegate) {
                            try {
                                fatturaSogei = facadeSogei.getFatturaByNumero(fattColl.getIdDocumento());
                                if (fatturaSogei != null && dataNotaDiCredito.before(fatturaSogei.getDataFattura())) {
                                    error = "error_dataNClessThanFattura";
                                    break;
                                }
                            } catch (Exception e) {
                            }
                        }
                    }
                }
            }catch (Exception e){
            }
        }
    }
    final long end_time = System.currentTimeMillis();
    LogUtils.info(getClass(), "isFatturaOK returned " + error + " for riga n." + fattura.getId()
        + " in " + (end_time - start_time) + " ms.");
    return error;
  }


  private void doRebuildRiepilogoFattura(FatturaElettronicaBodyType fattura) {
    final List<DatiRiepilogoType> r_list = fattura.getDatiBeniServizi().getDatiRiepilogo();
    r_list.clear();

    // Iterate on each rows!
    //
    final List<DettaglioLineeType> l_list = fattura.getDatiBeniServizi().getDettaglioLinee();
    final Iterator<DettaglioLineeType> l_it = l_list.iterator();
    final HashMap<BigDecimal, DatiRiepilogoType> aliquote =
        new HashMap<BigDecimal, DatiRiepilogoType>();
    final HashMap<NaturaType, DatiRiepilogoType> nature =
        new HashMap<NaturaType, DatiRiepilogoType>();

    while (l_it.hasNext()) {
      final DettaglioLineeType linea = l_it.next();
      BigDecimal aliquota = linea.getAliquotaIVA();
      final NaturaType natura = linea.getNatura();
      DatiRiepilogoType riepilogo = null;

      if (aliquota == null && natura == null) {
        aliquota = BigDecimal.ZERO;
      }

      if (aliquota != null && natura == null) {
        LogUtils.info(getClass(), "Build riepilogo (Aliquota) for row " + linea.getNumeroLinea());
        aliquota = aliquota.setScale(2, RoundingMode.HALF_UP);
        riepilogo = aliquote.get(aliquota);
        if (riepilogo == null) {
          riepilogo = obj.createDatiRiepilogoType();
          openMap.put(riepilogo.getId(), new OpenedAndSaved());
          riepilogo.setAliquotaIVA(aliquota);
          r_list.add(riepilogo);
          aliquote.put(aliquota, riepilogo);
        }
      } else if (natura != null) {
        LogUtils.info(getClass(), "Build riepilogo (Natura) for row " + linea.getNumeroLinea());
        riepilogo = nature.get(natura);
        if (riepilogo == null) {
          riepilogo = obj.createDatiRiepilogoType();
          openMap.put(riepilogo.getId(), new OpenedAndSaved());
          riepilogo.setNatura(natura);
          riepilogo.setAliquotaIVA(BigDecimal.ZERO);
          nature.put(natura, riepilogo);
          r_list.add(riepilogo);
        }
      }

      final BigDecimal perc = riepilogo.getAliquotaIVA().divide(new BigDecimal("100.00"));

      BigDecimal imponibileImporto = riepilogo.getImponibileImporto();
      if (imponibileImporto == null) {
        imponibileImporto = BigDecimal.ZERO;
      }

      imponibileImporto = imponibileImporto.add(linea.getPrezzoTotale());
      riepilogo.setImponibileImporto(imponibileImporto);

      final BigDecimal importoTassa =
          imponibileImporto.multiply(perc).setScale(2, RoundingMode.HALF_UP);
      riepilogo.setImposta(importoTassa);
    }

      // Cassa Previdenziale
      //
      final DatiGeneraliType dg_fattura = fattura.getDatiGenerali();
      final DatiGeneraliDocumentoType dg_documento = dg_fattura.getDatiGeneraliDocumento();
      final List<DatiCassaPrevidenzialeType> l_cassa = dg_documento.getDatiCassaPrevidenziale();
      if (l_cassa != null) {
          final Iterator<DatiCassaPrevidenzialeType> i_cassa = l_cassa.iterator();
          while (i_cassa.hasNext()) {
              final DatiCassaPrevidenzialeType cassa = i_cassa.next();
              BigDecimal aliquota_cassa = cassa.getAliquotaIVA();
              if (aliquota_cassa != null && aliquota_cassa.compareTo(BigDecimal.ZERO) > 0) {
                  aliquota_cassa = aliquota_cassa.setScale(2, HALF_UP);
                  DatiRiepilogoType riepilogo = aliquote.get(aliquota_cassa);
                  if (riepilogo == null) {
                      riepilogo = obj.createDatiRiepilogoType();
                      openMap.put(riepilogo.getId(), new OpenedAndSaved());
                      riepilogo.setAliquotaIVA(aliquota_cassa);
                      r_list.add(riepilogo);
                      aliquote.put(aliquota_cassa, riepilogo);
                  }


                  final BigDecimal perc = riepilogo.getAliquotaIVA().divide(new BigDecimal("100.00"));

                  BigDecimal imponibileImporto = riepilogo.getImponibileImporto();
                  if (imponibileImporto == null) {
                      imponibileImporto = BigDecimal.ZERO;
                  }

                  imponibileImporto = imponibileImporto.add(cassa.getImportoContributoCassa());
                  riepilogo.setImponibileImporto(imponibileImporto);

                  final BigDecimal importoTassa = imponibileImporto.multiply(perc).setScale(2, HALF_UP);
                  riepilogo.setImposta(importoTassa);
              }
          }
      }

      // Rebuild importo.
      //

      BigDecimal importoTotale = BigDecimal.ZERO;
      final Iterator<DatiRiepilogoType> r_i_list = r_list.iterator();
      while (r_i_list.hasNext()) {
          final DatiRiepilogoType dr = r_i_list.next();
          final BigDecimal importoRiepilogo = dr.getImponibileImporto().add(dr.getImposta());
          importoTotale = importoTotale.add(importoRiepilogo);
      }

      // DatiRitenuta
      //
      final DatiRitenutaType r_ritenuta = dg_documento.getDatiRitenuta();
      if (r_ritenuta != null && r_ritenuta.getImportoRitenuta() != null) {
          importoTotale = importoTotale.subtract(r_ritenuta.getImportoRitenuta());
      }

      // Sconti
      //
      final List<ScontoMaggiorazioneType> l_scm = dg_documento.getScontoMaggiorazione();
      if (l_scm != null) {
          for (final ScontoMaggiorazioneType scm : l_scm) {
              BigDecimal sign = new BigDecimal("1.0");
              if (scm.getTipo().equals(TipoScontoMaggiorazioneType.SC)) {
                  sign = new BigDecimal("-1.0");
              }

              BigDecimal importoScm = new BigDecimal("0.0");
              if (scm.getImporto() != null && !scm.getImporto().equals(BigDecimal.ZERO)) {
                  importoScm = sign.multiply(scm.getImporto().abs());
              } else if (scm.getPercentuale() != null) {
                  importoScm =
                          importoTotale.multiply(scm.getPercentuale())
                                  .divide(new BigDecimal("100.0"), HALF_UP).multiply(sign);
              }

              importoTotale = importoTotale.add(importoScm);
          }
      }

      fattura.getDatiGenerali().getDatiGeneraliDocumento().setImportoTotaleDocumento(importoTotale);
      fattura.setDatiPagamento(null);
      LogUtils.info(getClass(), "Riepilogo importi fattura successfully saved.");
  }

  public void doEliminaFatturaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");

    final List<FatturaElettronicaBodyType> c_list = invio.getFatturaElettronicaBody();
    final Iterator<FatturaElettronicaBodyType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final FatturaElettronicaBodyType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();
        return;
      }
    }
  }

  public void doEliminaRigaItem(ActionEvent e) {
    final String id = (String) FacesUtils.getRequestParameter("id");

    final List<DettaglioLineeType> c_list = fattura.getDatiBeniServizi().getDettaglioLinee();
    final Iterator<DettaglioLineeType> c_iter = c_list.iterator();
    while (c_iter.hasNext()) {
      final DettaglioLineeType d_c = c_iter.next();
      if (d_c.getId().equals(id)) {
        c_iter.remove();

        // Rebuild importi
        //
        doRebuildRiepilogoFattura(fattura);
        return;
      }
    }
  }

  public String getCausale1() {
    return causali.get(0);
  }

  public void setCausale1(String causale) {
    causali.put(0, causale);
  }

  public String getCausale2() {
    return causali.get(1);
  }

  public void setCausale2(String causale) {
    causali.put(1, causale);
  }

  public String getCausale3() {
    return causali.get(2);
  }

  public void setCausale3(String causale) {
    causali.put(2, causale);
  }

  public String getCausale4() {
    return causali.get(3);
  }

  public void setCausale4(String causale) {
    causali.put(3, causale);
  }

  public String getBolloVirtuale() {
    return BolloVirtualeType.SI.name();
  }


    public List<SelectItem> getListTipoUnitaMisura() {
        if (listTipoUnitaMisura == null) {

            final List<UnitaMisura> l_um = this.setUM();

            listTipoUnitaMisura = new ArrayList<SelectItem>();
            for (final UnitaMisura um : l_um) {
                 final SelectItem item = new SelectItem(um.getLabel(), um.getDescrizione());
                 listTipoUnitaMisura.add(item);
            }
            }
        return listTipoUnitaMisura;
    }

        public void setListTipoUnitaMisura(List<SelectItem> listTipoUnitaMisura) {
        this.listTipoUnitaMisura = listTipoUnitaMisura;
    }

    public List<UnitaMisura> setUM(){
        List<UnitaMisura> l_um = new ArrayList<UnitaMisura>();
        UnitaMisura um1 = new UnitaMisura(1, "GIORNI");
        l_um.add(um1);
        UnitaMisura um2 = new UnitaMisura(2, "ACCESSI");
        l_um.add(um2);
        UnitaMisura um3 = new UnitaMisura(3, "PEZZI");
        l_um.add(um3);
        UnitaMisura um4 = new UnitaMisura(4, "CONFEZIONI");
        l_um.add(um4);
        UnitaMisura um5 = new UnitaMisura(5, "MILLIGRAMMI");
        l_um.add(um5);
        UnitaMisura um6 = new UnitaMisura(6, "GRAMMI");
        l_um.add(um6);
        UnitaMisura um7 = new UnitaMisura(7, "CHILOGRAMMI");
        l_um.add(um7);
        UnitaMisura um8 = new UnitaMisura(8, "CENTILITRI");
        l_um.add(um8);
        UnitaMisura um9 = new UnitaMisura(9, "DECILITRI");
        l_um.add(um9);
        UnitaMisura um10 = new UnitaMisura(10, "LITRI");
        l_um.add(um10);
        UnitaMisura um11 = new UnitaMisura(11, "CENTIMETRI_CUBICI");
        l_um.add(um11);
        UnitaMisura um12 = new UnitaMisura(12, "ORE");
        l_um.add(um12);
        UnitaMisura um13 = new UnitaMisura(13, "CHILOMETRI");
        l_um.add(um13);
        UnitaMisura um14 = new UnitaMisura(14, "METRI_CUBI");
        l_um.add(um14);
        UnitaMisura um17 = new UnitaMisura(17, "CASI");
        l_um.add(um17);
        UnitaMisura um18 = new UnitaMisura(18, "GIORNATE");
        l_um.add(um18);
        UnitaMisura um19 = new UnitaMisura(19, "PRESTAZIONI");
        l_um.add(um19);
        UnitaMisura um20 = new UnitaMisura(20, "TRATTAMENTI");
        l_um.add(um20);
        UnitaMisura um21 = new UnitaMisura(21, "QUANTITA");
        l_um.add(um21);
        UnitaMisura um999 = new UnitaMisura(999, "NESSUNA");
        l_um.add(um999);

        return l_um;
    }

    public void doAggiornaRiepilogoFattura(ActionEvent e) {
        final DatiGeneraliDocumentoType g_type = fattura.getDatiGenerali().getDatiGeneraliDocumento();
        DatiRitenutaType r_type = g_type.getDatiRitenuta();
        if (r_type == null) {
            r_type = obj.createDatiRitenutaType();
            g_type.setDatiRitenuta(r_type);
        }
        doRebuildRiepilogoFattura(fattura);
    }
}
