Mostrar cantidad de empaques en PDF

This commit is contained in:
Mauricio Baeza 2019-02-04 22:13:11 -06:00
parent 5cdbb0aaa7
commit f761ab7a5a
6 changed files with 96 additions and 27 deletions

View File

@ -1,8 +1,28 @@
v 1.28.0 [03-feb-2019]
v 1.28.0 [04-feb-2019]
----------------------
- Mejora: Manejo de empaques para mensajeria
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar.
* IMPORTANTE:
Es necesario realizar una migración, despues de actualizar.
```
git pull origin master
cd source/app/models
python main.py -bk
python main.py -m
```
Es necesario agregar un nuevo requerimiento.
```
sudo pip install cryptography
```
Si envias tus facturas por correo directamente, es necesario volver a capturar
la contraseña de tu servidor de correo y guardar los datos nuevamente.
v 1.27.1 [23-ene-2019]

View File

@ -13,3 +13,4 @@ pyqrcode
pypng
reportlab
psycopg2-binary
cryptography

View File

@ -872,7 +872,7 @@ class LIBO(object):
currency = self.CELL_STYLE.get(self._currency, 'peso')
return '{}{}'.format(currency, match.groups()[1])
def _conceptos(self, data):
def _conceptos(self, data, pakings):
first = True
col1 = []
col2 = []
@ -881,8 +881,9 @@ class LIBO(object):
col5 = []
col6 = []
col7 = []
col8 = []
count = len(data) - 1
for concepto in data:
for i, concepto in enumerate(data):
key = concepto.get('noidentificacion', '')
description = concepto['descripcion']
unidad = concepto['unidad']
@ -899,6 +900,8 @@ class LIBO(object):
cell_5 = self._set_cell('{valorunitario}', valor_unitario, value=True)
cell_6 = self._set_cell('{importe}', importe, value=True)
cell_7 = self._set_cell('{descuento}', descuento, value=True)
if pakings:
cell_8 = self._set_cell('{empaque}', pakings[i], value=True)
if len(data) > 1:
row = cell_1.getCellAddress().Row + 1
self._sheet.getRows().insertByIndex(row, count)
@ -912,6 +915,8 @@ class LIBO(object):
col5.append((float(valor_unitario),))
col6.append((float(importe),))
col7.append((float(descuento),))
if pakings:
col8.append((pakings[i],))
self._total_cantidades += float(cantidad)
if not count:
return
@ -919,6 +924,9 @@ class LIBO(object):
style_5 = self._get_style(cell_5)
style_6 = self._get_style(cell_6)
style_7 = self._get_style(cell_7)
style_8 = ''
if pakings:
style_8 = self._get_style(cell_8)
col = cell_1.getCellAddress().Column
target1 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
@ -933,9 +941,13 @@ class LIBO(object):
col = cell_6.getCellAddress().Column
target6 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
target7 = None
target8 = None
if not cell_7 is None:
col = cell_7.getCellAddress().Column
target7 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
if pakings:
col = cell_8.getCellAddress().Column
target8 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
target1.setFormulaArray(tuple(col1))
target2.setDataArray(tuple(col2))
@ -945,6 +957,8 @@ class LIBO(object):
target6.setDataArray(tuple(col6))
if not target7 is None:
target7.setDataArray(tuple(col7))
if not target8 is None:
target8.setDataArray(tuple(col8))
if style_5:
cell_5.CellStyle = style_5
@ -955,6 +969,9 @@ class LIBO(object):
if style_7:
cell_7.CellStyle = style_7
target7.CellStyle = style_7
if style_8:
cell_8.CellStyle = style_8
target8.CellStyle = style_8
return
def _add_totales(self, data):
@ -1275,10 +1292,12 @@ class LIBO(object):
self._currency = data['totales']['moneda']
self._pagos = data.pop('pagos', False)
pakings = data.pop('pakings', [])
self._comprobante(data['comprobante'])
self._emisor(data['emisor'])
self._receptor(data['receptor'])
self._conceptos(data['conceptos'])
self._conceptos(data['conceptos'], pakings)
if self._pagos:
self._cfdipays(data['pays'])
@ -2105,7 +2124,7 @@ def get_data_from_xml(invoice, values):
data['pagos'] = values.get('pagos', False)
if data['pagos']:
data['pays'] = _cfdipays(doc, data, version)
data['pakings'] = values.get('pakings', [])
return data

View File

