""" ๐Ÿงฎ CoBIZ ์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ & R&D ์˜ˆ์‚ฐ ํŽธ์„ฑ ๊ณ„์‚ฐ๊ธฐ ================================================================================ 1. ์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ: ๊ธฐ์—… ํ”„๋กœํ•„ ๊ธฐ๋ฐ˜ 7๋Œ€ ์„ธ์ œ ํ˜œํƒ ์ž๋™ ์Šค์บ” + ์˜ˆ์ƒ ์ ˆ๊ฐ์•ก 2. R&D ์˜ˆ์‚ฐ ํŽธ์„ฑ ๊ณ„์‚ฐ๊ธฐ: ์ด ์‚ฌ์—…๋น„ โ†’ ๋น„๋ชฉ๋ณ„ ์ž๋™ ๋ฐฐ๋ถ„ + ์ƒํ•œ ์ฒดํฌ ================================================================================ """ import gradio as gr import math from datetime import datetime, date # ============================================================================ # 1. ์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ - ๋ฐ์ดํ„ฐ & ๋กœ์ง # ============================================================================ # ์ฐฝ์—…์ค‘์†Œ๊ธฐ์—… ์„ธ์•ก๊ฐ๋ฉด ์—…์ข… ์ฝ”๋“œ STARTUP_ELIGIBLE_INDUSTRIES = [ "C. ์ œ์กฐ์—…", "J. ์ •๋ณดํ†ต์‹ ์—…", "M. ์ „๋ฌธยท๊ณผํ•™ยท๊ธฐ์ˆ ", "N. ์‚ฌ์—…์‹œ์„ค๊ด€๋ฆฌ", "G. ๋„๋งคยท์†Œ๋งค์—…", "H. ์šด์ˆ˜ยท์ฐฝ๊ณ ์—…", "F. ๊ฑด์„ค์—…", "R. ์˜ˆ์ˆ ยท์Šคํฌ์ธ ", "P. ๊ต์œก์„œ๋น„์Šค์—…", "Q. ๋ณด๊ฑดยท์‚ฌํšŒ๋ณต์ง€" ] # ์ค‘์†Œ๊ธฐ์—… ํŠน๋ณ„์„ธ์•ก๊ฐ๋ฉด ์—…์ข…๋ณ„ ๊ฐ๋ฉด์œจ (์†Œ๊ธฐ์—…/์ค‘๊ธฐ์—…) SME_SPECIAL_RATES = { "C. ์ œ์กฐ์—…": {"์†Œ๊ธฐ์—…": 0.20, "์ค‘๊ธฐ์—…": 0.10, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.10}, "E. ์ˆ˜๋„ยทํ™˜๊ฒฝ": {"์†Œ๊ธฐ์—…": 0.20, "์ค‘๊ธฐ์—…": 0.10, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.10}, "F. ๊ฑด์„ค์—…": {"์†Œ๊ธฐ์—…": 0.20, "์ค‘๊ธฐ์—…": 0.10, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.10}, "G. ๋„๋งคยท์†Œ๋งค์—…": {"์†Œ๊ธฐ์—…": 0.10, "์ค‘๊ธฐ์—…": 0.05, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.05}, "H. ์šด์ˆ˜ยท์ฐฝ๊ณ ์—…": {"์†Œ๊ธฐ์—…": 0.20, "์ค‘๊ธฐ์—…": 0.10, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.10}, "J. ์ •๋ณดํ†ต์‹ ์—…": {"์†Œ๊ธฐ์—…": 0.20, "์ค‘๊ธฐ์—…": 0.10, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.10}, "K. ๊ธˆ์œตยท๋ณดํ—˜์—…": {"์†Œ๊ธฐ์—…": 0.10, "์ค‘๊ธฐ์—…": 0.05, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.05}, "L. ๋ถ€๋™์‚ฐ์—…": {"์†Œ๊ธฐ์—…": 0.10, "์ค‘๊ธฐ์—…": 0.05, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.05}, "M. ์ „๋ฌธยท๊ณผํ•™ยท๊ธฐ์ˆ ": {"์†Œ๊ธฐ์—…": 0.20, "์ค‘๊ธฐ์—…": 0.10, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.10}, "N. ์‚ฌ์—…์‹œ์„ค๊ด€๋ฆฌ": {"์†Œ๊ธฐ์—…": 0.20, "์ค‘๊ธฐ์—…": 0.10, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.10}, "P. ๊ต์œก์„œ๋น„์Šค์—…": {"์†Œ๊ธฐ์—…": 0.10, "์ค‘๊ธฐ์—…": 0.05, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.05}, "Q. ๋ณด๊ฑดยท์‚ฌํšŒ๋ณต์ง€": {"์†Œ๊ธฐ์—…": 0.10, "์ค‘๊ธฐ์—…": 0.05, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.05}, "R. ์˜ˆ์ˆ ยท์Šคํฌ์ธ ": {"์†Œ๊ธฐ์—…": 0.10, "์ค‘๊ธฐ์—…": 0.05, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.05}, "S. ์ˆ˜๋ฆฌยท๊ฐœ์ธ์„œ๋น„์Šค": {"์†Œ๊ธฐ์—…": 0.10, "์ค‘๊ธฐ์—…": 0.05, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.05}, "A. ๋†๋ฆผ์–ด์—…": {"์†Œ๊ธฐ์—…": 0.20, "์ค‘๊ธฐ์—…": 0.10, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.10}, "B. ๊ด‘์—…": {"์†Œ๊ธฐ์—…": 0.20, "์ค‘๊ธฐ์—…": 0.10, "์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ": 0.10}, } # ๊ณ ์šฉ์ฆ๋Œ€ ์„ธ์•ก๊ณต์ œ ๊ธˆ์•ก (์ค‘์†Œ๊ธฐ์—…, ์ˆ˜๋„๊ถŒ/๋น„์ˆ˜๋„๊ถŒ) EMPLOYMENT_CREDIT = { "์ฒญ๋…„": {"์ˆ˜๋„๊ถŒ": 1450, "๋น„์ˆ˜๋„๊ถŒ": 1550}, # ๋งŒ์›/์ธ/๋…„ "์žฅ์• ์ธ": {"์ˆ˜๋„๊ถŒ": 1450, "๋น„์ˆ˜๋„๊ถŒ": 1550}, "60์„ธ์ด์ƒ": {"์ˆ˜๋„๊ถŒ": 700, "๋น„์ˆ˜๋„๊ถŒ": 770}, "์ผ๋ฐ˜": {"์ˆ˜๋„๊ถŒ": 850, "๋น„์ˆ˜๋„๊ถŒ": 950}, } def simulate_tax_saving( industry, company_size, revenue_m, operating_profit_m, is_capital_region, establish_years, ceo_age, has_research_center, rd_investment_m, patent_count, total_employees, new_hires_youth, new_hires_general, facility_investment_m, has_venture, has_innobiz, is_female_company, is_disabled_company ): """์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹คํ–‰""" results = [] total_saving = 0 # ๋ฒ•์ธ์„ธ ๊ณผ์„ธํ‘œ์ค€ ์ถ”์ • (์˜์—…์ด์ต ๊ธฐ์ค€ ๊ฐ„์ด ๊ณ„์‚ฐ) taxable_income = max(0, operating_profit_m * 1_000_000) # ์› ๋‹จ์œ„ # ๋ฒ•์ธ์„ธ ๊ณ„์‚ฐ (์ค‘์†Œ๊ธฐ์—… ํŠน๋ก€) if taxable_income <= 500_000_000: # 5์–ต ์ดํ•˜ corp_tax = taxable_income * 0.09 elif taxable_income <= 20_000_000_000: # 200์–ต ์ดํ•˜ corp_tax = 500_000_000 * 0.09 + (taxable_income - 500_000_000) * 0.19 else: corp_tax = 500_000_000 * 0.09 + 19_500_000_000 * 0.19 + (taxable_income - 20_000_000_000) * 0.21 # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # โ‘  ์ฐฝ์—…์ค‘์†Œ๊ธฐ์—… ์„ธ์•ก๊ฐ๋ฉด # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ startup_saving = 0 startup_rate = 0 startup_eligible = (establish_years <= 5 and industry in STARTUP_ELIGIBLE_INDUSTRIES) startup_note = "" if startup_eligible: if not is_capital_region and ceo_age < 35: startup_rate = 1.0 startup_note = "๋น„์ˆ˜๋„๊ถŒ + ์ฒญ๋…„์ฐฝ์—… โ†’ 100% ๊ฐ๋ฉด (์ตœ์ €ํ•œ์„ธ ๋ฐฐ์ œ)" elif not is_capital_region: startup_rate = 0.5 startup_note = "๋น„์ˆ˜๋„๊ถŒ ์ฐฝ์—… โ†’ 50% ๊ฐ๋ฉด" elif ceo_age < 35: startup_rate = 0.5 startup_note = "์ˆ˜๋„๊ถŒ ์ฒญ๋…„์ฐฝ์—… โ†’ 50% ๊ฐ๋ฉด" else: startup_rate = 0.0 startup_note = "์ˆ˜๋„๊ถŒ ์ผ๋ฐ˜ ์ฐฝ์—… โ†’ ํ•ด๋‹น ์—†์Œ" startup_saving = int(corp_tax * startup_rate) else: if establish_years > 5: startup_note = "์—…๋ ฅ 5๋…„ ์ดˆ๊ณผ โ†’ ๋Œ€์ƒ ์™ธ" else: startup_note = "๋น„๋Œ€์ƒ ์—…์ข…" results.append({ "name": "์ฐฝ์—…์ค‘์†Œ๊ธฐ์—… ์„ธ์•ก๊ฐ๋ฉด", "icon": "๐ŸŒฑ", "saving": startup_saving, "rate": f"{int(startup_rate*100)}%", "note": startup_note, "eligible": startup_eligible and startup_rate > 0, "conflict": "์ค‘์†Œ๊ธฐ์—…ํŠน๋ณ„์„ธ์•ก๊ฐ๋ฉด" }) # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # โ‘ก ์ค‘์†Œ๊ธฐ์—… ํŠน๋ณ„์„ธ์•ก๊ฐ๋ฉด # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ sme_saving = 0 sme_rate = 0 sme_note = "" sme_eligible = industry in SME_SPECIAL_RATES if sme_eligible: rates = SME_SPECIAL_RATES[industry] if company_size == "์†Œ๊ธฐ์—…" and is_capital_region: sme_rate = rates.get("์†Œ๊ธฐ์—…_์ˆ˜๋„๊ถŒ", 0.05) elif company_size == "์†Œ๊ธฐ์—…": sme_rate = rates.get("์†Œ๊ธฐ์—…", 0.10) else: sme_rate = rates.get("์ค‘๊ธฐ์—…", 0.05) sme_saving = int(corp_tax * sme_rate) sme_note = f"{company_size} / {'์ˆ˜๋„๊ถŒ' if is_capital_region else '๋น„์ˆ˜๋„๊ถŒ'} โ†’ {int(sme_rate*100)}% ๊ฐ๋ฉด" else: sme_note = "๋น„๋Œ€์ƒ ์—…์ข…" results.append({ "name": "์ค‘์†Œ๊ธฐ์—… ํŠน๋ณ„์„ธ์•ก๊ฐ๋ฉด", "icon": "๐Ÿข", "saving": sme_saving, "rate": f"{int(sme_rate*100)}%", "note": sme_note, "eligible": sme_eligible and sme_rate > 0, "conflict": "์ฐฝ์—…์ค‘์†Œ๊ธฐ์—…์„ธ์•ก๊ฐ๋ฉด" }) # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # โ‘ข R&D ์„ธ์•ก๊ณต์ œ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ rd_saving = 0 rd_note = "" rd_eligible = has_research_center and rd_investment_m > 0 if rd_eligible: rd_amount = rd_investment_m * 1_000_000 # ์› rd_rate = 0.25 # ์ค‘์†Œ๊ธฐ์—… ์ผ๋ฐ˜ R&D ๋‹น๊ธฐ๋ถ„ 25% rd_saving = int(rd_amount * rd_rate) rd_note = f"์—ฐ๊ตฌ์†Œ ๋ณด์œ  + R&D {rd_investment_m:,.0f}๋ฐฑ๋งŒ์› ร— 25% = {rd_saving/10000:,.0f}๋งŒ์›" else: if not has_research_center: rd_note = "๊ธฐ์—…๋ถ€์„ค์—ฐ๊ตฌ์†Œ/์ „๋‹ด๋ถ€์„œ ๋ฏธ๋“ฑ๋ก" else: rd_note = "R&D ํˆฌ์ž์•ก ์—†์Œ" results.append({ "name": "R&D ์„ธ์•ก๊ณต์ œ", "icon": "๐Ÿ”ฌ", "saving": rd_saving, "rate": "25%", "note": rd_note, "eligible": rd_eligible, "conflict": None }) # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # โ‘ฃ ๊ณ ์šฉ์ฆ๋Œ€ ์„ธ์•ก๊ณต์ œ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ emp_saving = 0 emp_note_parts = [] region_key = "์ˆ˜๋„๊ถŒ" if is_capital_region else "๋น„์ˆ˜๋„๊ถŒ" if new_hires_youth > 0: youth_credit = EMPLOYMENT_CREDIT["์ฒญ๋…„"][region_key] * new_hires_youth * 10000 emp_saving += youth_credit emp_note_parts.append(f"์ฒญ๋…„ {new_hires_youth}๋ช… ร— {EMPLOYMENT_CREDIT['์ฒญ๋…„'][region_key]}๋งŒ์›") if new_hires_general > 0: gen_credit = EMPLOYMENT_CREDIT["์ผ๋ฐ˜"][region_key] * new_hires_general * 10000 emp_saving += gen_credit emp_note_parts.append(f"์ผ๋ฐ˜ {new_hires_general}๋ช… ร— {EMPLOYMENT_CREDIT['์ผ๋ฐ˜'][region_key]}๋งŒ์›") emp_saving = int(emp_saving) emp_note = " + ".join(emp_note_parts) if emp_note_parts else "์ „๋…„๋Œ€๋น„ ์‹ ๊ทœ ๊ณ ์šฉ ์ฆ๊ฐ€๋ถ„ ์—†์Œ" if emp_saving > 0: emp_note += f" (3๋…„๊ฐ„ ์ ์šฉ, ์—ฐ {emp_saving/10000:,.0f}๋งŒ์›)" results.append({ "name": "๊ณ ์šฉ์ฆ๋Œ€ ์„ธ์•ก๊ณต์ œ", "icon": "๐Ÿ‘ฅ", "saving": emp_saving, "rate": "์ธ๋‹น ์ตœ๋Œ€ 1,550๋งŒ์›", "note": emp_note, "eligible": emp_saving > 0, "conflict": None }) # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # โ‘ค ํ†ตํ•ฉํˆฌ์ž ์„ธ์•ก๊ณต์ œ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ invest_saving = 0 invest_note = "" if facility_investment_m > 0: invest_rate = 0.10 # ์ค‘์†Œ๊ธฐ์—… ๊ธฐ๋ณธ 10% invest_saving = int(facility_investment_m * 1_000_000 * invest_rate) invest_note = f"์„ค๋น„ํˆฌ์ž {facility_investment_m:,.0f}๋ฐฑ๋งŒ์› ร— 10% = {invest_saving/10000:,.0f}๋งŒ์›" if has_venture or has_innobiz: additional = int(facility_investment_m * 1_000_000 * 0.02) invest_saving += additional invest_note += f" + ์ถ”๊ฐ€ 2% ({additional/10000:,.0f}๋งŒ์›)" else: invest_note = "์‚ฌ์—…์šฉ ์ž์‚ฐ ํˆฌ์ž ์—†์Œ" results.append({ "name": "ํ†ตํ•ฉํˆฌ์ž ์„ธ์•ก๊ณต์ œ", "icon": "๐Ÿญ", "saving": invest_saving, "rate": "10~12%", "note": invest_note, "eligible": invest_saving > 0, "conflict": None }) # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # โ‘ฅ ์‚ฌํšŒ๋ณดํ—˜๋ฃŒ ์„ธ์•ก๊ณต์ œ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ social_saving = 0 social_note = "" total_new = new_hires_youth + new_hires_general if total_new > 0: avg_salary = 36_000_000 # ํ‰๊ท  ์—ฐ๋ด‰ 3,600๋งŒ์› ๊ฐ€์ • employer_rate = 0.098 # ์‚ฌ์—…์ฃผ ๋ถ€๋‹ด ์‚ฌํšŒ๋ณดํ—˜๋ฃŒ์œจ (๊ตญ๋ฏผ์—ฐ๊ธˆ+๊ฑด๊ฐ•+๊ณ ์šฉ+์‚ฐ์žฌ) ์•ฝ 9.8% social_saving = int(total_new * avg_salary * employer_rate * 0.5) # 50% ๊ณต์ œ social_note = f"์‹ ๊ทœ {total_new}๋ช… ร— ์‚ฌ์—…์ฃผ๋ถ€๋‹ด ๋ณดํ—˜๋ฃŒ 50% = {social_saving/10000:,.0f}๋งŒ์›" else: social_note = "์‹ ๊ทœ ๊ณ ์šฉ ์—†์Œ" results.append({ "name": "์‚ฌํšŒ๋ณดํ—˜๋ฃŒ ์„ธ์•ก๊ณต์ œ", "icon": "๐Ÿ›ก๏ธ", "saving": social_saving, "rate": "50%", "note": social_note, "eligible": social_saving > 0, "conflict": None }) # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # โ‘ฆ ๊ธฐ์ˆ ์ด์ „ ์„ธ์•ก๊ฐ๋ฉด # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ tech_saving = 0 tech_note = "" tech_eligible = patent_count > 0 if tech_eligible: tech_note = f"ํŠนํ—ˆ {patent_count}๊ฑด ๋ณด์œ  โ†’ ์ด์ „ ์‹œ ์†Œ๋“์˜ 50%, ๋Œ€์—ฌ ์‹œ 25% ๊ฐ๋ฉด ๊ฐ€๋Šฅ (์‹คํ˜„ ์‹œ ์ ์šฉ)" else: tech_note = "๋ณด์œ  ํŠนํ—ˆ ์—†์Œ" results.append({ "name": "๊ธฐ์ˆ ์ด์ „ ์„ธ์•ก๊ฐ๋ฉด", "icon": "๐Ÿ“œ", "saving": tech_saving, "rate": "์ด์ „50%/๋Œ€์—ฌ25%", "note": tech_note, "eligible": tech_eligible, "conflict": None }) # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # ์ค‘๋ณต ์ ์šฉ ์ฒ˜๋ฆฌ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # ์ฐฝ์—…๊ฐ๋ฉด vs ํŠน๋ณ„๊ฐ๋ฉด โ†’ ๋‘˜ ์ค‘ ํฐ ๊ฒƒ๋งŒ best_choice = "" if results[0]["eligible"] and results[1]["eligible"]: if results[0]["saving"] >= results[1]["saving"]: results[1]["saving"] = 0 results[1]["note"] += " โš ๏ธ ์ฐฝ์—…๊ฐ๋ฉด๊ณผ ์ค‘๋ณต ๋ถˆ๊ฐ€ (์ฐฝ์—…๊ฐ๋ฉด์ด ์œ ๋ฆฌ)" results[1]["eligible"] = False best_choice = "์ฐฝ์—…์ค‘์†Œ๊ธฐ์—… ์„ธ์•ก๊ฐ๋ฉด" else: results[0]["saving"] = 0 results[0]["note"] += " โš ๏ธ ํŠน๋ณ„๊ฐ๋ฉด๊ณผ ์ค‘๋ณต ๋ถˆ๊ฐ€ (ํŠน๋ณ„๊ฐ๋ฉด์ด ์œ ๋ฆฌ)" results[0]["eligible"] = False best_choice = "์ค‘์†Œ๊ธฐ์—… ํŠน๋ณ„์„ธ์•ก๊ฐ๋ฉด" elif results[0]["eligible"]: best_choice = "์ฐฝ์—…์ค‘์†Œ๊ธฐ์—… ์„ธ์•ก๊ฐ๋ฉด" elif results[1]["eligible"]: best_choice = "์ค‘์†Œ๊ธฐ์—… ํŠน๋ณ„์„ธ์•ก๊ฐ๋ฉด" total_saving = sum(r["saving"] for r in results) return results, total_saving, corp_tax, taxable_income, best_choice def generate_tax_html(results, total_saving, corp_tax, taxable_income, best_choice): """์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๊ฒฐ๊ณผ HTML ์ƒ์„ฑ""" eligible_count = sum(1 for r in results if r["eligible"]) saving_pct = (total_saving / corp_tax * 100) if corp_tax > 0 else 0 # ์›Œํ„ฐํด ์ฐจํŠธ ๋ฐ์ดํ„ฐ waterfall_items = [] cumulative = 0 for r in results: if r["saving"] > 0: cumulative += r["saving"] waterfall_items.append((r["icon"] + " " + r["name"][:6], r["saving"], cumulative)) max_val = max(corp_tax, cumulative) if cumulative > 0 else corp_tax # ๋ฐ” ์ฐจํŠธ ์ƒ์„ฑ bars_html = "" for r in results: color = "#6fd9a8" if r["eligible"] else "#3d3d5c" opacity = "1" if r["eligible"] else "0.4" width_pct = min(95, (r["saving"] / max_val * 100)) if max_val > 0 and r["saving"] > 0 else 0 saving_text = f"{r['saving']/10000:,.0f}๋งŒ์›" if r["saving"] > 0 else "ํ•ด๋‹น์—†์Œ" bars_html += f"""
{r['icon']} {r['name']} {'โœ“ ์ ์šฉ' if r['eligible'] else '๋ฏธ์ ์šฉ'} {saving_text}
{r['note']}
""" # ์›Œํ„ฐํด ์ฐจํŠธ waterfall_html = "" if waterfall_items: wf_max = max(cumulative, 1) for name, amount, cum in waterfall_items: bottom_pct = (cum - amount) / wf_max * 100 height_pct = amount / wf_max * 100 waterfall_html += f"""
+{amount/10000:,.0f}๋งŒ
{name}
""" html = f"""

