Passed
Push — main ( cbb3ab...c5dfea )
by Sat CFDI
03:12
created

NotificationsManager.serie()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
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):
66
        return self["Folio"]
67
68
    def serie(self):
69
        return self["Serie"]
70
71
    def set_folio(self, folio: int):
72
        self["Folio"] = folio
73
        self.save()
74
75
76
class ClientsManager(LocalData):
77
    file_source = "clients.yaml"
78
79
    def __init__(self):
80
        super().__init__()
81
        for k in self:
82
            self[k]["Rfc"] = k
83
84
85
class FacturasManager(dict):
86
    def __init__(self, values, file_source="facturas.yaml"):
87
        with open(file_source, "r", encoding="utf-8") as fs:
88
            template = environment_default.from_string(fs.read())
89
            rendered_template = template.render(
90
                values
91
            )
92
            super().__init__(yaml.safe_load(rendered_template))
93
94
95
class CanceladosManager(LocalData):
96
    file_source = "cancelados.yaml"
97
98
    def get_state(self, cfdi, only_cache=True):
99
        uuid = str(cfdi.uuid)
100
101
        res = self.get(uuid)
102
        if res:
103
            return res
104
105
        if only_cache:
106
            return {}
107
108
        try:
109
            res = sat_manager.status(cfdi)
110
            if res["ValidacionEFOS"] != "200":
111
                logger.error("CFDI No Encontrado '%s' %s", uuid, res)
112
            else:
113
                logger.info("CFDI Encontrado '%s' %s", uuid, res)
114
115
            self[uuid] = res
116
            return res
117
        except Exception:
118
            logger.exception("Failed to get Status for Invoice: ", uuid)
119
            return {}
120
121
122
def tag(text, tag):
123
    return '<' + tag + '>' + text + '</' + tag + '>'
124
125
126
def generate_pdf_template(template_name, fields):
127
    increment_template = environment_bold_escaped.get_template(template_name)
128
    md5_document = increment_template.render(
129
        fields
130
    )
131
    html = markdown(md5_document)
132
    pdf = HTML(string=html).write_pdf(
133
        target=None,
134
        stylesheets=[
135
            os.path.join(SOURCE_DIRECTORY, "markdown_styles", "markdown6.css"),
136
            CSS(
137
                string='@page { width: Letter; margin: 1.6cm 1.6cm 1.6cm 1.6cm; }'
138
            )
139
        ]
140
    )
141
142
    return pdf
143
144
145
yaml.SafeDumper.add_multi_representer(dict, lambda dumper, data: dumper.represent_dict(data))
146
yaml.SafeLoader.add_constructor("!decimal", lambda loader, node: Decimal(loader.construct_scalar(node)))
147
148
149
def represent_decimal(dumper, data):
150
    return dumper.represent_scalar('tag:yaml.org,2002:str', str(data))
151
152
153
def represent_str(dumper, data):
154
    return dumper.represent_scalar('tag:yaml.org,2002:str', str(data))
155
156
157
yaml.SafeDumper.add_representer(Decimal, represent_decimal)
158
yaml.SafeDumper.add_representer(Code, represent_str)
159
yaml.SafeDumper.add_representer(Xint, represent_str)
160