diff --git a/src/components/Modal/UploadPreviewModal.ts b/src/components/Modal/UploadPreviewModal.ts
index ff8ffaf..4c9fe56 100644
--- a/src/components/Modal/UploadPreviewModal.ts
+++ b/src/components/Modal/UploadPreviewModal.ts
@@ -1,6 +1,7 @@
import { openModal, closeModals } from './BaseModal';
-import { createIcons, X, Check, Database, Save, FileSpreadsheet, Layers } from 'lucide';
+import { createIcons, X, Check, Database, Save, FileSpreadsheet, Layers, RefreshCcw } from 'lucide';
import { state, loadMasterDataFromDB } from '../../core/state';
+import { TYPE_PREFIX_MAP } from './SharedData';
let parsedData: any = null;
let currentTab: string = '';
@@ -37,6 +38,9 @@ const UPLOAD_PREVIEW_MODAL_HTML = `
선택된 탭 없음
0건
+
* 아래 데이터가 신규로 추가되거나 기존 데이터가 갱신됩니다.
@@ -72,6 +76,9 @@ export function initUploadPreviewModal(onSuccess?: () => void) {
document.getElementById('btn-confirm-upload')?.addEventListener('click', () => {
confirmUpload();
});
+ document.getElementById('btn-bulk-generate-codes')?.addEventListener('click', () => {
+ generateBulkCodes();
+ });
}
export function openUploadPreview(data: any) {
@@ -87,7 +94,7 @@ export function openUploadPreview(data: any) {
renderCurrentTable();
openModal('upload-preview-modal');
- createIcons({ icons: { X, Check, Database, Save, FileSpreadsheet, Layers } });
+ createIcons({ icons: { X, Check, Database, Save, FileSpreadsheet, Layers, RefreshCcw } });
}
function renderTabs() {
@@ -138,6 +145,13 @@ function renderCurrentTable() {
tabNameEl.textContent = currentTab;
tabCountEl.textContent = `${data.length}건`;
+ const generateBtn = document.getElementById('btn-bulk-generate-codes');
+ const isHwTab = ['개인PC', '서버', '스토리지', '전산비품', '모바일기기'].includes(currentTab);
+ if (generateBtn) {
+ if (isHwTab) generateBtn.classList.remove('hidden');
+ else generateBtn.classList.add('hidden');
+ }
+
if (!data || data.length === 0) {
tableWrapper.innerHTML = '
표시할 데이터가 없습니다.
';
return;
@@ -222,3 +236,63 @@ async function confirmUpload() {
}
}
}
+
+async function generateBulkCodes() {
+ const data = parsedData[currentTab];
+ if (!data) return;
+
+ const generateBtn = document.getElementById('btn-bulk-generate-codes') as HTMLButtonElement;
+ if (generateBtn) {
+ generateBtn.disabled = true;
+ generateBtn.innerHTML = '
생성 중...';
+ createIcons({ icons: { RefreshCcw } });
+ }
+
+ try {
+ // Group rows by prefix (type + purchase_ym)
+ const rowsToProcess = data.filter((r: any) => !r.자산코드);
+ if (rowsToProcess.length === 0) {
+ alert('이미 모든 항목에 자산코드가 부여되어 있습니다.');
+ return;
+ }
+
+ const groups: Record
= {};
+ rowsToProcess.forEach((r: any) => {
+ const type = r.비품유형 || r.기기유형 || r.type || 'ETC';
+ const typeCode = TYPE_PREFIX_MAP[type] || 'ETC';
+ const purchaseYM = String(r.구매연월 || '').replace(/[^0-9]/g, '');
+ if (purchaseYM.length < 6) {
+ // Fallback or skip
+ return;
+ }
+ const prefix = `${typeCode}-${purchaseYM.substring(0, 6)}-`;
+ if (!groups[prefix]) groups[prefix] = [];
+ groups[prefix].push(r);
+ });
+
+ for (const prefix in groups) {
+ const rows = groups[prefix];
+ // Fetch current next code for this prefix
+ const res = await fetch(`http://172.16.40.100:3000/api/generate-asset-code?prefix=${prefix}`);
+ const result = await res.json();
+ if (result.nextCode) {
+ let baseNum = parseInt(result.nextCode.replace(prefix, ''));
+ rows.forEach((r, idx) => {
+ r.자산코드 = `${prefix}${(baseNum + idx).toString().padStart(4, '0')}`;
+ });
+ }
+ }
+
+ renderCurrentTable();
+ alert(`${rowsToProcess.length}건의 자산코드가 생성되었습니다.`);
+ } catch (err) {
+ console.error(err);
+ alert('자산코드 생성 중 오류가 발생했습니다.');
+ } finally {
+ if (generateBtn) {
+ generateBtn.disabled = false;
+ generateBtn.innerHTML = ' 자산코드 일괄 생성';
+ createIcons({ icons: { RefreshCcw } });
+ }
+ }
+}