๐Ÿงฎ ์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๊ฒฐ๊ณผ

2026๋…„ ์กฐ์„ธํŠน๋ก€์ œํ•œ๋ฒ• ๊ธฐ์ค€ | ์ค‘์†Œ๊ธฐ์—… ์„ธ์ œ ํ˜œํƒ ์ž๋™ ์Šค์บ”

์ถ”์ • ๋ฒ•์ธ์„ธ
{corp_tax/10000:,.0f}๋งŒ์›
์ด ์ ˆ๊ฐ์•ก
{total_saving/10000:,.0f}๋งŒ์›
์ ˆ๊ฐ๋ฅ 
{saving_pct:.1f}%
์ ์šฉ ๊ฐ€๋Šฅ
{eligible_count}๊ฑด / 7๊ฑด

๐Ÿ“Š ํ•ญ๋ชฉ๋ณ„ ์˜ˆ์ƒ ์ ˆ๊ฐ์•ก

{bars_html}
{'

๐Ÿ’ง ์ ˆ๊ฐ์•ก ๋ˆ„์  ์›Œํ„ฐํด

' + waterfall_html + '
' if waterfall_html else ''}

โš ๏ธ ์ค‘๋ณต ์ ์šฉ ์•ˆ๋‚ด

โ€ป ๋ณธ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์€ ์ฐธ๊ณ ์šฉ์ด๋ฉฐ, ์ •ํ™•ํ•œ ์„ธ๊ธˆ ๊ณ„์‚ฐ์€ ์„ธ๋ฌด์‚ฌ์™€ ์ƒ๋‹ดํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
์˜์—…์ด์ต ๊ธฐ๋ฐ˜ ๊ฐ„์ด ์ถ”์ • | ์‹ค์ œ ๊ณผ์„ธํ‘œ์ค€์€ ์„ธ๋ฌด์กฐ์ • ํ›„ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
""" return html # ============================================================================ # 2. R&D ์˜ˆ์‚ฐ ํŽธ์„ฑ ๊ณ„์‚ฐ๊ธฐ - ๋ฐ์ดํ„ฐ & ๋กœ์ง # ============================================================================ RD_BUDGET_CATEGORIES = { "์ธ๊ฑด๋น„": { "๋‚ด๋ถ€์ธ๊ฑด๋น„": {"desc": "์ฐธ์—ฌ์—ฐ๊ตฌ์› ์ธ๊ฑด๋น„ (์—ฐ๊ตฌ์ฑ…์ž„์ž, ์ฐธ์—ฌ์—ฐ๊ตฌ์›)", "default_pct": 0.45}, "์™ธ๋ถ€์ธ๊ฑด๋น„": {"desc": "์™ธ๋ถ€ ์ „๋ฌธ๊ฐ€ ์œ„์ด‰ ์ˆ˜๋‹น", "default_pct": 0.05}, }, "์ง์ ‘๋น„": { "์—ฐ๊ตฌ์žฅ๋น„ยท์žฌ๋ฃŒ๋น„": {"desc": "์—ฐ๊ตฌ์žฅ๋น„ ๊ตฌ์ž…ยท์ž„์ฐจ, ์žฌ๋ฃŒ๋น„, ์‹œ์•ฝ", "default_pct": 0.12}, "์—ฐ๊ตฌํ™œ๋™๋น„": {"desc": "๊ตญ๋‚ด์™ธ์ถœ์žฅ, ๊ธฐ์ˆ ์ •๋ณด์ˆ˜์ง‘, ํ•™ํšŒ์ฐธ๊ฐ€", "default_pct": 0.05}, "์œ„ํƒ์—ฐ๊ตฌ๋น„": {"desc": "์™ธ๋ถ€๊ธฐ๊ด€ ์œ„ํƒ ์—ฐ๊ตฌ ๋น„์šฉ", "default_pct": 0.08}, "์—ฐ๊ตฌ์‹œ์„คํ™œ์šฉ๋น„": {"desc": "์—ฐ๊ตฌ์‹œ์„ค ์ž„์ฐจ๋ฃŒ, ์ด์šฉ๋ฃŒ", "default_pct": 0.03}, }, "๊ฐ„์ ‘๋น„": { "๊ฐ„์ ‘๋น„": {"desc": "๊ธฐ๊ด€ ๊ด€๋ฆฌ๋น„, ๋ณต๋ฆฌํ›„์ƒ, ๋ณดํ—˜๋ฃŒ ๋“ฑ", "default_pct": 0.10}, } } def calculate_rd_budget( total_budget_m, gov_ratio, cash_ratio, personnel_pct, ext_personnel_pct, equipment_pct, activity_pct, consign_pct, facility_pct, overhead_pct ): """R&D ์˜ˆ์‚ฐ ํŽธ์„ฑ ๊ณ„์‚ฐ""" total = total_budget_m * 1_000_000 # ์› ๋‹จ์œ„ gov_amount = total * gov_ratio / 100 private_amount = total - gov_amount cash_amount = private_amount * cash_ratio / 100 inkind_amount = private_amount - cash_amount # ๋น„๋ชฉ๋ณ„ ๋ฐฐ๋ถ„ (์ •๋ถ€์ง€์›๊ธˆ ๊ธฐ์ค€) pct_sum = personnel_pct + ext_personnel_pct + equipment_pct + activity_pct + consign_pct + facility_pct + overhead_pct # ์ •๊ทœํ™” (ํ•ฉ์ด 100์ด ์•ˆ ๋  ๊ฒฝ์šฐ) if pct_sum == 0: pct_sum = 100 items = [ {"category": "์ธ๊ฑด๋น„", "name": "๋‚ด๋ถ€์ธ๊ฑด๋น„", "pct": personnel_pct, "amount": gov_amount * personnel_pct / pct_sum}, {"category": "์ธ๊ฑด๋น„", "name": "์™ธ๋ถ€์ธ๊ฑด๋น„", "pct": ext_personnel_pct, "amount": gov_amount * ext_personnel_pct / pct_sum}, {"category": "์ง์ ‘๋น„", "name": "์—ฐ๊ตฌ์žฅ๋น„ยท์žฌ๋ฃŒ๋น„", "pct": equipment_pct, "amount": gov_amount * equipment_pct / pct_sum}, {"category": "์ง์ ‘๋น„", "name": "์—ฐ๊ตฌํ™œ๋™๋น„", "pct": activity_pct, "amount": gov_amount * activity_pct / pct_sum}, {"category": "์ง์ ‘๋น„", "name": "์œ„ํƒ์—ฐ๊ตฌ๋น„", "pct": consign_pct, "amount": gov_amount * consign_pct / pct_sum}, {"category": "์ง์ ‘๋น„", "name": "์—ฐ๊ตฌ์‹œ์„คํ™œ์šฉ๋น„", "pct": facility_pct, "amount": gov_amount * facility_pct / pct_sum}, {"category": "๊ฐ„์ ‘๋น„", "name": "๊ฐ„์ ‘๋น„", "pct": overhead_pct, "amount": gov_amount * overhead_pct / pct_sum}, ] # ์ƒํ•œ ์ฒดํฌ warnings = [] personnel_total = items[0]["amount"] + items[1]["amount"] consign_amount = items[4]["amount"] overhead_amount = items[6]["amount"] direct_cost = sum(i["amount"] for i in items if i["category"] != "๊ฐ„์ ‘๋น„") # ์œ„ํƒ์—ฐ๊ตฌ๋น„ ์ƒํ•œ (์ •๋ถ€์ง€์›๊ธˆ์˜ 40%) if consign_amount > gov_amount * 0.40: warnings.append(f"โš ๏ธ ์œ„ํƒ์—ฐ๊ตฌ๋น„({consign_amount/10000:,.0f}๋งŒ)๊ฐ€ ์ •๋ถ€์ง€์›๊ธˆ 40% ์ƒํ•œ({gov_amount*0.40/10000:,.0f}๋งŒ) ์ดˆ๊ณผ") # ๊ฐ„์ ‘๋น„ ์ƒํ•œ (์ง์ ‘๋น„์˜ ์ผ์ • ๋น„์œจ, ํ†ต์ƒ ์ •๋ถ€์ง€์›๊ธˆ์˜ 10% ๋‚ด์™ธ) if overhead_pct > 15: warnings.append(f"โš ๏ธ ๊ฐ„์ ‘๋น„ ๋น„์œจ({overhead_pct:.0f}%)์ด ๊ถŒ์žฅ ์ƒํ•œ(15%) ์ดˆ๊ณผ") # ์ธ๊ฑด๋น„ ๋น„์œจ ์ฒดํฌ if personnel_pct + ext_personnel_pct > 70: warnings.append(f"โš ๏ธ ์ธ๊ฑด๋น„ ๋น„์œจ({personnel_pct+ext_personnel_pct:.0f}%)์ด ํ†ต์ƒ ์ƒํ•œ(70%) ์ดˆ๊ณผ") # ํ•ฉ๊ณ„ ๊ฒ€์ฆ if abs(pct_sum - 100) > 0.1: warnings.append(f"โ„น๏ธ ๋น„๋ชฉ ๋น„์œจ ํ•ฉ๊ณ„๊ฐ€ {pct_sum:.1f}%์ž…๋‹ˆ๋‹ค (์ž๋™ ์ •๊ทœํ™” ์ ์šฉ)") return { "total": total, "gov_amount": gov_amount, "private_amount": private_amount, "cash_amount": cash_amount, "inkind_amount": inkind_amount, "items": items, "warnings": warnings, "personnel_total": personnel_total, "direct_cost": direct_cost, "overhead_amount": overhead_amount, } def generate_rd_budget_html(data): """R&D ์˜ˆ์‚ฐ ํŽธ์„ฑ ๊ฒฐ๊ณผ HTML ์ƒ์„ฑ""" total = data["total"] gov = data["gov_amount"] priv = data["private_amount"] cash = data["cash_amount"] inkind = data["inkind_amount"] items = data["items"] warnings = data["warnings"] # ๋น„๋ชฉ๋ณ„ ํ…Œ์ด๋ธ” ํ–‰ ์ƒ์„ฑ rows_html = "" cat_colors = {"์ธ๊ฑด๋น„": "#6fd9a8", "์ง์ ‘๋น„": "#6495ed", "๊ฐ„์ ‘๋น„": "#ffd700"} prev_cat = "" for item in items: cat_label = "" if item["category"] != prev_cat: cat_label = item["category"] prev_cat = item["category"] color = cat_colors.get(item["category"], "#fff") bar_width = min(90, item["amount"] / gov * 100) if gov > 0 else 0 rows_html += f""" {cat_label} {item['name']} {item['pct']:.0f}% {item['amount']/10000:,.0f}๋งŒ์›
""" # ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€ warn_html = "" if warnings: warn_items = "".join(f'
  • {w}
  • ' for w in warnings) warn_html = f"""
    """ # ํŒŒ์ด ์ฐจํŠธ (CSS๋งŒ์œผ๋กœ) cat_totals = {} for item in items: cat_totals[item["category"]] = cat_totals.get(item["category"], 0) + item["amount"] pie_segments = "" legend_html = "" start_deg = 0 for cat, amount in cat_totals.items(): pct = amount / gov * 100 if gov > 0 else 0 end_deg = start_deg + pct * 3.6 color = cat_colors.get(cat, "#fff") pie_segments += f"{color} {start_deg}deg {end_deg}deg," legend_html += f"""
    {cat} {pct:.1f}% ({amount/10000:,.0f}๋งŒ)
    """ start_deg = end_deg pie_gradient = pie_segments.rstrip(",") html = f"""

    ๐Ÿ“Š R&D ์˜ˆ์‚ฐ ํŽธ์„ฑ ๊ฒฐ๊ณผ

    ๊ตญ๊ฐ€์—ฐ๊ตฌ๊ฐœ๋ฐœ์‚ฌ์—… ์—ฐ๊ตฌ๊ฐœ๋ฐœ๋น„ ์‚ฌ์šฉ๊ธฐ์ค€ ์ ์šฉ

    ์ด ์‚ฌ์—…๋น„
    {total/100000000:,.1f}์–ต
    ์ •๋ถ€์ง€์›๊ธˆ
    {gov/100000000:,.2f}์–ต
    ๋ฏผ๊ฐ„๋ถ€๋‹ด๊ธˆ
    {priv/100000000:,.2f}์–ต
    ํ˜„๊ธˆ
    {cash/10000:,.0f}๋งŒ
    ํ˜„๋ฌผ
    {inkind/10000:,.0f}๋งŒ
    {warn_html}

    ๐Ÿ“‹ ๋น„๋ชฉ๋ณ„ ๋ฐฐ๋ถ„ ๋‚ด์—ญ (์ •๋ถ€์ง€์›๊ธˆ ๊ธฐ์ค€)

    {rows_html}
    ๊ตฌ๋ถ„ ๋น„๋ชฉ ๋น„์œจ ๊ธˆ์•ก
    ํ•ฉ๊ณ„ 100% {gov/10000:,.0f}๋งŒ์›

    ๐Ÿฉ ๋น„๋ชฉ ๊ตฌ์„ฑ

    {legend_html}

    ๐Ÿ—๏ธ ์žฌ์› ๊ตฌ์กฐ

    ๐Ÿ’ฐ ์ด ์‚ฌ์—…๋น„: {total/10000:,.0f}๋งŒ์›
    โ”œ ๐Ÿ›๏ธ ์ •๋ถ€์ง€์›๊ธˆ ({gov/total*100:.0f}%): {gov/10000:,.0f}๋งŒ
    โ”” ๐Ÿข ๋ฏผ๊ฐ„๋ถ€๋‹ด๊ธˆ ({priv/total*100:.0f}%): {priv/10000:,.0f}๋งŒ
    โ”œ ํ˜„๊ธˆ ({cash/priv*100:.0f}%): {cash/10000:,.0f}๋งŒ
    โ”” ํ˜„๋ฌผ ({inkind/priv*100:.0f}%): {inkind/10000:,.0f}๋งŒ

    ๐Ÿ“ ์‚ฌ์—…๊ณ„ํš์„œ ๋ณต์‚ฌ์šฉ (ํ…์ŠคํŠธ)

    ์ด ์‚ฌ์—…๋น„: {total/10000:,.0f}๋งŒ์› ({total/100000000:,.2f}์–ต์›)
    - ์ •๋ถ€์ง€์›๊ธˆ: {gov/10000:,.0f}๋งŒ์› ({gov/total*100:.0f}%)
    - ๋ฏผ๊ฐ„๋ถ€๋‹ด๊ธˆ: {priv/10000:,.0f}๋งŒ์› (ํ˜„๊ธˆ {cash/10000:,.0f}๋งŒ + ํ˜„๋ฌผ {inkind/10000:,.0f}๋งŒ)
    
    [๋น„๋ชฉ๋ณ„ ๋ฐฐ๋ถ„ - ์ •๋ถ€์ง€์›๊ธˆ ๊ธฐ์ค€]
    {''.join(f"  {item['name']:12s}: {item['amount']/10000:>8,.0f}๋งŒ์› ({item['pct']:.0f}%)" + chr(10) for item in items)}
    โ€ป ์‹ค์ œ ์˜ˆ์‚ฐ ํŽธ์„ฑ ์‹œ ํ•ด๋‹น ์‚ฌ์—…์˜ ๊ณต๊ณ ๋ฌธ๊ณผ ์—ฐ๊ตฌ๋น„ ์‚ฌ์šฉ๊ธฐ์ค€์„ ๋ฐ˜๋“œ์‹œ ํ™•์ธํ•˜์„ธ์š”.
    """ return html # ============================================================================ # 3. Gradio ํƒญ ์ƒ์„ฑ # ============================================================================ INDUSTRY_OPTIONS = [ "A. ๋†๋ฆผ์–ด์—…", "B. ๊ด‘์—…", "C. ์ œ์กฐ์—…", "E. ์ˆ˜๋„ยทํ™˜๊ฒฝ", "F. ๊ฑด์„ค์—…", "G. ๋„๋งคยท์†Œ๋งค์—…", "H. ์šด์ˆ˜ยท์ฐฝ๊ณ ์—…", "J. ์ •๋ณดํ†ต์‹ ์—…", "K. ๊ธˆ์œตยท๋ณดํ—˜์—…", "L. ๋ถ€๋™์‚ฐ์—…", "M. ์ „๋ฌธยท๊ณผํ•™ยท๊ธฐ์ˆ ", "N. ์‚ฌ์—…์‹œ์„ค๊ด€๋ฆฌ", "P. ๊ต์œก์„œ๋น„์Šค์—…", "Q. ๋ณด๊ฑดยท์‚ฌํšŒ๋ณต์ง€", "R. ์˜ˆ์ˆ ยท์Šคํฌ์ธ ", "S. ์ˆ˜๋ฆฌยท๊ฐœ์ธ์„œ๋น„์Šค" ] def create_biz_tools_tab(): """์„ธ๊ธˆ ์ ˆ๊ฐ & R&D ์˜ˆ์‚ฐ ํƒญ ์ƒ์„ฑ""" with gr.Tab("๐Ÿงฎ ์„ธ๊ธˆยท์˜ˆ์‚ฐ ๊ณ„์‚ฐ๊ธฐ"): gr.HTML('''

    ๐Ÿงฎ ์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ & R&D ์˜ˆ์‚ฐ ํŽธ์„ฑ๊ธฐ

    ๊ธฐ์—… ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์ ์šฉ ๊ฐ€๋Šฅํ•œ ์„ธ์ œ ํ˜œํƒ๊ณผ R&D ์˜ˆ์‚ฐ์„ ์ž๋™ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค

    ''') with gr.Tabs(): # โ”€โ”€ ํƒญ 1: ์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ โ”€โ”€ with gr.Tab("๐Ÿ’ฐ ์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ"): with gr.Row(): with gr.Column(): gr.HTML('
    ๐Ÿ“‹ ๊ธฐ์—… ๊ธฐ๋ณธ์ •๋ณด
    ') tax_industry = gr.Dropdown(label="์—…์ข…", choices=INDUSTRY_OPTIONS, value="C. ์ œ์กฐ์—…") tax_company_size = gr.Radio(label="๊ธฐ์—… ๊ทœ๋ชจ", choices=["์†Œ๊ธฐ์—…", "์ค‘๊ธฐ์—…"], value="์†Œ๊ธฐ์—…") tax_revenue = gr.Number(label="์—ฐ๋งค์ถœ (๋ฐฑ๋งŒ์›)", value=500, minimum=0) tax_op_profit = gr.Number(label="์˜์—…์ด์ต (๋ฐฑ๋งŒ์›)", value=50, minimum=0) tax_is_capital = gr.Checkbox(label="์ˆ˜๋„๊ถŒ ์†Œ์žฌ", value=True) tax_establish_years = gr.Slider(label="์—…๋ ฅ (๋…„)", minimum=0, maximum=30, value=3, step=1) tax_ceo_age = gr.Slider(label="๋Œ€ํ‘œ์ž ๋‚˜์ด", minimum=20, maximum=70, value=35, step=1) with gr.Column(): gr.HTML('
    ๐Ÿ”ฌ ๊ธฐ์ˆ ยท์ธ์ฆยทํˆฌ์ž
    ') tax_research_center = gr.Checkbox(label="๊ธฐ์—…๋ถ€์„ค์—ฐ๊ตฌ์†Œ/์ „๋‹ด๋ถ€์„œ ๋ณด์œ ") tax_rd_investment = gr.Number(label="์—ฐ๊ฐ„ R&D ํˆฌ์ž์•ก (๋ฐฑ๋งŒ์›)", value=0, minimum=0) tax_patents = gr.Number(label="๋ณด์œ  ํŠนํ—ˆ ์ˆ˜", value=0, minimum=0) tax_has_venture = gr.Checkbox(label="๋ฒค์ฒ˜์ธ์ฆ") tax_has_innobiz = gr.Checkbox(label="์ด๋…ธ๋น„์ฆˆ") tax_is_female = gr.Checkbox(label="์—ฌ์„ฑ๊ธฐ์—…") tax_is_disabled = gr.Checkbox(label="์žฅ์• ์ธ๊ธฐ์—…") with gr.Column(): gr.HTML('
    ๐Ÿ‘ฅ ๊ณ ์šฉยท์„ค๋น„ํˆฌ์ž
    ') tax_employees = gr.Number(label="์ด ์ง์› ์ˆ˜", value=10, minimum=0) tax_new_youth = gr.Number(label="์‹ ๊ทœ ์ฑ„์šฉ - ์ฒญ๋…„ (์ „๋…„ ๋Œ€๋น„ ์ฆ๊ฐ€)", value=0, minimum=0) tax_new_general = gr.Number(label="์‹ ๊ทœ ์ฑ„์šฉ - ์ผ๋ฐ˜ (์ „๋…„ ๋Œ€๋น„ ์ฆ๊ฐ€)", value=0, minimum=0) tax_facility_invest = gr.Number(label="์„ค๋น„ํˆฌ์ž์•ก (๋ฐฑ๋งŒ์›)", value=0, minimum=0) tax_btn = gr.Button("๐Ÿงฎ ์„ธ๊ธˆ ์ ˆ๊ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹คํ–‰", variant="primary", size="lg") tax_result = gr.HTML() def run_tax_sim(ind, size, rev, op, cap, yrs, age, rc, rd, pat, emp, ny, ng, fac, ven, inno, fem, dis): results, total, corp_tax, taxable, best = simulate_tax_saving( ind, size, rev, op, cap, yrs, age, rc, rd, pat, emp, ny, ng, fac, ven, inno, fem, dis ) return generate_tax_html(results, total, corp_tax, taxable, best) tax_btn.click( fn=run_tax_sim, inputs=[ tax_industry, tax_company_size, tax_revenue, tax_op_profit, tax_is_capital, tax_establish_years, tax_ceo_age, tax_research_center, tax_rd_investment, tax_patents, tax_employees, tax_new_youth, tax_new_general, tax_facility_invest, tax_has_venture, tax_has_innobiz, tax_is_female, tax_is_disabled ], outputs=[tax_result] ) # โ”€โ”€ ํƒญ 2: R&D ์˜ˆ์‚ฐ ํŽธ์„ฑ ๊ณ„์‚ฐ๊ธฐ โ”€โ”€ with gr.Tab("๐Ÿ“Š R&D ์˜ˆ์‚ฐ ํŽธ์„ฑ๊ธฐ"): with gr.Row(): with gr.Column(): gr.HTML('
    ๐Ÿ’ฐ ์ด๊ด„ ์˜ˆ์‚ฐ
    ') rd_total = gr.Number(label="์ด ์‚ฌ์—…๋น„ (๋ฐฑ๋งŒ์›)", value=300, minimum=1) rd_gov_ratio = gr.Slider(label="์ •๋ถ€์ง€์› ๋น„์œจ (%)", minimum=50, maximum=100, value=75, step=5) rd_cash_ratio = gr.Slider(label="๋ฏผ๊ฐ„๋ถ€๋‹ด ์ค‘ ํ˜„๊ธˆ ๋น„์œจ (%)", minimum=0, maximum=100, value=50, step=10) with gr.Column(): gr.HTML('
    ๐Ÿ“‹ ๋น„๋ชฉ๋ณ„ ๋น„์œจ (์ •๋ถ€์ง€์›๊ธˆ ๊ธฐ์ค€, %)
    ') rd_personnel = gr.Slider(label="๋‚ด๋ถ€์ธ๊ฑด๋น„", minimum=0, maximum=70, value=45, step=1) rd_ext_personnel = gr.Slider(label="์™ธ๋ถ€์ธ๊ฑด๋น„", minimum=0, maximum=20, value=5, step=1) rd_equipment = gr.Slider(label="์—ฐ๊ตฌ์žฅ๋น„ยท์žฌ๋ฃŒ๋น„", minimum=0, maximum=40, value=15, step=1) rd_activity = gr.Slider(label="์—ฐ๊ตฌํ™œ๋™๋น„", minimum=0, maximum=20, value=5, step=1) with gr.Column(): gr.HTML('
    ๐Ÿ“‹ ๋น„๋ชฉ๋ณ„ ๋น„์œจ (๊ณ„์†)
    ') rd_consign = gr.Slider(label="์œ„ํƒ์—ฐ๊ตฌ๋น„", minimum=0, maximum=40, value=10, step=1) rd_facility = gr.Slider(label="์—ฐ๊ตฌ์‹œ์„คํ™œ์šฉ๋น„", minimum=0, maximum=20, value=5, step=1) rd_overhead = gr.Slider(label="๊ฐ„์ ‘๋น„", minimum=0, maximum=20, value=10, step=1) gr.HTML('''
    ๐Ÿ’ก ๋น„์œจ ๊ฐ€์ด๋“œ
    ยท ์ธ๊ฑด๋น„ ํ•ฉ๊ณ„: 40~60% ๊ถŒ์žฅ
    ยท ์œ„ํƒ์—ฐ๊ตฌ๋น„: ์ •๋ถ€์ง€์›๊ธˆ์˜ 40% ์ด๋‚ด
    ยท ๊ฐ„์ ‘๋น„: 10~15% ๊ถŒ์žฅ
    ยท ๋น„์œจ ํ•ฉ๊ณ„๊ฐ€ 100%๊ฐ€ ์•„๋‹ˆ๋ฉด ์ž๋™ ์ •๊ทœํ™”
    ''') rd_btn = gr.Button("๐Ÿ“Š ์˜ˆ์‚ฐ ํŽธ์„ฑ ๊ณ„์‚ฐ", variant="primary", size="lg") rd_result = gr.HTML() def run_rd_calc(total, gov, cash, p1, p2, eq, act, con, fac, oh): data = calculate_rd_budget(total, gov, cash, p1, p2, eq, act, con, fac, oh) return generate_rd_budget_html(data) rd_btn.click( fn=run_rd_calc, inputs=[ rd_total, rd_gov_ratio, rd_cash_ratio, rd_personnel, rd_ext_personnel, rd_equipment, rd_activity, rd_consign, rd_facility, rd_overhead ], outputs=[rd_result] ) # ============================================================================ # ๋…๋ฆฝ ์‹คํ–‰์šฉ # ============================================================================ def create_app(): """๋…๋ฆฝ ์‹คํ–‰""" with gr.Blocks(title="์„ธ๊ธˆยท์˜ˆ์‚ฐ ๊ณ„์‚ฐ๊ธฐ") as app: gr.HTML("""

    ๐Ÿงฎ CoBIZ ์„ธ๊ธˆยท์˜ˆ์‚ฐ ๊ณ„์‚ฐ๊ธฐ

    """) create_tax_calc_tab() return app if __name__ == "__main__": app = create_app() app.launch(server_name="0.0.0.0", server_port=7861)