summaryrefslogtreecommitdiff
path: root/lib/general-contracts/approval-template-variables.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/general-contracts/approval-template-variables.ts')
-rw-r--r--lib/general-contracts/approval-template-variables.ts345
1 files changed, 345 insertions, 0 deletions
diff --git a/lib/general-contracts/approval-template-variables.ts b/lib/general-contracts/approval-template-variables.ts
new file mode 100644
index 00000000..710e6101
--- /dev/null
+++ b/lib/general-contracts/approval-template-variables.ts
@@ -0,0 +1,345 @@
+/**
+ * 일반계약 결재 템플릿 변수 매핑 함수
+ *
+ * 제공된 HTML 템플릿의 변수명에 맞춰 매핑
+ */
+
+'use server';
+
+import { format } from 'date-fns';
+
+interface ContractSummary {
+ basicInfo: Record<string, unknown>;
+ items: Record<string, unknown>[];
+ subcontractChecklist: Record<string, unknown> | null;
+ storageInfo?: Record<string, unknown>[];
+}
+
+/**
+ * 일반계약 데이터를 결재 템플릿 변수로 매핑
+ *
+ * @param contractSummary - 계약 요약 정보
+ * @returns 템플릿 변수 객체 (Record<string, string>)
+ */
+export async function mapContractToApprovalTemplateVariables(
+ contractSummary: ContractSummary
+): Promise<Record<string, string>> {
+ const { basicInfo, items, subcontractChecklist } = contractSummary;
+
+ // 날짜 포맷팅 헬퍼
+ const formatDate = (date: any) => {
+ if (!date) return '';
+ try {
+ const d = new Date(date);
+ if (isNaN(d.getTime())) return String(date);
+ return format(d, 'yyyy-MM-dd');
+ } catch {
+ return String(date || '');
+ }
+ };
+
+ // 금액 포맷팅 헬퍼
+ const formatCurrency = (amount: any) => {
+ if (amount === undefined || amount === null || amount === '') return '';
+ const num = Number(amount);
+ if (isNaN(num)) return String(amount);
+ return num.toLocaleString('ko-KR');
+ };
+
+ // 계약기간 포맷팅
+ const contractPeriod = basicInfo.startDate && basicInfo.endDate
+ ? `${formatDate(basicInfo.startDate)} ~ ${formatDate(basicInfo.endDate)}`
+ : '';
+
+ // 계약체결방식
+ const contractExecutionMethod = basicInfo.executionMethod || '';
+
+ // 계약종류
+ const contractType = basicInfo.type || '';
+
+ // 업체선정방식
+ const vendorSelectionMethod = basicInfo.contractSourceType || '';
+
+ // 매입 부가가치세
+ const taxType = basicInfo.taxType || '';
+
+ // SHI 지급조건
+ const paymentTerm = basicInfo.paymentTerm || '';
+
+ // SHI 인도조건
+ const deliveryTerm = basicInfo.deliveryTerm || '';
+ const deliveryType = basicInfo.deliveryType || '';
+
+ // 사외업체 야드 투입 여부
+ const externalYardEntry = basicInfo.externalYardEntry === 'Y' ? '예' : '아니오';
+
+ // 직종
+ const workType = basicInfo.workType || '';
+
+ // 재하도 협력사
+ const subcontractVendor = basicInfo.subcontractVendorName || '';
+
+ // 계약 내용
+ const contractContent = basicInfo.notes || basicInfo.name || '';
+
+ // 계약성립조건
+ let establishmentConditionsText = '';
+ if (basicInfo.contractEstablishmentConditions) {
+ try {
+ const cond = typeof basicInfo.contractEstablishmentConditions === 'string'
+ ? JSON.parse(basicInfo.contractEstablishmentConditions)
+ : basicInfo.contractEstablishmentConditions;
+
+ const active: string[] = [];
+ if (cond.regularVendorRegistration) active.push('정규업체 등록(실사 포함) 시');
+ if (cond.projectAward) active.push('프로젝트 수주 시');
+ if (cond.ownerApproval) active.push('선주 승인 시');
+ if (cond.other) active.push('기타');
+ establishmentConditionsText = active.join(', ');
+ } catch (e) {
+ console.warn('계약성립조건 파싱 실패:', e);
+ }
+ }
+
+ // 계약해지조건
+ let terminationConditionsText = '';
+ if (basicInfo.contractTerminationConditions) {
+ try {
+ const cond = typeof basicInfo.contractTerminationConditions === 'string'
+ ? JSON.parse(basicInfo.contractTerminationConditions)
+ : basicInfo.contractTerminationConditions;
+
+ const active: string[] = [];
+ if (cond.standardTermination) active.push('표준 계약해지조건');
+ if (cond.projectNotAwarded) active.push('프로젝트 미수주 시');
+ if (cond.other) active.push('기타');
+ terminationConditionsText = active.join(', ');
+ } catch (e) {
+ console.warn('계약해지조건 파싱 실패:', e);
+ }
+ }
+
+ // 협력사 정보
+ const vendorCode = basicInfo.vendorCode || '';
+ const vendorName = basicInfo.vendorName || '';
+ const vendorContactPerson = basicInfo.vendorContactPerson || '';
+ const vendorPhone = basicInfo.vendorPhone || '';
+ const vendorEmail = basicInfo.vendorEmail || '';
+ const vendorNote = '';
+
+ // 자재 정보 (최대 100건)
+ const materialItems = items.slice(0, 100);
+ const materialCount = items.length;
+
+ // 보증 정보
+ const guarantees: Array<{
+ type: string;
+ order: number;
+ bondNumber: string;
+ rate: string;
+ amount: string;
+ period: string;
+ startDate: string;
+ endDate: string;
+ issuer: string;
+ }> = [];
+
+ // // 계약보증 (첫 번째 항목만 사용)
+ // if (basicInfo.contractBond) {
+ // const bond = typeof basicInfo.contractBond === 'string'
+ // ? JSON.parse(basicInfo.contractBond)
+ // : basicInfo.contractBond;
+
+ // if (bond && Array.isArray(bond) && bond.length > 0) {
+ // const b = bond[0];
+ // guarantees.push({
+ // type: '계약보증',
+ // order: 1,
+ // bondNumber: b.bondNumber || '',
+ // rate: b.rate ? `${b.rate}%` : '',
+ // amount: formatCurrency(b.amount),
+ // period: b.period || '',
+ // startDate: formatDate(b.startDate),
+ // endDate: formatDate(b.endDate),
+ // issuer: b.issuer || '',
+ // });
+ // }
+ // }
+
+ // // 지급보증 (첫 번째 항목만 사용)
+ // if (basicInfo.paymentBond) {
+ // const bond = typeof basicInfo.paymentBond === 'string'
+ // ? JSON.parse(basicInfo.paymentBond)
+ // : basicInfo.paymentBond;
+
+ // if (bond && Array.isArray(bond) && bond.length > 0) {
+ // const b = bond[0];
+ // guarantees.push({
+ // type: '지급보증',
+ // order: 1,
+ // bondNumber: b.bondNumber || '',
+ // rate: b.rate ? `${b.rate}%` : '',
+ // amount: formatCurrency(b.amount),
+ // period: b.period || '',
+ // startDate: formatDate(b.startDate),
+ // endDate: formatDate(b.endDate),
+ // issuer: b.issuer || '',
+ // });
+ // }
+ // }
+
+ // // 하자보증 (첫 번째 항목만 사용)
+ // if (basicInfo.defectBond) {
+ // const bond = typeof basicInfo.defectBond === 'string'
+ // ? JSON.parse(basicInfo.defectBond)
+ // : basicInfo.defectBond;
+
+ // if (bond && Array.isArray(bond) && bond.length > 0) {
+ // const b = bond[0];
+ // guarantees.push({
+ // type: '하자보증',
+ // order: 1,
+ // bondNumber: b.bondNumber || '',
+ // rate: b.rate ? `${b.rate}%` : '',
+ // amount: formatCurrency(b.amount),
+ // period: b.period || '',
+ // startDate: formatDate(b.startDate),
+ // endDate: formatDate(b.endDate),
+ // issuer: b.issuer || '',
+ // });
+ // }
+ // }
+
+ // // 보증 전체 비고
+ // const guaranteeNote = basicInfo.guaranteeNote || '';
+
+
+ // 총 계약 금액 계산
+ const totalContractAmount = items.reduce((sum, item) => {
+ const amount = Number(item.contractAmount || item.totalLineAmount || 0);
+ return sum + (isNaN(amount) ? 0 : amount);
+ }, 0);
+
+ // 변수 매핑
+ const variables: Record<string, string> = {
+ // 계약 기본 정보
+ '계약번호': String(basicInfo.contractNumber || ''),
+ '계약명': String(basicInfo.name || basicInfo.contractName || ''),
+ '계약체결방식': String(contractExecutionMethod),
+ '계약종류': String(contractType),
+ '구매담당자': String(basicInfo.managerName || basicInfo.registeredByName || ''),
+ '업체선정방식': String(vendorSelectionMethod),
+ '입찰번호': String(basicInfo.linkedBidNumber || ''),
+ '입찰명': String(basicInfo.linkedBidName || ''),
+ '계약기간': contractPeriod,
+ '계약일자': formatDate(basicInfo.registeredAt || basicInfo.createdAt),
+ '매입_부가가치세': String(taxType),
+ '계약_담당자': String(basicInfo.managerName || basicInfo.registeredByName || ''),
+ '계약부서': String(basicInfo.departmentName || ''),
+ '계약금액': formatCurrency(basicInfo.contractAmount),
+ 'SHI_지급조건': String(paymentTerm),
+ 'SHI_인도조건': String(deliveryTerm),
+ 'SHI_인도조건_옵션': String(deliveryType),
+ '선적지': String(basicInfo.shippingLocation || ''),
+ '하역지': String(basicInfo.dischargeLocation || ''),
+ '사외업체_야드_투입여부': externalYardEntry,
+ '프로젝트': String(basicInfo.projectName || basicInfo.projectCode || ''),
+ '직종': String(workType),
+ '재하도_협력사': String(subcontractVendor),
+ '계약내용': String(contractContent),
+ '계약성립조건': establishmentConditionsText,
+ '계약해지조건': terminationConditionsText,
+
+ // 협력사 정보
+ '협력사코드': String(vendorCode),
+ '협력사명': String(vendorName),
+ '협력사_담당자': String(vendorContactPerson),
+ '전화번호': String(vendorPhone),
+ '이메일': String(vendorEmail),
+ '비고': String(vendorNote),
+
+ // 자재 정보
+ '대상_자재_수': String(materialCount),
+ };
+
+ // 자재 정보 변수 (최대 100건)
+ materialItems.forEach((item, index) => {
+ const idx = index + 1;
+ variables[`플랜트_${idx}`] = String(item.plant || '');
+ variables[`프로젝트_${idx}`] = String(item.projectName || item.projectCode || '');
+ variables[`자재그룹_${idx}`] = String(item.itemGroup || item.itemCode || '');
+ variables[`자재그룹명_${idx}`] = String(item.itemGroupName || '');
+ variables[`자재번호_${idx}`] = String(item.itemCode || '');
+ variables[`자재상세_${idx}`] = String(item.itemInfo || item.description || '');
+ variables[`연간단가여부_${idx}`] = String(item.isAnnualPrice ? '예' : '아니오');
+ variables[`수량_${idx}`] = formatCurrency(item.quantity);
+ variables[`구매단위_${idx}`] = String(item.quantityUnit || '');
+ variables[`계약단가_${idx}`] = formatCurrency(item.contractUnitPrice || item.unitPrice);
+ variables[`수량단위_${idx}`] = String(item.quantityUnit || '');
+ variables[`총중량_${idx}`] = formatCurrency(item.totalWeight);
+ variables[`중량단위_${idx}`] = String(item.weightUnit || '');
+ variables[`계약금액_${idx}`] = formatCurrency(item.contractAmount || item.totalLineAmount);
+ });
+
+ // 총 계약 금액
+ variables['총_계약금액'] = formatCurrency(totalContractAmount);
+
+ // // 보증 정보 변수 (첫 번째 항목만 사용)
+ // const contractGuarantee = guarantees.find(g => g.type === '계약보증');
+ // if (contractGuarantee) {
+ // variables['계약보증_차수_1'] = String(contractGuarantee.order);
+ // variables['계약보증_증권번호_1'] = String(contractGuarantee.bondNumber || '');
+ // variables['계약보증_보증금율_1'] = String(contractGuarantee.rate || '');
+ // variables['계약보증_보증금액_1'] = String(contractGuarantee.amount || '');
+ // variables['계약보증_보증기간_1'] = String(contractGuarantee.period || '');
+ // variables['계약보증_시작일_1'] = String(contractGuarantee.startDate || '');
+ // variables['계약보증_종료일_1'] = String(contractGuarantee.endDate || '');
+ // variables['계약보증_발행기관_1'] = String(contractGuarantee.issuer || '');
+ // variables['계약보증_비고_1'] = String(guaranteeNote); // 기존 보증 전체 비고를 계약보증 비고로 사용
+ // }
+
+ // const paymentGuarantee = guarantees.find(g => g.type === '지급보증');
+ // if (paymentGuarantee) {
+ // variables['지급보증_차수_1'] = String(paymentGuarantee.order);
+ // variables['지급보증_증권번호_1'] = String(paymentGuarantee.bondNumber || '');
+ // variables['지급보증_보증금율_1'] = String(paymentGuarantee.rate || '');
+ // variables['지급보증_보증금액_1'] = String(paymentGuarantee.amount || '');
+ // variables['지급보증_보증기간_1'] = String(paymentGuarantee.period || '');
+ // variables['지급보증_시작일_1'] = String(paymentGuarantee.startDate || '');
+ // variables['지급보증_종료일_1'] = String(paymentGuarantee.endDate || '');
+ // variables['지급보증_발행기관_1'] = String(paymentGuarantee.issuer || '');
+ // variables['지급보증_비고_1'] = String(guaranteeNote); // 기존 보증 전체 비고를 지급보증 비고로 사용
+ // }
+
+ // const defectGuarantee = guarantees.find(g => g.type === '하자보증');
+ // if (defectGuarantee) {
+ // variables['하자보증_차수_1'] = String(defectGuarantee.order);
+ // variables['하자보증_증권번호_1'] = String(defectGuarantee.bondNumber || '');
+ // variables['하자보증_보증금율_1'] = String(defectGuarantee.rate || '');
+ // variables['하자보증_보증금액_1'] = String(defectGuarantee.amount || '');
+ // variables['하자보증_보증기간_1'] = String(defectGuarantee.period || '');
+ // variables['하자보증_시작일_1'] = String(defectGuarantee.startDate || '');
+ // variables['하자보증_종료일_1'] = String(defectGuarantee.endDate || '');
+ // variables['하자보증_발행기관_1'] = String(defectGuarantee.issuer || '');
+ // variables['하자보증_비고_1'] = String(guaranteeNote); // 기존 보증 전체 비고를 하자보증 비고로 사용
+ // }
+
+ // 하도급 체크리스트 변수 (새로운 템플릿 구조에 맞춤)
+ if (subcontractChecklist) {
+ variables['작업전_서면발급_체크'] = String(subcontractChecklist.workDocumentIssuedCheck || subcontractChecklist.workDocumentIssued || '');
+ variables['기재사항_1'] = String(subcontractChecklist.legalItem1 || subcontractChecklist.sixLegalItems1 || '');
+ variables['기재사항_2'] = String(subcontractChecklist.legalItem2 || subcontractChecklist.sixLegalItems2 || '');
+ variables['기재사항_3'] = String(subcontractChecklist.legalItem3 || subcontractChecklist.sixLegalItems3 || '');
+ variables['기재사항_4'] = String(subcontractChecklist.legalItem4 || subcontractChecklist.sixLegalItems4 || '');
+ variables['기재사항_5'] = String(subcontractChecklist.legalItem5 || subcontractChecklist.sixLegalItems5 || '');
+ variables['기재사항_6'] = String(subcontractChecklist.legalItem6 || subcontractChecklist.sixLegalItems6 || '');
+ variables['부당대금_결정'] = String(subcontractChecklist.unfairPriceDecision || subcontractChecklist.unfairSubcontractPrice || '');
+ variables['점검결과'] = String(subcontractChecklist.inspectionResult || subcontractChecklist.overallResult || '');
+ variables['귀책부서'] = String(subcontractChecklist.responsibleDepartment || subcontractChecklist.overallDepartment || '');
+ variables['원인'] = String(subcontractChecklist.cause || subcontractChecklist.overallCause || '');
+ variables['대책'] = String(subcontractChecklist.countermeasure || subcontractChecklist.overallMeasure || '');
+ }
+
+ return variables;
+}
+