Skip to content

Commit 1e70fe4

Browse files
committed
✨ feat: 특약 적법성 검토 API 연결 수정
1 parent afc55e0 commit 1e70fe4

File tree

1 file changed

+56
-140
lines changed

1 file changed

+56
-140
lines changed

app/main.py

Lines changed: 56 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import tempfile
77
import traceback
88
from typing import Optional, List
9+
from datetime import datetime
910

1011
# UTF-8 인코딩 설정
1112
import sys
@@ -26,7 +27,6 @@
2627

2728
# AI 모델 필수 import
2829
from generators.risk_report import RiskReportGenerator
29-
from generators.contract_report import ContractValidationGenerator
3030
from generators.clause_report import ClauseReportGenerator
3131
from generators.improve_report import ClauseImprovementController
3232

@@ -76,7 +76,6 @@
7676

7777
# 위험도 분석기 인스턴스 생성 (필수)
7878
risk_report_generator = None
79-
contract_validation_generator = None
8079
clause_report_generator = None
8180
clause_improvement_controller = None
8281
try:
@@ -89,9 +88,6 @@
8988
risk_report_generator = RiskReportGenerator()
9089
logger.info("Risk analysis model loaded successfully")
9190

92-
contract_validation_generator = ContractValidationGenerator()
93-
logger.info("Contract validation model loaded successfully")
94-
9591
clause_report_generator = ClauseReportGenerator()
9692
logger.info("Clause report generator loaded successfully")
9793

@@ -171,31 +167,6 @@ class RiskAnalysisRequest(BaseModel):
171167
model_config = ConfigDict(populate_by_name=True)
172168

173169

174-
class ContractValidationRequest(BaseModel):
175-
"""계약서 검증 요청 모델
176-
177-
Spring backend에서 전달하는 계약서 정보를 담는 데이터 전송 객체입니다.
178-
"""
179-
contract_id: int = Field(..., alias="contractId", description="계약서 ID", example=1)
180-
home_id: int = Field(..., alias="homeId", description="매물 ID", example=100)
181-
owner_id: int = Field(..., alias="ownerId", description="임대인 ID", example=10)
182-
buyer_id: int = Field(..., alias="buyerId", description="임차인 ID", example=20)
183-
contract_date: str = Field(..., alias="contractDate", description="계약 날짜 (YYYY-MM-DD)", example="2024-01-01")
184-
contract_expire_date: str = Field(..., alias="contractExpireDate", description="계약 만료 날짜 (YYYY-MM-DD)", example="2025-12-31")
185-
deposit_price: Optional[int] = Field(None, alias="depositPrice", description="보증금 (원)", example=200000000)
186-
monthly_rent: Optional[int] = Field(None, alias="monthlyRent", description="월세 (원)", example=1000000)
187-
maintenance_fee: Optional[int] = Field(None, alias="maintenanceFee", description="관리비 (원)", example=150000)
188-
special_clauses: List[str] = Field(..., alias="specialClauses", description="특약사항 목록",
189-
example=[
190-
"임차인은 계약 해지 시 원상복구 비용을 전액 부담한다.",
191-
"애완동물 사육을 허가하되, 추가 보증금 50만원을 납부한다.",
192-
"임대인은 언제든지 3일 전 통보로 계약을 해지할 수 있다.",
193-
"임차인은 전대 및 양도를 할 수 없다.",
194-
"월세를 3일 이상 연체 시 연체료는 일 1%로 한다."
195-
])
196-
197-
model_config = ConfigDict(populate_by_name=True)
198-
199170

200171
class RestoreCategoryInfo(BaseModel):
201172
"""원상복구 카테고리 정보"""
@@ -581,7 +552,6 @@ async def root():
581552
"parse_contract": "/api/parse/contract",
582553
"analyze_risk": "/api/analyze/risk",
583554
"validate_contract": "/api/contract/validate",
584-
"generate_contract": "/api/contract/generate",
585555
"recommend_clauses": "/api/clause/recommend",
586556
"improve_clause": "/api/clause/improve"
587557
}
@@ -933,16 +903,66 @@ async def analyze_risk(request: RiskAnalysisRequest):
933903
}
934904
}
935905
})
936-
async def validate_contract(request: ContractValidationRequest):
906+
async def validate_contract(request: ContractReportRequest):
937907
"""계약서 법령 검증 API"""
938908
try:
939-
logger.info(f"계약서 검증 시작: contract_id={request.contract_id}")
909+
logger.info(f"계약서 검증 시작: contract_chat_id={request.contract_chat_id}")
910+
911+
# ContractValidationGenerator 사용
912+
from generators.contract_report import ContractValidationGenerator
940913

