""" ๐งฎ 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"""
2026๋ ์กฐ์ธํน๋ก์ ํ๋ฒ ๊ธฐ์ค | ์ค์๊ธฐ์ ์ธ์ ํํ ์๋ ์ค์บ
๊ตญ๊ฐ์ฐ๊ตฌ๊ฐ๋ฐ์ฌ์ ์ฐ๊ตฌ๊ฐ๋ฐ๋น ์ฌ์ฉ๊ธฐ์ค ์ ์ฉ
| ๊ตฌ๋ถ | ๋น๋ชฉ | ๋น์จ | ๊ธ์ก | |
|---|---|---|---|---|
| ํฉ๊ณ | 100% | {gov/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)}
๊ธฐ์ ์ ๋ณด๋ฅผ ์ ๋ ฅํ๋ฉด ์ ์ฉ ๊ฐ๋ฅํ ์ธ์ ํํ๊ณผ R&D ์์ฐ์ ์๋ ๊ณ์ฐํฉ๋๋ค