feat: cashier/counter reports, service-order & remission flows, Rached migration utils
- Add "Mis cortes de caja" report for cashiers/counters with sales detail. - Cash register history scoped to own cuts for non-admin roles; new /register/<id>/sales endpoint. - Remove dashboard from cashier menu; add Reports to cashier/counter. - Service orders: assign mechanic, budget field, invoice flag, counter/cashier can add items/remissions, convert to remission. - Remission notes module (UI, CSS, courier, counter remissions). - Customer hard-delete and vehicle/customer linkage in workshop. - POS: always show search results, compact payment grid, credit validation, tier pricing (5%/10%), ticket with customer/folio. - Inventory: CSV template with sku_secondary, alias import. - Rached migration scripts and DB migrations. - Version-bump cached JS/CSS query strings. Excludes local Rached session tokens/captures (rached_*.json / rached_*.txt).
This commit is contained in:
@@ -21,6 +21,19 @@
|
||||
var userRole = (user.role || '').toLowerCase();
|
||||
var userPerms = user.permissions || [];
|
||||
var canEditPrices = userRole === 'owner' || userRole === 'admin' || userPerms.indexOf('config.edit_prices') !== -1;
|
||||
var canCreateItem = userRole === 'owner' || userRole === 'admin' || userRole === 'counter' || userRole === 'cashier' || userRole === 'warehouse' || userPerms.indexOf('inventory.create') !== -1;
|
||||
var canEditItem = userRole === 'owner' || userRole === 'admin' || userRole === 'warehouse' || userPerms.indexOf('inventory.edit') !== -1;
|
||||
var canImportItems = userRole === 'owner' || userRole === 'admin' || userRole === 'warehouse' || userPerms.indexOf('inventory.edit') !== -1;
|
||||
|
||||
// Hide toolbar actions the user is not allowed to use
|
||||
(function applyInventoryPermissions() {
|
||||
var headerNew = document.getElementById('btnHeaderNewProduct');
|
||||
var stockNew = document.getElementById('btnStockNewProduct');
|
||||
var headerImport = document.getElementById('btnHeaderImport');
|
||||
if (headerNew) headerNew.style.display = canCreateItem ? '' : 'none';
|
||||
if (stockNew) stockNew.style.display = canCreateItem ? '' : 'none';
|
||||
if (headerImport) headerImport.style.display = canImportItems ? '' : 'none';
|
||||
})();
|
||||
|
||||
// Load compatibility source setting
|
||||
(function loadCompatSource() {
|
||||
@@ -186,11 +199,11 @@
|
||||
'<td>' + esc(it.location) + '</td>' +
|
||||
'<td>' +
|
||||
'<button class="btn btn--ghost btn--sm" onclick="event.stopPropagation();viewHistory(' + it.id + ')">Historial</button> ' +
|
||||
'<button class="btn btn--ghost btn--sm" onclick="event.stopPropagation();showEditItemModal(' + it.id + ')">Editar</button> ' +
|
||||
'<button class="btn btn--ghost btn--sm" style="color:var(--color-accent);" onclick="event.stopPropagation();showPurchaseModalForItem(' + it.id + ')">Entrada</button> ' +
|
||||
'<button class="btn btn--sm btn--meli" onclick="event.stopPropagation();publishToMeli(' + it.id + ')">ML</button> ' +
|
||||
(canEditItem ? '<button class="btn btn--ghost btn--sm" onclick="event.stopPropagation();showEditItemModal(' + it.id + ')">Editar</button> ' : '') +
|
||||
(canCreateItem ? '<button class="btn btn--ghost btn--sm" style="color:var(--color-accent);" onclick="event.stopPropagation();showPurchaseModalForItem(' + it.id + ')">Entrada</button> ' : '') +
|
||||
(userPerms.indexOf('marketplace.manage') !== -1 || userRole === 'owner' || userRole === 'admin' ? '<button class="btn btn--sm btn--meli" onclick="event.stopPropagation();publishToMeli(' + it.id + ')">ML</button> ' : '') +
|
||||
'<button class="btn btn--ghost btn--sm" onclick="event.stopPropagation();printBarcode(\'' + esc(it.barcode) + '\',\'' + esc(it.part_number) + '\',\'' + esc(it.name) + '\')">Etiqueta</button> ' +
|
||||
'<button class="btn btn--ghost btn--sm" style="color:var(--color-error);" onclick="event.stopPropagation();deleteItem(' + it.id + ')">Eliminar</button>' +
|
||||
(canEditItem ? '<button class="btn btn--ghost btn--sm" style="color:var(--color-error);" onclick="event.stopPropagation();deleteItem(' + it.id + ')">Eliminar</button>' : '') +
|
||||
'</td></tr>';
|
||||
}
|
||||
|
||||
@@ -544,6 +557,28 @@
|
||||
}
|
||||
window.submitBulkImport = submitBulkImport;
|
||||
|
||||
function downloadBulkImportTemplate() {
|
||||
var headers = [
|
||||
'numero_de_parte','nombre','marca','precio','cantidad','costo',
|
||||
'sku_secundario','descripcion','categoria','fabricante','modelo','anio','motor','codigo_motor'
|
||||
];
|
||||
var example = [
|
||||
'EJ-001','Filtro de aceite','ACDelco','150.00','10','90.00',
|
||||
'EJ001-ALT','Filtro para sedan','Filtros','Nissan','Sentra','2020','1.8','MR18DE'
|
||||
];
|
||||
var csv = [headers.join(','), example.join(',')].join('\n');
|
||||
var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
||||
var url = URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'plantilla_inventario.csv';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
window.downloadBulkImportTemplate = downloadBulkImportTemplate;
|
||||
|
||||
// =====================================================================
|
||||
// PURCHASE / ENTRADA (purchaseModal)
|
||||
// =====================================================================
|
||||
|
||||
Reference in New Issue
Block a user