941-
# Request DTO를 generator가 기대하는 형식으로 변환
914+
# 요청 데이터를 Dict로 변환
942915
contract_data = request.model_dump(by_alias=True)
943916

944-
# 계약서 검증 수행
945-
result = contract_validation_generator.validate_contract_for_spring(contract_data)
917+
# 특약사항을 clauses_data 형식으로 변환
918+
clauses_data = {
919+
"timestamp": "", # ContractValidationGenerator에서 필요하지만 사용하지 않음
920+
"total_clauses": len(contract_data.get('specialContracts', [])),
921+
"clauses": [
922+
{
923+
"order": clause.get('order'),
924+
"title": clause.get('title'),
925+
"content": clause.get('content'),
926+
"assessment": {
927+
"owner": {
928+
"level": "안심",
929+
"reason": "검토 대기 중"
930+
},
931+
"tenant": {
932+
"level": "안심",
933+
"reason": "검토 대기 중"
934+
}
935+
}
936+
} for clause in contract_data.get('specialContracts', [])
937+
]
938+
}
939+
940+
# 기본 계약 정보 추출
941+
basic_info = {
942+
"contractChatId": contract_data.get('contractChatId'),
943+
"ownerName": contract_data.get('ownerName'),
944+
"ownerAddr": contract_data.get('ownerAddr'),
945+
"ownerPhoneNum": contract_data.get('ownerPhoneNum'),
946+
"buyerName": contract_data.get('buyerName'),
947+
"buyerAddr": contract_data.get('buyerAddr'),
948+
"buyerPhoneNum": contract_data.get('buyerPhoneNum'),
949+
"homeAddr1": contract_data.get('homeAddr1'),
950+
"homeAddr2": contract_data.get('homeAddr2'),
951+
"residenceType": contract_data.get('residenceType'),
952+
"exclusiveArea": contract_data.get('exclusiveArea'),
953+
"homeFloor": contract_data.get('homeFloor'),
954+
"contractStartDate": contract_data.get('contractStartDate'),
955+
"contractEndDate": contract_data.get('contractEndDate'),
956+
"depositPrice": contract_data.get('depositPrice'),
957+
"monthlyRent": contract_data.get('monthlyRent'),
958+
"maintenanceFee": contract_data.get('maintenanceFee')
959+
}
960+
961+
# 적법성 검사 수행
962+
result = ContractValidationGenerator.validate_contract_with_clauses(
963+
clauses_data_json=clauses_data,
964+
contract_basic_info_json=basic_info
965+
)
946966

947967
logger.info(f"계약서 검증 완료: status={result.get('validation_status')}, violations={result.get('total_violations')}")
948968

@@ -1164,110 +1184,6 @@ async def recommend_clauses(request: ClauseRecommendationRequest):
11641184
)
11651185

11661186