@ -18,12 +18,10 @@
import base64
import math
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
def round_up(value):
@ -31,19 +29,18 @@ def round_up(value):
def _get_key(password):
salt = os.urandom(16)
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt,
iterations=100000, backend=default_backend())
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(password.encode())
key = base64.urlsafe_b64encode(digest.finalize())
return key
def encrypt(data, password)
def encrypt(data, password):
f = Fernet(_get_key(password))
return f.encrypt(data.encode()).decode()
def decrypt(data, password)
def decrypt(data, password):
f = Fernet(_get_key(password))
return f.decrypt(data.encode()).decode()

View File

@ -351,6 +351,17 @@ class Configuracion(BaseModel):
msg = 'No se pudo guardar la configuración'
return {'ok': result, 'msg': msg}
def _save_mail(self, values):
rfc = Emisor.select()[0].rfc
values['correo_contra'] = utils.encrypt(values['correo_contra'], rfc)
for k, v in values.items():
obj, created = Configuracion.get_or_create(clave=k)
obj.valor = v
obj.save()
return {'ok': True}
@classmethod
def get_bool(cls, key):
data = (Configuracion
@ -438,6 +449,17 @@ class Configuracion(BaseModel):
values = {r.clave: util.get_bool(r.valor) for r in data}
return values
def _get_correo(self):
fields = ('correo_servidor', 'correo_puerto', 'correo_ssl',
'correo_usuario', 'correo_copia', 'correo_asunto',
'correo_mensaje', 'correo_directo', 'correo_confirmacion')
data = (Configuracion
.select()
.where(Configuracion.clave.in_(fields))
)
values = {r.clave: r.valor for r in data}
return values
@classmethod
def get_(cls, keys):
if isinstance(keys, str):
@ -450,9 +472,12 @@ class Configuracion(BaseModel):
return ''
options = ('partners',
'admin_products', 'main_products',
'admin_products',
'main_products',
'complements',
'folios')
'folios',
'correo',
)
opt = keys['fields']
if opt in options:
return getattr(cls, '_get_{}'.format(opt))(cls)
@ -513,16 +538,7 @@ class Configuracion(BaseModel):
values[f] = Configuracion.get_(f)
return values
if keys['fields'] == 'correo':
fields = ('correo_servidor', 'correo_puerto', 'correo_ssl',
'correo_usuario', 'correo_contra', 'correo_copia',
'correo_asunto', 'correo_mensaje', 'correo_directo',
'correo_confirmacion')
data = (Configuracion
.select()
.where(Configuracion.clave.in_(fields))
)
elif keys['fields'] == 'path_cer':
if keys['fields'] == 'path_cer':
fields = ('path_key', 'path_cer')
data = (Configuracion
.select()
@ -3720,6 +3736,8 @@ class Facturas(BaseModel):
return {'ok': True, 'msg': 'Notas guardadas correctamente'}
def _get_not_in_xml(self, invoice, emisor):
pdf_from = Configuracion.get_('make_pdf_from') or '1'
values = {}
values['notas'] = invoice.notas
@ -3757,6 +3775,16 @@ class Facturas(BaseModel):
for k, v in receptor.items():
values['receptor'][k] = v
use_packing = Configuracion.get_bool('chk_use_packing')
if use_packing:
w = FacturasDetalle.factura == invoice
q = (FacturasDetalle
.select(FacturasDetalle.empaques)
.where(w)
.order_by(FacturasDetalle.id.asc())
.tuples())
values['pakings'] = [str(int(r[0])) for r in q]
return values
@classmethod
@ -4005,6 +4033,7 @@ class Facturas(BaseModel):
@classmethod
def send(cls, id, rfc):
values = Configuracion.get_({'fields': 'correo'})
contra = Configuracion.get_('correo_contra')
in_zip = Configuracion.get_bool('chk_config_send_zip')
if not values:
@ -4031,7 +4060,7 @@ class Facturas(BaseModel):
'puerto': values['correo_puerto'],
'ssl': bool(int(values['correo_ssl'])),
'usuario': values['correo_usuario'],
'contra': values['correo_contra'],
'contra': utils.decrypt(contra, rfc),
}
options = {
'para': obj.cliente.correo_facturas,
@ -8888,6 +8917,8 @@ def _migrate_tables(rfc=''):
with database_proxy.atomic() as txn:
migrate(*migrations)
Configuracion.add({'version': VERSION})
log.info('Tablas migradas correctamente...')
_importar_valores('', rfc)

View File

@ -817,6 +817,7 @@ function cmd_probar_correo_click(){
function save_config_mail(values){
values['opt'] = 'save_mail'
webix.ajax().sync().post('/config', values, {
error: function(text, data, xhr) {
msg = 'Error al guardar la configuración'