Passed
Push — main ( 01321d...55509a )
by Sat CFDI
01:47
created

satdigitalinvoice.localdb.LocalDB.load_data()   A

Complexity

Conditions 3

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 3
nop 3
1
import logging
2
import os
3
import pickle
4
from enum import Enum
5
from uuid import UUID
6
7
import diskcache
8
from satcfdi.accounting import SatCFDI
9
from satcfdi.pacs import sat
10
11
from . import PPD
12
from .log_tools import print_yaml
13
from .mycfdi import CFDIEstatus
14
15
LIQUIDATED = 0
16
NOTIFIED = 2
17
STATUS_SAT = 3
18
FOLIO = 5
19
SERIE = 6
20
SOLICITUDES = 7
21
22
sat_manager = sat.SAT()
23
24
logger = logging.getLogger(__name__)
25
26
27
class LocalDB(diskcache.Cache):
28
    def __init__(self, base_path: str):
29
        super().__init__(directory=os.path.join(base_path, 'cache'))
30
        self.base_path = base_path
31
32
    def folio(self) -> int:
33
        return self.get(FOLIO, 1000)
34
35
    def folio_set(self, value: int):
36
        self[FOLIO] = value
37
38
    def serie(self) -> str:
39
        return self.get(SERIE, 'A')
40
41
    def serie_set(self, value: str):
42
        self[SERIE] = value
43
44
    def liquidated(self, uuid: UUID):
45
        return self.get((LIQUIDATED, uuid))
46
47
    def liquidated_set(self, uuid: UUID, value: bool):
48
        self[(LIQUIDATED, uuid)] = value
49
50
    def notified(self, uuid: UUID):
51
        return self.get((NOTIFIED, uuid))
52
53
    def notified_set(self, uuid: UUID, value: bool):
54
        self[(NOTIFIED, uuid)] = value
55
56
    def status_sat(self, uuid: UUID):
57
        return self.get((STATUS_SAT, uuid), {})
58
59
    def status_sat_set(self, uuid: UUID, value: dict):
60
        if value:
61
            self[(STATUS_SAT, uuid)] = value
62
        else:
63
            try:
64
                del self[(STATUS_SAT, uuid)]
65
            except KeyError:
66
                pass
67
68
    def get_solicitudes(self):
69
        return self.get(SOLICITUDES, {})
70
71
    def set_solicitudes(self, solicitudes):
72
        self[SOLICITUDES] = solicitudes
73
74
    def save_data(self, file, data):
75
        with open(os.path.join(self.base_path, file), 'wb') as f:
76
            pickle.dump(data, f)
77
78
    def load_data(self, file, default=None):
79
        try:
80
            with open(os.path.join(self.base_path, file), 'rb') as f:
81
                return pickle.load(f)
82
        except FileNotFoundError:
83
            return default
84
85
86
class StatusState(Enum):
87
    NONE = 1
88
    PAID = 2
89
    PENDING = 3
90
    IGNORED = 4
91
    CANCELLED = 5
92
93
    def __str__(self):
94
        if self.name == "NONE":
95
            return "💰"
96
        if self.name == "IGNORED":
97
            return "🚫"
98
        if self.name == "PAID":
99
            return "✔"
100
        if self.name == "PENDING":
101
            return ""
102
        if self.name == "CANCELLED":
103
            return "❌"
104
105
106
class LocalDBSatCFDI(LocalDB):
107
    def __init__(self, base_path, enviar_a_partir, pagar_a_partir):
108
        super().__init__(base_path)
109
        self.enviar_a_partir = enviar_a_partir
110
        self.pagar_a_partir = pagar_a_partir
111
112
    def notified(self, cfdi: SatCFDI):
113
        v = super().notified(cfdi.uuid)
114
        if v is None and cfdi["Fecha"] < self.enviar_a_partir:
115
            return True
116
        return v
117
118
    def notified_flip(self, cfdi: SatCFDI):
119
        v = not self.notified(cfdi)
120
        self.notified_set(cfdi.uuid, v)
121
        return v
122
123
    def liquidated(self, cfdi: SatCFDI):
124
        v = super().liquidated(cfdi.uuid)
125
        if v is None and cfdi["Fecha"] < self.pagar_a_partir[cfdi["MetodoPago"]]:
126
            return True
127
        return v
128
129
    def liquidated_flip(self, cfdi: SatCFDI):
130
        v = not self.liquidated(cfdi)
131
        self.liquidated_set(cfdi.uuid, v)
132
        return v
133
134
    def status_sat(self, cfdi: SatCFDI, update=False):
135
        if update:
136
            res = sat_manager.status(cfdi)
137
            if res["ValidacionEFOS"] == "200":
138
                self.status_sat_set(cfdi.uuid, res)
139
            return res
140
        else:
141
            return super().status_sat(cfdi.uuid)
142
143
    def liquidated_state(self, cfdi: SatCFDI):
144
        if cfdi.estatus == CFDIEstatus.Cancelado:
145
            return StatusState.CANCELLED
146
147
        if cfdi["TipoDeComprobante"] != "I":
148
            return StatusState.NONE
149
150
        mpago = cfdi["MetodoPago"]
151
        if cfdi['Total'] == 0 or (mpago == PPD and cfdi.saldo_pendiente == 0):
152
            return StatusState.PAID
153
154
        if self.liquidated(cfdi):
155
            if mpago == PPD:
156
                return StatusState.IGNORED
157
            return StatusState.PAID
158
159
        return StatusState.PENDING
160
161
    def describe(self, cfdi: SatCFDI):
162
        print_yaml({
163
            'saldada': self.liquidated(cfdi),
164
            'enviada': self.notified(cfdi),
165
            'status_sat': self.status_sat(cfdi)
166
        })
167