🔧 Mudanças Necessárias no Backend - Balancete Geral

📋 Resumo

O frontend foi refatorado para usar dois checkboxes independentes: - gerarLayoutTxt: Gera arquivo TXT no formato específico COSIF - gerarLayoutXML: Gera arquivo XML no formato específico COSIF

O backend precisa ser atualizado para: 1. Aceitar os novos campos gerarLayoutTxt e gerarLayoutXML 2. Processar a lógica de geração baseada nesses campos 3. Retornar arquivoXml quando gerarLayoutXML estiver marcado


🔄 Mudanças no Payload (Request)

Payload Atual (Frontend envia):

{
  "balanceteGeralDTO": {
    "dataReferencia": "2025-12-31T00:00:00.000Z",
    "paginaInicial": "1",
    "nivelMaximo": "9",
    "fundosEncerrados": false,
    "alertaSaldosInvertidos": false,
    "geraArquivoTexto": true,        // true quando gerarLayoutTxt OU gerarLayoutXML está marcado
    "gerarLayoutTxt": true,          // ⚠️ NOVO CAMPO
    "gerarLayoutXML": false,         // ⚠️ NOVO CAMPO
    "contasFantasmas": false,
    "valoresZerados": false,
    "empresa": "000000001",
    "filial": "000000001",
    "filialFim": "000000001",
    "usuario": "nome_usuario"
  },
  "printDTO": {
    "orientationEnum": "LANDSCAPE",
    "visualizationEnum": null        // null quando layouts estão marcados
  }
}

Possibilidades de Combinação:

gerarLayoutTxt gerarLayoutXML geraArquivoTexto visualizationEnum Resultado Esperado
false false false "PDF" ou "TXT" Relatório formatado (PDF/TXT report)
true false true null Arquivo TXT específico
false true true null Arquivo XML específico
true true true null Ambos arquivos (TXT + XML)

📝 Mudanças Necessárias no Backend

1. Adicionar Campos no DTO

Arquivo: ecosif-reports/src/main/java/io/ecosif/reports/model/dto/BalanceteGeralDTO.java

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class BalanceteGeralDTO {

    private LocalDateTime dataReferencia;
    private String paginaInicial;
    private String nivelMaximo;
    private Boolean fundosEncerrados; 
    private Boolean alertaSaldosInvertidos;
    private Boolean geraArquivoTexto;
    private Boolean contasFantasmas; 
    private Boolean valoresZerados;
    private String empresa; 
    private String filial;
    private String filialFim;
    private String usuario;

    // ⚠️ NOVOS CAMPOS
    private Boolean gerarLayoutTxt;      // Novo campo para Layout TXT
    private Boolean gerarLayoutXML;      // Novo campo para Layout XML

}

2. Adicionar Campo no Response DTO

Arquivo: ecosif-reports/src/main/java/io/ecosif/reports/model/dto/RetornoRelatorioBalanceteGeral.java

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class RetornoRelatorioBalanceteGeral extends RetornoRelatoriosDTO {

    private String relatorio;      // Para PDF/TXT report (quando layouts não estão marcados)
    private String arquivoTxt;      // Para Layout TXT
    private String arquivoXml;      // ⚠️ NOVO CAMPO - Para Layout XML

}

3. Modificar a Lógica do Service

Arquivo: ecosif-reports/src/main/java/io/ecosif/reports/service/impl/PrintReportServiceImpl.java

Método: getReportCosifGeneralBalance()

Lógica Atual (linhas 532-572):

