""" Leitura do arquivo padrão (leiaute) que o sistema (Questor) importa mensalmente, e escrita no mesmo formato. Formato: CSV separado por ';', sempre com este cabeçalho: CODIGOEMPRESA;NOMEFUNC;CPFFUNC;CODIGOOUTEMP;DATAINICIAL;NOMEDEPENDENTE; CPFDEPENDENTE;VALOREMPRESA;VALOR;DESCRICAO Porta de projects/project/core/leiaute_sistema.py. """ import csv import io from typing import List from portal_api.planos_saude.modelos import LinhaSistema CABECALHO = [ "CODIGOEMPRESA", "NOMEFUNC", "CPFFUNC", "CODIGOOUTEMP", "DATAINICIAL", "NOMEDEPENDENTE", "CPFDEPENDENTE", "VALOREMPRESA", "VALOR", "DESCRICAO", ] def _decodifica_planilha(caminho_csv: str) -> str: """A planilha padrão do Questor às vezes sai em UTF-8 (com ou sem BOM), às vezes em Windows-1252/ANSI — descobrimos isso na prática quando um nome com acento (ex.: "GONÇALVES") quebrava a leitura com UnicodeDecodeError, sempre tratado genericamente como "arquivo não é a planilha padrão" por quem chama esta função. Tenta UTF-8 primeiro (não muda nada pro caso comum, sem acentos, onde os dois formatos coincidem byte a byte) e cai pra cp1252 só se a decodificação falhar — mesmo espírito do `encoding="latin-1"` já usado pelo parser CSV da Unimed.""" with open(caminho_csv, "rb") as f: conteudo = f.read() try: return conteudo.decode("utf-8-sig") except UnicodeDecodeError: return conteudo.decode("cp1252") def le_planilha_padrao(caminho_csv: str) -> List[LinhaSistema]: linhas = [] texto = _decodifica_planilha(caminho_csv) with io.StringIO(texto, newline="") as f: leitor = csv.DictReader(f, delimiter=";") for row in leitor: linhas.append(LinhaSistema( codigo_empresa=row["CODIGOEMPRESA"].strip(), nome_func=row["NOMEFUNC"].strip(), cpf_func=row["CPFFUNC"].strip(), codigo_out_emp=row["CODIGOOUTEMP"].strip(), data_inicial=row["DATAINICIAL"].strip(), nome_dependente=row["NOMEDEPENDENTE"].strip(), cpf_dependente=row["CPFDEPENDENTE"].strip(), valor_empresa=row["VALOREMPRESA"].strip(), valor=row["VALOR"].strip(), descricao=row["DESCRICAO"].strip(), )) return linhas def formata_valor_br(valor: float) -> str: """0 -> '0' 83.38 -> '83,38' (mantém o padrão já usado na planilha)""" if valor == 0: return "0" return f"{valor:.2f}".replace(".", ",") def parse_valor_br(texto: str) -> float: """Inverso de formata_valor_br — '83,38' -> 83.38 '1.234,56' -> 1234.56. Usado pra interpretar o "limite de valor"/"% de custeio" digitados pelo usuário no formulário de nova importação (ver serializers.py).""" texto = (texto or "").strip().replace(".", "").replace(",", ".") return float(texto) if texto else 0.0