feat(config): agrega personalización de ticket con logo y opciones
- Nuevos endpoints /pos/api/config/receipt (GET/PUT) - Sección en config.html para subir logo, datos del negocio y toggles visuales - pos.js carga la config y renderiza el ticket usando logo, RFC, dirección, teléfono, mensajes y opciones de desglose/empleado/pago configurables - Logo se redimensiona a 300px de ancho y se guarda como base64 JPEG en tenant_config Tests: 35 passed
This commit is contained in:
@@ -752,3 +752,99 @@ def set_onboarding_status():
|
||||
cur.close()
|
||||
conn.close()
|
||||
return jsonify({'completed': completed == 'true'})
|
||||
|
||||
|
||||
# ─── Receipt / Ticket Customization ────────────────────────────────────────
|
||||
|
||||
RECEIPT_CONFIG_KEYS = [
|
||||
'receipt_logo',
|
||||
'receipt_store_name',
|
||||
'receipt_tagline',
|
||||
'receipt_rfc',
|
||||
'receipt_address',
|
||||
'receipt_phone',
|
||||
'receipt_footer',
|
||||
'receipt_thanks_message',
|
||||
'receipt_show_logo',
|
||||
'receipt_show_rfc',
|
||||
'receipt_show_address',
|
||||
'receipt_show_phone',
|
||||
'receipt_show_iva_breakdown',
|
||||
'receipt_show_payment_details',
|
||||
'receipt_show_employee',
|
||||
]
|
||||
|
||||
|
||||
@config_bp.route('/receipt', methods=['GET'])
|
||||
@require_auth('pos.view')
|
||||
def get_receipt_config():
|
||||
"""Get receipt customization settings."""
|
||||
conn = get_tenant_conn(g.tenant_id)
|
||||
cur = conn.cursor()
|
||||
cur.execute(
|
||||
"SELECT key, value FROM tenant_config WHERE key = ANY(%s)",
|
||||
(RECEIPT_CONFIG_KEYS,)
|
||||
)
|
||||
rows = {row[0]: row[1] for row in cur.fetchall()}
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
def _bool(key, default=False):
|
||||
v = rows.get(key, 'true' if default else 'false')
|
||||
return str(v).lower() == 'true'
|
||||
|
||||
return jsonify({
|
||||
'logo': rows.get('receipt_logo', ''),
|
||||
'store_name': rows.get('receipt_store_name', ''),
|
||||
'tagline': rows.get('receipt_tagline', ''),
|
||||
'rfc': rows.get('receipt_rfc', ''),
|
||||
'address': rows.get('receipt_address', ''),
|
||||
'phone': rows.get('receipt_phone', ''),
|
||||
'footer': rows.get('receipt_footer', ''),
|
||||
'thanks_message': rows.get('receipt_thanks_message', 'Gracias por su compra!'),
|
||||
'show_logo': _bool('receipt_show_logo', True),
|
||||
'show_rfc': _bool('receipt_show_rfc', True),
|
||||
'show_address': _bool('receipt_show_address', False),
|
||||
'show_phone': _bool('receipt_show_phone', False),
|
||||
'show_iva_breakdown': _bool('receipt_show_iva_breakdown', True),
|
||||
'show_payment_details': _bool('receipt_show_payment_details', True),
|
||||
'show_employee': _bool('receipt_show_employee', False),
|
||||
})
|
||||
|
||||
|
||||
@config_bp.route('/receipt', methods=['PUT'])
|
||||
@require_auth('config.edit')
|
||||
def update_receipt_config():
|
||||
"""Update receipt customization settings."""
|
||||
data = request.get_json() or {}
|
||||
conn = get_tenant_conn(g.tenant_id)
|
||||
cur = conn.cursor()
|
||||
|
||||
settings = {
|
||||
'receipt_logo': data.get('logo', ''),
|
||||
'receipt_store_name': data.get('store_name', ''),
|
||||
'receipt_tagline': data.get('tagline', ''),
|
||||
'receipt_rfc': data.get('rfc', ''),
|
||||
'receipt_address': data.get('address', ''),
|
||||
'receipt_phone': data.get('phone', ''),
|
||||
'receipt_footer': data.get('footer', ''),
|
||||
'receipt_thanks_message': data.get('thanks_message', 'Gracias por su compra!'),
|
||||
'receipt_show_logo': 'true' if data.get('show_logo') else 'false',
|
||||
'receipt_show_rfc': 'true' if data.get('show_rfc') else 'false',
|
||||
'receipt_show_address': 'true' if data.get('show_address') else 'false',
|
||||
'receipt_show_phone': 'true' if data.get('show_phone') else 'false',
|
||||
'receipt_show_iva_breakdown': 'true' if data.get('show_iva_breakdown') else 'false',
|
||||
'receipt_show_payment_details': 'true' if data.get('show_payment_details') else 'false',
|
||||
'receipt_show_employee': 'true' if data.get('show_employee') else 'false',
|
||||
}
|
||||
|
||||
for key, value in settings.items():
|
||||
cur.execute("""
|
||||
INSERT INTO tenant_config (key, value) VALUES (%s, %s)
|
||||
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value
|
||||
""", (key, value))
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
return jsonify({'message': 'Receipt configuration updated'})
|
||||
|
||||
Reference in New Issue
Block a user