작업계획서대로 진행
This commit is contained in:
44
backend/api/business/[id]/delete.delete.ts
Normal file
44
backend/api/business/[id]/delete.delete.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { queryOne, execute } from '../../../utils/db'
|
||||
|
||||
/**
|
||||
* 사업 삭제 (상태를 suspended로 변경)
|
||||
* DELETE /api/business/[id]/delete
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const businessId = Number(getRouterParam(event, 'id'))
|
||||
|
||||
if (!businessId) {
|
||||
throw createError({ statusCode: 400, message: '사업 ID가 필요합니다.' })
|
||||
}
|
||||
|
||||
const existing = await queryOne(`
|
||||
SELECT business_id FROM wr_business WHERE business_id = $1
|
||||
`, [businessId])
|
||||
|
||||
if (!existing) {
|
||||
throw createError({ statusCode: 404, message: '사업을 찾을 수 없습니다.' })
|
||||
}
|
||||
|
||||
// 소속 프로젝트 체크
|
||||
const projectCount = await queryOne(`
|
||||
SELECT COUNT(*) as cnt FROM wr_project_info WHERE business_id = $1
|
||||
`, [businessId])
|
||||
|
||||
if (Number(projectCount?.cnt) > 0) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
message: `소속된 프로젝트가 ${projectCount.cnt}개 있습니다. 먼저 프로젝트를 해제하세요.`
|
||||
})
|
||||
}
|
||||
|
||||
// 완전 삭제 대신 상태 변경
|
||||
await execute(`
|
||||
UPDATE wr_business SET business_status = 'suspended', updated_at = NOW()
|
||||
WHERE business_id = $1
|
||||
`, [businessId])
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: '사업이 삭제(중단) 처리되었습니다.'
|
||||
}
|
||||
})
|
||||
71
backend/api/business/[id]/detail.get.ts
Normal file
71
backend/api/business/[id]/detail.get.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { query, queryOne } from '../../../utils/db'
|
||||
|
||||
/**
|
||||
* 사업 상세 조회
|
||||
* GET /api/business/[id]/detail
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const businessId = Number(getRouterParam(event, 'id'))
|
||||
|
||||
if (!businessId) {
|
||||
throw createError({ statusCode: 400, message: '사업 ID가 필요합니다.' })
|
||||
}
|
||||
|
||||
const business = await queryOne(`
|
||||
SELECT
|
||||
b.*,
|
||||
e1.employee_name as created_by_name,
|
||||
e2.employee_name as updated_by_name
|
||||
FROM wr_business b
|
||||
LEFT JOIN wr_employee_info e1 ON b.created_by = e1.employee_id
|
||||
LEFT JOIN wr_employee_info e2 ON b.updated_by = e2.employee_id
|
||||
WHERE b.business_id = $1
|
||||
`, [businessId])
|
||||
|
||||
if (!business) {
|
||||
throw createError({ statusCode: 404, message: '사업을 찾을 수 없습니다.' })
|
||||
}
|
||||
|
||||
// 소속 프로젝트 목록
|
||||
const projects = await query(`
|
||||
SELECT
|
||||
p.project_id,
|
||||
p.project_name,
|
||||
p.project_code,
|
||||
p.project_type,
|
||||
p.project_status,
|
||||
p.start_date,
|
||||
p.end_date
|
||||
FROM wr_project_info p
|
||||
WHERE p.business_id = $1
|
||||
ORDER BY p.project_name
|
||||
`, [businessId])
|
||||
|
||||
return {
|
||||
business: {
|
||||
businessId: business.business_id,
|
||||
businessName: business.business_name,
|
||||
businessCode: business.business_code,
|
||||
clientName: business.client_name,
|
||||
contractStartDate: business.contract_start_date,
|
||||
contractEndDate: business.contract_end_date,
|
||||
businessStatus: business.business_status,
|
||||
description: business.description,
|
||||
createdBy: business.created_by,
|
||||
createdByName: business.created_by_name,
|
||||
updatedBy: business.updated_by,
|
||||
updatedByName: business.updated_by_name,
|
||||
createdAt: business.created_at,
|
||||
updatedAt: business.updated_at
|
||||
},
|
||||
projects: projects.map((p: any) => ({
|
||||
projectId: p.project_id,
|
||||
projectName: p.project_name,
|
||||
projectCode: p.project_code,
|
||||
projectType: p.project_type,
|
||||
projectStatus: p.project_status,
|
||||
startDate: p.start_date,
|
||||
endDate: p.end_date
|
||||
}))
|
||||
}
|
||||
})
|
||||
68
backend/api/business/[id]/update.put.ts
Normal file
68
backend/api/business/[id]/update.put.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { queryOne, execute } from '../../../utils/db'
|
||||
import { getCurrentUserId } from '../../../utils/user'
|
||||
|
||||
interface UpdateBusinessBody {
|
||||
businessName: string
|
||||
businessCode?: string
|
||||
clientName?: string
|
||||
contractStartDate?: string
|
||||
contractEndDate?: string
|
||||
businessStatus?: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 사업 수정
|
||||
* PUT /api/business/[id]/update
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const businessId = Number(getRouterParam(event, 'id'))
|
||||
const body = await readBody<UpdateBusinessBody>(event)
|
||||
const userId = await getCurrentUserId(event)
|
||||
|
||||
if (!businessId) {
|
||||
throw createError({ statusCode: 400, message: '사업 ID가 필요합니다.' })
|
||||
}
|
||||
|
||||
if (!body.businessName) {
|
||||
throw createError({ statusCode: 400, message: '사업명은 필수입니다.' })
|
||||
}
|
||||
|
||||
const existing = await queryOne(`
|
||||
SELECT business_id FROM wr_business WHERE business_id = $1
|
||||
`, [businessId])
|
||||
|
||||
if (!existing) {
|
||||
throw createError({ statusCode: 404, message: '사업을 찾을 수 없습니다.' })
|
||||
}
|
||||
|
||||
await execute(`
|
||||
UPDATE wr_business SET
|
||||
business_name = $1,
|
||||
business_code = $2,
|
||||
client_name = $3,
|
||||
contract_start_date = $4,
|
||||
contract_end_date = $5,
|
||||
business_status = $6,
|
||||
description = $7,
|
||||
updated_at = NOW(),
|
||||
updated_by = $8
|
||||
WHERE business_id = $9
|
||||
`, [
|
||||
body.businessName,
|
||||
body.businessCode || null,
|
||||
body.clientName || null,
|
||||
body.contractStartDate || null,
|
||||
body.contractEndDate || null,
|
||||
body.businessStatus || 'active',
|
||||
body.description || null,
|
||||
userId,
|
||||
businessId
|
||||
])
|
||||
|
||||
return {
|
||||
success: true,
|
||||
businessId,
|
||||
message: '사업이 수정되었습니다.'
|
||||
}
|
||||
})
|
||||
47
backend/api/business/create.post.ts
Normal file
47
backend/api/business/create.post.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { insertReturning } from '../../utils/db'
|
||||
import { getCurrentUserId } from '../../utils/user'
|
||||
|
||||
interface CreateBusinessBody {
|
||||
businessName: string
|
||||
businessCode?: string
|
||||
clientName?: string
|
||||
contractStartDate?: string
|
||||
contractEndDate?: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 사업 생성
|
||||
* POST /api/business/create
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody<CreateBusinessBody>(event)
|
||||
const userId = await getCurrentUserId(event)
|
||||
|
||||
if (!body.businessName) {
|
||||
throw createError({ statusCode: 400, message: '사업명은 필수입니다.' })
|
||||
}
|
||||
|
||||
const business = await insertReturning(`
|
||||
INSERT INTO wr_business (
|
||||
business_name, business_code, client_name,
|
||||
contract_start_date, contract_end_date, description,
|
||||
business_status, created_by, updated_by
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, 'active', $7, $7)
|
||||
RETURNING *
|
||||
`, [
|
||||
body.businessName,
|
||||
body.businessCode || null,
|
||||
body.clientName || null,
|
||||
body.contractStartDate || null,
|
||||
body.contractEndDate || null,
|
||||
body.description || null,
|
||||
userId
|
||||
])
|
||||
|
||||
return {
|
||||
success: true,
|
||||
businessId: business.business_id,
|
||||
message: '사업이 등록되었습니다.'
|
||||
}
|
||||
})
|
||||
77
backend/api/business/list.get.ts
Normal file
77
backend/api/business/list.get.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { query } from '../../utils/db'
|
||||
|
||||
/**
|
||||
* 사업 목록 조회
|
||||
* GET /api/business/list
|
||||
*
|
||||
* Query params:
|
||||
* - status: 상태 필터 (active, completed, suspended)
|
||||
* - businessName: 사업명 검색
|
||||
* - businessCode: 사업코드 검색
|
||||
* - clientName: 발주처 검색
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const params = getQuery(event)
|
||||
|
||||
const status = params.status as string | null
|
||||
const businessName = params.businessName as string | null
|
||||
const businessCode = params.businessCode as string | null
|
||||
const clientName = params.clientName as string | null
|
||||
|
||||
const conditions: string[] = []
|
||||
const values: any[] = []
|
||||
let paramIndex = 1
|
||||
|
||||
if (status) {
|
||||
conditions.push(`b.business_status = $${paramIndex++}`)
|
||||
values.push(status)
|
||||
}
|
||||
|
||||
if (businessName) {
|
||||
conditions.push(`b.business_name ILIKE $${paramIndex++}`)
|
||||
values.push(`%${businessName}%`)
|
||||
}
|
||||
|
||||
if (businessCode) {
|
||||
conditions.push(`b.business_code ILIKE $${paramIndex++}`)
|
||||
values.push(`%${businessCode}%`)
|
||||
}
|
||||
|
||||
if (clientName) {
|
||||
conditions.push(`b.client_name ILIKE $${paramIndex++}`)
|
||||
values.push(`%${clientName}%`)
|
||||
}
|
||||
|
||||
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''
|
||||
|
||||
const sql = `
|
||||
SELECT
|
||||
b.*,
|
||||
e.employee_name as created_by_name,
|
||||
(SELECT COUNT(*) FROM wr_project_info WHERE business_id = b.business_id) as project_count
|
||||
FROM wr_business b
|
||||
LEFT JOIN wr_employee_info e ON b.created_by = e.employee_id
|
||||
${whereClause}
|
||||
ORDER BY b.created_at DESC
|
||||
`
|
||||
|
||||
const businesses = await query(sql, values)
|
||||
|
||||
return {
|
||||
businesses: businesses.map((b: any) => ({
|
||||
businessId: b.business_id,
|
||||
businessName: b.business_name,
|
||||
businessCode: b.business_code,
|
||||
clientName: b.client_name,
|
||||
contractStartDate: b.contract_start_date,
|
||||
contractEndDate: b.contract_end_date,
|
||||
businessStatus: b.business_status,
|
||||
description: b.description,
|
||||
projectCount: Number(b.project_count),
|
||||
createdBy: b.created_by,
|
||||
createdByName: b.created_by_name,
|
||||
createdAt: b.created_at,
|
||||
updatedAt: b.updated_at
|
||||
}))
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user