Mostrar cantidad de empaques en PDF
This commit is contained in:
parent
5cdbb0aaa7
commit
f761ab7a5a
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -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]
|
||||
|
|
|
@ -13,3 +13,4 @@ pyqrcode
|
|||
pypng
|
||||
reportlab
|
||||
psycopg2-binary
|
||||
cryptography
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in New Issue