From 395b1f6e8542bb5a7ee09d58935bdf1749402119 Mon Sep 17 00:00:00 2001 From: DungTT Date: Wed, 6 May 2026 16:56:58 +0700 Subject: [PATCH] fixx 01 --- backend/server.js | 10 ++++++- public/js/app.js | 74 ++++++++++++++++++++++++++++++++++++++++++++-- public/modals.html | 20 +++++++++++++ 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/backend/server.js b/backend/server.js index 43d4afd..87dda81 100644 --- a/backend/server.js +++ b/backend/server.js @@ -4254,7 +4254,8 @@ app.post('/api/assets/:id/export', requireAssetOrAdmin, async (req, res) => { NewQuantity, UsedQuantity, Custodian, - Borrower + Borrower, + Notes FROM AssetInventory WITH (UPDLOCK, ROWLOCK) WHERE AssetId = @assetId `); @@ -4311,6 +4312,11 @@ app.post('/api/assets/:id/export', requireAssetOrAdmin, async (req, res) => { const nextNewQuantity = Math.max(stockBuckets.newQuantity - borrowFromNew, 0); const nextUsedQuantity = Math.max(stockBuckets.usedQuantity - borrowFromUsed, 0); const nextStatus = resolveAssetStatusFromStock(nextEndingBalance, nextExportInPeriod); + const existingAssetNotes = String(asset.Notes || '').trim(); + const cleanExportNote = String(exportNote || '').trim(); + const nextAssetNotes = cleanExportNote + ? (existingAssetNotes ? `${existingAssetNotes}\n${cleanExportNote}` : cleanExportNote) + : (existingAssetNotes || null); await new sql.Request(transaction) .input('assetId', sql.Int, assetId) @@ -4322,6 +4328,7 @@ app.post('/api/assets/:id/export', requireAssetOrAdmin, async (req, res) => { .input('usedQuantity', sql.Int, nextUsedQuantity) .input('status', sql.NVarChar, nextStatus) .input('exportedBy', sql.NVarChar, exportedByName) + .input('notes', sql.NVarChar, nextAssetNotes) .query(` UPDATE AssetInventory SET Project = @project, @@ -4332,6 +4339,7 @@ app.post('/api/assets/:id/export', requireAssetOrAdmin, async (req, res) => { UsedQuantity = @usedQuantity, Status = @status, ExportedBy = @exportedBy, + Notes = @notes, UpdatedDate = GETDATE() WHERE AssetId = @assetId `); diff --git a/public/js/app.js b/public/js/app.js index 33a0a90..dba7a07 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -66,6 +66,7 @@ class AccountManager { this.pendingAssetRequestRejectId = undefined; this.assetBorrowAutoRefreshTimer = undefined; this.pendingAssetRequestDeleteConfirmResolver = undefined; + this.pendingBulkAssetDeleteConfirmResolver = undefined; } configureNotifications() { @@ -1228,6 +1229,21 @@ class AccountManager { btn.dataset.boundClick = 'true'; }); + const confirmBulkAssetDeleteBtn = document.getElementById('confirmBulkAssetDeleteBtn'); + if (confirmBulkAssetDeleteBtn && confirmBulkAssetDeleteBtn.dataset.boundClick !== 'true') { + confirmBulkAssetDeleteBtn.addEventListener('click', () => this.resolveBulkAssetDeleteConfirm(true)); + confirmBulkAssetDeleteBtn.dataset.boundClick = 'true'; + } + + document.querySelectorAll('.cancel-bulk-asset-delete-confirm').forEach(btn => { + if (btn.dataset.boundClick === 'true') { + return; + } + + btn.addEventListener('click', () => this.resolveBulkAssetDeleteConfirm(false)); + btn.dataset.boundClick = 'true'; + }); + this.setupAssetBorrowRequestModalListeners(); const assetDepartmentForm = document.getElementById('assetDepartmentForm'); @@ -3358,6 +3374,42 @@ class AccountManager { } } + resolveBulkAssetDeleteConfirm(confirmed) { + const modal = document.getElementById('bulkDeleteAssetsConfirmModal'); + if (modal) { + modal.classList.remove('open'); + } + + const resolver = this.pendingBulkAssetDeleteConfirmResolver; + this.pendingBulkAssetDeleteConfirmResolver = undefined; + if (typeof resolver === 'function') { + resolver(Boolean(confirmed)); + } + } + + async confirmBulkAssetDelete(selectedCount) { + const modal = document.getElementById('bulkDeleteAssetsConfirmModal'); + const messageNode = document.getElementById('bulkDeleteAssetsConfirmMessage'); + const countNode = document.getElementById('bulkDeleteAssetsConfirmCount'); + + if (!modal || !messageNode || !countNode) { + return window.confirm(`Bạn có chắc muốn xóa ${selectedCount} tài sản đã chọn?`); + } + + countNode.textContent = String(selectedCount); + messageNode.textContent = `Bạn có chắc muốn xóa ${selectedCount} tài sản đã chọn?`; + + if (this.pendingBulkAssetDeleteConfirmResolver) { + this.resolveBulkAssetDeleteConfirm(false); + } + + modal.classList.add('open'); + + return new Promise(resolve => { + this.pendingBulkAssetDeleteConfirmResolver = resolve; + }); + } + async confirmAssetRequestDelete(message, confirmButtonText = 'Xóa đơn') { const modal = document.getElementById('assetRequestDeleteConfirmModal'); const messageNode = document.getElementById('assetRequestDeleteConfirmMessage'); @@ -3580,7 +3632,7 @@ class AccountManager { @@ -3897,7 +3949,7 @@ class AccountManager { return; } - const confirmed = window.confirm(`Bạn có chắc mudn xóa ${selectedIds.length} tài sản dã chọn?`); + const confirmed = await this.confirmBulkAssetDelete(selectedIds.length); if (!confirmed) { return; } @@ -6148,6 +6200,9 @@ class AccountManager { if (this.pendingAssetRequestDeleteConfirmResolver) { this.resolveAssetRequestDeleteConfirm(false); } + if (this.pendingBulkAssetDeleteConfirmResolver) { + this.resolveBulkAssetDeleteConfirm(false); + } document.querySelectorAll('.modal-backdrop').forEach(modal => { modal.classList.remove('open'); }); @@ -7058,6 +7113,9 @@ function closeAllModals() { if (app?.pendingAssetRequestDeleteConfirmResolver) { app.resolveAssetRequestDeleteConfirm(false); } + if (app?.pendingBulkAssetDeleteConfirmResolver) { + app.resolveBulkAssetDeleteConfirm(false); + } document.querySelectorAll('.modal-backdrop').forEach(modal => { modal.classList.remove('open'); }); @@ -7099,6 +7157,18 @@ function closeDeleteAssetModal() { document.getElementById('deleteAssetModal').classList.remove('open'); } +function closeBulkDeleteAssetsConfirmModal() { + if (app?.pendingBulkAssetDeleteConfirmResolver) { + app.resolveBulkAssetDeleteConfirm(false); + return; + } + + const modal = document.getElementById('bulkDeleteAssetsConfirmModal'); + if (modal) { + modal.classList.remove('open'); + } +} + function closeBorrowAssetModal() { const modal = document.getElementById('borrowAssetModal'); if (modal) { diff --git a/public/modals.html b/public/modals.html index 4bae62f..e7109e9 100644 --- a/public/modals.html +++ b/public/modals.html @@ -571,6 +571,26 @@ + + +