summaryrefslogtreecommitdiff
path: root/lib/basic-contract/vendor-table/survey-conditional.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/basic-contract/vendor-table/survey-conditional.ts')
-rw-r--r--lib/basic-contract/vendor-table/survey-conditional.ts180
1 files changed, 28 insertions, 152 deletions
diff --git a/lib/basic-contract/vendor-table/survey-conditional.ts b/lib/basic-contract/vendor-table/survey-conditional.ts
index 71c2c1ff..686cc4ba 100644
--- a/lib/basic-contract/vendor-table/survey-conditional.ts
+++ b/lib/basic-contract/vendor-table/survey-conditional.ts
@@ -131,6 +131,22 @@ public getIncompleteReason(question: SurveyQuestion, surveyAnswers: Record<numbe
return true;
}
+ private isValidFile(file: any): boolean {
+ if (!file || typeof file !== 'object') return false;
+
+ // 브라우저 File 객체 체크 (새로 업로드한 파일)
+ if (file.name || file.size || file.type) return true;
+
+ // 서버 파일 메타데이터 체크 (기존 파일)
+ if (file.filename || file.originalName || file.id || file.mimeType) return true;
+
+ return false;
+ }
+
+ private hasValidFiles(files: any[]): boolean {
+ return files && files.length > 0 && files.every(file => this.isValidFile(file));
+ }
+
private isQuestionCompleteEnhanced(question: SurveyQuestion, surveyAnswers: Record<number, any>): boolean {
const answer = surveyAnswers[question.id];
@@ -157,60 +173,50 @@ public getIncompleteReason(question: SurveyQuestion, surveyAnswers: Record<numbe
const hasOtherText = answer.answerValue === 'OTHER' ?
(answer.otherText && answer.otherText.trim() !== '') : true;
- // 4️⃣ files 체크 (실제 파일이 있는 경우)
- const hasValidFiles = answer.files && answer.files.length > 0 &&
- answer.files.every((file: any) => file && typeof file === 'object' &&
- (file.name || file.size || file.type)); // 빈 객체 {} 제외
+ // 4️⃣ files 체크 (브라우저 File 객체와 서버 파일 메타데이터 모두 처리) - 수정된 부분
+ const hasValidFilesResult = this.hasValidFiles(answer.files || []);
console.log(`📊 Q${question.questionNumber} 완료 조건 체크:`, {
hasAnswerValue,
hasDetailText,
hasOtherText,
- hasValidFiles,
+ hasValidFiles: hasValidFilesResult,
questionType: question.questionType,
hasDetailTextRequired: question.hasDetailText,
hasFileUploadRequired: question.hasFileUpload || question.questionType === 'FILE'
});
- // 🎯 질문 타입별 완료 조건
+ // 질문 타입별 완료 조건은 동일하지만 hasValidFilesResult 변수 사용
switch (question.questionType) {
case 'RADIO':
case 'DROPDOWN':
- // 선택형: answerValue가 있고, OTHER인 경우 otherText도 필요
const isSelectComplete = hasAnswerValue && hasOtherText;
- // detailText가 필요한 경우 추가 체크
if (question.hasDetailText && isSelectComplete) {
return hasDetailText;
}
- // 파일 업로드가 필요한 경우 추가 체크
if ((question.hasFileUpload || question.questionType === 'FILE') && isSelectComplete) {
- return hasValidFiles;
+ return hasValidFilesResult; // 수정된 부분
}
return isSelectComplete;
case 'TEXTAREA':
- // 텍스트 영역: detailText 또는 answerValue 중 하나라도 있으면 됨
return hasDetailText || hasAnswerValue;
case 'FILE':
- // 파일 업로드: 유효한 파일이 있어야 함
- return hasValidFiles;
+ return hasValidFilesResult; // 수정된 부분
default:
- // 기본: answerValue, detailText, 파일 중 하나라도 있으면 완료
- let isComplete = hasAnswerValue || hasDetailText || hasValidFiles;
+ let isComplete = hasAnswerValue || hasDetailText || hasValidFilesResult; // 수정된 부분
- // detailText가 필수인 경우
if (question.hasDetailText) {
isComplete = isComplete && hasDetailText;
}
- // 파일 업로드가 필수인 경우
if (question.hasFileUpload) {
- isComplete = isComplete && hasValidFiles;
+ isComplete = isComplete && hasValidFilesResult; // 수정된 부분
}
return isComplete;
@@ -303,17 +309,7 @@ private getCompletionDetailsEnhanced(question: SurveyQuestion, answer: any): any
// 🎯 현재 답변 상태에 따라 표시되는 질문들 계산
const visibleQuestions = this.getVisibleQuestions(surveyAnswers);
- console.log('🔍 표시되는 모든 질문들의 상세 정보:', visibleQuestions.map(q => ({
- id: q.id,
- questionNumber: q.questionNumber,
- questionText: q.questionText?.substring(0, 30) + '...',
- isRequired: q.isRequired,
- parentQuestionId: q.parentQuestionId,
- conditionalValue: q.conditionalValue,
- isConditional: !!q.parentQuestionId,
- hasAnswer: !!surveyAnswers[q.id]?.answerValue,
- answerValue: surveyAnswers[q.id]?.answerValue
- })));
+
// 🚨 중요: 트리거된 조건부 질문들을 필수로 처리
const requiredQuestions = visibleQuestions.filter(q => {
@@ -334,26 +330,6 @@ private getCompletionDetailsEnhanced(question: SurveyQuestion, answer: any): any
return false;
});
- console.log('📊 필수 질문 필터링 결과:', {
- 전체질문수: this.questions.length,
- 표시되는질문수: visibleQuestions.length,
- 원래필수질문: visibleQuestions.filter(q => q.isRequired).length,
- 트리거된조건부질문: visibleQuestions.filter(q => {
- if (!q.parentQuestionId || !q.conditionalValue) return false;
- const parentAnswer = surveyAnswers[q.parentQuestionId];
- return parentAnswer?.answerValue === q.conditionalValue;
- }).length,
- 최종필수질문: requiredQuestions.length,
- 현재답변수: Object.keys(surveyAnswers).length,
- 필수질문들: requiredQuestions.map(q => ({
- id: q.id,
- questionNumber: q.questionNumber,
- isRequired: q.isRequired,
- isConditional: !!q.parentQuestionId,
- hasAnswer: !!surveyAnswers[q.id]?.answerValue,
- 처리방식: q.isRequired ? '원래필수' : '트리거됨'
- }))
- });
const completedQuestionIds: number[] = [];
const incompleteQuestionIds: number[] = [];
@@ -365,10 +341,7 @@ private getCompletionDetailsEnhanced(question: SurveyQuestion, answer: any): any
// 🎯 개선된 완료 체크: 모든 답변 형태를 고려
const isComplete = this.isQuestionCompleteEnhanced(question, surveyAnswers);
-
- console.log(`📊 Q${question.questionNumber} 완료 상태: ${isComplete}`);
- console.log(`📝 Q${question.questionNumber} 답변 내용:`, surveyAnswers[question.id]);
-
+
// 디버깅 정보 수집
debugInfo[question.id] = {
questionText: question.questionText,
@@ -414,25 +387,6 @@ private getCompletionDetailsEnhanced(question: SurveyQuestion, answer: any): any
if (process.env.NODE_ENV === 'development') {
(result as any).debugInfo = debugInfo;
- // 📋 상세한 진행 상황 로그
- console.log('📋 최종 진행 상황:', {
- 총필수질문: requiredQuestions.length,
- 완료된질문: completedQuestionIds.length,
- 미완료질문: incompleteQuestionIds.length,
- 진행률: `${Math.round(progressPercentage)}%`,
- 기본질문: visibleQuestions.filter(q => !q.parentQuestionId).length,
- 조건부질문: visibleQuestions.filter(q => q.parentQuestionId).length,
- 완료된기본질문: completedQuestionIds.filter(id => !visibleQuestions.find(q => q.id === id)?.parentQuestionId).length,
- 완료된조건부질문: completedQuestionIds.filter(id => !!visibleQuestions.find(q => q.id === id)?.parentQuestionId).length,
- 필수질문상세: requiredQuestions.map(q => ({
- id: q.id,
- questionNumber: q.questionNumber,
- isRequired: q.isRequired,
- isConditional: !!q.parentQuestionId,
- isComplete: completedQuestionIds.includes(q.id)
- }))
- });
-
// 🔍 미완료 질문들의 구체적 이유
if (incompleteQuestionIds.length > 0) {
console.log('🔍 미완료 질문들:', incompleteQuestionIds.map(id => ({
@@ -446,24 +400,7 @@ private getCompletionDetailsEnhanced(question: SurveyQuestion, answer: any): any
// ⚡ 조건부 질문 활성화 및 완료 현황
const conditionalQuestions = visibleQuestions.filter(q => q.parentQuestionId);
- if (conditionalQuestions.length > 0) {
- console.log('⚡ 조건부 질문 상세 현황:', conditionalQuestions.map(q => ({
- id: q.id,
- questionNumber: q.questionNumber,
- isRequired: q.isRequired,
- parentId: q.parentQuestionId,
- condition: q.conditionalValue,
- parentAnswer: surveyAnswers[q.parentQuestionId!]?.answerValue,
- isTriggered: surveyAnswers[q.parentQuestionId!]?.answerValue === q.conditionalValue,
- hasAnswer: !!surveyAnswers[q.id]?.answerValue,
- answerValue: surveyAnswers[q.id]?.answerValue,
- detailText: surveyAnswers[q.id]?.detailText,
- files: surveyAnswers[q.id]?.files,
- isComplete: debugInfo[q.id]?.isComplete,
- isIncludedInRequired: requiredQuestions.some(rq => rq.id === q.id),
- completionDetails: this.getCompletionDetailsEnhanced(q, surveyAnswers[q.id])
- })));
- }
+
}
return result;
@@ -606,37 +543,21 @@ getOverallProgressStatus(surveyAnswers: Record<number, any>): {
const childQuestion = this.questions.find(q => q.id === childId);
if (!childQuestion) return;
- console.log(`🔍 자식 질문 ${childId} 체크:`, {
- childId,
- questionNumber: childQuestion.questionNumber,
- conditionalValue: childQuestion.conditionalValue,
- newParentValue,
- shouldKeep: childQuestion.conditionalValue === newParentValue,
- currentAnswer: updatedAnswers[childId]?.answerValue
- });
-
// 새로운 부모 값이 자식의 조건과 맞지 않으면 자식 답변 삭제
if (childQuestion.conditionalValue !== newParentValue) {
- console.log(`🗑️ 자식 질문 Q${childQuestion.questionNumber} 답변 초기화 (조건 불일치)`);
delete updatedAnswers[childId];
// 재귀적으로 손자 질문들도 정리
const grandChildAnswers = this.clearAffectedChildAnswers(childId, '', updatedAnswers);
Object.assign(updatedAnswers, grandChildAnswers);
} else {
- console.log(`✅ 자식 질문 Q${childQuestion.questionNumber} 유지 (조건 일치)`);
}
});
const clearedCount = childQuestionIds.filter(childId => !updatedAnswers[childId]).length;
const keptCount = childQuestionIds.filter(childId => !!updatedAnswers[childId]).length;
- console.log(`📊 자식 질문 정리 완료:`, {
- parentQuestionId,
- 총자식질문: childQuestionIds.length,
- 초기화된질문: clearedCount,
- 유지된질문: keptCount
- });
+
return updatedAnswers;
}
@@ -680,21 +601,17 @@ getOverallProgressStatus(surveyAnswers: Record<number, any>): {
conditionalValue: question.conditionalValue
};
- console.log(`🔍 질문 완료 체크 [Q${question.questionNumber}]:`, logData);
if (!question.isRequired) {
- console.log(`✅ Q${question.questionNumber}: 선택 질문이므로 완료`);
return true;
}
if (!answer?.answerValue) {
- console.log(`❌ Q${question.questionNumber}: 답변이 없음`);
return false;
}
// 1. '기타' 선택 시 추가 입력이 필요한 경우
if (answer.answerValue === 'OTHER' && !answer.otherText?.trim()) {
- console.log(`❌ Q${question.questionNumber}: '기타' 선택했지만 상세 내용 없음`);
return false;
}
@@ -702,16 +619,8 @@ getOverallProgressStatus(surveyAnswers: Record<number, any>): {
if (question.hasDetailText) {
const needsDetailText = ['YES', '네', 'Y', 'true', '1'].includes(answer.answerValue);
- console.log(`📝 Q${question.questionNumber} 상세텍스트 체크:`, {
- hasDetailText: question.hasDetailText,
- answerValue: answer.answerValue,
- needsDetailText,
- detailText: answer.detailText?.length || 0,
- detailTextExists: !!answer.detailText?.trim()
- });
if (needsDetailText && !answer.detailText?.trim()) {
- console.log(`❌ Q${question.questionNumber}: '${answer.answerValue}' 선택했지만 상세 내용 없음`);
return false;
}
}
@@ -720,17 +629,7 @@ getOverallProgressStatus(surveyAnswers: Record<number, any>): {
if (question.hasFileUpload || question.questionType === 'FILE') {
const needsFileUpload = ['YES', '네', 'Y', 'true', '1'].includes(answer.answerValue);
- console.log(`📁 Q${question.questionNumber} 파일업로드 체크:`, {
- hasFileUpload: question.hasFileUpload,
- questionType: question.questionType,
- answerValue: answer.answerValue,
- needsFileUpload,
- filesCount: answer.files?.length || 0,
- hasFiles: !!answer.files && answer.files.length > 0
- });
-
if (needsFileUpload && (!answer.files || answer.files.length === 0)) {
- console.log(`❌ Q${question.questionNumber}: '${answer.answerValue}' 선택했지만 파일 업로드 없음`);
return false;
}
}
@@ -739,50 +638,27 @@ getOverallProgressStatus(surveyAnswers: Record<number, any>): {
const childQuestions = this.getChildQuestions(question.id);
if (childQuestions.length > 0) {
- console.log(`🔗 Q${question.questionNumber} 부모 질문 - 자식 질문들:`,
- childQuestions.map(c => ({
- id: c.id,
- questionNumber: c.questionNumber,
- condition: c.conditionalValue,
- required: c.isRequired,
- text: c.questionText?.substring(0, 20) + '...'
- }))
- );
// 현재 답변으로 트리거되는 자식 질문들 찾기
const triggeredChildren = childQuestions.filter(child =>
child.conditionalValue === answer.answerValue
);
- console.log(`🎯 Q${question.questionNumber} 답변 '${answer.answerValue}'로 트리거된 자식들:`,
- triggeredChildren.map(c => ({
- id: c.id,
- questionNumber: c.questionNumber,
- required: c.isRequired,
- text: c.questionText?.substring(0, 30) + '...'
- }))
- );
-
// 트리거된 필수 자식 질문들이 모두 완료되었는지 확인
for (const childQuestion of triggeredChildren) {
if (childQuestion.isRequired) {
- console.log(`🔄 자식 질문 Q${childQuestion.questionNumber} 완료 체크 시작...`);
const childComplete = this.isQuestionComplete(childQuestion, surveyAnswers);
- console.log(`📊 자식 질문 Q${childQuestion.questionNumber} 완료 상태: ${childComplete}`);
if (!childComplete) {
- console.log(`❌ 부모 Q${question.questionNumber}의 자식 Q${childQuestion.questionNumber} 미완료`);
return false;
}
}
}
if (triggeredChildren.filter(c => c.isRequired).length > 0) {
- console.log(`✅ Q${question.questionNumber}의 모든 필수 조건부 자식 질문들 완료됨`);
}
}
- console.log(`✅ Q${question.questionNumber} 완료 체크 통과`);
return true;
}