1167-
@app.post("/api/contract/generate",
1168-
summary="계약서 적법성 검사",
1169-
description="""임대차 계약서 정보의 적법성을 검사합니다.
1170-
1171-
주요 기능:
1172-
- 계약 조건 적법성 검사
1173-
- 특약사항 법적 문제 분석
1174-
- 주의사항 및 위반사항 도출
1175-
- 개선 권고사항 제공
1176-
1177-
검사 항목:
1178-
- 계약 기간 및 금액의 적정성
1179-
- 특약사항의 법적 유효성
1180-
- 임대차보호법 준수 여부
1181-
- 계약 당사자 정보 완전성
1182-
1183-
응답 형식:
1184-
- 검사 상태 (SAFE/WARN/DANGER)
1185-
- 문제점 목록 (violations/warnings)
1186-
- 계약 정보 요약
1187-
- 개선 권고사항
1188-
""",
1189-
tags=["위험도 분석"],
1190-
response_model=ApiResponse)
1191-
async def generate_contract(request: ContractReportRequest):
1192-
"""계약서 적법성 검사 API
1193-
1194-
임대차 계약서 정보를 분석하여 법적 문제점을 검사합니다.
1195-
"""
1196-
try:
1197-
logger.info(f"계약서 검사 API 호출 - 채팅방 ID: {request.contract_chat_id}")
1198-
1199-
# 기존 ContractValidationGenerator 사용
1200-
from generators.contract_report import ContractValidationGenerator
1201-
1202-
# 요청 데이터를 Dict로 변환
1203-
contract_data = request.model_dump(by_alias=True)
1204-
1205-
# 특약사항을 clauses_data 형식으로 변환
1206-
# timestamp는 ApiResponse에서 자동 생성되므로 여기서는 빈 문자열로 설정
1207-
clauses_data = {
1208-
"timestamp": "", # ContractValidationGenerator에서 필요하지만 사용하지 않음
1209-
"total_clauses": len(contract_data.get('specialContracts', [])),
1210-
"clauses": [
1211-
{
1212-
"order": clause.get('order'),
1213-
"title": clause.get('title'),
1214-
"content": clause.get('content'),
1215-
"assessment": {
1216-
"owner": {
1217-
"level": "안심",
1218-
"reason": "검토 대기 중"
1219-
},
1220-
"tenant": {
1221-
"level": "안심",
1222-
"reason": "검토 대기 중"
1223-
}
1224-
}
1225-
} for clause in contract_data.get('specialContracts', [])
1226-
]
1227-
}
1228-
1229-
# 기본 계약 정보 추출
1230-
basic_info = {
1231-
"contractChatId": contract_data.get('contractChatId'),
1232-
"ownerName": contract_data.get('ownerName'),
1233-
"ownerAddr": contract_data.get('ownerAddr'),
1234-
"ownerPhoneNum": contract_data.get('ownerPhoneNum'),
1235-
"buyerName": contract_data.get('buyerName'),
1236-
"buyerAddr": contract_data.get('buyerAddr'),
1237-
"buyerPhoneNum": contract_data.get('buyerPhoneNum'),
1238-
"homeAddr1": contract_data.get('homeAddr1'),
1239-
"homeAddr2": contract_data.get('homeAddr2'),
1240-
"residenceType": contract_data.get('residenceType'),
1241-
"exclusiveArea": contract_data.get('exclusiveArea'),
1242-
"homeFloor": contract_data.get('homeFloor'),
1243-
"contractStartDate": contract_data.get('contractStartDate'),
1244-
"contractEndDate": contract_data.get('contractEndDate'),
1245-
"depositPrice": contract_data.get('depositPrice'),
1246-
"monthlyRent": contract_data.get('monthlyRent'),
1247-
"maintenanceFee": contract_data.get('maintenanceFee')
1248-
}
1249-
1250-
# 적법성 검사 수행
1251-
result = ContractValidationGenerator.validate_contract_with_clauses(
1252-
clauses_data_json=clauses_data,
1253-
contract_basic_info_json=basic_info
1254-
)
1255-
1256-
logger.info(f"계약서 검사 완료 - 상태: {result.get('validation_status')}, 문제: {result.get('total_violations', 0)}개")
1257-
1258-
return ApiResponse.success(
1259-
data=result,
1260-
message="계약서 적법성 검사가 완료되었습니다."
1261-
)
1262-
1263-
except Exception as e:
1264-
logger.error(f"계약서 검사 API 오류: {str(e)}")
1265-
logger.error(traceback.format_exc())
1266-
return ApiResponse.error(
1267-
message="계약서 검사 중 예상치 못한 오류가 발생했습니다.",
1268-
code="INTERNAL_ERROR"
1269-
)
1270-
12711187

12721188
@app.post("/api/clause/improve",
12731189
summary="특약 개선",

0 commit comments

Comments
 (0)