fix(workshop): restrict workshop/mechanic views to only 'autorizada' status
This commit is contained in:
@@ -48,6 +48,9 @@ _MECHANIC_HIDDEN_STATUSES = {
|
|||||||
'por_facturar', 'facturada'
|
'por_facturar', 'facturada'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Statuses visible to workshop/mechanic accounts (taller only works on authorized orders).
|
||||||
|
_TALLER_ALLOWED_STATUSES = {'autorizada'}
|
||||||
|
|
||||||
|
|
||||||
def _can_view_workshop():
|
def _can_view_workshop():
|
||||||
return g.employee_role in _WORKSHOP_VIEW_ROLES or 'workshop.view' in g.permissions
|
return g.employee_role in _WORKSHOP_VIEW_ROLES or 'workshop.view' in g.permissions
|
||||||
@@ -143,11 +146,10 @@ def list_orders():
|
|||||||
)
|
)
|
||||||
if _is_restricted_workshop_viewer():
|
if _is_restricted_workshop_viewer():
|
||||||
result['data'] = [_redact_order_for_mechanic(o) for o in result.get('data', [])]
|
result['data'] = [_redact_order_for_mechanic(o) for o in result.get('data', [])]
|
||||||
# Shared mechanic account can see all orders except commercial/closed statuses.
|
# Workshop/mechanic accounts only see orders ready to be worked on.
|
||||||
if g.employee_role == 'mechanic':
|
|
||||||
result['data'] = [
|
result['data'] = [
|
||||||
o for o in result.get('data', [])
|
o for o in result.get('data', [])
|
||||||
if o.get('status') not in _MECHANIC_HIDDEN_STATUSES
|
if o.get('status') in _TALLER_ALLOWED_STATUSES
|
||||||
]
|
]
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
finally:
|
finally:
|
||||||
@@ -237,8 +239,8 @@ def get_order(so_id):
|
|||||||
order = get_service_order(conn, so_id)
|
order = get_service_order(conn, so_id)
|
||||||
if not order:
|
if not order:
|
||||||
return jsonify({'error': 'Service order not found'}), 404
|
return jsonify({'error': 'Service order not found'}), 404
|
||||||
# Shared mechanic account cannot view commercial/closed statuses.
|
# Workshop/mechanic accounts can only view orders that are ready to be worked on.
|
||||||
if g.employee_role == 'mechanic' and order.get('status') in _MECHANIC_HIDDEN_STATUSES:
|
if _is_restricted_workshop_viewer() and order.get('status') not in _TALLER_ALLOWED_STATUSES:
|
||||||
return jsonify({'error': 'No tienes acceso a esta orden'}), 403
|
return jsonify({'error': 'No tienes acceso a esta orden'}), 403
|
||||||
return jsonify(_redact_order_for_mechanic(order))
|
return jsonify(_redact_order_for_mechanic(order))
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
@@ -196,6 +196,14 @@ var Workshop = (function() {
|
|||||||
document.querySelectorAll('.restricted-hide').forEach(function(el) { el.style.display = 'none'; });
|
document.querySelectorAll('.restricted-hide').forEach(function(el) { el.style.display = 'none'; });
|
||||||
var searchInput = document.getElementById('filterSearch');
|
var searchInput = document.getElementById('filterSearch');
|
||||||
if (searchInput) searchInput.placeholder = 'Buscar orden';
|
if (searchInput) searchInput.placeholder = 'Buscar orden';
|
||||||
|
// Limit status filter to the only status taller accounts can see.
|
||||||
|
var statusSel = document.getElementById('filterStatus');
|
||||||
|
if (statusSel) {
|
||||||
|
Array.from(statusSel.options).forEach(function(opt) {
|
||||||
|
if (opt.value && opt.value !== 'autorizada') opt.remove();
|
||||||
|
});
|
||||||
|
statusSel.value = 'autorizada';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hidePrices) {
|
if (hidePrices) {
|
||||||
var btnCatalog = document.getElementById('btnCatalog');
|
var btnCatalog = document.getElementById('btnCatalog');
|
||||||
@@ -251,6 +259,22 @@ var Workshop = (function() {
|
|||||||
fetch(API + '/kanban/summary', {headers: headers()})
|
fetch(API + '/kanban/summary', {headers: headers()})
|
||||||
.then(function(r) { return r.json(); })
|
.then(function(r) { return r.json(); })
|
||||||
.then(function(d) {
|
.then(function(d) {
|
||||||
|
var cards = document.querySelectorAll('#statsRow .summary-card');
|
||||||
|
if (isRestricted) {
|
||||||
|
// Taller accounts only see authorized orders.
|
||||||
|
cards.forEach(function(card, idx) {
|
||||||
|
if (idx === 0) {
|
||||||
|
card.style.display = '';
|
||||||
|
var label = card.querySelector('.summary-card__label');
|
||||||
|
if (label) label.textContent = 'Autorizadas';
|
||||||
|
} else {
|
||||||
|
card.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.getElementById('statReceived').textContent = fmt(d.autorizada || 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cards.forEach(function(card) { card.style.display = ''; });
|
||||||
document.getElementById('statReceived').textContent = fmt(d.por_revisar || 0);
|
document.getElementById('statReceived').textContent = fmt(d.por_revisar || 0);
|
||||||
document.getElementById('statRepair').textContent = fmt((d.en_reparacion || 0) + (d.en_revision || 0) + (d.revisada || 0) + (d.cotizada || 0) + (d.por_autorizar || 0));
|
document.getElementById('statRepair').textContent = fmt((d.en_reparacion || 0) + (d.en_revision || 0) + (d.revisada || 0) + (d.cotizada || 0) + (d.por_autorizar || 0));
|
||||||
document.getElementById('statReady').textContent = fmt(d.por_entregar || 0);
|
document.getElementById('statReady').textContent = fmt(d.por_entregar || 0);
|
||||||
@@ -379,7 +403,13 @@ var Workshop = (function() {
|
|||||||
function renderKanban() {
|
function renderKanban() {
|
||||||
var board = document.getElementById('kanbanBoard');
|
var board = document.getElementById('kanbanBoard');
|
||||||
board.innerHTML = '';
|
board.innerHTML = '';
|
||||||
var hiddenCols = isMechanic ? ['cotizada','por_autorizar','autorizada','autorizacion_parcial','por_facturar','facturada'] : [];
|
var hiddenCols = [];
|
||||||
|
if (isRestricted) {
|
||||||
|
// Taller accounts only see the "autorizada" column.
|
||||||
|
hiddenCols = COLUMNS.filter(function(c) { return c.key !== 'autorizada'; }).map(function(c) { return c.key; });
|
||||||
|
} else if (isMechanic) {
|
||||||
|
hiddenCols = ['cotizada','por_autorizar','autorizada','autorizacion_parcial','por_facturar','facturada'];
|
||||||
|
}
|
||||||
COLUMNS.filter(function(col) { return hiddenCols.indexOf(col.key) === -1; }).forEach(function(col) {
|
COLUMNS.filter(function(col) { return hiddenCols.indexOf(col.key) === -1; }).forEach(function(col) {
|
||||||
var colOrders = orders.filter(function(o) { return o.status === col.key; });
|
var colOrders = orders.filter(function(o) { return o.status === col.key; });
|
||||||
var colEl = document.createElement('div');
|
var colEl = document.createElement('div');
|
||||||
|
|||||||
@@ -499,7 +499,7 @@
|
|||||||
<script src="/pos/static/js/pos-utils.js?v=33" defer></script>
|
<script src="/pos/static/js/pos-utils.js?v=33" defer></script>
|
||||||
<script src="/pos/static/js/sidebar.js?v=44" defer></script>
|
<script src="/pos/static/js/sidebar.js?v=44" defer></script>
|
||||||
<script src="/pos/static/js/offline-banner.js" defer></script>
|
<script src="/pos/static/js/offline-banner.js" defer></script>
|
||||||
<script src="/pos/static/js/workshop.js?v=55" defer></script>
|
<script src="/pos/static/js/workshop.js?v=56" defer></script>
|
||||||
<script>if('serviceWorker' in navigator){navigator.serviceWorker.register('/pos/sw.js',{scope:'/pos/'});}</script>
|
<script>if('serviceWorker' in navigator){navigator.serviceWorker.register('/pos/sw.js',{scope:'/pos/'});}</script>
|
||||||
<script src="/pos/static/js/pwa-install.js" defer></script>
|
<script src="/pos/static/js/pwa-install.js" defer></script>
|
||||||
<script src="/pos/static/js/chat.js" defer></script>
|
<script src="/pos/static/js/chat.js" defer></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user