/// <summary>
        /// Escrever campos p/ qualquer arquivo do projeto SPED (Contábil, Fiscal, Pis/Cofins)
        /// </summary>
        /// <param name="source">Objeto com os dados a serem tratados e gerados na linha do arquivo.</param>
        /// <param name="competenciaDeclaracao">Mês a que se referem as informações no arquivo(exceto informações extemporâneas).</param>
        /// <param name="tryTrim">Remove a quebra de linha no final de cada registro.</param>
        /// <returns>Linha de arquivo SPED escrita e formatada.</returns>
        public static string EscreverCampos(this object source, DateTime?competenciaDeclaracao = null, bool tryTrim = false)
        {
            var type = ObtemTipo(source);

            var registroAtual = ObtemRegistroAtual(type);

            var spedRegistroAttr = ObtemAtributoAtual(type);

            var dataObrigatoriedadeInicial = spedRegistroAttr?.ObrigatoriedadeInicial.ToDateTimeNullable();
            var dataObrigatoriedadeFinal   = spedRegistroAttr?.ObrigatoriedadeFinal.ToDateTimeNullable();

            if (!competenciaDeclaracao.HasValue)
            {
                competenciaDeclaracao = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
            }
            else
            {
                competenciaDeclaracao = new DateTime(competenciaDeclaracao.Value.Year, competenciaDeclaracao.Value.Month, 1);
            }

            var deveGerarCamposDoRegistro =
                VerificaObrigatoriedadeRegistro(new Tuple <DateTime?, DateTime?, DateTime>(dataObrigatoriedadeInicial,
                                                                                           dataObrigatoriedadeFinal, competenciaDeclaracao.Value));

            var listaComPropriedadesOrdenadas = ObtemListaComPropriedadesOrdenadas(type);

            var sb = new StringBuilder();

            if (deveGerarCamposDoRegistro)
            {
                foreach (var property in listaComPropriedadesOrdenadas)
                {
                    sb.Append("|");
                    foreach (
                        var spedCampoAttr in
                        from Attribute attr in property.GetCustomAttributes(true) select attr as SpedCamposAttribute
                        )
                    {
                        if (spedCampoAttr == null)
                        {
                            throw new Exception(
                                      $"O campo {property.Name} no registro {registroAtual} não possui atributo SPED definido!");
                        }

                        var propertyValue             = RegistroBaseSped.GetPropValue(source, property.Name);
                        var propertyValueToStringSafe = propertyValue.ToStringSafe().Trim();

                        var isRequired   = spedCampoAttr.IsObrigatorio;
                        var campoEscrito =
                            propertyValueToStringSafe.EscreverCampo(
                                new Tuple <
                                    InformationType,
                                    InformationType,
                                    bool,
                                    int,
                                    int>(
                                    ObtemTipoDoAtributo(spedCampoAttr),
                                    ObtemTipoDaPropriedade(property),
                                    isRequired,
                                    spedCampoAttr.Tamanho,
                                    spedCampoAttr.QtdCasas
                                    ));

                        if (campoEscrito == Constants.StructuralError)
                        {
                            throw new Exception(
                                      $"O campo {spedCampoAttr.Ordem} - {spedCampoAttr.Campo} no Registro {registroAtual} é obrigatório e não foi informado!");
                        }

                        sb.Append(campoEscrito);
                    }
                }
                sb.Append("|");
                sb.Append(Environment.NewLine);
            }

            return(tryTrim ? sb.ToString().Trim() : sb.ToString());
        }
