Test Failed
Push — main ( 905e23...cbb3ab )
by Sat CFDI
03:33
created

ClientsManager.__init__()   A

Complexity

Conditions 2

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
nop 1
1
import logging
2
import os
3
from decimal import Decimal
4
from html import escape as html_escape
5
6
import jinja2
7
import yaml
8
from jinja2 import Environment
9
from jinja2.filters import do_mark_safe
10
from markdown2 import markdown
11
from satcfdi import Code
12
from satcfdi.pacs import sat
13
from satcfdi.transform.helpers import Xint
14
from weasyprint import HTML, CSS
15
16
from . import SOURCE_DIRECTORY
17
18
logger = logging.getLogger()
19
sat_manager = sat.SAT()
20
21
environment_default = Environment(
22
    loader=jinja2.FileSystemLoader(searchpath=['templates']),
23
    autoescape=False,
24
    trim_blocks=True,
25
    lstrip_blocks=True,
26
    undefined=jinja2.StrictUndefined,
27
)
28
29
30
def finalize_html(val):
31
    return do_mark_safe(
32
        tag(html_escape(val), "b")
33
    )
34
35
36
environment_bold_escaped = Environment(
37
    loader=jinja2.FileSystemLoader(searchpath=['templates']),
38
    autoescape=True,
39
    trim_blocks=True,
40
    lstrip_blocks=True,
41
    undefined=jinja2.StrictUndefined,
42
    finalize=finalize_html
43
)
44
45
46
class LocalData(dict):
47
    file_source = None
48
49
    def __init__(self):
50
        with open(self.file_source, "r", encoding="utf-8") as fs:
51
            super().__init__(yaml.safe_load(fs))
52
53
    def save(self):
54
        with open(self.file_source, "w", encoding="utf-8") as fs:
55
            yaml.dump_all([self], fs, Dumper=yaml.SafeDumper, encoding="utf-8", allow_unicode=True, sort_keys=False)
56
57
58
class PaymentsManager(LocalData):
59
    file_source = "pagos.yaml"
60
61
62
class NotificationsManager(LocalData):
63
    file_source = "notifications.yaml"
64
65
    def folio(self, serie):
66
        return self["Series"][serie]
67
68
    def set_folio(self, serie: str, folio: int):
69
        self["Series"][serie] = max(self["Series"][serie], folio + 1)
70
        self.save()
71
72
73
class ClientsManager(LocalData):
74
    file_source = "clients.yaml"
75
76
    def __init__(self):
77
        super().__init__()
78
        for k in self:
79
            self[k]["Rfc"] = k
80
81
82
class FacturasManager(dict):
83
    def __init__(self, values, file_source="facturas.yaml"):
84
        with open(file_source, "r", encoding="utf-8") as fs:
85
            template = environment_default.from_string(fs.read())
86
            rendered_template = template.render(
87
                values
88
            )
89
            super().__init__(yaml.safe_load(rendered_template))
90
91
92
class CanceladosManager(LocalData):
93
    file_source = "cancelados.yaml"
94
95
    def get_state(self, cfdi, only_cache=True):
96
        uuid = str(cfdi.uuid)
97
98
        res = self.get(uuid)
99
        if res:
100
            return res
101
102
        if only_cache:
103
            return {}
104
105
        try:
106
            res = sat_manager.status(cfdi)
107
            if res["ValidacionEFOS"] != "200":
108
                logger.error("CFDI No Encontrado '%s' %s", uuid, res)
109
            else:
110
                logger.info("CFDI Encontrado '%s' %s", uuid, res)
111
112
            self[uuid] = res
113
            return res
114
        except Exception:
115
            logger.exception("Failed to get Status for Invoice: ", uuid)
116
            return {}
117
118
119
def tag(text, tag):
120
    return '<' + tag + '>' + text + '</' + tag + '>'
121
122
123
def generate_pdf_template(template_name, fields):
124
    increment_template = environment_bold_escaped.get_template(template_name)
125
    md5_document = increment_template.render(
126
        fields
127
    )
128
    html = markdown(md5_document)
129
    pdf = HTML(string=html).write_pdf(
130
        target=None,
131
        stylesheets=[
132
            os.path.join(SOURCE_DIRECTORY, "markdown_styles", "markdown6.css"),
133
            CSS(
134
                string='@page { width: Letter; margin: 1.6cm 1.6cm 1.6cm 1.6cm; }'
135
            )
136
        ]
137
    )
138
139
    return pdf
140
141
142
yaml.SafeDumper.add_multi_representer(dict, lambda dumper, data: dumper.represent_dict(data))
143
yaml.SafeLoader.add_constructor("!decimal", lambda loader, node: Decimal(loader.construct_scalar(node)))
144
145
146
def represent_decimal(dumper, data):
147
    return dumper.represent_scalar('tag:yaml.org,2002:str', str(data))
148
149
150
def represent_str(dumper, data):
151
    return dumper.represent_scalar('tag:yaml.org,2002:str', str(data))
152
153
154
yaml.SafeDumper.add_representer(Decimal, represent_decimal)
155
yaml.SafeDumper.add_representer(Code, represent_str)
156
yaml.SafeDumper.add_representer(Xint, represent_str)
157