fixx 01
This commit is contained in:
@@ -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
|
||||
`);
|
||||
|
||||
@@ -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 {
|
||||
</div>
|
||||
<button id="bulkDeleteAssetsBtn" class="border border-red-200 text-red-600 px-3 py-1.5 rounded-md text-[11px] font-bold flex items-center gap-1.5 transition-colors ${(selectedCount === 0 || !canManageAssets) ? 'opacity-50 cursor-not-allowed' : 'hover:bg-red-50'}" ${(selectedCount === 0 || !canManageAssets) ? 'disabled' : ''}>
|
||||
<span class="material-symbols-outlined text-base">delete_sweep</span>
|
||||
Xóa dã chọn (<span id="selectedAssetCount">${selectedCount}</span>)
|
||||
Xóa đã chọn (<span id="selectedAssetCount">${selectedCount}</span>)
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -571,6 +571,26 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bulk Delete Assets Confirm Modal -->
|
||||
<div class="modal-backdrop fixed inset-0 z-[110] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="bulkDeleteAssetsConfirmModal" style="z-index: 130;">
|
||||
<div class="modal-content w-full max-w-md bg-white rounded-xl shadow-2xl border border-slate-200 overflow-hidden m-4">
|
||||
<div class="px-6 py-4 border-b border-slate-100 bg-red-50 flex items-center gap-3">
|
||||
<span class="material-symbols-outlined text-red-600 text-2xl">warning</span>
|
||||
<h3 class="text-base font-extrabold text-red-700">Xóa tài sản đã chọn</h3>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<p id="bulkDeleteAssetsConfirmMessage" class="text-sm text-slate-600 mb-6">Bạn có chắc muốn xóa các tài sản đã chọn?</p>
|
||||
<div class="mb-4 rounded-lg border border-red-100 bg-red-50 px-3 py-2 text-xs text-red-700">
|
||||
Số lượng: <strong id="bulkDeleteAssetsConfirmCount">0</strong> tài sản
|
||||
</div>
|
||||
<div class="flex gap-3">
|
||||
<button type="button" class="cancel-bulk-asset-delete-confirm flex-1 px-4 py-2 text-xs font-bold text-slate-600 border border-slate-200 rounded-lg" onclick="closeBulkDeleteAssetsConfirmModal()">Hủy</button>
|
||||
<button type="button" id="confirmBulkAssetDeleteBtn" class="flex-1 px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg text-xs font-bold">Xóa</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add/Edit Asset Department Modal -->
|
||||
<div class="modal-backdrop fixed inset-0 z-[100] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="assetDepartmentModal">
|
||||
<div class="modal-content w-full max-w-md bg-white rounded-xl shadow-2xl border border-slate-200 overflow-hidden m-4">
|
||||
|
||||
Reference in New Issue
Block a user