From 7e3205b03ab4937a7b21600c6c5620dcdf959e2e Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Tue, 30 Jun 2026 17:57:29 +0000 Subject: [PATCH] feat(config): allow admin/owner to delete branches - Added DELETE /pos/api/config/branches/ that soft-deletes the branch (is_active=false). - Restricted to owner/admin; main branch cannot be deleted. - Added 'Eliminar' button in the branches grid for admin/owner. --- pos/blueprints/config_bp.py | 27 +++++++++++++++++++++++++++ pos/static/js/config.js | 21 +++++++++++++++++++++ pos/templates/config.html | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/pos/blueprints/config_bp.py b/pos/blueprints/config_bp.py index 2e353f3..c7b8abc 100644 --- a/pos/blueprints/config_bp.py +++ b/pos/blueprints/config_bp.py @@ -150,6 +150,33 @@ def update_branch(branch_id): return jsonify({'ok': True, 'message': 'Branch updated'}) +@config_bp.route('/branches/', methods=['DELETE']) +@require_auth('config.edit') +def delete_branch(branch_id): + """Soft-delete a branch. Only owner/admin can delete; main branch cannot be deleted.""" + if g.employee_role not in ('owner', 'admin'): + return jsonify({'error': 'Solo administradores pueden eliminar sucursales'}), 403 + + conn = get_tenant_conn(g.tenant_id) + cur = conn.cursor() + + cur.execute("SELECT is_main FROM branches WHERE id = %s", (branch_id,)) + row = cur.fetchone() + if not row: + cur.close(); conn.close() + return jsonify({'error': 'Branch not found'}), 404 + + if row[0]: + cur.close(); conn.close() + return jsonify({'error': 'No se puede eliminar la sucursal principal'}), 403 + + cur.execute("UPDATE branches SET is_active = false WHERE id = %s", (branch_id,)) + conn.commit() + cur.close() + conn.close() + return jsonify({'ok': True, 'message': 'Sucursal eliminada'}) + + @config_bp.route('/employees', methods=['GET']) @require_auth() def list_employees(): diff --git a/pos/static/js/config.js b/pos/static/js/config.js index 8f597cf..5fcb571 100644 --- a/pos/static/js/config.js +++ b/pos/static/js/config.js @@ -4,6 +4,9 @@ const Config = (() => { const API = '/pos/api/config'; + const user = window.POS_USER || {}; + const canDeleteBranch = (user.role === 'owner' || user.role === 'admin'); + // Cache for branches (used by employee modal selector) let _branches = []; @@ -183,6 +186,7 @@ const Config = (() => { + '' + '
' + '' + + (canDeleteBranch && b.is_active && !b.is_main ? '' : '') + '
'; }); @@ -238,6 +242,22 @@ const Config = (() => { openBranchModal(b); } + async function deleteBranch(branchId) { + var b = _branches.find(function(x) { return x.id === branchId; }); + if (!b) { toast('Sucursal no encontrada', 'error'); return; } + if (b.is_main) { toast('No se puede eliminar la sucursal principal', 'error'); return; } + if (!confirm('¿Eliminar la sucursal "' + b.name + '"? Se marcará como inactiva.')) return; + try { + var res = await fetch(API + '/branches/' + branchId, { method: 'DELETE', headers: headers() }); + var json = await res.json().catch(function() { return {}; }); + if (!res.ok) throw new Error(json.error || res.statusText); + toast('Sucursal eliminada'); + loadBranches(); + } catch (e) { + toast(e.message || 'Error al eliminar sucursal', 'error'); + } + } + async function saveBranch(data) { var branchId = document.getElementById('branch-id').value; var url = API + '/branches' + (branchId ? '/' + branchId : ''); @@ -1047,6 +1067,7 @@ const Config = (() => { return { init, setTheme, selectThemeOption, loadAllowedBrands, saveAllowedBrands, loadBranches, loadEmployees, saveBranch, saveEmployee, editEmployee, deleteEmployee, + deleteBranch, loadBusiness, saveBusiness, saveTaxParams, saveAll, loadCurrency, saveCurrency, loadVehicleCompatSource, saveVehicleCompatSource, diff --git a/pos/templates/config.html b/pos/templates/config.html index 50e03bb..98aca52 100644 --- a/pos/templates/config.html +++ b/pos/templates/config.html @@ -928,7 +928,7 @@ - +