diff --git a/server.js b/server.js index 4083009..42796a0 100644 --- a/server.js +++ b/server.js @@ -143,6 +143,9 @@ app.get('/api/assets/master', async (req, res) => { s.hw_status, s.model_name, s.mainboard, s.os, s.cpu, s.ram, s.gpu, s.monitoring, s.price, s.monitor_inch, s.serial_num, l.location, l.location_detail, l.location_photo, l.loc_x, l.loc_y, + ( + SELECT EXISTS(SELECT 1 FROM asset_audit_pending WHERE asset_code = c.asset_code AND status = 'APPROVED') + ) AS is_audit_approved, ( SELECT JSON_ARRAYAGG(JSON_OBJECT('type', net_type, 'name', net_name, 'val1', net_value1, 'val2', net_value2)) FROM asset_remote WHERE asset_id = c.id AND is_active = 1 @@ -786,11 +789,13 @@ app.post('/api/maps/save', async (req, res) => { ); // Insert new active location mapping + const pathPartsForMap = path.split('/'); + const stdDetailForMap = pathPartsForMap[pathPartsForMap.length - 2] || locDetail; await connection.query(` INSERT INTO asset_location (asset_id, location, location_detail, location_photo, loc_x, loc_y, physical_location_code, is_active) VALUES (?, ?, ?, ?, ?, ?, ?, 1) - `, [box.asset_id, locName, locDetail, path, box.x, box.y, locCode]); + `, [box.asset_id, locName, stdDetailForMap, path, box.x, box.y, locCode]); } } @@ -867,6 +872,7 @@ app.get('/api/audit/pending', async (req, res) => { JOIN asset_core c ON c.asset_code = ap.asset_code JOIN physical_locations pl ON pl.location_code = ap.physical_location_code LEFT JOIN asset_location l ON l.asset_id = c.id AND l.is_active = 1 + WHERE ap.status = 'PENDING' ORDER BY ap.scanned_at DESC `); res.json(rows); @@ -923,11 +929,13 @@ app.post('/api/audit/approve', async (req, res) => { ); // 5. Insert new active location + const pathPartsForApprove = loc.map_image.split('/'); + const stdDetailForApprove = pathPartsForApprove[pathPartsForApprove.length - 2] || loc.location_detail; await connection.query(` INSERT INTO asset_location (asset_id, location, location_detail, location_photo, loc_x, loc_y, physical_location_code, is_active) VALUES (?, ?, ?, ?, ?, ?, ?, 1) - `, [assetId, loc.location_name, loc.location_detail, loc.map_image, loc.map_x, loc.map_y, physical_location_code]); + `, [assetId, loc.location_name, stdDetailForApprove, loc.map_image, loc.map_x, loc.map_y, physical_location_code]); // 6. Update pending audit status await connection.query( diff --git a/src/components/Modal/HWModal.ts b/src/components/Modal/HWModal.ts index 906baac..5629f40 100644 --- a/src/components/Modal/HWModal.ts +++ b/src/components/Modal/HWModal.ts @@ -35,6 +35,7 @@ class HwAssetModal extends BaseModal {
+ @@ -666,6 +667,12 @@ class HwAssetModal extends BaseModal { qrBtn.classList.toggle('hidden', mode !== 'view' || !hasCode); } + const approvedBadge = document.getElementById('hw-modal-audit-approved-badge'); + if (approvedBadge) { + const isApproved = asset && asset.is_audit_approved; + approvedBadge.style.display = (mode === 'view' && isApproved) ? 'inline-flex' : 'none'; + } + this.toggleFileUploadUI(mode !== 'view'); this.toggleEditOnlyBtns(mode !== 'view'); this.updateMapButtonVisibility(); diff --git a/src/views/List/ListFactory.ts b/src/views/List/ListFactory.ts index 176007a..c4e8ac2 100644 --- a/src/views/List/ListFactory.ts +++ b/src/views/List/ListFactory.ts @@ -681,7 +681,19 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { const rendered = col.render(asset); const rawText = rendered.replace(/<[^>]*>/g, '').trim(); const titleAttr = rawText && rawText !== '-' ? `title="${rawText.replace(/"/g, '"')}"` : ''; - return `${rendered}`; + + let displayContent = rendered; + if (col.header === ASSET_SCHEMA.LOCATION.ui && asset.is_audit_approved) { + const justify = col.align === 'center' ? 'center' : (col.align === 'right' ? 'flex-end' : 'flex-start'); + displayContent = ` +
+ ${rendered} + 승인완료 +
+ `; + } + + return `${displayContent}`; }).join('')}`).join(''); tbody.querySelectorAll('.asset-row').forEach((tr, idx) => { tr.addEventListener('click', () => config.onRowClick && config.onRowClick(filtered[idx])); }); diff --git a/src/views/LocationView.ts b/src/views/LocationView.ts index 05af2be..4dc0bb1 100644 --- a/src/views/LocationView.ts +++ b/src/views/LocationView.ts @@ -241,7 +241,10 @@ export async function renderLocationView(container: HTMLElement) { ${asset.service_type || '운영'} ${asset.asset_type || 'PC'} - +
+ ${asset.is_audit_approved ? `승인완료` : ''} + +
`;