fix(auth): redirige a taller y limpia SW para usuarios workshop/mechanic
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled

- Agrega script inline en todas las plantillas (excepto login/workshop) que lee
  el rol del JWT y redirige a /pos/workshop si es workshop/mechanic.
- Desregistra el Service Worker antes de redirigir para forzar carga fresca
  de assets y evitar que menus antiguos permanezcan por cache.
- Actualiza labels de rol en auth_bp.py para taller y mecanico.

Tests: 35 passed
This commit is contained in:
2026-06-30 16:46:30 +00:00
parent 4d971dd1a4
commit 688ea8c70c
18 changed files with 205 additions and 1 deletions

View File

@@ -197,7 +197,7 @@ def list_login_employees(tenant_id=None):
name = row[1] name = row[1]
parts = name.split() parts = name.split()
initials = ''.join([p[0].upper() for p in parts[:2]]) if parts else '?' initials = ''.join([p[0].upper() for p in parts[:2]]) if parts else '?'
role_labels = {'owner': 'Dueño', 'admin': 'Administrador', 'cashier': 'Cajero', 'warehouse': 'Almacén', 'accountant': 'Contador'} role_labels = {'owner': 'Dueño', 'admin': 'Administrador', 'cashier': 'Cajero', 'warehouse': 'Almacén', 'accountant': 'Contador', 'workshop': 'Taller', 'mechanic': 'Mecánico'}
employees.append({ employees.append({
'id': row[0], 'id': row[0],
'name': name, 'name': name,

View File

@@ -16,6 +16,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/accounting.css?v=33"> <link rel="stylesheet" href="/pos/static/css/accounting.css?v=33">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -18,6 +18,18 @@
<script src="/pos/static/js/native-bridge.js" defer></script> <script src="/pos/static/js/native-bridge.js" defer></script>
<link rel="stylesheet" href="/pos/static/css/catalog.css"> <link rel="stylesheet" href="/pos/static/css/catalog.css">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -16,6 +16,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/config.css?v=33"> <link rel="stylesheet" href="/pos/static/css/config.css?v=33">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -16,6 +16,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/customers.css"> <link rel="stylesheet" href="/pos/static/css/customers.css">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -16,6 +16,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/dashboard.css?v=33"> <link rel="stylesheet" href="/pos/static/css/dashboard.css?v=33">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -18,6 +18,18 @@
<script src="/pos/static/js/native-bridge.js" defer></script> <script src="/pos/static/js/native-bridge.js" defer></script>
<link rel="stylesheet" href="/pos/static/css/diagrams.css"> <link rel="stylesheet" href="/pos/static/css/diagrams.css">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>
<div class="app-shell"> <div class="app-shell">

View File

@@ -16,6 +16,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/fleet.css"> <link rel="stylesheet" href="/pos/static/css/fleet.css">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -35,6 +35,18 @@
.pagination span { font-size: 13px; color: #4b5563; } .pagination span { font-size: 13px; color: #4b5563; }
.loading { text-align: center; padding: 40px; color: #6b7280; } .loading { text-align: center; padding: 40px; color: #6b7280; }
</style> </style>
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>
<div class="header"> <div class="header">

View File

@@ -16,6 +16,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/inventory.css?v=33"> <link rel="stylesheet" href="/pos/static/css/inventory.css?v=33">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -16,6 +16,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/invoicing.css"> <link rel="stylesheet" href="/pos/static/css/invoicing.css">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -16,6 +16,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/marketplace.css"> <link rel="stylesheet" href="/pos/static/css/marketplace.css">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -29,6 +29,18 @@
.meli-config-row label { display:block;font-size:var(--text-caption);color:var(--color-text-muted);margin-bottom:4px; } .meli-config-row label { display:block;font-size:var(--text-caption);color:var(--color-text-muted);margin-bottom:4px; }
.meli-config-row input, .meli-config-row select { padding:8px 12px;border:1px solid var(--color-border);border-radius:var(--radius-sm);background:var(--color-surface-0);color:var(--color-text-primary); } .meli-config-row input, .meli-config-row select { padding:8px 12px;border:1px solid var(--color-border);border-radius:var(--radius-sm);background:var(--color-surface-0);color:var(--color-text-primary); }
</style> </style>
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -17,6 +17,18 @@
<script src="/pos/static/js/native-bridge.js" defer></script> <script src="/pos/static/js/native-bridge.js" defer></script>
<link rel="stylesheet" href="/pos/static/css/pos.css?v=33"> <link rel="stylesheet" href="/pos/static/css/pos.css?v=33">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body class="pos-shell" id="appBody"> <body class="pos-shell" id="appBody">

View File

@@ -12,6 +12,18 @@
<link rel="stylesheet" href="/pos/static/css/sidebar.css" /> <link rel="stylesheet" href="/pos/static/css/sidebar.css" />
<link rel="stylesheet" href="/pos/static/css/pos-glass.css" /> <link rel="stylesheet" href="/pos/static/css/pos-glass.css" />
<link rel="stylesheet" href="/pos/static/css/quotations.css"> <link rel="stylesheet" href="/pos/static/css/quotations.css">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>
<script src="/pos/static/js/pos-utils.js?v=33" defer></script> <script src="/pos/static/js/pos-utils.js?v=33" defer></script>

View File

@@ -16,6 +16,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/reports.css"> <link rel="stylesheet" href="/pos/static/css/reports.css">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -50,6 +50,18 @@
.sc-interchange-chip { background:var(--color-surface-2); border:1px solid var(--color-border); border-radius:var(--radius-full); padding:2px 10px; font-size:var(--text-caption); } .sc-interchange-chip { background:var(--color-surface-2); border:1px solid var(--color-border); border-radius:var(--radius-full); padding:2px 10px; font-size:var(--text-caption); }
.sc-close { background:none; border:none; font-size:20px; color:var(--color-text-muted); cursor:pointer; } .sc-close { background:none; border:none; font-size:20px; color:var(--color-text-muted); cursor:pointer; }
</style> </style>
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>

View File

@@ -19,6 +19,18 @@
<link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" /> <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />
<link rel="stylesheet" href="/pos/static/css/whatsapp.css"> <link rel="stylesheet" href="/pos/static/css/whatsapp.css">
<script id="workshop-mechanic-redirect">
(function(){
var t=localStorage.getItem("pos_token");
if(!t)return;
try{var p=JSON.parse(atob(t.split(".")[1]));var r=(p.role||"").toLowerCase();
if((r==="workshop"||r==="mechanic")&&window.location.pathname!=="/pos/workshop"){
if("serviceWorker" in navigator){navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(reg){reg.unregister();});});}
window.location.replace("/pos/workshop");
}
}catch(e){}
})();
</script>
</head> </head>
<body> <body>