diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index 0aaf567..70266d7 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -1186,6 +1186,8 @@ class ImportFacturaLibre(object): self._con = None self._cursor = None self._is_connect = self._connect(path) + self._clientes = [] + self._clientes_rfc = [] @property def is_connect(self): @@ -1213,21 +1215,172 @@ class ImportFacturaLibre(object): data = {} tables = ( ('receptores', 'Socios'), + ('cfdfacturas', 'Facturas'), ) for source, target in tables: data[target] = self._get_table(source) + + data['Socios'] += self._clientes + return data def _get_table(self, table): return getattr(self, '_{}'.format(table))() + def _get_cliente(self, invoice): + sql = "SELECT rfc, nombre FROM receptores WHERE id=?" + self._cursor.execute(sql, [invoice['id_cliente']]) + obj = self._cursor.fetchone() + if not obj is None: + data = { + 'rfc': obj['rfc'], + 'slug': to_slug(obj['nombre']), + } + return data + + if not invoice['xml']: + return {} + + doc = parse_xml(invoice['xml']) + version = doc.attrib['version'] + node = doc.find('{}Receptor'.format(PRE[version])) + rfc = node.attrib['rfc'] + nombre = node.attrib['nombre'] + + tipo_persona = 1 + if rfc == 'XEXX010101000': + tipo_persona = 4 + elif rfc == 'XAXX010101000': + tipo_persona = 3 + elif len(rfc) == 12: + tipo_persona = 2 + + data = { + 'tipo_persona': tipo_persona, + 'rfc': rfc, + 'nombre': nombre, + 'slug': to_slug(nombre), + 'es_cliente': True, + 'es_activo': False, + } + if not rfc in self._clientes_rfc: + self._clientes_rfc.append(rfc) + self._clientes.append(data) + + data = { + 'rfc': data['rfc'], + 'slug': data['slug'], + } + return data + + def _get_detalles(self, id): + sql = "SELECT * FROM cfddetalle WHERE id_cfd=?" + self._cursor.execute(sql, [id]) + rows = self._cursor.fetchall() + + fields = ( + ('categoria', 'categoria'), + ('cantidad', 'cantidad'), + ('unidad', 'unidad'), + ('noIdentificacion', 'clave'), + ('descripcion', 'descripcion'), + ('valorUnitario', 'valor_unitario'), + ('importe', 'importe'), + ('numero', 'pedimento'), + ('fecha', 'fecha_pedimento'), + ('aduana', 'aduana'), + ('CuentaPredial', 'cuenta_predial'), + ('alumno', 'alumno'), + ('curp', 'curp'), + ('nivel', 'nivel'), + ('autorizacion', 'autorizacion'), + ) + + data = [] + for row in rows: + new = {t: row[s] for s, t in fields} + data.append(new) + + return data + + def _get_impuestos(self, id): + sql = "SELECT * FROM cfdimpuestos WHERE id_cfd=?" + self._cursor.execute(sql, [id]) + rows = self._cursor.fetchall() + + tasas = { + '16': 0.16, + '-10': 0.10, + '0': 0.0, + '-2/3': 0.666667, + } + + data = [] + for row in rows: + filtro = { + 'name': row['nombre'], + 'tasa': tasas[row['tasa']], + 'tipo': row['tipo'][0], + } + new = { + 'importe': row['importe'], + 'filtro': filtro + } + data.append(new) + + return data + + def _cfdfacturas(self): + sql = "SELECT * FROM cfdfacturas" + self._cursor.execute(sql) + rows = self._cursor.fetchall() + fields = ( + ('version', 'version'), + ('serie', 'serie'), + ('folio', 'folio'), + ('fecha', 'fecha'), + ('fecha_timbrado', 'fecha_timbrado'), + ('formaDePago', 'forma_pago'), + ('condicionesDePago', 'condiciones_pago'), + ('subTotal', 'subtotal'), + ('descuento', 'descuento'), + ('TipoCambio', 'tipo_cambio'), + ('Moneda', 'moneda'), + ('total', 'total'), + ('tipoDeComprobante', 'tipo_comprobante'), + ('metodoDePago', 'metodo_pago'), + ('LugarExpedicion', 'lugar_expedicion'), + ('totalImpuestosRetenidos', 'total_retenciones'), + ('totalImpuestosTrasladados', 'total_traslados'), + ('xml', 'xml'), + ('id_cliente', 'cliente'), + ('notas', 'notas'), + ('uuid', 'uuid'), + ('donativo', 'donativo'), + ('estatus', 'estatus'), + ('regimen', 'regimen_fiscal'), + ('xml_acuse', 'acuse'), + ) + data = [] + for row in rows: + new = {t: row[s] for s, t in fields} + if row['estatus'] == 'Pagada': + new['pagada'] = True + elif row['estatus'] == 'Cancelada': + new['cancelada'] = True + new['total_mn'] = round(row['TipoCambio'] * row['total'], 2) + new['detalles'] = self._get_detalles(row['id']) + new['impuestos'] = self._get_impuestos(row['id']) + new['cliente'] = self._get_cliente(row) + data.append(new) + return data + def _receptores(self): sql = "SELECT * FROM receptores" self._cursor.execute(sql) rows = self._cursor.fetchall() - #~ names = [d[0] for d in self._cursor.description] + fields = ( - ('id', 'id'), ('rfc', 'rfc'), ('nombre', 'nombre'), ('calle', 'calle'), @@ -1263,12 +1416,12 @@ class ImportFacturaLibre(object): elif len(new['rfc']) == 12: new['tipo_persona'] = 2 - self._cursor.execute(sql1, (new['id'],)) + self._cursor.execute(sql1, (row['id'],)) tmp = self._cursor.fetchall() if tmp: new['correo_facturas'] = ', '.join([r[0] for r in tmp]) - self._cursor.execute(sql2, (new['id'],)) + self._cursor.execute(sql2, (row['id'],)) tmp = self._cursor.fetchall() if tmp: new['telefonos'] = ', '.join([r[0] for r in tmp]) diff --git a/source/app/models/main.py b/source/app/models/main.py index 622c35b..6048a89 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -1178,13 +1178,12 @@ class Facturas(BaseModel): def filter_years(cls): data = [{'id': -1, 'value': 'Todos'}] rows = (Facturas - .select(Facturas.fecha.year) + .select(Facturas.fecha.year.alias('year')) .group_by(Facturas.fecha.year) .order_by(Facturas.fecha.year) - .scalar(as_tuple=True) ) if not rows is None: - data += [{'id': int(row), 'value': int(row)} for row in rows] + data += [{'id': int(r.year), 'value': int(r.year)} for r in rows] return tuple(data) @classmethod @@ -2410,19 +2409,23 @@ def _crear_tablas(rfc): Productos.impuestos.get_through_model(), Productos.tags.get_through_model(), ] + log.info('Creando tablas...') database_proxy.create_tables(tablas, True) log.info('Tablas creadas correctamente...') - usuario = 'admin' contraseña = 'blades3.3' + usuarios = ( + {'usuario': 'superadmin', 'contraseña': contraseña, 'es_superusuario': True}, + {'usuario': 'admin', 'contraseña': contraseña, 'es_admin': True}, + ) - if not Usuarios.select().where(Usuarios.usuario==usuario).exists(): - Usuarios.create( - usuario=usuario, contraseña=contraseña, es_superusuario=True) - log.info('SuperUsuario creado correctamente...') - else: - msg = 'El usuario ya existe' - log.error(msg) + for usuario in usuarios: + try: + with database_proxy.atomic() as txn: + Usuarios.create(**usuario) + log.info('Usuario creado correctamente...') + except IntegrityError: + log.info('Usuario ya existe...') _init_values(rfc) _importar_valores('', rfc) @@ -2603,7 +2606,6 @@ def _listar_rfc(): log.info(msg) return - def _importar_valores(archivo='', rfc=''): if not rfc: rfc = input('Introduce el RFC: ').strip().upper() @@ -2638,6 +2640,47 @@ def _importar_valores(archivo='', rfc=''): return +def _importar_socios(rows): + log.info('\tImportando Clientes...') + for row in rows: + try: + with database_proxy.atomic() as txn: + Socios.create(**row) + except IntegrityError: + msg = '\tSocio: id: {}'.format(row['nombre']) + log.error(msg) + log.info('\tClientes importados...') + return + + +def _importar_facturas(rows): + log.info('\tImportando Facturas...') + for row in rows: + try: + detalles = row.pop('detalles') + impuestos = row.pop('impuestos') + cliente = row.pop('cliente') + row['cliente'] = Socios.get(**cliente) + with database_proxy.atomic() as txn: + obj = Facturas.create(**row) + for detalle in detalles: + detalle['factura'] = obj + FacturasDetalle.create(**detalle) + for impuesto in impuestos: + imp = SATImpuestos.get(**impuesto['filtro']) + new = { + 'factura': obj, + 'impuesto': imp, + 'importe': impuesto['importe'], + } + FacturasImpuestos.create(**new) + except IntegrityError: + msg = '\tFactura: id: {}'.format(row['serie'] + row['folio']) + log.error(msg) + log.info('\tFacturas importadas...') + return + + def _importar_factura_libre(archivo): rfc = input('Introduce el RFC: ').strip().upper() if not rfc: @@ -2658,15 +2701,9 @@ def _importar_factura_libre(archivo): return data = app.import_data() - for table, rows in data.items(): - log.info('\tImportando: {}'.format(table)) - model = globals()[table] - for row in rows: - try: - model.create(**row) - except IntegrityError: - msg = '\t{}'.format(str(row)) - log.error(msg) + + _importar_socios(data['Socios']) + _importar_facturas(data['Facturas']) log.info('Importación terminada...') return diff --git a/source/db/valores_iniciales.json b/source/db/valores_iniciales.json index 322bcef..c66fe65 100644 --- a/source/db/valores_iniciales.json +++ b/source/db/valores_iniciales.json @@ -2,8 +2,8 @@ { "tabla": "Categorias", "datos": [ - {"categoria": "Productos"}, - {"categoria": "Servicios"} + {"id": 1, "categoria": "Productos"}, + {"id": 2, "categoria": "Servicios"} ] }, {