- construction actions.ts 파일들 API 응답 래퍼 패턴 수정
- handover-report, order-management, site-management, structure-review
- apiClient 반환값 { success, data } 구조에 맞게 수정
- ShipmentManagement 기능 개선
- WorkerScreen 컴포넌트 수정
- .gitignore에 package-lock.json, tsconfig.tsbuildinfo 추가
644 lines
22 KiB
TypeScript
644 lines
22 KiB
TypeScript
'use server';
|
|
|
|
import type {
|
|
HandoverReport,
|
|
HandoverReportDetail,
|
|
HandoverReportStats,
|
|
HandoverReportFormData,
|
|
ConstructionManager,
|
|
ContractItem,
|
|
ExternalEquipmentCost,
|
|
} from './types';
|
|
import { apiClient } from '@/lib/api';
|
|
|
|
/**
|
|
* 주일 기업 - 인수인계보고서관리 Server Actions
|
|
* 표준화된 apiClient 사용 버전
|
|
*/
|
|
|
|
// ========================================
|
|
// API 응답 타입
|
|
// ========================================
|
|
|
|
// 목록 조회 시: Contract 데이터 + handover_report 관계
|
|
interface ApiContractWithHandover {
|
|
id: number;
|
|
contract_code: string;
|
|
project_name: string;
|
|
partner_id: number | null;
|
|
partner_name: string | null;
|
|
contract_manager_id: number | null;
|
|
contract_manager_name: string | null;
|
|
construction_pm_id: number | null;
|
|
construction_pm_name: string | null;
|
|
total_locations: number;
|
|
contract_amount: string | number;
|
|
contract_start_date: string | null;
|
|
contract_end_date: string | null;
|
|
status: 'pending' | 'completed';
|
|
stage: string;
|
|
bidding_id: number | null;
|
|
bidding_code: string | null;
|
|
remarks: string | null;
|
|
is_active: boolean;
|
|
created_at: string;
|
|
updated_at: string;
|
|
// 인수인계 보고서 관계 (없으면 null)
|
|
handover_report: ApiHandoverReportRelation | null;
|
|
}
|
|
|
|
// 인수인계 보고서 관계 데이터
|
|
interface ApiHandoverReportRelation {
|
|
id: number;
|
|
report_number: string;
|
|
status: 'pending' | 'completed';
|
|
completion_date: string | null;
|
|
}
|
|
|
|
// 상세 조회 시: HandoverReport 직접 반환
|
|
interface ApiHandoverReport {
|
|
id: number;
|
|
report_number: string;
|
|
partner_name: string | null;
|
|
site_name: string;
|
|
contract_manager_name: string | null;
|
|
construction_pm_name: string | null;
|
|
construction_pm_id: number | null;
|
|
total_sites: number;
|
|
contract_amount: number;
|
|
contract_date: string | null;
|
|
contract_start_date: string | null;
|
|
contract_end_date: string | null;
|
|
completion_date: string | null;
|
|
status: 'pending' | 'completed';
|
|
contract_id: number | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
// 상세 조회 시 포함
|
|
managers?: ApiManager[];
|
|
items?: ApiContractItem[];
|
|
has_secondary_piping?: boolean;
|
|
secondary_piping_amount?: number;
|
|
secondary_piping_note?: string | null;
|
|
has_coating?: boolean;
|
|
coating_amount?: number;
|
|
coating_note?: string | null;
|
|
external_equipment_cost?: ApiExternalEquipmentCost;
|
|
special_notes?: string | null;
|
|
}
|
|
|
|
interface ApiManager {
|
|
id: number;
|
|
name: string;
|
|
non_performance_reason: string | null;
|
|
signature: string | null;
|
|
}
|
|
|
|
interface ApiContractItem {
|
|
id: number;
|
|
item_no: number;
|
|
name: string;
|
|
product: string | null;
|
|
quantity: number;
|
|
remark: string | null;
|
|
}
|
|
|
|
interface ApiExternalEquipmentCost {
|
|
shipping_cost: number;
|
|
high_altitude_work: number;
|
|
public_expense: number;
|
|
}
|
|
|
|
// 통계 응답 (계약 완료건 기준)
|
|
interface ApiHandoverReportStats {
|
|
total_count: number;
|
|
handover_completed_count: number;
|
|
handover_pending_count: number;
|
|
total_amount?: number;
|
|
total_locations?: number;
|
|
}
|
|
|
|
// 상세 조회 시: Contract + handover_report 관계 (API show 응답)
|
|
interface ApiContractWithHandoverDetail extends ApiContractWithHandover {
|
|
contract_manager?: {
|
|
id: number;
|
|
name: string;
|
|
} | null;
|
|
construction_pm?: {
|
|
id: number;
|
|
name: string;
|
|
} | null;
|
|
handover_report: {
|
|
id: number;
|
|
report_number: string;
|
|
status: 'pending' | 'completed';
|
|
completion_date: string | null;
|
|
contract_date: string | null;
|
|
has_secondary_piping?: boolean;
|
|
secondary_piping_amount?: number;
|
|
secondary_piping_note?: string | null;
|
|
has_coating?: boolean;
|
|
coating_amount?: number;
|
|
coating_note?: string | null;
|
|
external_equipment_cost?: ApiExternalEquipmentCost;
|
|
special_notes?: string | null;
|
|
managers?: ApiManager[];
|
|
items?: ApiContractItem[];
|
|
} | null;
|
|
}
|
|
|
|
// ========================================
|
|
// 타입 변환 함수
|
|
// ========================================
|
|
|
|
/**
|
|
* Contract + handover_report 관계 → HandoverReport 타입 변환 (목록용)
|
|
* 계약 완료건 기준 목록 조회용
|
|
*/
|
|
function transformContractToHandoverReport(apiData: ApiContractWithHandover): HandoverReport {
|
|
// 인수인계 상태: 보고서가 있으면 completed, 없으면 pending
|
|
const handoverStatus = apiData.handover_report ? 'completed' : 'pending';
|
|
|
|
return {
|
|
id: String(apiData.id),
|
|
// 보고서 번호: 보고서가 있으면 보고서 번호, 없으면 계약 코드
|
|
reportNumber: apiData.handover_report?.report_number || apiData.contract_code || '',
|
|
partnerName: apiData.partner_name || '',
|
|
// 현장명 = 프로젝트명
|
|
siteName: apiData.project_name || '',
|
|
contractManagerName: apiData.contract_manager_name || '',
|
|
constructionPMName: apiData.construction_pm_name || null,
|
|
// 총 개소 = total_locations
|
|
totalSites: apiData.total_locations || 0,
|
|
contractAmount: Number(apiData.contract_amount) || 0,
|
|
contractStartDate: apiData.contract_start_date || null,
|
|
contractEndDate: apiData.contract_end_date || null,
|
|
// 인수인계 상태 (보고서 유무 기준)
|
|
status: handoverStatus,
|
|
contractId: String(apiData.id),
|
|
createdAt: apiData.created_at || '',
|
|
updatedAt: apiData.updated_at || '',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* API 응답 → HandoverReport 타입 변환 (상세용 - 기존 유지)
|
|
*/
|
|
function transformHandoverReport(apiData: ApiHandoverReport): HandoverReport {
|
|
return {
|
|
id: String(apiData.id),
|
|
reportNumber: apiData.report_number || '',
|
|
partnerName: apiData.partner_name || '',
|
|
siteName: apiData.site_name || '',
|
|
contractManagerName: apiData.contract_manager_name || '',
|
|
constructionPMName: apiData.construction_pm_name || null,
|
|
totalSites: apiData.total_sites || 0,
|
|
contractAmount: apiData.contract_amount || 0,
|
|
contractStartDate: apiData.contract_start_date || null,
|
|
contractEndDate: apiData.contract_end_date || null,
|
|
status: apiData.status || 'pending',
|
|
contractId: apiData.contract_id ? String(apiData.contract_id) : '',
|
|
createdAt: apiData.created_at || '',
|
|
updatedAt: apiData.updated_at || '',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* API 응답 → HandoverReportDetail 타입 변환 (상세용 - 기존 HandoverReport 직접 조회용)
|
|
*/
|
|
function transformHandoverReportDetail(apiData: ApiHandoverReport): HandoverReportDetail {
|
|
// 공사담당자 목록 변환
|
|
const constructionManagers: ConstructionManager[] = (apiData.managers || []).map((m) => ({
|
|
id: String(m.id),
|
|
name: m.name || '',
|
|
nonPerformanceReason: m.non_performance_reason || '',
|
|
signature: m.signature || null,
|
|
}));
|
|
|
|
// 계약 ITEM 목록 변환
|
|
const contractItems: ContractItem[] = (apiData.items || []).map((item) => ({
|
|
id: String(item.id),
|
|
no: item.item_no || 0,
|
|
name: item.name || '',
|
|
product: item.product || '',
|
|
quantity: item.quantity || 0,
|
|
remark: item.remark || '',
|
|
}));
|
|
|
|
// 장비 외 실행금액 변환
|
|
const externalCost = apiData.external_equipment_cost;
|
|
const externalEquipmentCost: ExternalEquipmentCost = externalCost
|
|
? {
|
|
shippingCost: externalCost.shipping_cost || 0,
|
|
highAltitudeWork: externalCost.high_altitude_work || 0,
|
|
publicExpense: externalCost.public_expense || 0,
|
|
}
|
|
: {
|
|
shippingCost: 0,
|
|
highAltitudeWork: 0,
|
|
publicExpense: 0,
|
|
};
|
|
|
|
return {
|
|
id: String(apiData.id),
|
|
reportNumber: apiData.report_number || '',
|
|
partnerName: apiData.partner_name || '',
|
|
siteName: apiData.site_name || '',
|
|
contractManagerName: apiData.contract_manager_name || '',
|
|
constructionPMName: apiData.construction_pm_name || null,
|
|
constructionPMId: apiData.construction_pm_id ? String(apiData.construction_pm_id) : null,
|
|
totalSites: apiData.total_sites || 0,
|
|
contractAmount: apiData.contract_amount || 0,
|
|
contractDate: apiData.contract_date || null,
|
|
contractStartDate: apiData.contract_start_date || null,
|
|
contractEndDate: apiData.contract_end_date || null,
|
|
completionDate: apiData.completion_date || null,
|
|
status: apiData.status || 'pending',
|
|
contractId: apiData.contract_id ? String(apiData.contract_id) : '',
|
|
createdAt: apiData.created_at || '',
|
|
updatedAt: apiData.updated_at || '',
|
|
constructionManagers,
|
|
contractItems,
|
|
hasSecondaryPiping: apiData.has_secondary_piping || false,
|
|
secondaryPipingAmount: apiData.secondary_piping_amount || 0,
|
|
secondaryPipingNote: apiData.secondary_piping_note || '',
|
|
hasCoating: apiData.has_coating || false,
|
|
coatingAmount: apiData.coating_amount || 0,
|
|
coatingNote: apiData.coating_note || '',
|
|
externalEquipmentCost,
|
|
specialNotes: apiData.special_notes || '',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Contract + handover_report → HandoverReportDetail 타입 변환 (상세용 - Contract 기반 조회)
|
|
*/
|
|
function transformContractToHandoverReportDetail(apiData: ApiContractWithHandoverDetail): HandoverReportDetail {
|
|
const report = apiData.handover_report;
|
|
|
|
// 공사담당자 목록 변환
|
|
const constructionManagers: ConstructionManager[] = (report?.managers || []).map((m) => ({
|
|
id: String(m.id),
|
|
name: m.name || '',
|
|
nonPerformanceReason: m.non_performance_reason || '',
|
|
signature: m.signature || null,
|
|
}));
|
|
|
|
// 계약 ITEM 목록 변환
|
|
const contractItems: ContractItem[] = (report?.items || []).map((item) => ({
|
|
id: String(item.id),
|
|
no: item.item_no || 0,
|
|
name: item.name || '',
|
|
product: item.product || '',
|
|
quantity: item.quantity || 0,
|
|
remark: item.remark || '',
|
|
}));
|
|
|
|
// 장비 외 실행금액 변환
|
|
const externalCost = report?.external_equipment_cost;
|
|
const externalEquipmentCost: ExternalEquipmentCost = externalCost
|
|
? {
|
|
shippingCost: externalCost.shipping_cost || 0,
|
|
highAltitudeWork: externalCost.high_altitude_work || 0,
|
|
publicExpense: externalCost.public_expense || 0,
|
|
}
|
|
: {
|
|
shippingCost: 0,
|
|
highAltitudeWork: 0,
|
|
publicExpense: 0,
|
|
};
|
|
|
|
// 인수인계 상태: 보고서가 있으면 completed, 없으면 pending
|
|
const handoverStatus = report ? (report.status || 'pending') : 'pending';
|
|
|
|
return {
|
|
// Contract 기반 ID (상세 조회에서는 contract_id를 사용)
|
|
id: String(apiData.id),
|
|
// 보고서 번호: 보고서가 있으면 보고서 번호, 없으면 계약 코드
|
|
reportNumber: report?.report_number || apiData.contract_code || '',
|
|
partnerName: apiData.partner_name || '',
|
|
// 현장명 = 프로젝트명
|
|
siteName: apiData.project_name || '',
|
|
contractManagerName: apiData.contract_manager_name || apiData.contract_manager?.name || '',
|
|
constructionPMName: apiData.construction_pm_name || apiData.construction_pm?.name || null,
|
|
constructionPMId: apiData.construction_pm_id ? String(apiData.construction_pm_id) : null,
|
|
// 총 개소 = total_locations
|
|
totalSites: apiData.total_locations || 0,
|
|
contractAmount: Number(apiData.contract_amount) || 0,
|
|
contractDate: report?.contract_date || null,
|
|
contractStartDate: apiData.contract_start_date || null,
|
|
contractEndDate: apiData.contract_end_date || null,
|
|
completionDate: report?.completion_date || null,
|
|
status: handoverStatus,
|
|
contractId: String(apiData.id),
|
|
createdAt: apiData.created_at || '',
|
|
updatedAt: apiData.updated_at || '',
|
|
constructionManagers,
|
|
contractItems,
|
|
hasSecondaryPiping: report?.has_secondary_piping || false,
|
|
secondaryPipingAmount: report?.secondary_piping_amount || 0,
|
|
secondaryPipingNote: report?.secondary_piping_note || '',
|
|
hasCoating: report?.has_coating || false,
|
|
coatingAmount: report?.coating_amount || 0,
|
|
coatingNote: report?.coating_note || '',
|
|
externalEquipmentCost,
|
|
specialNotes: report?.special_notes || '',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* HandoverReportFormData → API 요청 데이터 변환
|
|
*/
|
|
function transformToApiRequest(data: Partial<HandoverReportFormData>): Record<string, unknown> {
|
|
const apiData: Record<string, unknown> = {};
|
|
|
|
if (data.reportNumber !== undefined) apiData.report_number = data.reportNumber;
|
|
if (data.partnerName !== undefined) apiData.partner_name = data.partnerName || null;
|
|
if (data.siteName !== undefined) apiData.site_name = data.siteName;
|
|
if (data.contractManagerName !== undefined) apiData.contract_manager_name = data.contractManagerName || null;
|
|
if (data.contractDate !== undefined) apiData.contract_date = data.contractDate || null;
|
|
if (data.totalSites !== undefined) apiData.total_sites = data.totalSites;
|
|
if (data.contractStartDate !== undefined) apiData.contract_start_date = data.contractStartDate || null;
|
|
if (data.contractEndDate !== undefined) apiData.contract_end_date = data.contractEndDate || null;
|
|
if (data.contractAmount !== undefined) apiData.contract_amount = data.contractAmount;
|
|
if (data.constructionPMId !== undefined) apiData.construction_pm_id = data.constructionPMId || null;
|
|
if (data.constructionPMName !== undefined) apiData.construction_pm_name = data.constructionPMName || null;
|
|
if (data.status !== undefined) apiData.status = data.status;
|
|
if (data.hasSecondaryPiping !== undefined) apiData.has_secondary_piping = data.hasSecondaryPiping;
|
|
if (data.secondaryPipingNote !== undefined) apiData.secondary_piping_note = data.secondaryPipingNote || null;
|
|
if (data.hasCoating !== undefined) apiData.has_coating = data.hasCoating;
|
|
if (data.coatingNote !== undefined) apiData.coating_note = data.coatingNote || null;
|
|
if (data.specialNotes !== undefined) apiData.special_notes = data.specialNotes || null;
|
|
|
|
// 장비 외 실행금액 변환
|
|
if (data.externalEquipmentCost !== undefined) {
|
|
apiData.external_equipment_cost = {
|
|
shipping_cost: data.externalEquipmentCost.shippingCost,
|
|
high_altitude_work: data.externalEquipmentCost.highAltitudeWork,
|
|
public_expense: data.externalEquipmentCost.publicExpense,
|
|
};
|
|
}
|
|
|
|
// 공사담당자 변환
|
|
if (data.constructionManagers !== undefined) {
|
|
apiData.managers = data.constructionManagers.map((m) => ({
|
|
name: m.name,
|
|
non_performance_reason: m.nonPerformanceReason || null,
|
|
signature: m.signature || null,
|
|
}));
|
|
}
|
|
|
|
// 계약 ITEM 변환
|
|
if (data.contractItems !== undefined) {
|
|
apiData.items = data.contractItems.map((item, index) => ({
|
|
item_no: item.no || index + 1,
|
|
name: item.name,
|
|
product: item.product || null,
|
|
quantity: item.quantity,
|
|
remark: item.remark || null,
|
|
}));
|
|
}
|
|
|
|
return apiData;
|
|
}
|
|
|
|
// ========================================
|
|
// API 함수
|
|
// ========================================
|
|
|
|
/**
|
|
* 인수인계보고서 목록 조회
|
|
* GET /api/v1/construction/handover-reports
|
|
*/
|
|
export async function getHandoverReportList(params?: {
|
|
size?: number;
|
|
page?: number;
|
|
startDate?: string;
|
|
endDate?: string;
|
|
search?: string;
|
|
status?: string;
|
|
partnerId?: string;
|
|
contractManagerId?: string;
|
|
constructionPMId?: string;
|
|
sortBy?: string;
|
|
}): Promise<{
|
|
success: boolean;
|
|
data?: {
|
|
items: HandoverReport[];
|
|
total: number;
|
|
page: number;
|
|
size: number;
|
|
totalPages: number;
|
|
};
|
|
error?: string;
|
|
}> {
|
|
try {
|
|
const queryParams: Record<string, string> = {};
|
|
|
|
// 페이지네이션
|
|
if (params?.page) queryParams.page = String(params.page);
|
|
if (params?.size) queryParams.per_page = String(params.size);
|
|
|
|
// 검색
|
|
if (params?.search) queryParams.search = params.search;
|
|
|
|
// 인수인계 상태 필터 (API는 handover_status 파라미터 사용)
|
|
if (params?.status && params.status !== 'all') queryParams.handover_status = params.status;
|
|
if (params?.partnerId && params.partnerId !== 'all') queryParams.partner_id = params.partnerId;
|
|
if (params?.contractManagerId && params.contractManagerId !== 'all') {
|
|
queryParams.contract_manager_id = params.contractManagerId;
|
|
}
|
|
if (params?.constructionPMId && params.constructionPMId !== 'all') {
|
|
queryParams.construction_pm_id = params.constructionPMId;
|
|
}
|
|
|
|
// 날짜 범위
|
|
if (params?.startDate) queryParams.start_date = params.startDate;
|
|
if (params?.endDate) queryParams.end_date = params.endDate;
|
|
|
|
// 정렬
|
|
if (params?.sortBy) {
|
|
const sortMap: Record<string, { field: string; dir: string }> = {
|
|
contractDateDesc: { field: 'contract_start_date', dir: 'desc' },
|
|
contractDateAsc: { field: 'contract_start_date', dir: 'asc' },
|
|
partnerNameAsc: { field: 'partner_name', dir: 'asc' },
|
|
partnerNameDesc: { field: 'partner_name', dir: 'desc' },
|
|
siteNameAsc: { field: 'site_name', dir: 'asc' },
|
|
siteNameDesc: { field: 'site_name', dir: 'desc' },
|
|
};
|
|
const sort = sortMap[params.sortBy];
|
|
if (sort) {
|
|
queryParams.sort_by = sort.field;
|
|
queryParams.sort_dir = sort.dir;
|
|
}
|
|
}
|
|
|
|
// API 응답: Contract 목록 + handover_report 관계
|
|
const response = await apiClient.get<{
|
|
success: boolean;
|
|
data: {
|
|
data: ApiContractWithHandover[];
|
|
current_page: number;
|
|
per_page: number;
|
|
total: number;
|
|
last_page: number;
|
|
};
|
|
}>('/construction/handover-reports', { params: queryParams });
|
|
|
|
// Contract → HandoverReport 변환
|
|
const paginatedData = response.data;
|
|
const items = (paginatedData.data || []).map(transformContractToHandoverReport);
|
|
|
|
return {
|
|
success: true,
|
|
data: {
|
|
items,
|
|
total: paginatedData.total || 0,
|
|
page: paginatedData.current_page || 1,
|
|
size: paginatedData.per_page || 20,
|
|
totalPages: paginatedData.last_page || 1,
|
|
},
|
|
};
|
|
} catch (error) {
|
|
console.error('인수인계보고서 목록 조회 오류:', error);
|
|
return { success: false, error: '인수인계보고서 목록을 불러오는데 실패했습니다.' };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 인수인계보고서 통계 조회
|
|
* GET /api/v1/construction/handover-reports/stats
|
|
*/
|
|
export async function getHandoverReportStats(): Promise<{
|
|
success: boolean;
|
|
data?: HandoverReportStats;
|
|
error?: string;
|
|
}> {
|
|
try {
|
|
const response = await apiClient.get<{
|
|
success: boolean;
|
|
data: ApiHandoverReportStats;
|
|
}>('/construction/handover-reports/stats');
|
|
|
|
const statsData = response.data;
|
|
return {
|
|
success: true,
|
|
data: {
|
|
total: statsData.total_count || 0,
|
|
pending: statsData.handover_pending_count || 0,
|
|
completed: statsData.handover_completed_count || 0,
|
|
},
|
|
};
|
|
} catch (error) {
|
|
console.error('인수인계보고서 통계 조회 오류:', error);
|
|
return { success: false, error: '통계를 불러오는데 실패했습니다.' };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 인수인계보고서 삭제
|
|
* DELETE /api/v1/construction/handover-reports/{id}
|
|
*/
|
|
export async function deleteHandoverReport(id: string): Promise<{
|
|
success: boolean;
|
|
error?: string;
|
|
}> {
|
|
try {
|
|
await apiClient.delete(`/construction/handover-reports/${id}`);
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error('인수인계보고서 삭제 오류:', error);
|
|
return { success: false, error: '삭제에 실패했습니다.' };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 인수인계보고서 일괄 삭제
|
|
* DELETE /api/v1/construction/handover-reports/bulk
|
|
*/
|
|
export async function deleteHandoverReports(ids: string[]): Promise<{
|
|
success: boolean;
|
|
deletedCount?: number;
|
|
error?: string;
|
|
}> {
|
|
try {
|
|
await apiClient.delete('/construction/handover-reports/bulk', {
|
|
data: { ids: ids.map((id) => Number(id)) },
|
|
});
|
|
return { success: true, deletedCount: ids.length };
|
|
} catch (error) {
|
|
console.error('인수인계보고서 일괄 삭제 오류:', error);
|
|
return { success: false, error: '일괄 삭제에 실패했습니다.' };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 인수인계보고서 상세 조회 (계약 ID 기준)
|
|
* GET /api/v1/construction/handover-reports/{contractId}
|
|
* 백엔드는 Contract + handover_report 관계로 반환
|
|
*/
|
|
export async function getHandoverReportDetail(id: string): Promise<{
|
|
success: boolean;
|
|
data?: HandoverReportDetail;
|
|
error?: string;
|
|
}> {
|
|
try {
|
|
const response = await apiClient.get<{
|
|
success: boolean;
|
|
data: ApiContractWithHandoverDetail;
|
|
}>(`/construction/handover-reports/${id}`);
|
|
return { success: true, data: transformContractToHandoverReportDetail(response.data) };
|
|
} catch (error) {
|
|
console.error('인수인계보고서 상세 조회 오류:', error);
|
|
return { success: false, error: '인수인계보고서를 찾을 수 없습니다.' };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 인수인계보고서 수정
|
|
* PUT /api/v1/construction/handover-reports/{id}
|
|
*/
|
|
export async function updateHandoverReport(
|
|
id: string,
|
|
data: HandoverReportFormData
|
|
): Promise<{
|
|
success: boolean;
|
|
data?: HandoverReportDetail;
|
|
error?: string;
|
|
}> {
|
|
try {
|
|
const apiData = transformToApiRequest(data);
|
|
const response = await apiClient.put<{
|
|
success: boolean;
|
|
data: ApiHandoverReport;
|
|
}>(`/construction/handover-reports/${id}`, apiData);
|
|
return { success: true, data: transformHandoverReportDetail(response.data) };
|
|
} catch (error) {
|
|
console.error('인수인계보고서 수정 오류:', error);
|
|
return { success: false, error: '수정에 실패했습니다.' };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 인수인계보고서 등록
|
|
* POST /api/v1/construction/handover-reports
|
|
*/
|
|
export async function createHandoverReport(
|
|
data: HandoverReportFormData
|
|
): Promise<{
|
|
success: boolean;
|
|
data?: HandoverReportDetail;
|
|
error?: string;
|
|
}> {
|
|
try {
|
|
const apiData = transformToApiRequest(data);
|
|
const response = await apiClient.post<{
|
|
success: boolean;
|
|
data: ApiHandoverReport;
|
|
}>('/construction/handover-reports', apiData);
|
|
return { success: true, data: transformHandoverReportDetail(response.data) };
|
|
} catch (error) {
|
|
console.error('인수인계보고서 등록 오류:', error);
|
|
return { success: false, error: '등록에 실패했습니다.' };
|
|
}
|
|
} |