Spaces:
Sleeping
Sleeping
| """ | |
| Formatadores de texto e valores monetários. | |
| """ | |
| import re | |
| from typing import Tuple, List, Dict | |
| def numero_para_extenso(valor: float) -> str: | |
| """Converte um valor numérico para sua representação por extenso em português.""" | |
| if valor == 0: | |
| return "zero reais" | |
| unidades = ['', 'um', 'dois', 'três', 'quatro', 'cinco', 'seis', 'sete', 'oito', 'nove'] | |
| especiais = ['dez', 'onze', 'doze', 'treze', 'quatorze', 'quinze', 'dezesseis', 'dezessete', 'dezoito', 'dezenove'] | |
| dezenas = ['', '', 'vinte', 'trinta', 'quarenta', 'cinquenta', 'sessenta', 'setenta', 'oitenta', 'noventa'] | |
| centenas = ['', 'cento', 'duzentos', 'trezentos', 'quatrocentos', 'quinhentos', 'seiscentos', 'setecentos', 'oitocentos', 'novecentos'] | |
| def converter_grupo(n): | |
| if n == 0: | |
| return '' | |
| if n == 100: | |
| return 'cem' | |
| resultado = '' | |
| if n >= 100: | |
| resultado += centenas[n // 100] | |
| n %= 100 | |
| if n > 0: | |
| resultado += ' e ' | |
| if n >= 20: | |
| resultado += dezenas[n // 10] | |
| n %= 10 | |
| if n > 0: | |
| resultado += ' e ' + unidades[n] | |
| elif n >= 10: | |
| resultado += especiais[n - 10] | |
| elif n > 0: | |
| resultado += unidades[n] | |
| return resultado | |
| parte_inteira = int(valor) | |
| centavos = round((valor - parte_inteira) * 100) | |
| resultado = '' | |
| if parte_inteira >= 1000000: | |
| milhoes = parte_inteira // 1000000 | |
| if milhoes == 1: | |
| resultado += 'um milhão' | |
| else: | |
| resultado += converter_grupo(milhoes) + ' milhões' | |
| parte_inteira %= 1000000 | |
| if parte_inteira > 0: | |
| resultado += ' e ' | |
| if parte_inteira >= 1000: | |
| milhares = parte_inteira // 1000 | |
| if milhares == 1: | |
| resultado += 'mil' | |
| else: | |
| resultado += converter_grupo(milhares) + ' mil' | |
| parte_inteira %= 1000 | |
| if parte_inteira > 0: | |
| resultado += ' e ' | |
| if parte_inteira > 0: | |
| resultado += converter_grupo(parte_inteira) | |
| if resultado: | |
| if int(valor) == 1: | |
| resultado += ' real' | |
| else: | |
| resultado += ' reais' | |
| if centavos > 0: | |
| if resultado: | |
| resultado += ' e ' | |
| resultado += converter_grupo(centavos) | |
| if centavos == 1: | |
| resultado += ' centavo' | |
| else: | |
| resultado += ' centavos' | |
| return resultado | |
| def parse_valor_monetario(valor_str: str) -> float: | |
| """Converte string de valor monetário para float.""" | |
| if not valor_str: | |
| return 0.0 | |
| valor_limpo = re.sub(r'[^\d,.]', '', valor_str) | |
| valor_limpo = valor_limpo.replace('.', '').replace(',', '.') | |
| try: | |
| return float(valor_limpo) | |
| except ValueError: | |
| return 0.0 | |
| def formatar_valor_monetario(valor_str: str) -> Tuple[str, str]: | |
| """Formata valor monetário e retorna tupla (valor_formatado, extenso).""" | |
| valor_float = parse_valor_monetario(valor_str) | |
| if valor_float == 0: | |
| return valor_str, "" | |
| valor_formatado = f"R$ {valor_float:,.2f}".replace(',', 'X').replace('.', ',').replace('X', '.') | |
| extenso = numero_para_extenso(valor_float) | |
| return valor_formatado, extenso | |
| def aplicar_mascara_monetaria(valor: str) -> str: | |
| """Aplica máscara monetária brasileira a um valor.""" | |
| if not valor: | |
| return "" | |
| valor = valor.strip() | |
| if re.match(r'^R\$\s*[\d\.]+,\d{2}$', valor): | |
| return valor | |
| if re.search(r'[a-zA-ZáéíóúãõâêîôûàèìòùçÁÉÍÓÚÃÕÂÊÎÔÛÀÈÌÒÙÇ]', valor): | |
| return valor | |
| valor_limpo = re.sub(r'R\$\s*', '', valor) | |
| if ',' in valor_limpo and '.' in valor_limpo: | |
| valor_limpo = valor_limpo.replace('.', '').replace(',', '.') | |
| elif ',' in valor_limpo: | |
| valor_limpo = valor_limpo.replace(',', '.') | |
| try: | |
| valor_float = float(valor_limpo) | |
| except ValueError: | |
| return valor | |
| return f"R$ {valor_float:,.2f}".replace(',', 'X').replace('.', ',').replace('X', '.') | |
| def formatar_lista_para_documento(items: List[str]) -> str: | |
| """Formata lista de itens para inclusão no documento.""" | |
| items_limpos = [i.strip() for i in items if i and i.strip()] | |
| if not items_limpos: | |
| return "" | |
| return "\n".join([f"- {i};" for i in items_limpos]) | |
| def formatar_valores_mercado_para_documento(anos: List[str], valores: List[str]) -> str: | |
| """Formata lista de valores de mercado por ano para inclusão no documento.""" | |
| linhas = [] | |
| for ano, valor in zip(anos, valores): | |
| if ano and valor: | |
| try: | |
| ano_str = str(int(float(ano))) if ano else "" | |
| except (ValueError, TypeError): | |
| ano_str = str(ano) if ano else "" | |
| valor_float = parse_valor_monetario(valor) | |
| if valor_float > 0: | |
| extenso = numero_para_extenso(valor_float) | |
| linhas.append(f"{ano_str} - {valor} ({extenso})") | |
| else: | |
| linhas.append(f"{ano_str} - {valor}") | |
| if not linhas: | |
| return "" | |
| return "\n".join(linhas) | |
| def formatar_motivos_desvalorizantes(motivos: List[Dict]) -> Dict: | |
| """Formata a lista unificada de motivos desvalorizantes.""" | |
| if not motivos: | |
| return { | |
| 'alegados': [], | |
| 'confirmados': [], | |
| 'todos': [], | |
| 'alegados_texto': '', | |
| 'confirmados_texto': '', | |
| 'secoes': [] | |
| } | |
| alegados = [] | |
| confirmados = [] | |
| todos = [] | |
| secoes = [] | |
| for i, motivo in enumerate(motivos, 1): | |
| descricao = motivo.get('descricao', '').strip() | |
| foi_alegado = motivo.get('alegado', False) | |
| foi_confirmado = motivo.get('confirmado', False) | |
| if not descricao: | |
| continue | |
| item = { | |
| 'numero': i, | |
| 'descricao': descricao, | |
| 'alegado': foi_alegado, | |
| 'confirmado': foi_confirmado | |
| } | |
| todos.append(item) | |
| if foi_alegado: | |
| alegados.append(descricao) | |
| if foi_confirmado: | |
| confirmados.append(descricao) | |
| status = [] | |
| if foi_alegado: | |
| status.append("alegado pelo contribuinte") | |
| else: | |
| status.append("não alegado pelo contribuinte") | |
| if foi_confirmado: | |
| status.append("e confirmado na análise") | |
| else: | |
| status.append("e não confirmado na análise") | |
| secoes.append({ | |
| 'numero': i, | |
| 'titulo': descricao, | |
| 'status': ", ".join(status) if status else "identificado na vistoria", | |
| 'confirmado': foi_confirmado | |
| }) | |
| alegados_texto = formatar_lista_para_documento(alegados) | |
| confirmados_texto = formatar_lista_para_documento(confirmados) | |
| return { | |
| 'alegados': alegados, | |
| 'confirmados': confirmados, | |
| 'todos': todos, | |
| 'alegados_texto': alegados_texto, | |
| 'confirmados_texto': confirmados_texto, | |
| 'secoes': secoes | |
| } | |