feat: 소프트웨어 자산 관리 기능 고도화 및 대시보드 누적 비용 분석 기능 추가
This commit is contained in:
@@ -92,6 +92,7 @@ export interface HardwareLog {
|
||||
date: string;
|
||||
details: string;
|
||||
user: string;
|
||||
cost?: number;
|
||||
}
|
||||
|
||||
export interface MasterAssetData {
|
||||
@@ -119,7 +120,7 @@ const EQUIP_HEADERS = ['구매법인', '비품유형', '자산코드', '명칭',
|
||||
const MOBILE_HEADERS = ['구매법인', '자산코드', '명칭', '위치', '관리자', '기기유형', 'OS', '구매연월', '금액', '납품업체', '품의서명', '비고'];
|
||||
|
||||
const SUB_SW_HEADERS = ['ID', '분야', '법인', '부서', '제품명', '구매연월', '만료일', '라이선스유형', '금액', '수량', '계정명', '납품업체', '비고'];
|
||||
const PERM_SW_HEADERS = ['ID', '분야', '법인', '부서', '제품명', '구매연월', '라이선스키', '금액', '수량', '계정명', '납품업체', '비고'];
|
||||
const PERM_SW_HEADERS = ['ID', '분야', '법인', '부서', '제품명', '구매연월', '만료일', '라이선스키', '금액', '수량', '계정명', '납품업체', '비고'];
|
||||
const CLOUD_HEADERS = ['ID', '플랫폼명', '법인', '부서', '사용용도(제품명)', '계정명', '결제수단', '결제일', '연결카드번호', '당월청구액', '비고'];
|
||||
|
||||
export function downloadTemplate() {
|
||||
@@ -157,7 +158,7 @@ export function exportToExcel(masterData: MasterAssetData) {
|
||||
{ tab: '전산비품', list: masterData.equip, headers: EQUIP_HEADERS, map: (a: any) => [a.법인, a.비품유형, a.자산코드, a.명칭, a.위치, a.관리자, a.IP주소, a.MACaddress, a.HW사양, a.OS, a.구매일||a.구매연월, a.금액, a.납품업체, a.품의서명, a.비고] },
|
||||
{ tab: '모바일기기', list: masterData.mobile, headers: MOBILE_HEADERS, map: (a: any) => [a.법인, a.자산코드, a.명칭, a.위치, a.관리자, a.type, a.OS, a.구매일||a.구매연월, a.금액, a.납품업체, a.품의서명, a.비고] },
|
||||
{ tab: '구독SW', list: masterData.subSw, headers: SUB_SW_HEADERS, map: (a: any) => [a.id, a.분야, a.법인, a.부서, a.제품명, a.구매일||a.구매연월, a.만료일, a.라이선스유형, a.금액, a.수량, a.계정명, a.납품업체, a.비고] },
|
||||
{ tab: '영구SW', list: masterData.permSw, headers: PERM_SW_HEADERS, map: (a: any) => [a.id, a.분야, a.법인, a.부서, a.제품명, a.구매일||a.구매연월, a.라이선스키, a.금액, a.수량, a.계정명, a.납품업체, a.비고] }
|
||||
{ tab: '영구SW', list: masterData.permSw, headers: PERM_SW_HEADERS, map: (a: any) => [a.id, a.분야, a.법인, a.부서, a.제품명, a.구매일||a.구매연월, a.만료일, a.라이선스키, a.금액, a.수량, a.계정명, a.납품업체, a.비고] }
|
||||
];
|
||||
|
||||
exportMap.forEach(m => {
|
||||
@@ -189,7 +190,7 @@ export async function parseExcel(file: File): Promise<MasterAssetData> {
|
||||
} else if (sheetName === '구독SW') {
|
||||
rows.forEach(r => data.subSw.push({ id: r['ID']||Math.random().toString(36).substring(2, 9), type: '구독SW', 분야: r['분야']||'', 법인: r['법인']||'', 부서: r['부서']||'', 제품명: r['제품명']||'', 구매연월: r['구매연월']||r['구매일']||'', 만료일: r['만료일']||'', 라이선스유형: r['라이선스유형']||'', 금액: r['금액']||'', 수량: parseInt(r['수량']||'1'), 계정명: r['계정명']||'', 납품업체: r['납품업체']||'', 비고: r['비고']||'' }));
|
||||
} else if (sheetName === '영구SW') {
|
||||
rows.forEach(r => data.permSw.push({ id: r['ID']||Math.random().toString(36).substring(2, 9), type: '영구SW', 분야: r['분야']||'', 법인: r['법인']||'', 부서: r['부서']||'', 제품명: r['제품명']||'', 구매연월: r['구매연월']||r['구매일']||'', 라이선스키: r['라이선스키']||'', 금액: r['금액']||'', 수량: parseInt(r['수량']||'1'), 계정명: r['계정명']||'', 납품업체: r['납품업체']||'', 비고: r['비고']||'' }));
|
||||
rows.forEach(r => data.permSw.push({ id: r['ID']||Math.random().toString(36).substring(2, 9), type: '영구SW', 분야: r['분야']||'', 법인: r['법인']||'', 부서: r['부서']||'', 제품명: r['제품명']||'', 구매연월: r['구매연월']||r['구매일']||'', 만료일: r['만료일']||'', 라이선스키: r['라이선스키']||'', 금액: r['금액']||'', 수량: parseInt(r['수량']||'1'), 계정명: r['계정명']||'', 납품업체: r['납품업체']||'', 비고: r['비고']||'' }));
|
||||
}
|
||||
});
|
||||
resolve(data);
|
||||
|
||||
@@ -51,16 +51,16 @@ export const state: AppState = {
|
||||
export async function loadMasterDataFromDB() {
|
||||
try {
|
||||
const endpoints = [
|
||||
{ key: 'pc', url: 'http://172.16.40.100:3000/api/pc' },
|
||||
{ key: 'server', url: 'http://172.16.40.100:3000/api/server' },
|
||||
{ key: 'storage', url: 'http://172.16.40.100:3000/api/storage' },
|
||||
{ key: 'equip', url: 'http://172.16.40.100:3000/api/equip' },
|
||||
{ key: 'mobile', url: 'http://172.16.40.100:3000/api/mobile' },
|
||||
{ key: 'subSw', url: 'http://172.16.40.100:3000/api/sw/sub' },
|
||||
{ key: 'permSw', url: 'http://172.16.40.100:3000/api/sw/perm' },
|
||||
{ key: 'cloud', url: 'http://172.16.40.100:3000/api/cloud' },
|
||||
{ key: 'swUsers', url: 'http://172.16.40.100:3000/api/sw-users' },
|
||||
{ key: 'logs', url: 'http://172.16.40.100:3000/api/logs' }
|
||||
{ key: 'pc', url: `http://${location.hostname}:3000/api/pc` },
|
||||
{ key: 'server', url: `http://${location.hostname}:3000/api/server` },
|
||||
{ key: 'storage', url: `http://${location.hostname}:3000/api/storage` },
|
||||
{ key: 'equip', url: `http://${location.hostname}:3000/api/equip` },
|
||||
{ key: 'mobile', url: `http://${location.hostname}:3000/api/mobile` },
|
||||
{ key: 'subSw', url: `http://${location.hostname}:3000/api/sw/sub` },
|
||||
{ key: 'permSw', url: `http://${location.hostname}:3000/api/sw/perm` },
|
||||
{ key: 'cloud', url: `http://${location.hostname}:3000/api/cloud` },
|
||||
{ key: 'swUsers', url: `http://${location.hostname}:3000/api/sw-users` },
|
||||
{ key: 'logs', url: `http://${location.hostname}:3000/api/logs` }
|
||||
];
|
||||
|
||||
const results = await Promise.all(endpoints.map(e => fetch(e.url)));
|
||||
@@ -195,7 +195,7 @@ export function deleteHardwareAsset(assetId: string) {
|
||||
*/
|
||||
export async function saveSoftwareAsset(asset: SoftwareAsset) {
|
||||
try {
|
||||
const response = await fetch('http://172.16.40.100:3000/api/software/save', {
|
||||
const response = await fetch(`http://${location.hostname}:3000/api/software/save`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(asset)
|
||||
@@ -224,7 +224,7 @@ export async function saveSoftwareAsset(asset: SoftwareAsset) {
|
||||
*/
|
||||
export async function deleteSoftwareAsset(type: string, id: string) {
|
||||
try {
|
||||
const response = await fetch(`http://172.16.40.100:3000/api/asset/${type}/${id}`, {
|
||||
const response = await fetch(`http://${location.hostname}:3000/api/asset/${type}/${id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user