public RetornoGenerico getReportCosifGeneralBalance(BalanceteGeralRequestDTO balanceteGeralDTO) throws Exception {
    // ... código de preparação ...

    RetornoRelatorioBalanceteGeral result = new RetornoRelatorioBalanceteGeral();

    if(balanceteGeralDTO.getBalanceteGeralDTO().getGeraArquivoTexto()){
        if(dado.getArquivo() == null || dado.getArquivo().isEmpty()) {
            result.setArquivoTxt("");
        }else{
            result.setArquivoTxt(reportsHelpers.txtCosif4010Txt(dado.getArquivo()));
        }
    }else{
        // Gera relatório formatado (PDF/TXT)
        if ("pdf".equals(balanceteGeralDTO.getPrintDTO().getVisualizationEnum().getValor())) {
            result.setRelatorio(reportsHelpers.pdfCosif4010(dado));
        } else if ("txt".equals(balanceteGeralDTO.getPrintDTO().getVisualizationEnum().getValor())) {
            result.setRelatorio(reportsHelpers.txtCosif4010(dado));
        } else if ("csv".equals(balanceteGeralDTO.getPrintDTO().getVisualizationEnum().getValor())) {
            result.setRelatorio(reportsHelpers.pdfCosif4010(dado));
        } else {
            result.setRelatorio("Tipo de arquivo inválido");
        }
    }
    return new RetornoGenerico(200,"", result);
}

Lógica Nova (proposta):

public RetornoGenerico getReportCosifGeneralBalance(BalanceteGeralRequestDTO balanceteGeralDTO) throws Exception {
    // ... código de preparação (mantém igual) ...

    RetornoRelatorioBalanceteGeral result = new RetornoRelatorioBalanceteGeral();

    // Ler os novos campos (com fallback para compatibilidade)
    Boolean gerarLayoutTxt = balanceteGeralDTO.getBalanceteGeralDTO().getGerarLayoutTxt() != null 
        ? balanceteGeralDTO.getBalanceteGeralDTO().getGerarLayoutTxt() 
        : false;
    Boolean gerarLayoutXML = balanceteGeralDTO.getBalanceteGeralDTO().getGerarLayoutXML() != null 
        ? balanceteGeralDTO.getBalanceteGeralDTO().getGerarLayoutXML() 
        : false;

    // Se algum layout está marcado, processa layouts
    if (gerarLayoutTxt || gerarLayoutXML) {

        // Gerar TXT se solicitado
        if (gerarLayoutTxt) {
            if(dado.getArquivo() == null || dado.getArquivo().isEmpty()) {
                result.setArquivoTxt("");
            } else {
                result.setArquivoTxt(reportsHelpers.txtCosif4010Txt(dado.getArquivo()));
            }
        }

        // Gerar XML se solicitado
        if (gerarLayoutXML) {
            try {
                // Se TXT também foi gerado, usa o TXT gerado para converter em XML
                String txtContent;
                if (gerarLayoutTxt && result.getArquivoTxt() != null && !result.getArquivoTxt().isEmpty()) {
                    // Decodifica o base64 do TXT
                    byte[] txtBytes = Base64.getDecoder().decode(result.getArquivoTxt());
                    txtContent = new String(txtBytes, StandardCharsets.UTF_8);
                } else {
                    // Se TXT não foi gerado, precisa gerar o TXT primeiro para converter
                    if(dado.getArquivo() == null || dado.getArquivo().isEmpty()) {
                        txtContent = "";
                    } else {
                        String txtBase64 = reportsHelpers.txtCosif4010Txt(dado.getArquivo());
                        byte[] txtBytes = Base64.getDecoder().decode(txtBase64);
                        txtContent = new String(txtBytes, StandardCharsets.UTF_8);
                    }
                }

                // Converte TXT para XML usando Report4010Service
                String xmlContent = report4010Service.generateXmlFromTxt(txtContent);

                // Codifica XML em base64
                String xmlBase64 = Base64.getEncoder().encodeToString(
                    xmlContent.getBytes(StandardCharsets.UTF_8)
                );
                result.setArquivoXml(xmlBase64);

            } catch (Exception e) {
                // Log do erro e retorna XML vazio ou erro
                logger.error("Erro ao gerar XML: " + e.getMessage(), e);
                result.setArquivoXml("");
            }
        }

    } else {
        // Modo normal: gera relatório formatado (PDF/TXT report)
        // Mantém compatibilidade com código antigo usando geraArquivoTexto
        if (balanceteGeralDTO.getBalanceteGeralDTO().getGeraArquivoTexto() != null 
            && balanceteGeralDTO.getBalanceteGeralDTO().getGeraArquivoTexto()) {
            // Código legado: gera TXT quando geraArquivoTexto está marcado
            if(dado.getArquivo() == null || dado.getArquivo().isEmpty()) {
                result.setArquivoTxt("");
            } else {
                result.setArquivoTxt(reportsHelpers.txtCosif4010Txt(dado.getArquivo()));
            }
        } else {
            // Gera relatório formatado
            if (balanceteGeralDTO.getPrintDTO() != null 
                && balanceteGeralDTO.getPrintDTO().getVisualizationEnum() != null) {
                String vizEnum = balanceteGeralDTO.getPrintDTO().getVisualizationEnum().getValor();
                if ("pdf".equals(vizEnum)) {
                    result.setRelatorio(reportsHelpers.pdfCosif4010(dado));
                } else if ("txt".equals(vizEnum)) {
                    result.setRelatorio(reportsHelpers.txtCosif4010(dado));
                } else if ("csv".equals(vizEnum)) {
                    result.setRelatorio(reportsHelpers.pdfCosif4010(dado)); // ⚠️ BUG: CSV retorna PDF
                } else {
                    result.setRelatorio("Tipo de arquivo inválido");
                }
            } else {
                // Default: PDF
                result.setRelatorio(reportsHelpers.pdfCosif4010(dado));
            }
        }
    }

    return new RetornoGenerico(200, "", result);
}

