@@ -585,6 +585,12 @@ class SaveFinalContractDTO(BaseModel):
585585 example = ["๋ณธ ๊ณ์ฝ์ ์ฃผํ์๋์ฐจ๋ณดํธ๋ฒ์ ์ ์ฉ์ ๋ฐ์ต๋๋ค." ,
586586 "์์ฐจ์ธ์ ์๋์ธ์ ์๋ฉด ๋์ ์์ด ์์ฐจ๊ถ์ ์๋ํ๊ฑฐ๋ ์ ๋ํ ์ ์์ต๋๋ค." ])
587587
588+ # ์๋ช
์ด๋ฏธ์ง (Base64 ์ธ์ฝ๋ฉ) - JSON ๋ฐฉ์์ฉ
589+ owner_sign1_base64 : Optional [str ] = Field (None , alias = "ownerSign1Base64" , description = "์๋์ธ ์๋ช
1 Base64 (๋ฏธ๋ฉ์ธ๊ธ ์์ ๋)" )
590+ owner_sign2_base64 : Optional [str ] = Field (None , alias = "ownerSign2Base64" , description = "์๋์ธ ์๋ช
2 (์ ์์ ํ์ ์ผ์ ์์ ๋)" )
591+ owner_sign3_base64 : Optional [str ] = Field (None , alias = "ownerSign3Base64" , description = "์๋์ธ ์๋ช
3 (๊ธฐ๋ณธ)" )
592+ buyer_sign1_base64 : Optional [str ] = Field (None , alias = "buyerSign1Base64" , description = "์์ฐจ์ธ ์๋ช
Base64" )
593+
588594 model_config = ConfigDict (populate_by_name = True )
589595
590596
@@ -2093,10 +2099,22 @@ def fix_encoding(text):
20932099
20942100 **์ธ์ฝ๋ฉ ๋ฌธ์ ๊ฐ ์๋ ์์ ํ ๋ฐฉ์์
๋๋ค!**
20952101
2102+ **์๋ช
์ด๋ฏธ์ง ์ฒ๋ฆฌ**:
2103+ - ์๋ช
์ด๋ฏธ์ง๋ Base64 ๋ฌธ์์ด๋ก ์ ์ก
2104+ - ownerSign1Base64: ์กฐ์ธ ์ฒด๋ฉ ๊ด๋ จ ์๋ช
2105+ - ownerSign2Base64: ์ ์์ ํ์ ์ผ์ ๊ด๋ จ ์๋ช
2106+ - ownerSign3Base64: ์๋์ธ ๊ธฐ๋ณธ ์๋ช
2107+ - buyerSign1Base64: ์์ฐจ์ธ ์๋ช
2108+
20962109 **Spring์์ ํธ์ถ ์์**:
20972110 ```java
20982111 SaveFinalContractDTO dto = // ... DTO ์์ฑ
20992112
2113+ // ์๋ช
์ด๋ฏธ์ง๋ฅผ Base64๋ก ๋ณํ
2114+ if (ownerSignatureImage1 != null) {
2115+ dto.setOwnerSign1Base64(Base64.getEncoder().encodeToString(ownerSignatureImage1));
2116+ }
2117+
21002118 HttpHeaders headers = new HttpHeaders();
21012119 headers.setContentType(MediaType.APPLICATION_JSON);
21022120 headers.set("Accept-Charset", "UTF-8");
@@ -2129,21 +2147,74 @@ async def generate_contract_json(contract_data: SaveFinalContractDTO):
21292147 logger .error (f"Template file not found: { template_path } " )
21302148 raise HTTPException (status_code = 500 , detail = "ํ
ํ๋ฆฟ ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค." )
21312149
2132- # PDF ์์ฑ๊ธฐ ์ด๊ธฐํ
2133- pdf_replacer = PDFTextReplacer (template_path )
2150+ # PDF ์์ฑ๊ธฐ ์ด๊ธฐํ (์ธ์ ์์ด)
2151+ pdf_replacer = PDFTextReplacer ()
21342152
21352153 # SaveFinalContractDTO๋ฅผ ๋์
๋๋ฆฌ๋ก ๋ณํ
21362154 contract_dict = contract_data .model_dump ()
21372155
2138- # snake_case๋ฅผ camelCase๋ก ๋ณํ
2156+ # Base64 ์๋ช
์ด๋ฏธ์ง ์ฒ๋ฆฌ
2157+ images = {}
2158+ import base64
2159+
2160+ def safe_b64decode (b64_string ):
2161+ """Base64 ๋ฌธ์์ด์ ์์ ํ๊ฒ ๋์ฝ๋ฉ (ํจ๋ฉ ๋ฌธ์ ํด๊ฒฐ)"""
2162+ if not b64_string :
2163+ return None
2164+ try :
2165+ # ํจ๋ฉ ๋ฌธ์ ํด๊ฒฐ - base64 ๋ฌธ์์ด ๊ธธ์ด๋ฅผ 4์ ๋ฐฐ์๋ก ๋ง์ถค
2166+ missing_padding = len (b64_string ) % 4
2167+ if missing_padding :
2168+ b64_string += '=' * (4 - missing_padding )
2169+ return base64 .b64decode (b64_string )
2170+ except Exception as e :
2171+ logger .warning (f"Base64 decode failed: { e } " )
2172+ return None
2173+
2174+ # ์๋์ธ ์๋ช
1 (์กฐ์ธ ์ฒด๋ฉ ๊ด๋ จ)
2175+ if contract_data .has_tax_arrears and contract_data .owner_sign1_base64 :
2176+ decoded = safe_b64decode (contract_data .owner_sign1_base64 )
2177+ if decoded :
2178+ images ['ownerSign1' ] = decoded
2179+ logger .info ("Decoded owner signature 1 (tax arrears)" )
2180+
2181+ # ์๋์ธ ์๋ช
2 (์ ์์ ํ์ ์ผ์ ๊ด๋ จ)
2182+ if contract_data .has_prior_fixed_date and contract_data .owner_sign2_base64 :
2183+ decoded = safe_b64decode (contract_data .owner_sign2_base64 )
2184+ if decoded :
2185+ images ['ownerSign2' ] = decoded
2186+ logger .info ("Decoded owner signature 2 (prior fixed date)" )
2187+
2188+ # ์๋์ธ ์๋ช
3 (๊ธฐ๋ณธ ์๋ช
)
2189+ if contract_data .owner_sign3_base64 :
2190+ decoded = safe_b64decode (contract_data .owner_sign3_base64 )
2191+ if decoded :
2192+ images ['ownerSign3' ] = decoded
2193+ logger .info ("Decoded owner signature 3 (main)" )
2194+
2195+ # ์์ฐจ์ธ ์๋ช
2196+ if contract_data .buyer_sign1_base64 :
2197+ decoded = safe_b64decode (contract_data .buyer_sign1_base64 )
2198+ if decoded :
2199+ images ['buyerSign1' ] = decoded
2200+ logger .info ("Decoded buyer signature 1" )
2201+
2202+ # snake_case๋ฅผ camelCase๋ก ๋ณํ (Base64 ํ๋ ์ ์ธ)
21392203 contract_dict_camel = {}
21402204 for key , value in contract_dict .items ():
2205+ # Base64 ํ๋๋ ์ ์ธ
2206+ if key .endswith ('_base64' ):
2207+ continue
21412208 # snake_case๋ฅผ camelCase๋ก ๋ณํ
21422209 camel_key = '' .join (word .capitalize () if i > 0 else word for i , word in enumerate (key .split ('_' )))
21432210 contract_dict_camel [camel_key ] = value
21442211
2145- # PDF ์์ฑ
2146- pdf_content = pdf_replacer .generate_contract_pdf (contract_dict_camel )
2212+ # PDF ์์ฑ (์๋ช
์ด๋ฏธ์ง ํฌํจ)
2213+ pdf_content = pdf_replacer .generate_contract_pdf (
2214+ template_path ,
2215+ contract_dict_camel ,
2216+ images if images else None
2217+ )
21472218
21482219 if not pdf_content :
21492220 raise HTTPException (status_code = 500 , detail = "PDF ์์ฑ์ ์คํจํ์ต๋๋ค." )
0 commit comments