private List<byte[]> getModuloPages(IList<DatiCertificazioneDTO> datiCertificazione, PersonaDTO firmatarioDichiarazione, PersonaDTO intermediarioDichiarazione, bool aggregatoPerFornitore, bool intermediarioDichiarazioneCondominio, DateTime dataDichiarazione, TipoOperazioneFiscale tipoOperazione, int anno, Azienda azienda, byte[] templateFrontespizio, byte[] templatePercipiente, byte[] templateDatiLavoratoreAutonomo)
        {
            var moduloFrontespizio = new Dictionary<int, byte[]>();
            var moduloFornitori = new Dictionary<int, IList<byte[]>>();

            var datiGroupByCondominio = datiCertificazione.GroupBy(item => item.IdCondominio);
            foreach (var datiPerCondominio in datiGroupByCondominio)
            {
                try
                {
                    var condominio = _daoFactory.GetCondominioDao().GetById(datiPerCondominio.Key, false);

                    var datiGroupByFornitore = datiPerCondominio.GroupBy(item => item.IdFornitore).ToList();

                    // =============================================================================================
                    // Creazione dei moduli
                    // =============================================================================================

                    // -----------------------------------------------------------------------------
                    // Frontespizio
                    // -----------------------------------------------------------------------------
                    string codiceFiscaleFirmatario;
                    string nomeFirmatario;
                    string cognomeFirmatario;
                    if (firmatarioDichiarazione != null)
                    {
                        nomeFirmatario = firmatarioDichiarazione.Nome;
                        cognomeFirmatario = firmatarioDichiarazione.Cognome;
                        codiceFiscaleFirmatario = firmatarioDichiarazione.CodiceFiscale;
                    }
                    else
                    {
                        nomeFirmatario = condominio.Azienda.Amministratore.PersonaRiferimento.Nome;
                        cognomeFirmatario = condominio.Azienda.Amministratore.PersonaRiferimento.Cognome;
                        codiceFiscaleFirmatario = condominio.Azienda.Amministratore.PersonaRiferimento.CodiceFiscale;
                    }

                    var numeroCertificazioniLavoroAutonomo = 0;
                    if (!aggregatoPerFornitore)
                        numeroCertificazioniLavoroAutonomo += datiCertificazione.Sum(datiCertificazioneDTO => datiCertificazioneDTO.Dettaglio.Count);
                    else
                        numeroCertificazioniLavoroAutonomo = datiGroupByFornitore.Count();

                    string codiceFiscaleIntermediario;
                    string nominativoIntermediario;
                    if (intermediarioDichiarazione != null)
                    {
                        codiceFiscaleIntermediario = intermediarioDichiarazione.CodiceFiscale;
                        nominativoIntermediario = intermediarioDichiarazione.DisplayName;
                    }
                    else if (intermediarioDichiarazioneCondominio)
                    {
                        codiceFiscaleIntermediario = condominio.CodiceFiscale;
                        nominativoIntermediario = condominio.Descrizione;
                    }
                    else
                    {
                        codiceFiscaleIntermediario = azienda.CodiceFiscale;
                        nominativoIntermediario = azienda.Descrizione;
                    }

                    var datiFrontespizio = new DatiFrontespizioCU
                    {
                        CodiceFiscaleCondominio = condominio.CodiceFiscale,
                        DenominazioneCondominio = condominio.Descrizione,
                        Annullamento = tipoOperazione == TipoOperazioneFiscale.Annullamento ? "1" : string.Empty,
                        Sostituzione = tipoOperazione == TipoOperazioneFiscale.Sostituzione ? "1" : string.Empty,
                        CodiceFiscaleAmministratore = codiceFiscaleFirmatario,
                        CognomeAmministratore = cognomeFirmatario.ToUpper(),
                        NomeAmministratore = nomeFirmatario.ToUpper(),
                        CodiceCarica = "13",
                        CodiceFiscaleIntermediario = codiceFiscaleIntermediario,
                        DataPresentazione = dataDichiarazione.ToShortDateString(),
                        NominativoIntermediario = nominativoIntermediario.ToUpper(),
                        NumeroCertificazioniLavoroAutonomo = numeroCertificazioniLavoroAutonomo.ToString(_cultureInfo),
                        NumeroCertificazioniLavoroDipendente = "0",
                        FirmaComunicazione = azienda.Amministratore.PersonaRiferimento.DisplayName,
                        ImpegnoTrasmettereComunicazione = "1"
                    };

                    var bytes = FillForm.FillStream(datiFrontespizio, templateFrontespizio, GestioneFiscaleResources.ModelloCUFrontespizio_FieldMapping, false, true);

                    // Firma
                    if (azienda.FirmaAmministratore != null)
                    {
                        var signature = new Signature(bytes);
                        var firma = _documentService.GetDocument(azienda.FirmaAmministratore.Checksum, azienda.ID, TipoDocumentoArchiviazione.Contratto);
                        if(firma.Body != null)
                            bytes = signature.AddSignature(firma.Body, 1, 470, 460, string.Empty);
                    }

                    moduloFrontespizio.Add(condominio.ID, bytes);

                    // -----------------------------------------------------------------------------
                    // Dati Percipiente - FORNITORE
                    // -----------------------------------------------------------------------------
                    var listaModuloFornitori = new List<byte[]>(datiGroupByFornitore.Count());
                    foreach (var datiPerFornitore in datiGroupByFornitore)
                    {
                        var progressivoModulo = 0;
                        var fornitore = _daoFactory.GetFornitoreDao().GetById(datiPerFornitore.Key, false);

                        var codiceSedeEntratel = "000";
                        if (!string.IsNullOrEmpty(azienda.CodiceSedeEntratel))
                            codiceSedeEntratel = azienda.CodiceSedeEntratel;

                        var datiFornitore = new DatiPercipienteCU
                        {
                            Anno = anno.ToString(_cultureInfo),
                            CodiceFiscaleCondominio = condominio.CodiceFiscale,
                            DenominazioneCondominio = condominio.Descrizione,
                            ComuneCondominio = condominio.Indirizzo.Comune.Descrizione,
                            ProvinciaCondominio = condominio.Indirizzo.Comune.ProvinciaAppartenenza.Codice,
                            CapCondominio = condominio.Indirizzo.Cap,
                            IndirizzoCondominio = condominio.Indirizzo.GetIndirizzoCompleto(),
                            CodiceFiscalePercipiente = fornitore.GetCodiceFiscale(),
                            CognomeRagioneSocialePercipiente = (fornitore.PersonaRiferimento.TipoPersona.GetValueOrDefault() == TipoPersonaEnum.Giuridica) ? fornitore.PersonaRiferimento.RagioneSociale.ToUpper() : fornitore.PersonaRiferimento.Cognome.ToUpper(),
                            NomePercipiente = (fornitore.PersonaRiferimento.TipoPersona.GetValueOrDefault() == TipoPersonaEnum.Giuridica) ? string.Empty : fornitore.PersonaRiferimento.Nome.ToUpper(),
                            ComuneNascitaPercipiente = (fornitore.PersonaRiferimento.TipoPersona.GetValueOrDefault() == TipoPersonaEnum.Fisica) ? fornitore.PersonaRiferimento.ComuneNascita.Descrizione : string.Empty,
                            ProvinciaNascitaPercipiente = (fornitore.PersonaRiferimento.TipoPersona.GetValueOrDefault() == TipoPersonaEnum.Fisica) ? fornitore.PersonaRiferimento.ComuneNascita.ProvinciaAppartenenza.Codice : string.Empty,
                            DataNascitaPercipiente = (fornitore.PersonaRiferimento.TipoPersona.GetValueOrDefault() == TipoPersonaEnum.Fisica) ? fornitore.PersonaRiferimento.DataNascita.GetValueOrDefault().ToShortDateString() : string.Empty,
                            SessoPercipiente = (fornitore.PersonaRiferimento.TipoPersona.GetValueOrDefault() == TipoPersonaEnum.Fisica) ? fornitore.PersonaRiferimento.Sesso.ToString().Substring(0, 1).ToUpper() : string.Empty,
                            ComuneResidenzaPercipiente2014 = fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.Descrizione,
                            ProvinciaResidenzaPercipiente2014 = fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.ProvinciaAppartenenza.Codice,
                            CodiceComuneResidenzaPercipiente2014 =  fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.CodiceCatastale,
                            ComuneResidenzaPercipiente2015 = fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.Descrizione,
                            ProvinciaResidenzaPercipiente2015 = fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.ProvinciaAppartenenza.Codice,
                            CodiceComuneResidenzaPercipiente2015 = fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.CodiceCatastale,
                            CodiceAttivita = "970000",
                            CodiceSedeEntratel = codiceSedeEntratel,
                            DataPresentazione = dataDichiarazione.ToShortDateString(),
                            FirmaSostitutoImposta = condominio.Descrizione
                        };

                        if (fornitore.PersonaRiferimento.TipoPersona.GetValueOrDefault() == TipoPersonaEnum.Fisica && int.Parse(fornitore.PersonaRiferimento.ComuneNascita.Codice) > 999201)
                            datiFornitore.ProvinciaNascitaPercipiente = "EE";

                        bytes = FillForm.FillStream(datiFornitore, templatePercipiente, GestioneFiscaleResources.ModelloCUPercipiente_FieldMapping, false, true);

                        // Firma
                        if (azienda.FirmaAmministratore != null)
                        {
                            var signature = new Signature(bytes);
                            var firma = _documentService.GetDocument(azienda.FirmaAmministratore.Checksum, azienda.ID, TipoDocumentoArchiviazione.Contratto);
                            if(firma.Body != null)
                                bytes = signature.AddSignature(firma.Body, 1, 470, 350, string.Empty);
                        }

                        listaModuloFornitori.Add(bytes);

                        if (tipoOperazione != TipoOperazioneFiscale.Annullamento)
                        {
                            if (aggregatoPerFornitore)
                            {
                                var datiCertificazioneFornitore = datiPerFornitore.FirstOrDefault();
                                if (datiCertificazioneFornitore != null)
                                {
                                    progressivoModulo++;
                                    listaModuloFornitori.Add(getModuloLavoratoreAutonomo(fornitore, datiCertificazioneFornitore.Dettaglio, datiCertificazioneFornitore.EsenteRegimeMinimo, anno, progressivoModulo, templateDatiLavoratoreAutonomo, azienda));
                                }
                            }
                            else
                            {
                                foreach (var datiCertificazioneDTO in datiPerFornitore)
                                {
                                    foreach (var dettaglioDatiCertificazioneDTO in datiCertificazioneDTO.Dettaglio)
                                    {
                                        progressivoModulo++;
                                        listaModuloFornitori.Add(getModuloLavoratoreAutonomo(fornitore, new List<DettaglioDatiCertificazioneDTO> { dettaglioDatiCertificazioneDTO }, datiCertificazioneDTO.EsenteRegimeMinimo, anno, progressivoModulo, templateDatiLavoratoreAutonomo, azienda));
                                    }
                                }
                            }
                        }
                    }

                    moduloFornitori.Add(condominio.ID, listaModuloFornitori);
                }
                catch (Exception ex)
                {
                    _log.ErrorFormat("Errore inaspettato durante la creazione del file per il modello CU - {0} - anno:{1} - azienda:{2}", ex, Library.Utility.GetMethodDescription(), anno, azienda);
                    throw;
                }
            }

            var result = new List<byte[]>();
            foreach (var frontespizio in moduloFrontespizio)
            {
                // frontespizio
                result.Add(frontespizio.Value);

                // percipiente
                result.AddRange(moduloFornitori[frontespizio.Key]);
            }

            return result;
        } 
        /// <summary>
        /// RECORD DI TIPO "D": Dati anagrafici del percipiente - CU 2015
        /// </summary>
        /// <param name="condominio"></param>
        /// <param name="fornitore">Fornitore percipiente</param>
        /// <param name="progressivoCertificazione">Progressivo della certificazione</param>
        /// <param name="dataDichiarazione"></param>
        /// <param name="progressivoInvio">Progressivo Attribuito dal Servizio telematico alla singola C.U.</param>
        /// <param name="sw">File di scrittura</param>
        /// <param name="tipoOperazione">Identifica se si tratta di un nuovo invio oppure di una sostituzione o un annullamento di un invio precedente</param>
        /// <param name="protocolloComunicazione">Protocollo assegnato dal Servizio telematico alla singola C.U. che si intende sostituire</param>
        private void writeRowD(Condominio condominio, Fornitore fornitore, int progressivoCertificazione, DateTime dataDichiarazione, TipoOperazioneFiscale tipoOperazione, long? protocolloComunicazione, int? progressivoInvio, StreamWriter sw)
        {
            try
            {
                var cognomeFornitore = fornitore.PersonaRiferimento.RagioneSociale;
                var nomeFornitore = string.Empty;
                var sessoFornitore = string.Empty;
                var dataNascitaFornitore = string.Empty;
                if (fornitore.PersonaRiferimento.TipoPersona == TipoPersonaEnum.Fisica)
                {
                    cognomeFornitore = fornitore.PersonaRiferimento.Cognome;
                    nomeFornitore = fornitore.PersonaRiferimento.Nome;
                    sessoFornitore = fornitore.PersonaRiferimento.Sesso.GetValueOrDefault().ToString().ToUpper().Substring(0, 1);
                    dataNascitaFornitore = convertData(fornitore.PersonaRiferimento.DataNascita);
                }

                var sb = new StringBuilder(1900);

                //======================================================
                // CAMPI POSIZIONALI (da carattere 1 a carattere 89)
                //======================================================

                // Tipo record
                sb.Append("D");

                // Codice Fiscale del sostituto d'imposta (Condominio)
                sb.Append(condominio.CodiceFiscale.PadRight(16, ' '));

                // Progressivo Modulo
                const int progressivoModulo = 1;
                sb.Append(progressivoModulo.ToString(CultureInfo.InvariantCulture).PadLeft(8, '0'));

                // Codice fiscale del percipiente
                sb.Append(fornitore.GetCodiceFiscale().PadRight(16, ' '));

                // Progressivo Certificazione
                sb.Append(progressivoCertificazione.ToString(CultureInfo.InvariantCulture).PadLeft(5, '0'));

                // -------------------------------------------------------------------------------------------------------------
                // Sezione da compilare per la sostituzione di una singola certificazione già trasmessa e accolta (Campi 6 e 7)
                // -------------------------------------------------------------------------------------------------------------
                // Protocollo assegnato dal Servizio telematico alla singola C.U. che si intende sostituire - Identificativo dell'invio
                sb.Append(tipoOperazione == TipoOperazioneFiscale.Nuovo
                    ? string.Empty.PadLeft(17, '0')
                    : protocolloComunicazione.ToString().PadLeft(17, '0'));

                // Protocollo assegnato dal Servizio telematico alla singola C.U. che si intende sostituire - Progressivo Attribuito dal Servizio telematico alla singola C.U.
                sb.Append(tipoOperazione == TipoOperazioneFiscale.Nuovo
                    ? string.Empty.PadLeft(6, '0')
                    : progressivoInvio.ToString().PadLeft(6, '0'));

                // Spazio a disposizione dell'utente 
                sb.Append(string.Empty.PadLeft(14));

                // Tipo operazione: Annullamento - Sostituzione
                var tipoOperazioneAnnSost = string.Empty;
                switch (tipoOperazione)
                {
                    case TipoOperazioneFiscale.Annullamento:
                        tipoOperazioneAnnSost = "A";
                        break;
                    case TipoOperazioneFiscale.Sostituzione:
                        tipoOperazioneAnnSost = "S";
                        break;
                }
                sb.Append(tipoOperazioneAnnSost.PadLeft(1));

                // Filler
                sb.Append(string.Empty.PadLeft(4));

                // Flag conferma Singola Certificazione per i controlli di rispondenza
                sb.Append("0");

                //======================================================
                // CAMPI NON POSIZIONALI (da carattere 90)
                //======================================================

                //---------------------------------------------
                // Dati relativi al datore di lavoro, ente pensionistico o altro sostituto d'imposta
                //---------------------------------------------

                // Codice Fiscale
                sb.Append(getCampoNonPosizionale("DA001001", condominio.CodiceFiscale, AllineamentoCaratteri.Sinistro));

                // Cognome o denominazione 
                sb.Append(getCampoNonPosizionale("DA001002", condominio.Descrizione, AllineamentoCaratteri.Sinistro));

                // Comune di residenza 
                sb.Append(getCampoNonPosizionale("DA001004", condominio.Indirizzo.Comune.Descrizione, AllineamentoCaratteri.Sinistro));

                // Provincia di residenza 
                sb.Append(getCampoNonPosizionale("DA001005", getSiglaProvincia(condominio.Indirizzo.Comune), AllineamentoCaratteri.Sinistro));

                // Cap 
                sb.Append(getCampoNonPosizionale("DA001006", condominio.Indirizzo.Cap, AllineamentoCaratteri.Sinistro));

                // Via e numero civico  
                sb.Append(getCampoNonPosizionale("DA001007", string.Format("{0} {1}", condominio.Indirizzo.Indirizzo, condominio.Indirizzo.Civico), AllineamentoCaratteri.Sinistro));

                // Codice attività
                sb.Append(getCampoNonPosizionale("DA001010", "970000", AllineamentoCaratteri.Sinistro));

                // Codice Sede  
                var codiceSedeEntratel = "000";
                if (!string.IsNullOrEmpty(condominio.Azienda.CodiceSedeEntratel))
                    codiceSedeEntratel = condominio.Azienda.CodiceSedeEntratel;
                sb.Append(getCampoNonPosizionale("DA001011", codiceSedeEntratel, AllineamentoCaratteri.Sinistro));

                //---------------------------------------------
                // Dati relativi al dipendente, pensionato o altro percettore delle somme
                //---------------------------------------------

                // Codice Fiscale
                sb.Append(getCampoNonPosizionale("DA002001", fornitore.GetCodiceFiscale().ToUpper(), AllineamentoCaratteri.Sinistro));

                // Cognome
                sb.Append(getCampoNonPosizionale("DA002002", cognomeFornitore.ToUpper(), AllineamentoCaratteri.Sinistro));

                // Nome
                sb.Append(getCampoNonPosizionale("DA002003", nomeFornitore.ToUpper(), AllineamentoCaratteri.Sinistro));

                // Sesso 
                sb.Append(getCampoNonPosizionale("DA002004", sessoFornitore, AllineamentoCaratteri.Sinistro));

                // Data di nascita
                sb.Append(getCampoNonPosizionale("DA002005", dataNascitaFornitore, AllineamentoCaratteri.Destro));

                if (fornitore.PersonaRiferimento.ComuneNascita != null)
                {
                    // Comune (o Stato estero) di nascita
                    sb.Append(getCampoNonPosizionale("DA002006", fornitore.PersonaRiferimento.ComuneNascita.Descrizione, AllineamentoCaratteri.Sinistro));

                    // Provincia di nascita (sigla) 
                    sb.Append(getCampoNonPosizionale("DA002007", getSiglaProvincia(fornitore.PersonaRiferimento.ComuneNascita), AllineamentoCaratteri.Sinistro));
                }

                // Domicilio fiscale al 1/1/2014
                // -----------------------------

                // Comune
                sb.Append(getCampoNonPosizionale("DA002020", fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.Descrizione, AllineamentoCaratteri.Sinistro));

                // Provincia (sigla) 
                sb.Append(getCampoNonPosizionale("DA002021", getSiglaProvincia(fornitore.PersonaRiferimento.IndirizzoResidenza.Comune), AllineamentoCaratteri.Sinistro));

                // Codice comune 
                sb.Append(getCampoNonPosizionale("DA002022", fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.CodiceCatastale, AllineamentoCaratteri.Sinistro));


                // Domicilio fiscale al 1/1/2015
                // -----------------------------

                // Comune
                sb.Append(getCampoNonPosizionale("DA002023", fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.Descrizione, AllineamentoCaratteri.Sinistro));

                // Provincia (sigla) 
                sb.Append(getCampoNonPosizionale("DA002024", getSiglaProvincia(fornitore.PersonaRiferimento.IndirizzoResidenza.Comune), AllineamentoCaratteri.Sinistro));

                // Codice comune 
                sb.Append(getCampoNonPosizionale("DA002025", fornitore.PersonaRiferimento.IndirizzoResidenza.Comune.CodiceCatastale, AllineamentoCaratteri.Sinistro));

                // Sezione Firma Certificazione Unica
                // -----------------------------

                // Data Firma Sostituto d'imposta
                sb.Append(getCampoNonPosizionale("DA003001", convertData(dataDichiarazione), AllineamentoCaratteri.Destro));

                // Firma 
                sb.Append(getCampoNonPosizionale("DA003002", "1".PadLeft(16), AllineamentoCaratteri.Destro));


                //======================================================
                // CAMPI POSIZIONALI (da carattere 1890 a carattere 1900)
                //======================================================

                var charToEnd = 1889 - sb.ToString().Length;
                sb.Append(string.Empty.PadRight(charToEnd));

                // filler
                sb.Append(string.Empty.PadLeft(8));

                //---------------------------------------------
                // Ultimi caratteri di controllo
                //---------------------------------------------
                sb.Append("A");

                // CarriageReturn LineFeed
                sb.Append(CRLF);

                sw.Write(sb.ToString());
            }
            catch (Exception ex)
            {
                _log.ErrorFormat("Errore inaspettato durante la creazione della sezione D per il modello Certificazione Unica - {0} - condominio:{1}", ex, Library.Utility.GetMethodDescription(), condominio.ID);
                throw;
        public ResultCreazioneFile GetModello(int idAzienda, int anno, IList<DatiCertificazioneDTO> datiCertificazione, DateTime dataDichiarazione, bool intermediarioDichiarazioneCondominio, bool aggregatoPerFornitore, bool ordinatoPerFornitore, PersonaDTO firmatarioDichiarazione, PersonaDTO intermediarioDichiarazione, TipoOperazioneFiscale tipoOperazione, long? protocolloComunicazione, int? progressivoInvio)
        {
            byte[] bytes = null;
            var message = string.Empty;

            var annoModulo = string.Empty;
            if (anno > 2009)
                annoModulo = (anno + 1).ToString(CultureInfo.InvariantCulture);

            var azienda = _daoFactory.GetAziendaDao().GetById(idAzienda, false);

            var templateFrontespizio = getTemplate("frontespizio", annoModulo);
            var templatePercipiente = getTemplate("percipiente", annoModulo);
            var templateDatiLavoratoreAutonomo = getTemplate("lavoratoreAutonomo", annoModulo);
            
            if (templateFrontespizio != null && templatePercipiente != null && templateDatiLavoratoreAutonomo != null)
            {
                try
                {
                    var pageBytes = new List<byte[]>();
                    if (ordinatoPerFornitore)
                    {
                        var dataSource = datiCertificazione.GroupBy(item => item.IdFornitore).ToList();
                        foreach (var dataSourcePerFornitore in dataSource)
                        {
                            pageBytes.AddRange(getModuloPages(dataSourcePerFornitore.ToList(), firmatarioDichiarazione, intermediarioDichiarazione, aggregatoPerFornitore, intermediarioDichiarazioneCondominio, dataDichiarazione, tipoOperazione, anno, azienda, templateFrontespizio, templatePercipiente, templateDatiLavoratoreAutonomo));
                        }
                    }
                    else
                        pageBytes.AddRange(getModuloPages(datiCertificazione, firmatarioDichiarazione, intermediarioDichiarazione, aggregatoPerFornitore, intermediarioDichiarazioneCondominio, dataDichiarazione, tipoOperazione, anno, azienda, templateFrontespizio, templatePercipiente, templateDatiLavoratoreAutonomo));


                    // =============================================================================================
                    // Merge dei moduli
                    // =============================================================================================
                    var stream = new MemoryStream();
                    var doc = new PdfMerge();

                    foreach (var pageByte in pageBytes)
                    {
                        doc.AddDocument(pageByte);
                    }
                    doc.Merge(stream, true);

                    bytes = new byte[stream.Length];
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Read(bytes, 0, bytes.Length);
                    stream.Close();

                    return new ResultCreazioneFile(bytes, message);
                }
                catch (Exception ex)
                {
                    _log.ErrorFormat("Errore inaspettato durante la creazione del file per il modello CU - {0} - anno:{1} - azienda:{2}", ex, Library.Utility.GetMethodDescription(), anno, azienda);
                    message = "Si sono verificati problemi inaspettati durante la generazione del modello CU." + Environment.NewLine + "Controllare il log per ulteriori dettagli.";
                    return new ResultCreazioneFile(bytes, message);
                } 
            }

            return new ResultCreazioneFile(null, string.Format("Il modulo per l'anno {0} non è ancora disponibile", annoModulo));
        }
        /// <summary>
        /// Record contenente i dati anagrafici del contribuente e gli altri dati del modello base
        /// </summary>
        /// <param name="condominio"></param>
        /// <param name="numeroCertificazioniLavoroAutonomo"></param>
        /// <param name="intermediarioDichiarazioneCondominio">Se true è il condominio che invia la dichiarazione</param>
        /// <param name="firmatarioDichiarazione">Persona firmatario della dichiarazione, se null viene usato l'amministratore dello studio</param>
        /// <param name="intermediarioDichiarazione">Persona intermediario della dichiarazione, se null sono usate le informazioni dello studio</param>
        /// <param name="tipoOperazione">Identifica se si tratta di un nuovo invio oppure di una sostituzione o un annullamento di un invio precedente</param>
        /// <param name="sw">File di scrittura</param>
        /// <param name="dataDichiarazione"></param>
        private void writeRowB(Condominio condominio, DateTime dataDichiarazione, int numeroCertificazioniLavoroAutonomo, bool intermediarioDichiarazioneCondominio, PersonaDTO firmatarioDichiarazione, PersonaDTO intermediarioDichiarazione, TipoOperazioneFiscale tipoOperazione, StreamWriter sw)
        {
            try
            {
                var sb = new StringBuilder(1900);

                // Tipo record
                sb.Append("B");

                // Codice Fiscale del sostituto d'imposta (Condominio)
                sb.Append(condominio.CodiceFiscale.PadRight(16, ' '));

                // Progressivo Modulo
                const int progressivoModulo = 1;
                sb.Append(progressivoModulo.ToString(CultureInfo.InvariantCulture).PadLeft(8, '0'));

                // filler
                sb.Append(string.Empty.PadLeft(1));
                // filler
                sb.Append(string.Empty.PadLeft(8));
                // filler
                sb.Append(string.Empty.PadLeft(25));

                // Spazio a disposizione dell'utente 
                sb.Append(string.Empty.PadRight(14));

                // Identificativo del produttore del software (codice fiscale)
                sb.Append("02818651206".PadRight(16));

                // filler
                sb.Append(string.Empty.PadLeft(1));

                //======================================================
                // Dati del frontespizio
                //======================================================

                //---------------------------------------------
                // Tipo di dichiarazione
                //---------------------------------------------

                // Fornitura relativa all'invio di certificazioni da annullare
                if(tipoOperazione != TipoOperazioneFiscale.Annullamento)
                    sb.Append("0");
                else
                    sb.Append("1");

                // Fornitura relativa all'invio di certificazioni da sostituire
                if (tipoOperazione != TipoOperazioneFiscale.Sostituzione)
                    sb.Append("0");
                else
                    sb.Append("1");

                //---------------------------------------------
                // Dati del sostituto (condominio)
                //---------------------------------------------

                // Cognome
                sb.Append(string.Empty.PadRight(24));
                // Nome
                sb.Append(string.Empty.PadRight(20));

                // Denominazione
                var denominazione = Library.Conversione.ToInvioTelematico(condominio.Descrizione);
                if (denominazione.Length > 60)
                    denominazione = denominazione.Substring(0, 60);
                sb.Append(denominazione.PadRight(60));

                // Indirizzo posta elettronica
                sb.Append(string.Empty.PadRight(100));
                // Telefono o Fax
                sb.Append(string.Empty.PadRight(12));
                // Filler
                sb.Append(string.Empty.PadRight(12));

                //---------------------------------------------
                // Dati relativi al rappresentante firmatario della comunicazione
                // La sezione è obbligatoria per i contribuenti diversi dalle persone fisiche
                //---------------------------------------------

                // Codice fiscale del firmatario della dichiarazione il dato è obbligatorio se presente un campo della sezione.
                // Deve essere diverso dal codice fiscale del sostituto (campo 2). 
                // Il codice fiscale deve essere formalmente corretto, registrato in Anagrafe tributaria e deve essere attribuito ad una persona fisica.
                var codiceFiscale = firmatarioDichiarazione != null ? firmatarioDichiarazione.CodiceFiscale : condominio.Azienda.Amministratore.PersonaRiferimento.CodiceFiscale;
                sb.Append(codiceFiscale.ToUpper().PadRight(16));

                // Codice carica del rappresentante
                sb.Append("13");

                // Cognome del rappresentante
                var cognome = firmatarioDichiarazione != null ? firmatarioDichiarazione.Cognome : condominio.Azienda.Amministratore.PersonaRiferimento.Cognome;
                sb.Append(Library.Conversione.ToInvioTelematico(cognome).ToUpper().PadRight(24));

                // Nome del rappresentante
                var nome = firmatarioDichiarazione != null ? firmatarioDichiarazione.Nome : condominio.Azienda.Amministratore.PersonaRiferimento.Nome;
                sb.Append(Library.Conversione.ToInvioTelematico(nome).ToUpper().PadRight(20));

                // Codice fiscale societa o ente dichiarante solo in caso di società
    			sb.Append(string.Empty.PadRight(11, '0'));

                //---------------------------------------------
                // Firma della comunicazione
                //---------------------------------------------

                // Numero comunicazioni relative a certificazioni lavoro dipendente ed assimilati
                sb.Append("0".PadLeft(8, '0'));

                // Numero comunicazioni relative a certificazioni lavoro autonomo e provvigioni
                sb.Append(numeroCertificazioniLavoroAutonomo.ToString(CultureInfo.InvariantCulture).PadLeft(8, '0'));

                // Casella Quadro CT
                sb.Append("0");

                // Firma
                sb.Append("1");

                //---------------------------------------------
                // Impegno alla trasmissione telematica
                //---------------------------------------------

                // Codice fiscale dell'intermediario
                string codiceFiscaleIntermediario;
                if (intermediarioDichiarazione != null)
                    codiceFiscaleIntermediario = intermediarioDichiarazione.CodiceFiscale;
                else if (intermediarioDichiarazioneCondominio)
                    codiceFiscaleIntermediario = condominio.CodiceFiscale;
                else 
                    codiceFiscaleIntermediario = condominio.Azienda.CodiceFiscale;
                sb.Append(codiceFiscaleIntermediario.ToUpper().PadRight(16));

                // Impegno a trasmettere in via telematica la dichiarazione
                sb.Append("1");

                // Data dell'impegno
                var dataImpegno = convertData(dataDichiarazione);
                sb.Append(dataImpegno);

                // Firma dell'intermediario
                sb.Append("1");

                // filler
                sb.Append(string.Empty.PadLeft(1));
                sb.Append(string.Empty.PadLeft(40));
                sb.Append(string.Empty.PadLeft(2));
                sb.Append(string.Empty.PadLeft(5));
                sb.Append(string.Empty.PadLeft(35));
                sb.Append(string.Empty.PadLeft(6));
                sb.Append(string.Empty.PadLeft(3));
                sb.Append(string.Empty.PadLeft(8));
                sb.Append(string.Empty.PadLeft(1));
                sb.Append(string.Empty.PadLeft(1305));

                //---------------------------------------------
                // Spazio riservato al Servizio telematico
                //---------------------------------------------

                // Spazio riservato al Servizio Telematico
                sb.Append(string.Empty.PadLeft(20));

                // filler
                sb.Append(string.Empty.PadLeft(7));
                sb.Append(string.Empty.PadLeft(3));
                sb.Append(string.Empty.PadLeft(3));
                sb.Append(string.Empty.PadLeft(1));

                // filler
                sb.Append(string.Empty.PadLeft(1));
                sb.Append(string.Empty.PadLeft(1));
                sb.Append(string.Empty.PadLeft(1));
                sb.Append(string.Empty.PadLeft(1));
                sb.Append(string.Empty.PadLeft(1));
                sb.Append(string.Empty.PadLeft(15));

                //---------------------------------------------
                // Ultimi caratteri di controllo
                //---------------------------------------------
                sb.Append("A");

                // CarriageReturn LineFeed
                sb.Append(CRLF);

                sw.Write(sb.ToString());
            }
            catch (Exception ex)
            {
                _log.ErrorFormat("Errore inaspettato durante la creazione della riga B per modello 770 - {0} - condominio:{1} - data dichiarazione:{2}", ex, Library.Utility.GetMethodDescription(), condominio.ID, dataDichiarazione);
                throw;
            }
        }
        public ResultCreazioneFile GetModello(int idAzienda, int anno, IList<DatiCertificazioneDTO> datiCertificazione, DateTime dataDichiarazione, bool intermediarioDichiarazioneCondominio, bool aggregatoPerFornitore, bool ordinatoPerFornitore, PersonaDTO firmatarioDichiarazione, PersonaDTO intermediarioDichiarazione, TipoOperazioneFiscale tipoOperazione, long? protocolloComunicazione, int? progressivoInvio)
        {
            byte[] bytes = null;
            var message = string.Empty;

            var numeroRecordB = 0;
            var numeroRecordD = 0;
            var numeroRecordH = 0;

            StreamWriter sw = null;
            try
            {
                var fileName = Path.GetTempPath() + "\\" + Guid.NewGuid();
                if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
                    fileName = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.DataDirectory + "\\" + Guid.NewGuid();
                if (File.Exists(fileName))
                    File.Delete(fileName);

                var azienda = _daoFactory.GetAziendaDao().GetById(idAzienda, false);

                // -----------------------------------------------------------------
                // Raggruppamento per condominio
                // -----------------------------------------------------------------
                var datiGroupByCondominio = datiCertificazione.GroupBy(item => item.IdCondominio).ToList();

                // =============================================================================================
                // Creazione del file
                // =============================================================================================
                using (sw = File.CreateText(fileName))
                {
                    var codiceFiscale = azienda.CodiceFiscale;

                    if (intermediarioDichiarazione != null)
                        codiceFiscale = intermediarioDichiarazione.CodiceFiscale;
                    else if (intermediarioDichiarazioneCondominio)
                    {
                        var condominio = _daoFactory.GetCondominioDao().GetById(datiGroupByCondominio.FirstOrDefault().Key, false);
                        codiceFiscale = condominio.CodiceFiscale;
                    }

                    writeTestataA("CUR", codiceFiscale, anno, sw);

                    foreach (var datiPerCondominio in datiGroupByCondominio)
                    {
                        var condominio = _daoFactory.GetCondominioDao().GetById(datiPerCondominio.Key, false);

                        // -----------------------------------------------------------------
                        // Raggruppamento per fornitore
                        // -----------------------------------------------------------------
                        var datiPerFornitore = datiPerCondominio.GroupBy(item => item.IdFornitore).ToList();
                        var numeroCertificazioniLavoroAutonomo = datiPerFornitore.Count();

                        writeRowB(condominio, dataDichiarazione, numeroCertificazioniLavoroAutonomo, intermediarioDichiarazioneCondominio, firmatarioDichiarazione, intermediarioDichiarazione, tipoOperazione, sw);
                        numeroRecordB++;

                        // Una comunicazione per ogni fornitore
                        var index = 0;
                        foreach (var datiFornitore in datiPerFornitore)
                        {
                            var fornitore = _daoFactory.GetFornitoreDao().GetById(datiFornitore.Key, false);
                            if (aggregatoPerFornitore)
                            {
                                index++;
                                writeRowD(condominio, fornitore, index, dataDichiarazione, tipoOperazione, protocolloComunicazione, progressivoInvio, sw);
                                numeroRecordD++;

                                var datiCertificazioneFornitore = datiFornitore.FirstOrDefault();
                                if (datiCertificazioneFornitore != null)
                                {
                                    if (tipoOperazione != TipoOperazioneFiscale.Annullamento)
                                    {
                                        writeRowH(condominio, fornitore, anno, datiCertificazioneFornitore.Dettaglio, datiCertificazioneFornitore.EsenteRegimeMinimo, index, 1, sw);
                                        numeroRecordH++;
                                    }
                                }
                            }
                            else
                            {
                                foreach (var datiCertificazioneDTO in datiFornitore)
                                {
                                    foreach (var dettaglioDatiCertificazioneDTO in datiCertificazioneDTO.Dettaglio)
                                    {
                                        index++;
                                        writeRowD(condominio, fornitore, index, dataDichiarazione, tipoOperazione, protocolloComunicazione, progressivoInvio, sw);
                                        numeroRecordD++;

                                        if (tipoOperazione != TipoOperazioneFiscale.Annullamento)
                                        {
                                            writeRowH(condominio, fornitore, anno, new List<DettaglioDatiCertificazioneDTO> { dettaglioDatiCertificazioneDTO }, datiCertificazioneDTO.EsenteRegimeMinimo, index, 1, sw);
                                            numeroRecordH++;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    writePiedeZ(numeroRecordB, 0, numeroRecordD, 0, numeroRecordH, sw);
                }

                var infile = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                bytes = new byte[infile.Length];
                infile.Read(bytes, 0, bytes.Length);

                return new ResultCreazioneFile(bytes, message);
            }
            catch (Exception ex)
            {
                _log.ErrorFormat("Errore inaspettato durante la creazione del file per il modello CU - Certificazione Unica - {0} - anno:{1}", ex, Library.Utility.GetMethodDescription(), anno);
                message = "Si sono verificati problemi inaspettati durante la generazione del modello CU - Certificazione Unica." + Environment.NewLine + "Controllare il log per ulteriori dettagli.";
                return new ResultCreazioneFile(bytes, message);
            }
            finally
            {
                if (sw != null)
                {
                    sw.Close();
                    sw.Dispose();
                }
            }
        }
        public string GetModelloCertificazioneUnicaPDF(int anno, List<DatiCertificazioneDTO> datiCertificazione, string nomeFile, DateTime dataDichiarazione, bool aggregatoPerFornitore, bool ordinatoPerFornitore, bool intermediarioDichiarazioneCondominio, PersonaDTO firmatarioDichiarazione, PersonaDTO intermediarioDichiarazione, TipoOperazioneFiscale tipoOperazione, TipoStampaModelloCU tipoStampa)
        {
            var result = GetServiceClient().GetModelloCertificazioneUnicaPDF(anno, datiCertificazione, dataDichiarazione, aggregatoPerFornitore, ordinatoPerFornitore, intermediarioDichiarazioneCondominio, firmatarioDichiarazione, intermediarioDichiarazione, tipoOperazione, tipoStampa, GetUserInfo());
            if (string.IsNullOrEmpty(result.Message))
            {
                var doc = new DocumentInfo { Body = result.FileBody, FileName = nomeFile };
                _manageDocumentService.Open(doc, "Modello CU", false, MergeFieldType.Default);
            }

            CloseService();
            return result.Message;
        }
        public string GetModelloCertificazioneUnica(int anno, List<DatiCertificazioneDTO> datiCertificazione, string nomeFile, DateTime dataDichiarazione, bool aggregatoPerFornitore, bool ordinatoPerFornitore, bool intermediarioDichiarazioneCondominio, PersonaDTO firmatarioDichiarazione, PersonaDTO intermediarioDichiarazione, TipoOperazioneFiscale tipoOperazione, TipoStampaModelloCU tipoStampa, long? protocolloComunicazione, int? progressivoInvio)
        {
            var result = GetServiceClient().GetModelloCertificazioneUnica(anno, datiCertificazione, dataDichiarazione, aggregatoPerFornitore, ordinatoPerFornitore, intermediarioDichiarazioneCondominio, firmatarioDichiarazione, intermediarioDichiarazione, tipoOperazione, tipoStampa, protocolloComunicazione, progressivoInvio, GetUserInfo());
            if (string.IsNullOrEmpty(result.Message))
            {
                var doc = new DocumentInfo { Body = result.FileBody, FileName = nomeFile };
                _manageDocumentService.Save(doc);
            }

            CloseService();
            return result.Message;
        }
예제 #8
0
 public ResultCreazioneFile GetModelloCertificazioneUnicaPDF(int anno, IList<DatiCertificazioneDTO> datiCertificazione, DateTime dataDichiarazione, bool aggregatoPerFornitore, bool ordinatoPerFornitore, bool intermediarioDichiarazioneCondominio, PersonaDTO firmatarioDichiarazione, PersonaDTO intermediarioDichiarazione, TipoOperazioneFiscale tipoOperazione, TipoStampaModelloCU tipoStampa, UserInfo userinfo)
 {
     var windsorRep = new WindsorConfigRepository();
     try
     {
         windsorRep.BeginTransaction(userinfo);
         var service = windsorRep.GetContainer(userinfo.Azienda).Resolve<IGestioneFiscaleModelloCUService>("gestionefiscalemodellocu.pdf");
         var item = service.GetModello(userinfo.Azienda, anno, datiCertificazione, dataDichiarazione, intermediarioDichiarazioneCondominio, aggregatoPerFornitore, ordinatoPerFornitore, firmatarioDichiarazione, intermediarioDichiarazione, tipoOperazione, tipoStampa, null, null);
         windsorRep.Commit();
         return item;
     }
     catch (Exception ex)
     {
         _log.ErrorFormat("Errore durante la generazione del modello CU - Certificazione Unica PDF - {0} - anno:{1} - dataDichiarazione:{2}", ex, Utility.GetMethodDescription(), anno, dataDichiarazione.ToShortDateString());
         windsorRep.Rollback();
         throw;
     }
 }