4. Injetar Report4010Service no PrintReportServiceImpl

Arquivo: ecosif-reports/src/main/java/io/ecosif/reports/service/impl/PrintReportServiceImpl.java

@Service
public class PrintReportServiceImpl implements PrintReportService {

    // ... outros campos ...

    @Autowired
    private Report4010Service report4010Service;  // ⚠️ ADICIONAR

    // ... resto do código ...
}

5. Adicionar Imports Necessários

Arquivo: ecosif-reports/src/main/java/io/ecosif/reports/service/impl/PrintReportServiceImpl.java

import java.util.Base64;
import java.nio.charset.StandardCharsets;
import io.ecosif.reports.cos4010.Report4010Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

📊 Estrutura de Resposta Esperada

Quando gerarLayoutTxt = true e gerarLayoutXML = false:

{
  "status": 200,
  "mensagem": "",
  "elemento": {
    "relatorio": null,
    "arquivoTxt": "base64_encoded_txt_content",
    "arquivoXml": null
  }
}

Quando gerarLayoutTxt = false e gerarLayoutXML = true:

{
  "status": 200,
  "mensagem": "",
  "elemento": {
    "relatorio": null,
    "arquivoTxt": null,
    "arquivoXml": "base64_encoded_xml_content"
  }
}

Quando gerarLayoutTxt = true e gerarLayoutXML = true:

{
  "status": 200,
  "mensagem": "",
  "elemento": {
    "relatorio": null,
    "arquivoTxt": "base64_encoded_txt_content",
    "arquivoXml": "base64_encoded_xml_content"
  }
}

Quando ambos false (modo normal):

{
  "status": 200,
  "mensagem": "",
  "elemento": {
    "relatorio": "base64_encoded_pdf_or_txt_report",
    "arquivoTxt": null,
    "arquivoXml": null
  }
}

✅ Checklist de Implementação

Status: código implementado em BalanceteGeralDTO, RetornoRelatorioBalanceteGeral e PrintReportServiceImpl (+ Report4010Service).
Itens de teste manual/homolog permanecem abertos até evidência de QA.


🔍 Notas Importantes

  1. Compatibilidade Retroativa: O código deve manter compatibilidade com requisições antigas que não enviam gerarLayoutTxt e gerarLayoutXML. Use getGerarLayoutTxt() != null para verificar se o campo foi enviado.

  2. Geração de XML: O XML é gerado a partir do conteúdo TXT usando Report4010Service.generateXmlFromTxt(). Se ambos TXT e XML estão marcados, o TXT é gerado primeiro e depois convertido para XML.

  3. Base64: Tanto arquivoTxt quanto arquivoXml devem ser retornados em base64, assim como relatorio.

  4. Tratamento de Erros: Se a geração de XML falhar, considere retornar um XML vazio ou uma mensagem de erro apropriada. Não deve quebrar a geração do TXT se ambos estiverem marcados.


Última atualização: 2026-01-28