File size: 2,968 Bytes
d9d7b41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

from __future__ import annotations

import hashlib
from datetime import date
from decimal import Decimal
from pathlib import Path
from typing import Any


def _fmt_data(d: date | None) -> str:
    if d is None:
        return ""
    return d.strftime("%d%m%Y")


def _fmt_decimal(v: Decimal | None, casas: int = 2) -> str:
    if v is None or v == 0:
        return ""
    return f"{v:.{casas}f}".replace(".", ",")


def _fmt_str(v: Any) -> str:
    if v is None:
        return ""
    return str(v).strip()


class RegistroSPED:
    

    def __init__(self, tipo: str):
        self.tipo = tipo
        self._campos: list[str] = []

    def add(self, valor: Any, tipo_campo: str = "str", casas: int = 2) -> "RegistroSPED":
        if valor is None or valor == "":
            self._campos.append("")
        elif tipo_campo == "data":
            self._campos.append(_fmt_data(valor))
        elif tipo_campo == "decimal":
            self._campos.append(_fmt_decimal(Decimal(str(valor)), casas))
        elif tipo_campo == "int":
            self._campos.append(str(int(valor)))
        else:
            self._campos.append(str(valor).strip())
        return self

    def to_line(self) -> str:
        campos = [self.tipo] + self._campos
        return "|" + "|".join(campos) + "|\n"


class ArquivoSPED:
    

    def __init__(self, nome_arquivo: str):
        self.nome_arquivo = nome_arquivo
        self._linhas: list[str] = []
        self._contadores: dict[str, int] = {}

    def _add_linha(self, linha: str) -> None:
        self._linhas.append(linha)
        tipo = linha.split("|")[1] if "|" in linha else ""
        self._contadores[tipo] = self._contadores.get(tipo, 0) + 1

    def adicionar_registro(self, reg: RegistroSPED) -> None:
        self._add_linha(reg.to_line())

    def adicionar_linha_raw(self, linha: str) -> None:
        if not linha.endswith("\n"):
            linha += "\n"
        self._add_linha(linha)

    def total_linhas(self) -> int:
        return len(self._linhas)

    def conteudo(self) -> str:
        return "".join(self._linhas)

    def salvar(self, diretorio: str | Path = ".") -> Path:
        caminho = Path(diretorio) / self.nome_arquivo
        caminho.parent.mkdir(parents=True, exist_ok=True)
        caminho.write_text(self.conteudo(), encoding="utf-8")
        return caminho

    def hash_md5(self) -> str:
        return hashlib.md5(self.conteudo().encode("utf-8")).hexdigest()


def criar_registro(tipo: str, *campos) -> str:
    
    partes = [tipo]
    for campo in campos:
        if campo is None:
            partes.append("")
        elif isinstance(campo, date):
            partes.append(_fmt_data(campo))
        elif isinstance(campo, Decimal):
            partes.append(_fmt_decimal(campo))
        elif isinstance(campo, float):
            partes.append(_fmt_decimal(Decimal(str(campo))))
        else:
            partes.append(str(campo).strip())
    return "|" + "|".join(partes) + "|\n"