Passed
Push — main ( 69a97f...2ac74a )
by Sat CFDI
01:49
created

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