Exemplo n.º 2
0
        /// <summary>
        /// Escrever campos p/ qualquer arquivo do projeto SPED (Contábil, Fiscal, Pis/Cofins)
        /// </summary>
        /// <param name="source">Objeto com os dados a serem tratados e gerados na linha do arquivo.</param>
        /// <param name="competenciaDeclaracao">Mês a que se referem as informações no arquivo(exceto informações extemporâneas).</param>
        /// <param name="errosEncontrados">Lista com erros encontrados no processo de escrita.</param>
        /// <param name="tryTrim">Remove a quebra de linha no final de cada registro.</param>
        /// <returns>Linha de arquivo SPED escrita e formatada.</returns>
        public static string EscreverCampos(this object source, out string errosEncontrados,
                                            DateTime?competenciaDeclaracao = null, bool tryTrim = false)
        {
            errosEncontrados = string.Empty;

            var type = ObtemTipo(source);

            var registroAtual = ObtemRegistroAtual(type);

            var spedRegistroAttr = ObtemAtributoAtual(type);

            var dataObrigatoriedadeInicial = spedRegistroAttr != null?spedRegistroAttr.ObrigatoriedadeInicial.ToDateTimeNullable() : null;

            var dataObrigatoriedadeFinal = spedRegistroAttr != null?spedRegistroAttr.ObrigatoriedadeFinal.ToDateTimeNullable() : null;

            if (!competenciaDeclaracao.HasValue)
            {
                competenciaDeclaracao = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
            }
            else
            {
                competenciaDeclaracao = new DateTime(competenciaDeclaracao.Value.Year, competenciaDeclaracao.Value.Month, 1);
            }

            var deveGerarCamposDoRegistro =
                VerificaObrigatoriedadeRegistro(new Tuple <DateTime?, DateTime?, DateTime>(dataObrigatoriedadeInicial,
                                                                                           dataObrigatoriedadeFinal, competenciaDeclaracao.Value));

            var listaComPropriedadesOrdenadas = ObtemListaComPropriedadesOrdenadas(type);

            var sb = new StringBuilder();

            if (deveGerarCamposDoRegistro)
            {
                foreach (var property in listaComPropriedadesOrdenadas)
                {
                    if (SomenteParaLeitura(property))
                    {
                        continue;
                    }

                    sb.Append("|");
                    foreach (
                        var spedCampoAttr in
                        from Attribute attr in property.GetCustomAttributes(true) select attr as SpedCamposAttribute
                        )
                    {
                        if (spedCampoAttr == null)
                        {
                            errosEncontrados +=
                                string.Format("O campo {0} no registro {1} não possui atributo SPED definido!\n", property.Name, registroAtual);
                        }

                        var propertyValue             = RegistroBaseSped.GetPropValue(source, property.Name);
                        var propertyValueToStringSafe = propertyValue.ToStringSafe().Trim();

                        var isRequired            = spedCampoAttr.IsObrigatorio;
                        var resultadoCampoEscrito =
                            propertyValueToStringSafe.EscreverCampo(
                                new Tuple <
                                    InformationType,
                                    InformationType,
                                    bool,
                                    int,
                                    int>(
                                    ObtemTipoDoAtributo(spedCampoAttr),
                                    ObtemTipoDaPropriedade(property),
                                    isRequired,
                                    spedCampoAttr.Tamanho,
                                    spedCampoAttr.QtdCasas
                                    ));

                        if (resultadoCampoEscrito == Constants.StructuralError)
                        {
                            errosEncontrados +=
                                string.Format("O campo {0} - {1} no Registro {2} é obrigatório e não foi informado!\n", spedCampoAttr.Ordem, spedCampoAttr.Campo, registroAtual);
                        }
                        else
                        {
                            sb.Append(resultadoCampoEscrito);
                        }
                    }
                }
                sb.Append("|");
                sb.Append(Environment.NewLine);
            }
            if (errosEncontrados.Length > 0)
            {
                errosEncontrados =
                    string.Format("Registro {0} -  Contém os seguintes erros: \n{1}", source.GetType().FullName, errosEncontrados);
            }
            return(tryTrim ? sb.ToString().Trim() : sb.ToString());
        }
        /// <summary>
        /// Escrever campos p/ qualquer arquivo do projeto SPED (Contábil, Fiscal, Pis/Cofins)
        /// </summary>
        /// <param name="source"></param>
        /// <param name="competenciaDeclaracao"></param>
        /// <returns></returns>
        public static string EscreverCampos(this object source, DateTime competenciaDeclaracao)
        {
            var type = source.GetType();

            if (type == null)
            {
                throw new Exception("Falha ao identificar tipo do objeto!");
            }

            // Extrai o nome do registro atual. Ex.: RegistroA001 -> Resultado: A001
            var registroAtual = type.Name.Substring(type.Name.Length - 4);

            var spedRegistroAttr =
                (SpedRegistrosAttribute)
                Attribute.GetCustomAttribute(type, typeof(SpedRegistrosAttribute));

            var deveGerarCamposDoRegistro  = true;
            var dataObrigatoriedadeInicial = spedRegistroAttr?.ObrigatoriedadeInicial.ToDateTimeNullable();
            var dataObrigatoriedadeFinal   = spedRegistroAttr?.ObrigatoriedadeFinal.ToDateTimeNullable();

            /*
             * Verifica obrigatoriedade de escrita do registro. Ex.: M225/M625 -> Obrigatório a partir de 01/10/2015
             */
            if (dataObrigatoriedadeInicial.HasValue &&
                (dataObrigatoriedadeInicial.Value > competenciaDeclaracao))
            {
                deveGerarCamposDoRegistro = false;
            }

            if (dataObrigatoriedadeFinal.HasValue &&
                (dataObrigatoriedadeFinal.Value < competenciaDeclaracao.ObterProximoMesPrimeiroDia().AddDays(-1)))
            {
                deveGerarCamposDoRegistro = false;
            }

            /*
             * http://stackoverflow.com/questions/22306689/get-properties-of-class-by-order-using-reflection
             */
            var listaComPropriedadesOrdenadas =
                type.GetProperties().OrderBy(p => p.GetCustomAttributes(typeof(SpedCamposAttribute), true)
                                             .Cast <SpedCamposAttribute>()
                                             .Select(a => a.Ordem)
                                             .FirstOrDefault())
                .ToList();

            var sb = new StringBuilder();

            if (deveGerarCamposDoRegistro)
            {
                foreach (var property in listaComPropriedadesOrdenadas)
                {
                    sb.Append("|");
                    foreach (
                        var spedCampoAttr in
                        from Attribute attr in property.GetCustomAttributes(true) select attr as SpedCamposAttribute
                        )
                    {
                        if (spedCampoAttr == null)
                        {
                            throw new Exception(
                                      $"O campo {property.Name} no registro {registroAtual} não possui atributo SPED definido!");
                        }

                        var isLiteralEnum             = spedCampoAttr.Tipo == "LE"; // Literal Enum
                        var propertyValue             = RegistroBaseSped.GetPropValue(source, property.Name, isLiteralEnum);
                        var propertyValueToStringSafe = propertyValue.ToStringSafe().Trim();

                        /*
                         * INDICADORES PARA FORMATAÇÃO DOS CAMPOS NOS REGISTROS
                         */

                        var isRequired         = spedCampoAttr.IsObrigatorio;
                        var isDecimal          = property.PropertyType == typeof(decimal);
                        var isNullableDecimal  = property.PropertyType == typeof(decimal?);
                        var isDateTime         = property.PropertyType == typeof(DateTime);
                        var isNullableDateTime = property.PropertyType == typeof(DateTime?);
                        var hasValue           = !string.IsNullOrEmpty(propertyValueToStringSafe) ||
                                                 !string.IsNullOrWhiteSpace(propertyValueToStringSafe);

                        var propertyLength = hasValue
                            ? propertyValueToStringSafe.Length
                            : 0;


                        // Verificação necessária p/ ajustes no tamanho de campos como CSTs e Indicadores. Ex.: CST PIS '1' -> Deve estar no arquivo como '01'.
                        var isCodeOrNumberAndHasLength = (spedCampoAttr.Tipo == "C" || spedCampoAttr.Tipo == "N") &&
                                                         (spedCampoAttr.Tamanho > 0 && spedCampoAttr.Tamanho <= 4);

                        var isHour           = spedCampoAttr.Tipo == "H";
                        var onlyMonthAndYear = spedCampoAttr.Tipo == "MA";

                        if (isRequired && !hasValue)
                        {
                            throw new Exception(
                                      $"O campo {spedCampoAttr.Ordem} - {spedCampoAttr.Campo} no Registro {registroAtual} é obrigatório e não foi informado!");
                        }

                        const decimal vZero = 0M;
                        if (isRequired && isDecimal &&
                            (propertyValueToStringSafe == string.Empty || propertyValueToStringSafe.ToDecimal() == 0))
                        {
                            sb.Append(vZero.ToString("N" + spedCampoAttr.QtdCasas));
                        }
                        else
                        {
                            if (isDecimal && hasValue)
                            {
                                var vDecimal =
                                    Convert.ToDecimal(propertyValue).ToString("N" + spedCampoAttr.QtdCasas);
                                sb.Append(vDecimal.ToStringSafe().Replace(".", ""));
                            }
                            else if (isNullableDecimal && hasValue)
                            {
                                var vDecimal =
                                    Convert.ToDecimal(propertyValue).ToString("N" + spedCampoAttr.QtdCasas);
                                sb.Append(vDecimal.ToStringSafe().Replace(".", ""));
                            }
                            else if (isDateTime && hasValue)
                            {
                                sb.Append(Convert.ToDateTime(propertyValue).Date.ToString("ddMMyyyy"));
                            }
                            else if (isNullableDateTime && hasValue)
                            {
                                sb.Append(Convert.ToDateTime(propertyValue).Date.ToString("ddMMyyyy"));
                            }
                            else if ((isDateTime && hasValue) && isHour)
                            {
                                sb.Append(Convert.ToDateTime(propertyValue).Date.ToString("hhmmss"));
                            }
                            else if ((isDateTime && hasValue) && onlyMonthAndYear)
                            {
                                sb.Append(Convert.ToDateTime(propertyValue).Date.ToString("MMyyyy"));
                            }
                            else if ((isCodeOrNumberAndHasLength && hasValue) || (isLiteralEnum && hasValue))
                            {
                                sb.Append(propertyValue.ToString().PadLeft(spedCampoAttr.Tamanho, '0'));
                            }
                            else
                            {
                                if (propertyLength > 0 && (propertyLength > spedCampoAttr.Tamanho))
                                {
                                    sb.Append(propertyValueToStringSafe.Substring(0, spedCampoAttr.Tamanho));
                                }
                                else
                                {
                                    sb.Append(propertyValueToStringSafe);
                                }
                            }
                        }
                    }
                }
                sb.Append("|");
                sb.Append(Environment.NewLine);
            }

            return(sb.ToString());
        }