const path = require('path'); const pool = require('../db/pool.js'); const fs = require('fs'); const multer = require('multer'); const { getSignedUrl } = require('@aws-sdk/s3-request-presigner'); const { PutObjectCommand, GetObjectCommand, DeleteObjectCommand } = require('@aws-sdk/client-s3'); const onPremiseClient = require('../config/onPremiseClient.js'); const cloudClient = require('../config/cloudClient.js'); const storageClients = { 'ONPREMISE': onPremiseClient, 'CLOUD': cloudClient } const deploymentType = process.env.DEPLOYMENT_TYPE; const s3 = storageClients[deploymentType]; exports.getData = async (req, res, next) => { const client = await pool.connect(); try { let { projectId } = req.query; let queryString = ` select project_id, project_no, business_purpose, location_img, continent, performance_area, reference_area, overview_img, facility_size_overview, task_nm_kr, task_nm_en, task_purpose, task_type, client, financial, financial_country, bid, selection_method, joint_contract_nm, joint_contract_shareratio, contract_amount, foreign_currency_amount, contract_date, commencement_date, original_completion_date, completion_date, projectmanager_nm, manager_nm, nation_nm, client_origin, support_department, support_manager_nm, representative_company, order_size_krw, order_size_usd, scheuled_commencement_date, contract_period, abbreviated_name, department, data_size, issue, currency_code, joint_contract, lead_company, nation_code, nation_offset from ver4.tb_overview where project_id = $1; `; const result = await client.query(queryString, [projectId]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('getData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } }; exports.getCalendarEventData = async (req, res) => { const client = await pool.connect(); try { let { nationName, projectId, currentYear, currentMonth } = req.query; let queryString = ` SELECT calendar_event_id, project_id, type, title, content, color, start_date, end_date, nation_nm FROM ver4.tb_calendar_event WHERE ( (type = 'holiday' AND nation_nm IN ('한국', $1)) OR (type = 'schedule' AND project_id = $2) ) AND EXTRACT(YEAR FROM TO_DATE(start_date, 'YYYY-MM-DD')) = $3 AND EXTRACT(MONTH FROM TO_DATE(start_date, 'YYYY-MM-DD')) = $4; ` const result = await client.query(queryString, [nationName, projectId, currentYear, currentMonth]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('getCalendarEventData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message }); } finally { client.release(); } } exports.getTaskPeriodData = async (req, res) => { const client = await pool.connect(); try { let { projectId } = req.query; let queryString = ` SELECT task_history_id, project_id, task_order, suspension_date, suspension_reason, resumption_date, consultation_content, change_date FROM ver4.tb_task_history WHERE project_id = $1; `; const result = await client.query(queryString, [projectId]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('getTaskPeriodData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } }; exports.getFacilitySizeData = async (req, res) => { const client = await pool.connect(); try { let { projectId } = req.query; let queryString = ` SELECT facility_id, project_id, key, value, title FROM ver4.tb_facility_size AS t WHERE project_id = $1 ORDER BY (SELECT MIN(facility_id) FROM ver4.tb_facility_size WHERE title = t.title), facility_id; `; const result = await client.query(queryString, [projectId]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('getFacilitySizeData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } }; exports.saveScheduleData = async (req, res) => { const client = await pool.connect(); try { let {scheduleId, projectId, title, content, color, startDateTimeStr, endDateTimeStr, country } = req.body; const type = 'schedule'; let queryString; let result; if(scheduleId === undefined){ queryString = ` INSERT INTO ver4.tb_calendar_event (project_id, type, title, content, color, start_date, end_date, nation_nm) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ` result = await client.query(queryString, [projectId, type, title, content, color, startDateTimeStr, endDateTimeStr, country]); } else { queryString = ` INSERT INTO ver4.tb_calendar_event (calendar_event_id, project_id, type, title, content, color, start_date, end_date, nation_nm) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (calendar_event_id) DO UPDATE SET project_id = EXCLUDED.project_id, type = EXCLUDED.type, title = EXCLUDED.title, content = EXCLUDED.content, color = EXCLUDED.color, start_date = EXCLUDED.start_date, end_date = EXCLUDED.end_date, nation_nm = EXCLUDED.nation_nm `; result = await client.query(queryString, [scheduleId, projectId, type, title, content, color, startDateTimeStr, endDateTimeStr, country]); } res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('saveScheduleData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } } exports.deleteScheduleData = async (req, res) => { const client = await pool.connect(); try { let { scheduleId } = req.body; let queryString = ` DELETE FROM ver4.tb_calendar_event WHERE calendar_event_id = $1; `; const result = await client.query(queryString, [scheduleId]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('deleteScheduleData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } }; exports.deleteTaskPeriodData = async (req, res) => { const client = await pool.connect(); try { let { deleteArr } = req.body; let queryString = ` DELETE FROM ver4.tb_task_history WHERE task_history_id = ANY($1); `; const result = await client.query(queryString, [deleteArr]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('deleteTaskHistory error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } }; exports.deleteSectionData = async (req, res) => { const client = await pool.connect(); try { let { title } = req.body; let queryString = ` DELETE FROM ver4.tb_facility_size WHERE title = $1; `; const result = await client.query(queryString, [title]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('deleteSectionData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } }; exports.deleteCellData = async (req, res) => { const client = await pool.connect(); try { let { deleteArr } = req.body; const ids = deleteArr.map(cell => cell.id); let queryString = ` DELETE FROM ver4.tb_facility_size WHERE facility_id = ANY($1); `; const result = await client.query(queryString, [ids]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('deleteCellData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } }; exports.deleteLocationImgData = async (req, res) => { const client = await pool.connect(); try { let { projectId } = req.body; let queryString = ` UPDATE ver4.tb_overview SET location_img = '' WHERE project_id = $1; `; const result = await client.query(queryString, [projectId]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('updateLocationImgData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } }; exports.deleteOverviewImgData = async (req, res) => { const client = await pool.connect(); try { let { projectId } = req.body; let queryString = ` UPDATE ver4.tb_overview SET overview_img = '' WHERE project_id = $1; `; const result = await client.query(queryString, [projectId]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('updateLocationImgData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } }; exports.saveSectionLeftData = async (req, res, next) => { const client = await pool.connect(); try { let {projectId, businessPurpose, continent, performanceArea, referenceArea, nation, facilityOverview, locationImgKey, originFileSize } = req.body; let values = [projectId, businessPurpose, continent, performanceArea, referenceArea, nation, facilityOverview, locationImgKey, originFileSize]; let queryString = ` INSERT INTO ver4.tb_overview ( project_id, business_purpose, continent, performance_area, reference_area, nation_nm, facility_size_overview, location_img, data_size) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (project_id) DO UPDATE SET business_purpose = EXCLUDED.business_purpose, location_img = EXCLUDED.location_img, continent = EXCLUDED.continent,performance_area = EXCLUDED.performance_area, reference_area = EXCLUDED.reference_area, data_size = EXCLUDED.data_size, nation_nm = EXCLUDED.nation_nm, facility_size_overview = EXCLUDED.facility_size_overview; `; const result = await client.query(queryString, values); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { next(error); res.status(500).json({ success: false, message: '파일 업로드 중 오류가 발생했습니다.' }); } finally { client.release(); } } exports.saveSectionMiddleData = async (req, res, next) => { const client = await pool.connect(); try { let {projectId, abbreviatedName, taskNmKr, taskNmEn, taskPurpose, orderSizeUsd, orderSizeKrw, scheduledCommencementDate, contractPeriod, clientOrigin, financial, financialCountry, selectionMethod, projectManagerNm, managerNm, supportDepartment, supportManagerNm, contractDate, commencementDate, originalCompletionDate, completionDate, projectNo, taskType, bid, relativeClient, department, jointContractComapnyName, jointContractShares, jointContractKrw, jointContractUsd, representativeCompany } = req.body; let values = [projectId, abbreviatedName, taskNmKr, taskNmEn, taskPurpose, orderSizeUsd, orderSizeKrw, scheduledCommencementDate, contractPeriod, clientOrigin, financial, financialCountry, selectionMethod, projectManagerNm, managerNm, supportDepartment, supportManagerNm, contractDate, commencementDate, originalCompletionDate, completionDate, projectNo, taskType, bid, relativeClient, department, jointContractComapnyName, jointContractShares, jointContractKrw, jointContractUsd, representativeCompany]; let queryString = ` INSERT INTO ver4.tb_overview ( project_id, abbreviated_name, task_nm_kr, task_nm_en, task_purpose, order_size_usd, order_size_krw, scheuled_commencement_date, contract_period, client_origin, financial, financial_country, selection_method, projectmanager_nm, manager_nm, support_department, support_manager_nm, contract_date, commencement_date, original_completion_date, completion_date, project_no, task_type, bid, client, department, joint_contract_nm, joint_contract_shareratio, contract_amount, foreign_currency_amount, representative_company ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31 ) ON CONFLICT (project_id) DO UPDATE SET abbreviated_name = EXCLUDED.abbreviated_name, task_nm_kr = EXCLUDED.task_nm_kr, task_nm_en = EXCLUDED.task_nm_en, task_purpose = EXCLUDED.task_purpose, order_size_usd = EXCLUDED.order_size_usd, order_size_krw = EXCLUDED.order_size_krw, scheuled_commencement_date = EXCLUDED.scheuled_commencement_date, contract_period = EXCLUDED.contract_period, client_origin = EXCLUDED.client_origin, financial = EXCLUDED.financial, financial_country = EXCLUDED.financial_country, selection_method = EXCLUDED.selection_method, projectmanager_nm = EXCLUDED.projectmanager_nm, manager_nm = EXCLUDED.manager_nm, support_department = EXCLUDED.support_department, support_manager_nm = EXCLUDED.support_manager_nm, contract_date = EXCLUDED.contract_date, commencement_date = EXCLUDED.commencement_date, original_completion_date = EXCLUDED.original_completion_date, completion_date = EXCLUDED.completion_date, project_no = EXCLUDED.project_no, task_type = EXCLUDED.task_type, bid = EXCLUDED.bid, client = EXCLUDED.client, department = EXCLUDED.department, joint_contract_nm = EXCLUDED.joint_contract_nm, joint_contract_shareratio = EXCLUDED.joint_contract_shareratio, contract_amount = EXCLUDED.contract_amount, foreign_currency_amount = EXCLUDED.foreign_currency_amount, representative_company = EXCLUDED.representative_company; ` const result = await client.query(queryString, values); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { next(error); res.status(500).json({ success: false, message: 'section2 Save Data Error' }); } finally { client.release(); } }; exports.saveTaskHistoryData = async (req, res, next) => { const client = await pool.connect(); try { for (let i = 0; i < req.body.length; i++) { let { projectId, order, suspensionDate, suspensionReason, resumptionDate, consultationContent, changeDate } = req.body[i]; let queryString = ` INSERT INTO ver4.tb_task_history (project_id, task_order, suspension_date, suspension_reason, resumption_date, consultation_content, change_date) VALUES ($1, $2, $3, $4, $5, $6, $7); ` await client.query(queryString, [projectId, order, suspensionDate, suspensionReason, resumptionDate, consultationContent, changeDate]); } res.json({ success: true, message: '200', }); } catch (error) { next(error); res.status(500).json({ success: false, message: 'task history Save Data Error' }); } finally { client.release(); } }; exports.saveSectionLeftTabData = async (req, res, next) => { const client = await pool.connect(); try { const sections = req.body; for (const title of Object.keys(sections)) { const rows = sections[title]; for (let i = 0; i < rows.length; i++) { const { key, value, id, projectId } = rows[i]; if (id == null || id === '') { const queryStringInsert = ` INSERT INTO ver4.tb_facility_size (project_id, key, value, title) VALUES ($1, $2, $3 , $4) ON CONFLICT (facility_id) DO UPDATE SET project_id = EXCLUDED.project_id, key = EXCLUDED.key, value = EXCLUDED.value, title = EXCLUDED.title; `; await client.query(queryStringInsert, [projectId, key, value, title]); } else { const queryStringUpdate = ` INSERT INTO ver4.tb_facility_size (project_id, key, value, facility_id, title) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (facility_id) DO UPDATE SET project_id = EXCLUDED.project_id, key = EXCLUDED.key, value = EXCLUDED.value, title = EXCLUDED.title; `; await client.query(queryStringUpdate, [projectId, key, value, id, title]); } } } return res.json({ success: true, message: '200', }); } catch (error) { next(error); res.status(500).json({ success: false, message: 'FacilitySize Save Data Error' }); } finally { client.release(); } }; exports.saveIssueData = async (req, res, next) => { const client = await pool.connect(); try { let { projectId, issueData } = req.body; let queryString = ` INSERT INTO ver4.tb_overview ( project_id, issue ) VALUES ( $1, $2 ) ON CONFLICT (project_id) DO UPDATE SET issue = EXCLUDED.issue ` const result = await client.query(queryString, [projectId, issueData]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { next(error); res.status(500).json({ success: false, message: 'Save Issue Data Error' }); } finally { client.release(); } }; exports.generateUploadImgUrl = async (req,res,next) => { const projectId = req.baseUrl.split('/')[1]; let {fileName} = req.body; let bucket = projectId; let key = 'overview/' + fileName; try{ // s3 명렁어 구성 const command = new PutObjectCommand({ Bucket: bucket, Key: key, ContentType: 'application/octet-stream' }); // presigned url 생성 const url = await getSignedUrl(s3, command, { expiresIn: 60 * 5}); // 클라이언트에 return res.json({ url, key }); }catch(error){ console.error('UploadPresigned URL 생성 실패: ', error); next(error); } } exports.generateGetImgUrl = async (req,res,next) => { const projectId = req.baseUrl.split('/')[1]; let { key } = req.query; let bucket = projectId; try{ // s3 명렁어 구성 const command = new GetObjectCommand({ Bucket : bucket, Key : key }); const url = await getSignedUrl(s3, command, {expiresIn: 60}); res.json({ url }); } catch(error){ console.error('GetPresigned URL 생성 실패: ',error); next(error); } } exports.generateDeleteImgUrl = async (req, res, next) => { const projectId = req.baseUrl.split('/')[1]; let { key } = req.body; let bucket = projectId; try{ // s3 명령어 구성 const command = new DeleteObjectCommand({ Bucket : bucket, Key : key }); const url = await getSignedUrl(s3, command, {expiresIn: 60}); res.json({ url }); } catch(error) { console.error('DeletePresigned URL 생성 실패: ',error); next(error) } } exports.updateOverviewImgData = async (req, res) => { const client = await pool.connect(); try { let { projectId, locationImgKey, originFileSize } = req.body; let queryString = ` UPDATE ver4.tb_overview SET location_img = $2, data_size = $3 WHERE project_id = $1; `; const result = await client.query(queryString, [projectId, locationImgKey, originFileSize]); res.json({ success: true, message: '200', data: result.rows, }); } catch (error) { console.error('updateLocationImgData error: ', error); res.status(500).json({ success: false, message: '500', error: error.message, }); } finally { client.release(); } };