seawolf2357 commited on
Commit
948507d
·
verified ·
1 Parent(s): 4e6c75b

Upload biz_tools.py

Browse files
Files changed (1) hide show
  1. biz_tools.py +918 -0
biz_tools.py ADDED
@@ -0,0 +1,918 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ 🧮 CoBIZ 세금 절감 시뮬레이터 & R&D 예산 편성 계산기
3
+ ================================================================================
4
+ 1. 세금 절감 시뮬레이터: 기업 프로필 기반 7대 세제 혜택 자동 스캔 + 예상 절감액
5
+ 2. R&D 예산 편성 계산기: 총 사업비 → 비목별 자동 배분 + 상한 체크
6
+ ================================================================================
7
+ """
8
+
9
+ import gradio as gr
10
+ import math
11
+ from datetime import datetime, date
12
+
13
+ # ============================================================================
14
+ # 1. 세금 절감 시뮬레이터 - 데이터 & 로직
15
+ # ============================================================================
16
+
17
+ # 창업중소기업 세액감면 업종 코드
18
+ STARTUP_ELIGIBLE_INDUSTRIES = [
19
+ "C. 제조업", "J. 정보통신업", "M. 전문·과학·기술", "N. 사업시설관리",
20
+ "G. 도매·소매업", "H. 운수·창고업", "F. 건설업", "R. 예술·스포츠",
21
+ "P. 교육서비스업", "Q. 보건·사회복지"
22
+ ]
23
+
24
+ # 중소기업 특별세액감면 업종별 감면율 (소기업/중기업)
25
+ SME_SPECIAL_RATES = {
26
+ "C. 제조업": {"소기업": 0.20, "중기업": 0.10, "소기업_수도권": 0.10},
27
+ "E. 수도·환경": {"소기업": 0.20, "중기업": 0.10, "소기업_수도권": 0.10},
28
+ "F. 건설업": {"소기업": 0.20, "중기업": 0.10, "소기업_수도권": 0.10},
29
+ "G. 도매·소매업": {"소기업": 0.10, "중기업": 0.05, "소기업_수도권": 0.05},
30
+ "H. 운수·창고업": {"소기업": 0.20, "중기업": 0.10, "소기업_수도권": 0.10},
31
+ "J. 정보통신업": {"소기업": 0.20, "중기업": 0.10, "소기업_수도권": 0.10},
32
+ "K. 금융·보험업": {"소기업": 0.10, "중기업": 0.05, "소기업_수도권": 0.05},
33
+ "L. 부동산업": {"소기업": 0.10, "중기업": 0.05, "소기업_수도권": 0.05},
34
+ "M. 전문·과학·기술": {"소기업": 0.20, "중기업": 0.10, "소기업_수도권": 0.10},
35
+ "N. 사업시설관리": {"소기업": 0.20, "중기업": 0.10, "소기업_수도권": 0.10},
36
+ "P. 교육서비스업": {"소기업": 0.10, "중기업": 0.05, "소기업_수도권": 0.05},
37
+ "Q. 보건·사회복지": {"소기업": 0.10, "중기업": 0.05, "소기업_수도권": 0.05},
38
+ "R. 예술·스포츠": {"소기업": 0.10, "중기업": 0.05, "소기업_수도권": 0.05},
39
+ "S. 수리·개인서비스": {"소기업": 0.10, "중기업": 0.05, "소기업_수도권": 0.05},
40
+ "A. 농림어업": {"소기업": 0.20, "중기업": 0.10, "소기업_수도권": 0.10},
41
+ "B. 광업": {"소기업": 0.20, "중기업": 0.10, "소기업_수도권": 0.10},
42
+ }
43
+
44
+ # 고용증대 세액공제 금액 (중소기업, 수도권/비수도권)
45
+ EMPLOYMENT_CREDIT = {
46
+ "청년": {"수도권": 1450, "비수도권": 1550}, # 만원/인/년
47
+ "장애인": {"수도권": 1450, "비수도권": 1550},
48
+ "60세이상": {"수도권": 700, "비수도권": 770},
49
+ "일반": {"수도권": 850, "비수도권": 950},
50
+ }
51
+
52
+
53
+ def simulate_tax_saving(
54
+ industry, company_size, revenue_m, operating_profit_m,
55
+ is_capital_region, establish_years, ceo_age,
56
+ has_research_center, rd_investment_m, patent_count,
57
+ total_employees, new_hires_youth, new_hires_general,
58
+ facility_investment_m, has_venture, has_innobiz,
59
+ is_female_company, is_disabled_company
60
+ ):
61
+ """세금 절감 시뮬레이션 실행"""
62
+
63
+ results = []
64
+ total_saving = 0
65
+
66
+ # 법인세 과세표준 추정 (영업이익 기준 간이 계산)
67
+ taxable_income = max(0, operating_profit_m * 1_000_000) # 원 단위
68
+
69
+ # 법인세 계산 (중소기업 특례)
70
+ if taxable_income <= 500_000_000: # 5억 이하
71
+ corp_tax = taxable_income * 0.09
72
+ elif taxable_income <= 20_000_000_000: # 200억 이하
73
+ corp_tax = 500_000_000 * 0.09 + (taxable_income - 500_000_000) * 0.19
74
+ else:
75
+ corp_tax = 500_000_000 * 0.09 + 19_500_000_000 * 0.19 + (taxable_income - 20_000_000_000) * 0.21
76
+
77
+ # ─────────────────────────────────────────────
78
+ # ① 창업중소기업 세액감면
79
+ # ─────────────────────────────────────────────
80
+ startup_saving = 0
81
+ startup_rate = 0
82
+ startup_eligible = (establish_years <= 5 and industry in STARTUP_ELIGIBLE_INDUSTRIES)
83
+ startup_note = ""
84
+
85
+ if startup_eligible:
86
+ if not is_capital_region and ceo_age < 35:
87
+ startup_rate = 1.0
88
+ startup_note = "비수도권 + 청년창업 → 100% 감면 (최저한세 배제)"
89
+ elif not is_capital_region:
90
+ startup_rate = 0.5
91
+ startup_note = "비수도권 창업 → 50% 감면"
92
+ elif ceo_age < 35:
93
+ startup_rate = 0.5
94
+ startup_note = "수도권 청년창업 → 50% 감면"
95
+ else:
96
+ startup_rate = 0.0
97
+ startup_note = "수도권 일반 창업 → 해당 없음"
98
+
99
+ startup_saving = int(corp_tax * startup_rate)
100
+ else:
101
+ if establish_years > 5:
102
+ startup_note = "업력 5년 초과 → 대상 외"
103
+ else:
104
+ startup_note = "비대상 업종"
105
+
106
+ results.append({
107
+ "name": "창업중소기업 세액감면",
108
+ "icon": "🌱",
109
+ "saving": startup_saving,
110
+ "rate": f"{int(startup_rate*100)}%",
111
+ "note": startup_note,
112
+ "eligible": startup_eligible and startup_rate > 0,
113
+ "conflict": "중소기업특별세액감면"
114
+ })
115
+
116
+ # ─────────────────────────────────────────────
117
+ # ② 중소기업 특별세액감면
118
+ # ─────────────────────────────────────────────
119
+ sme_saving = 0
120
+ sme_rate = 0
121
+ sme_note = ""
122
+ sme_eligible = industry in SME_SPECIAL_RATES
123
+
124
+ if sme_eligible:
125
+ rates = SME_SPECIAL_RATES[industry]
126
+ if company_size == "소기업" and is_capital_region:
127
+ sme_rate = rates.get("소기업_수도권", 0.05)
128
+ elif company_size == "소기업":
129
+ sme_rate = rates.get("소기업", 0.10)
130
+ else:
131
+ sme_rate = rates.get("중기업", 0.05)
132
+
133
+ sme_saving = int(corp_tax * sme_rate)
134
+ sme_note = f"{company_size} / {'수도권' if is_capital_region else '비수도권'} → {int(sme_rate*100)}% 감면"
135
+ else:
136
+ sme_note = "비대상 업종"
137
+
138
+ results.append({
139
+ "name": "중소기업 특별세액감면",
140
+ "icon": "🏢",
141
+ "saving": sme_saving,
142
+ "rate": f"{int(sme_rate*100)}%",
143
+ "note": sme_note,
144
+ "eligible": sme_eligible and sme_rate > 0,
145
+ "conflict": "창업중소기업세액감면"
146
+ })
147
+
148
+ # ─────────────────────────────────────────────
149
+ # ③ R&D 세액공제
150
+ # ─────────────────────────────────────────────
151
+ rd_saving = 0
152
+ rd_note = ""
153
+ rd_eligible = has_research_center and rd_investment_m > 0
154
+
155
+ if rd_eligible:
156
+ rd_amount = rd_investment_m * 1_000_000 # 원
157
+ rd_rate = 0.25 # 중소기업 일반 R&D 당기분 25%
158
+ rd_saving = int(rd_amount * rd_rate)
159
+ rd_note = f"연구소 보유 + R&D {rd_investment_m:,.0f}백만원 × 25% = {rd_saving/10000:,.0f}만원"
160
+ else:
161
+ if not has_research_center:
162
+ rd_note = "기업부설연구소/전담부서 미등록"
163
+ else:
164
+ rd_note = "R&D 투자액 없음"
165
+
166
+ results.append({
167
+ "name": "R&D 세액공제",
168
+ "icon": "🔬",
169
+ "saving": rd_saving,
170
+ "rate": "25%",
171
+ "note": rd_note,
172
+ "eligible": rd_eligible,
173
+ "conflict": None
174
+ })
175
+
176
+ # ─────────────────────────────────────────────
177
+ # ④ 고용증대 세액공제
178
+ # ─────────────────────────────────────────────
179
+ emp_saving = 0
180
+ emp_note_parts = []
181
+ region_key = "수도권" if is_capital_region else "비수도권"
182
+
183
+ if new_hires_youth > 0:
184
+ youth_credit = EMPLOYMENT_CREDIT["청년"][region_key] * new_hires_youth * 10000
185
+ emp_saving += youth_credit
186
+ emp_note_parts.append(f"청년 {new_hires_youth}명 × {EMPLOYMENT_CREDIT['청년'][region_key]}만원")
187
+
188
+ if new_hires_general > 0:
189
+ gen_credit = EMPLOYMENT_CREDIT["일반"][region_key] * new_hires_general * 10000
190
+ emp_saving += gen_credit
191
+ emp_note_parts.append(f"일반 {new_hires_general}명 × {EMPLOYMENT_CREDIT['일반'][region_key]}만원")
192
+
193
+ emp_saving = int(emp_saving)
194
+ emp_note = " + ".join(emp_note_parts) if emp_note_parts else "전년대비 신규 고용 증가분 없음"
195
+ if emp_saving > 0:
196
+ emp_note += f" (3년간 적용, 연 {emp_saving/10000:,.0f}만원)"
197
+
198
+ results.append({
199
+ "name": "고용증대 세액공제",
200
+ "icon": "👥",
201
+ "saving": emp_saving,
202
+ "rate": "인당 최대 1,550만원",
203
+ "note": emp_note,
204
+ "eligible": emp_saving > 0,
205
+ "conflict": None
206
+ })
207
+
208
+ # ─────────────────────────────────────────────
209
+ # ⑤ 통합투자 세액공제
210
+ # ─────────────────────────────────────────────
211
+ invest_saving = 0
212
+ invest_note = ""
213
+
214
+ if facility_investment_m > 0:
215
+ invest_rate = 0.10 # 중소기업 기본 10%
216
+ invest_saving = int(facility_investment_m * 1_000_000 * invest_rate)
217
+ invest_note = f"설비투자 {facility_investment_m:,.0f}백만원 × 10% = {invest_saving/10000:,.0f}만원"
218
+ if has_venture or has_innobiz:
219
+ additional = int(facility_investment_m * 1_000_000 * 0.02)
220
+ invest_saving += additional
221
+ invest_note += f" + 추가 2% ({additional/10000:,.0f}만원)"
222
+ else:
223
+ invest_note = "사업용 자산 투자 없음"
224
+
225
+ results.append({
226
+ "name": "통합투자 세액공제",
227
+ "icon": "🏭",
228
+ "saving": invest_saving,
229
+ "rate": "10~12%",
230
+ "note": invest_note,
231
+ "eligible": invest_saving > 0,
232
+ "conflict": None
233
+ })
234
+
235
+ # ─────────────────────────────────────────────
236
+ # ⑥ 사회보험료 세액공제
237
+ # ─────────────────────────────────────────────
238
+ social_saving = 0
239
+ social_note = ""
240
+ total_new = new_hires_youth + new_hires_general
241
+
242
+ if total_new > 0:
243
+ avg_salary = 36_000_000 # 평균 연봉 3,600만원 가정
244
+ employer_rate = 0.098 # 사업주 부담 사회보험료율 (국민연금+건강+고용+산재) 약 9.8%
245
+ social_saving = int(total_new * avg_salary * employer_rate * 0.5) # 50% 공제
246
+ social_note = f"신규 {total_new}명 × 사업주부담 보험료 50% = {social_saving/10000:,.0f}만원"
247
+ else:
248
+ social_note = "신규 고용 없음"
249
+
250
+ results.append({
251
+ "name": "사회보험료 세액공제",
252
+ "icon": "🛡️",
253
+ "saving": social_saving,
254
+ "rate": "50%",
255
+ "note": social_note,
256
+ "eligible": social_saving > 0,
257
+ "conflict": None
258
+ })
259
+
260
+ # ─────────────────────────────────────────────
261
+ # ⑦ 기술이전 세액감면
262
+ # ─────────────────────────────────────────────
263
+ tech_saving = 0
264
+ tech_note = ""
265
+ tech_eligible = patent_count > 0
266
+
267
+ if tech_eligible:
268
+ tech_note = f"특허 {patent_count}건 보유 → 이전 시 소득의 50%, 대여 시 25% 감면 가능 (실현 시 적용)"
269
+ else:
270
+ tech_note = "보유 특허 없음"
271
+
272
+ results.append({
273
+ "name": "기술이전 세액감면",
274
+ "icon": "📜",
275
+ "saving": tech_saving,
276
+ "rate": "이전50%/대여25%",
277
+ "note": tech_note,
278
+ "eligible": tech_eligible,
279
+ "conflict": None
280
+ })
281
+
282
+ # ─────────────────────────────────────────────
283
+ # 중복 적용 처리
284
+ # ─────────────────────────────────────────────
285
+ # 창업감면 vs 특별감면 → 둘 중 큰 것만
286
+ best_choice = ""
287
+ if results[0]["eligible"] and results[1]["eligible"]:
288
+ if results[0]["saving"] >= results[1]["saving"]:
289
+ results[1]["saving"] = 0
290
+ results[1]["note"] += " ⚠️ 창업감면과 중복 불가 (창업감면이 유리)"
291
+ results[1]["eligible"] = False
292
+ best_choice = "창업중소기업 세액감면"
293
+ else:
294
+ results[0]["saving"] = 0
295
+ results[0]["note"] += " ⚠️ 특별감면과 중복 불가 (특별감면이 유리)"
296
+ results[0]["eligible"] = False
297
+ best_choice = "중소기업 특별세액감면"
298
+ elif results[0]["eligible"]:
299
+ best_choice = "창업중소기업 세액감면"
300
+ elif results[1]["eligible"]:
301
+ best_choice = "중소기업 특별세액감면"
302
+
303
+ total_saving = sum(r["saving"] for r in results)
304
+
305
+ return results, total_saving, corp_tax, taxable_income, best_choice
306
+
307
+
308
+ def generate_tax_html(results, total_saving, corp_tax, taxable_income, best_choice):
309
+ """세금 절감 시뮬레이션 결과 HTML 생성"""
310
+
311
+ eligible_count = sum(1 for r in results if r["eligible"])
312
+ saving_pct = (total_saving / corp_tax * 100) if corp_tax > 0 else 0
313
+
314
+ # 워터폴 차트 데이터
315
+ waterfall_items = []
316
+ cumulative = 0
317
+ for r in results:
318
+ if r["saving"] > 0:
319
+ cumulative += r["saving"]
320
+ waterfall_items.append((r["icon"] + " " + r["name"][:6], r["saving"], cumulative))
321
+
322
+ max_val = max(corp_tax, cumulative) if cumulative > 0 else corp_tax
323
+
324
+ # 바 차트 생성
325
+ bars_html = ""
326
+ for r in results:
327
+ color = "#6fd9a8" if r["eligible"] else "#3d3d5c"
328
+ opacity = "1" if r["eligible"] else "0.4"
329
+ width_pct = min(95, (r["saving"] / max_val * 100)) if max_val > 0 and r["saving"] > 0 else 0
330
+ saving_text = f"{r['saving']/10000:,.0f}만원" if r["saving"] > 0 else "해당없음"
331
+
332
+ bars_html += f"""
333
+ <div style="margin-bottom:16px;opacity:{opacity};">
334
+ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;">
335
+ <span style="font-size:14px;font-weight:600;color:#e8e8f0;">
336
+ {r['icon']} {r['name']}
337
+ {'<span style="color:#6fd9a8;font-size:11px;margin-left:6px;">✓ 적용</span>' if r['eligible'] else '<span style="color:#666;font-size:11px;margin-left:6px;">미적용</span>'}
338
+ </span>
339
+ <span style="font-size:15px;font-weight:700;color:{color};">{saving_text}</span>
340
+ </div>
341
+ <div style="background:#1a1a2e;border-radius:8px;height:28px;overflow:hidden;position:relative;">
342
+ <div style="width:{width_pct}%;height:100%;background:linear-gradient(90deg,{color},{color}88);
343
+ border-radius:8px;transition:width 0.8s ease;"></div>
344
+ </div>
345
+ <div style="font-size:11px;color:#8888a0;margin-top:4px;">{r['note']}</div>
346
+ </div>
347
+ """
348
+
349
+ # 워터폴 차트
350
+ waterfall_html = ""
351
+ if waterfall_items:
352
+ wf_max = max(cumulative, 1)
353
+ for name, amount, cum in waterfall_items:
354
+ bottom_pct = (cum - amount) / wf_max * 100
355
+ height_pct = amount / wf_max * 100
356
+ waterfall_html += f"""
357
+ <div style="flex:1;display:flex;flex-direction:column;align-items:center;min-width:70px;">
358
+ <div style="font-size:10px;color:#6fd9a8;font-weight:600;margin-bottom:4px;">
359
+ +{amount/10000:,.0f}만
360
+ </div>
361
+ <div style="width:100%;height:200px;position:relative;background:#1a1a2e;border-radius:6px;">
362
+ <div style="position:absolute;bottom:{bottom_pct}%;width:100%;height:{max(height_pct, 3)}%;
363
+ background:linear-gradient(180deg,#6fd9a8,#4a9d7d);border-radius:4px;"></div>
364
+ </div>
365
+ <div style="font-size:9px;color:#8888a0;margin-top:6px;text-align:center;
366
+ word-break:keep-all;">{name}</div>
367
+ </div>
368
+ """
369
+
370
+ html = f"""
371
+ <div style="background:linear-gradient(135deg,#0d1117,#161b22,#0d1117);padding:30px;
372
+ border-radius:20px;border:1px solid rgba(111,217,168,0.2);font-family:'Noto Sans KR',sans-serif;">
373
+
374
+ <!-- 헤더 -->
375
+ <div style="text-align:center;margin-bottom:30px;">
376
+ <h2 style="margin:0;font-size:26px;background:linear-gradient(135deg,#6fd9a8,#fff);
377
+ -webkit-background-clip:text;-webkit-text-fill-color:transparent;">
378
+ 🧮 세금 절감 시뮬레이션 결과
379
+ </h2>
380
+ <p style="color:#8888a0;margin:8px 0 0;font-size:13px;">
381
+ 2026년 조세특례제한법 기준 | 중소기업 세제 혜택 자동 스캔
382
+ </p>
383
+ </div>
384
+
385
+ <!-- 핵심 KPI -->
386
+ <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:30px;">
387
+ <div style="background:#1a1a2e;border-radius:14px;padding:20px;text-align:center;
388
+ border:1px solid rgba(111,217,168,0.15);">
389
+ <div style="font-size:11px;color:#8888a0;">추정 법인세</div>
390
+ <div style="font-size:22px;font-weight:700;color:#ff6b6b;margin-top:6px;">
391
+ {corp_tax/10000:,.0f}<span style="font-size:12px;color:#8888a0;">만원</span>
392
+ </div>
393
+ </div>
394
+ <div style="background:#1a1a2e;border-radius:14px;padding:20px;text-align:center;
395
+ border:1px solid rgba(111,217,168,0.3);">
396
+ <div style="font-size:11px;color:#8888a0;">총 절감액</div>
397
+ <div style="font-size:22px;font-weight:700;color:#6fd9a8;margin-top:6px;">
398
+ {total_saving/10000:,.0f}<span style="font-size:12px;color:#8888a0;">만원</span>
399
+ </div>
400
+ </div>
401
+ <div style="background:#1a1a2e;border-radius:14px;padding:20px;text-align:center;
402
+ border:1px solid rgba(255,215,0,0.2);">
403
+ <div style="font-size:11px;color:#8888a0;">절감률</div>
404
+ <div style="font-size:22px;font-weight:700;color:#ffd700;margin-top:6px;">
405
+ {saving_pct:.1f}<span style="font-size:12px;color:#8888a0;">%</span>
406
+ </div>
407
+ </div>
408
+ <div style="background:#1a1a2e;border-radius:14px;padding:20px;text-align:center;
409
+ border:1px solid rgba(100,149,237,0.2);">
410
+ <div style="font-size:11px;color:#8888a0;">적용 가능</div>
411
+ <div style="font-size:22px;font-weight:700;color:#6495ed;margin-top:6px;">
412
+ {eligible_count}<span style="font-size:12px;color:#8888a0;">건 / 7건</span>
413
+ </div>
414
+ </div>
415
+ </div>
416
+
417
+ <!-- 항목별 절감액 바 차트 -->
418
+ <div style="background:#12121e;border-radius:14px;padding:24px;margin-bottom:24px;
419
+ border:1px solid rgba(111,217,168,0.1);">
420
+ <h3 style="color:#e8e8f0;font-size:16px;margin:0 0 20px;">
421
+ 📊 항목별 예상 절감액
422
+ </h3>
423
+ {bars_html}
424
+ </div>
425
+
426
+ <!-- 워터폴 차트 -->
427
+ {'<div style="background:#12121e;border-radius:14px;padding:24px;margin-bottom:24px;border:1px solid rgba(111,217,168,0.1);"><h3 style="color:#e8e8f0;font-size:16px;margin:0 0 16px;">💧 절감액 누적 워터폴</h3><div style="display:flex;gap:8px;align-items:flex-end;">' + waterfall_html + '</div></div>' if waterfall_html else ''}
428
+
429
+ <!-- 중복 적용 안내 -->
430
+ <div style="background:linear-gradient(145deg,#1a2a30,#0d1a1f);border-radius:14px;padding:20px;
431
+ border-left:4px solid #ffd700;margin-bottom:20px;">
432
+ <h4 style="color:#ffd700;margin:0 0 12px;font-size:14px;">⚠️ 중복 적용 안내</h4>
433
+ <ul style="margin:0;padding-left:20px;color:#c8c8d8;font-size:13px;line-height:2;">
434
+ <li><strong>창업감면 ↔ 특별감면:</strong> 중복 불가 → {'<span style="color:#6fd9a8;">' + best_choice + ' 적용 (유리)</span>' if best_choice else '둘 다 미해당'}</li>
435
+ <li><strong>R&D 세액공제:</strong> 위 감면과 <span style="color:#6fd9a8;">중복 적용 가능</span></li>
436
+ <li><strong>고용증대 + 사회보험료:</strong> <span style="color:#6fd9a8;">중복 적용 가능</span> (3년간)</li>
437
+ <li><strong>통합투자:</strong> 창업감면과 중복 불가, 특별감면과는 가능</li>
438
+ </ul>
439
+ </div>
440
+
441
+ <!-- 면책 -->
442
+ <div style="text-align:center;padding:12px;color:#555;font-size:11px;
443
+ border-top:1px solid rgba(111,217,168,0.1);margin-top:16px;">
444
+ ※ 본 시뮬레이션은 참고용이며, 정확한 세금 계산은 세무사와 상담하시기 바랍니다.
445
+ <br>영업이익 기반 간이 추정 | 실제 과세표준은 세무조정 후 달라질 수 있습니다.
446
+ </div>
447
+ </div>
448
+ """
449
+ return html
450
+
451
+
452
+ # ============================================================================
453
+ # 2. R&D 예산 편성 계산기 - 데이터 & 로직
454
+ # ============================================================================
455
+
456
+ RD_BUDGET_CATEGORIES = {
457
+ "인건비": {
458
+ "내부인건비": {"desc": "참여연구원 인건비 (연구책임자, 참여연구원)", "default_pct": 0.45},
459
+ "외부인건비": {"desc": "외부 전문가 위촉 수당", "default_pct": 0.05},
460
+ },
461
+ "직접비": {
462
+ "연구장비·재료비": {"desc": "연구장비 구입·임차, 재료비, 시약", "default_pct": 0.12},
463
+ "연구활동비": {"desc": "국내외출장, 기술정보수집, 학회참가", "default_pct": 0.05},
464
+ "위탁연구비": {"desc": "외부기관 위탁 연구 비용", "default_pct": 0.08},
465
+ "연구시설활용비": {"desc": "연구시설 임차료, 이용료", "default_pct": 0.03},
466
+ },
467
+ "간접비": {
468
+ "간접비": {"desc": "기관 관리비, 복리후생, 보험료 등", "default_pct": 0.10},
469
+ }
470
+ }
471
+
472
+
473
+ def calculate_rd_budget(
474
+ total_budget_m, gov_ratio, cash_ratio,
475
+ personnel_pct, ext_personnel_pct,
476
+ equipment_pct, activity_pct, consign_pct, facility_pct,
477
+ overhead_pct
478
+ ):
479
+ """R&D 예산 편성 계산"""
480
+
481
+ total = total_budget_m * 1_000_000 # 원 단위
482
+ gov_amount = total * gov_ratio / 100
483
+ private_amount = total - gov_amount
484
+ cash_amount = private_amount * cash_ratio / 100
485
+ inkind_amount = private_amount - cash_amount
486
+
487
+ # 비목별 배분 (정부지원금 기준)
488
+ pct_sum = personnel_pct + ext_personnel_pct + equipment_pct + activity_pct + consign_pct + facility_pct + overhead_pct
489
+
490
+ # 정규화 (합이 100이 안 될 경우)
491
+ if pct_sum == 0:
492
+ pct_sum = 100
493
+
494
+ items = [
495
+ {"category": "인건비", "name": "내부인건비", "pct": personnel_pct, "amount": gov_amount * personnel_pct / pct_sum},
496
+ {"category": "인건비", "name": "외부인건비", "pct": ext_personnel_pct, "amount": gov_amount * ext_personnel_pct / pct_sum},
497
+ {"category": "직접비", "name": "연구장비·재료비", "pct": equipment_pct, "amount": gov_amount * equipment_pct / pct_sum},
498
+ {"category": "직접비", "name": "연구활동비", "pct": activity_pct, "amount": gov_amount * activity_pct / pct_sum},
499
+ {"category": "직접비", "name": "위탁연구비", "pct": consign_pct, "amount": gov_amount * consign_pct / pct_sum},
500
+ {"category": "직접비", "name": "연구시설활용비", "pct": facility_pct, "amount": gov_amount * facility_pct / pct_sum},
501
+ {"category": "간접비", "name": "간접비", "pct": overhead_pct, "amount": gov_amount * overhead_pct / pct_sum},
502
+ ]
503
+
504
+ # 상한 체크
505
+ warnings = []
506
+ personnel_total = items[0]["amount"] + items[1]["amount"]
507
+ consign_amount = items[4]["amount"]
508
+ overhead_amount = items[6]["amount"]
509
+ direct_cost = sum(i["amount"] for i in items if i["category"] != "간접비")
510
+
511
+ # 위탁연구비 상한 (정부지원금의 40%)
512
+ if consign_amount > gov_amount * 0.40:
513
+ warnings.append(f"⚠️ 위탁연구비({consign_amount/10000:,.0f}만)가 정부지원금 40% 상한({gov_amount*0.40/10000:,.0f}만) 초과")
514
+
515
+ # 간접비 상한 (직접비의 일정 비율, 통상 정부지원금의 10% 내외)
516
+ if overhead_pct > 15:
517
+ warnings.append(f"⚠️ 간접비 비율({overhead_pct:.0f}%)이 권장 상한(15%) 초과")
518
+
519
+ # 인건비 비율 체크
520
+ if personnel_pct + ext_personnel_pct > 70:
521
+ warnings.append(f"⚠️ 인건비 비율({personnel_pct+ext_personnel_pct:.0f}%)이 통상 상한(70%) 초과")
522
+
523
+ # 합계 검증
524
+ if abs(pct_sum - 100) > 0.1:
525
+ warnings.append(f"ℹ️ 비목 비율 합계가 {pct_sum:.1f}%입니다 (자동 정규화 적용)")
526
+
527
+ return {
528
+ "total": total,
529
+ "gov_amount": gov_amount,
530
+ "private_amount": private_amount,
531
+ "cash_amount": cash_amount,
532
+ "inkind_amount": inkind_amount,
533
+ "items": items,
534
+ "warnings": warnings,
535
+ "personnel_total": personnel_total,
536
+ "direct_cost": direct_cost,
537
+ "overhead_amount": overhead_amount,
538
+ }
539
+
540
+
541
+ def generate_rd_budget_html(data):
542
+ """R&D 예산 편성 결과 HTML 생성"""
543
+
544
+ total = data["total"]
545
+ gov = data["gov_amount"]
546
+ priv = data["private_amount"]
547
+ cash = data["cash_amount"]
548
+ inkind = data["inkind_amount"]
549
+ items = data["items"]
550
+ warnings = data["warnings"]
551
+
552
+ # 비목별 테이블 행 생성
553
+ rows_html = ""
554
+ cat_colors = {"인건비": "#6fd9a8", "직접비": "#6495ed", "간접비": "#ffd700"}
555
+ prev_cat = ""
556
+
557
+ for item in items:
558
+ cat_label = ""
559
+ if item["category"] != prev_cat:
560
+ cat_label = item["category"]
561
+ prev_cat = item["category"]
562
+
563
+ color = cat_colors.get(item["category"], "#fff")
564
+ bar_width = min(90, item["amount"] / gov * 100) if gov > 0 else 0
565
+
566
+ rows_html += f"""
567
+ <tr style="border-bottom:1px solid rgba(255,255,255,0.06);">
568
+ <td style="padding:12px;color:{color};font-weight:{'700' if cat_label else '400'};font-size:13px;
569
+ width:80px;">{cat_label}</td>
570
+ <td style="padding:12px;color:#e8e8f0;font-size:13px;">{item['name']}</td>
571
+ <td style="padding:12px;text-align:right;color:#8888a0;font-size:13px;">{item['pct']:.0f}%</td>
572
+ <td style="padding:12px;text-align:right;color:#e8e8f0;font-weight:600;font-size:14px;">
573
+ {item['amount']/10000:,.0f}만원
574
+ </td>
575
+ <td style="padding:12px;width:120px;">
576
+ <div style="background:#1a1a2e;border-radius:4px;height:12px;overflow:hidden;">
577
+ <div style="width:{bar_width}%;height:100%;background:{color};border-radius:4px;"></div>
578
+ </div>
579
+ </td>
580
+ </tr>
581
+ """
582
+
583
+ # 경고 메시지
584
+ warn_html = ""
585
+ if warnings:
586
+ warn_items = "".join(f'<li style="margin-bottom:6px;">{w}</li>' for w in warnings)
587
+ warn_html = f"""
588
+ <div style="background:rgba(255,107,107,0.1);border-radius:10px;padding:16px;margin-bottom:20px;
589
+ border:1px solid rgba(255,107,107,0.3);">
590
+ <ul style="margin:0;padding-left:20px;color:#ff9999;font-size:13px;line-height:1.8;">
591
+ {warn_items}
592
+ </ul>
593
+ </div>
594
+ """
595
+
596
+ # 파이 차트 (CSS만으로)
597
+ cat_totals = {}
598
+ for item in items:
599
+ cat_totals[item["category"]] = cat_totals.get(item["category"], 0) + item["amount"]
600
+
601
+ pie_segments = ""
602
+ legend_html = ""
603
+ start_deg = 0
604
+ for cat, amount in cat_totals.items():
605
+ pct = amount / gov * 100 if gov > 0 else 0
606
+ end_deg = start_deg + pct * 3.6
607
+ color = cat_colors.get(cat, "#fff")
608
+ pie_segments += f"{color} {start_deg}deg {end_deg}deg,"
609
+ legend_html += f"""
610
+ <div style="display:flex;align-items:center;gap:8px;margin-bottom:8px;">
611
+ <div style="width:12px;height:12px;border-radius:3px;background:{color};"></div>
612
+ <span style="color:#c8c8d8;font-size:13px;">{cat} {pct:.1f}% ({amount/10000:,.0f}만)</span>
613
+ </div>
614
+ """
615
+ start_deg = end_deg
616
+
617
+ pie_gradient = pie_segments.rstrip(",")
618
+
619
+ html = f"""
620
+ <div style="background:linear-gradient(135deg,#0d1117,#161b22,#0d1117);padding:30px;
621
+ border-radius:20px;border:1px solid rgba(100,149,237,0.2);font-family:'Noto Sans KR',sans-serif;">
622
+
623
+ <!-- 헤더 -->
624
+ <div style="text-align:center;margin-bottom:30px;">
625
+ <h2 style="margin:0;font-size:26px;background:linear-gradient(135deg,#6495ed,#fff);
626
+ -webkit-background-clip:text;-webkit-text-fill-color:transparent;">
627
+ 📊 R&D 예산 편성 결과
628
+ </h2>
629
+ <p style="color:#8888a0;margin:8px 0 0;font-size:13px;">
630
+ 국가연구개발사업 연구개발비 사용기준 적용
631
+ </p>
632
+ </div>
633
+
634
+ <!-- 총괄 KPI -->
635
+ <div style="display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:24px;">
636
+ <div style="background:#1a1a2e;border-radius:12px;padding:16px;text-align:center;
637
+ border:1px solid rgba(100,149,237,0.15);">
638
+ <div style="font-size:10px;color:#8888a0;">총 사업비</div>
639
+ <div style="font-size:18px;font-weight:700;color:#e8e8f0;margin-top:4px;">
640
+ {total/100000000:,.1f}<span style="font-size:11px;">억</span>
641
+ </div>
642
+ </div>
643
+ <div style="background:#1a1a2e;border-radius:12px;padding:16px;text-align:center;
644
+ border:1px solid rgba(111,217,168,0.2);">
645
+ <div style="font-size:10px;color:#8888a0;">정부지원금</div>
646
+ <div style="font-size:18px;font-weight:700;color:#6fd9a8;margin-top:4px;">
647
+ {gov/100000000:,.2f}<span style="font-size:11px;">억</span>
648
+ </div>
649
+ </div>
650
+ <div style="background:#1a1a2e;border-radius:12px;padding:16px;text-align:center;
651
+ border:1px solid rgba(255,215,0,0.15);">
652
+ <div style="font-size:10px;color:#8888a0;">민간부담금</div>
653
+ <div style="font-size:18px;font-weight:700;color:#ffd700;margin-top:4px;">
654
+ {priv/100000000:,.2f}<span style="font-size:11px;">억</span>
655
+ </div>
656
+ </div>
657
+ <div style="background:#1a1a2e;border-radius:12px;padding:16px;text-align:center;">
658
+ <div style="font-size:10px;color:#8888a0;">현금</div>
659
+ <div style="font-size:18px;font-weight:700;color:#c8c8d8;margin-top:4px;">
660
+ {cash/10000:,.0f}<span style="font-size:11px;">만</span>
661
+ </div>
662
+ </div>
663
+ <div style="background:#1a1a2e;border-radius:12px;padding:16px;text-align:center;">
664
+ <div style="font-size:10px;color:#8888a0;">현물</div>
665
+ <div style="font-size:18px;font-weight:700;color:#c8c8d8;margin-top:4px;">
666
+ {inkind/10000:,.0f}<span style="font-size:11px;">만</span>
667
+ </div>
668
+ </div>
669
+ </div>
670
+
671
+ {warn_html}
672
+
673
+ <!-- 비목별 상세 테이블 -->
674
+ <div style="background:#12121e;border-radius:14px;padding:24px;margin-bottom:24px;
675
+ border:1px solid rgba(100,149,237,0.1);overflow-x:auto;">
676
+ <h3 style="color:#e8e8f0;font-size:16px;margin:0 0 16px;">📋 비목별 배분 내역 (정부지원금 기준)</h3>
677
+ <table style="width:100%;border-collapse:collapse;">
678
+ <thead>
679
+ <tr style="border-bottom:2px solid rgba(100,149,237,0.2);">
680
+ <th style="padding:10px;text-align:left;color:#6495ed;font-size:12px;">구분</th>
681
+ <th style="padding:10px;text-align:left;color:#6495ed;font-size:12px;">비목</th>
682
+ <th style="padding:10px;text-align:right;color:#6495ed;font-size:12px;">비율</th>
683
+ <th style="padding:10px;text-align:right;color:#6495ed;font-size:12px;">금액</th>
684
+ <th style="padding:10px;color:#6495ed;font-size:12px;width:120px;"></th>
685
+ </tr>
686
+ </thead>
687
+ <tbody>
688
+ {rows_html}
689
+ <tr style="border-top:2px solid rgba(100,149,237,0.3);">
690
+ <td colspan="2" style="padding:12px;color:#fff;font-weight:700;font-size:14px;">합계</td>
691
+ <td style="padding:12px;text-align:right;color:#fff;font-weight:700;">100%</td>
692
+ <td style="padding:12px;text-align:right;color:#6fd9a8;font-weight:700;font-size:15px;">
693
+ {gov/10000:,.0f}만원
694
+ </td>
695
+ <td></td>
696
+ </tr>
697
+ </tbody>
698
+ </table>
699
+ </div>
700
+
701
+ <!-- 비율 파이차트 + 구조도 -->
702
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:20px;">
703
+ <!-- 파이 차트 -->
704
+ <div style="background:#12121e;border-radius:14px;padding:24px;
705
+ border:1px solid rgba(100,149,237,0.1);">
706
+ <h3 style="color:#e8e8f0;font-size:16px;margin:0 0 16px;">🍩 비목 구성</h3>
707
+ <div style="display:flex;align-items:center;gap:24px;">
708
+ <div style="width:120px;height:120px;border-radius:50%;
709
+ background:conic-gradient({pie_gradient});flex-shrink:0;"></div>
710
+ <div>{legend_html}</div>
711
+ </div>
712
+ </div>
713
+
714
+ <!-- 구조도 -->
715
+ <div style="background:#12121e;border-radius:14px;padding:24px;
716
+ border:1px solid rgba(100,149,237,0.1);">
717
+ <h3 style="color:#e8e8f0;font-size:16px;margin:0 0 16px;">🏗️ 재원 구조</h3>
718
+ <div style="font-size:13px;color:#c8c8d8;line-height:2.2;">
719
+ <div>💰 총 사업비: <strong style="color:#fff;">{total/10000:,.0f}만원</strong></div>
720
+ <div style="padding-left:20px;">
721
+ ├ 🏛️ 정부지원금 ({gov/total*100:.0f}%): <strong style="color:#6fd9a8;">{gov/10000:,.0f}만</strong>
722
+ </div>
723
+ <div style="padding-left:20px;">
724
+ └ 🏢 민간부담금 ({priv/total*100:.0f}%): <strong style="color:#ffd700;">{priv/10000:,.0f}만</strong>
725
+ </div>
726
+ <div style="padding-left:48px;">
727
+ ├ 현금 ({cash/priv*100:.0f}%): {cash/10000:,.0f}만
728
+ </div>
729
+ <div style="padding-left:48px;">
730
+ └ 현물 ({inkind/priv*100:.0f}%): {inkind/10000:,.0f}만
731
+ </div>
732
+ </div>
733
+ </div>
734
+ </div>
735
+
736
+ <!-- 사업계획서 복사용 텍스트 -->
737
+ <div style="background:#12121e;border-radius:14px;padding:20px;
738
+ border:1px solid rgba(100,149,237,0.1);">
739
+ <h3 style="color:#e8e8f0;font-size:14px;margin:0 0 12px;">📝 사업계획서 복사용 (텍스트)</h3>
740
+ <pre style="background:#0d0d1a;color:#c8c8d8;padding:16px;border-radius:8px;font-size:12px;
741
+ overflow-x:auto;white-space:pre-wrap;margin:0;line-height:1.8;">총 사업비: {total/10000:,.0f}만원 ({total/100000000:,.2f}억원)
742
+ - 정부지원금: {gov/10000:,.0f}만원 ({gov/total*100:.0f}%)
743
+ - 민간부담금: {priv/10000:,.0f}만원 (현금 {cash/10000:,.0f}만 + 현물 {inkind/10000:,.0f}만)
744
+
745
+ [비목별 배분 - 정부지원금 기준]
746
+ {''.join(f" {item['name']:12s}: {item['amount']/10000:>8,.0f}만원 ({item['pct']:.0f}%)" + chr(10) for item in items)}</pre>
747
+ </div>
748
+
749
+ <div style="text-align:center;padding:12px;color:#555;font-size:11px;
750
+ border-top:1px solid rgba(100,149,237,0.1);margin-top:16px;">
751
+ ※ 실제 예산 편성 시 해당 사업의 공고문과 연구비 사용기준을 반드시 확인하세요.
752
+ </div>
753
+ </div>
754
+ """
755
+ return html
756
+
757
+
758
+ # ============================================================================
759
+ # 3. Gradio 탭 생성
760
+ # ============================================================================
761
+
762
+ INDUSTRY_OPTIONS = [
763
+ "A. 농림어업", "B. 광업", "C. 제조업", "E. 수도·환경", "F. 건설업",
764
+ "G. 도매·소매업", "H. 운수·창고업", "J. 정보통신업", "K. 금융·보험업",
765
+ "L. 부동산업", "M. 전문·과학·기술", "N. 사업시설관리",
766
+ "P. 교육서비스업", "Q. 보건·사회복지", "R. 예술·스포츠", "S. 수리·개인서비스"
767
+ ]
768
+
769
+
770
+ def create_biz_tools_tab():
771
+ """세금 절감 & R&D 예산 탭 생성"""
772
+
773
+ with gr.Tab("🧮 세금·예산 계산기"):
774
+ gr.HTML('''
775
+ <div style="background:linear-gradient(135deg,#0d1117,#161b22,#0d1117);padding:30px;border-radius:20px;
776
+ margin-bottom:24px;border:2px solid rgba(111,217,168,0.3);text-align:center;
777
+ box-shadow:0 10px 40px rgba(0,0,0,0.5);">
778
+ <h2 style="margin:0 0 8px;font-size:28px;
779
+ background:linear-gradient(135deg,#6fd9a8,#6495ed,#fff);
780
+ -webkit-background-clip:text;-webkit-text-fill-color:transparent;">
781
+ 🧮 세금 절감 시뮬레이터 & R&D 예산 편성기
782
+ </h2>
783
+ <p style="color:#8888a0;margin:0;font-size:13px;">
784
+ 기업 정보를 입력하면 적용 가능한 세제 혜택과 R&D 예산을 자동 계산합니다
785
+ </p>
786
+ </div>
787
+ ''')
788
+
789
+ with gr.Tabs():
790
+ # ── 탭 1: 세금 절감 시뮬레이터 ──
791
+ with gr.Tab("💰 세금 절감 시뮬레이터"):
792
+ with gr.Row():
793
+ with gr.Column():
794
+ gr.HTML('<div style="background:#12121e;color:#6fd9a8;padding:10px 16px;border-radius:10px;font-weight:600;margin-bottom:12px;">📋 기업 기본정보</div>')
795
+ tax_industry = gr.Dropdown(label="업종", choices=INDUSTRY_OPTIONS, value="C. 제조업")
796
+ tax_company_size = gr.Radio(label="기업 규모", choices=["소기업", "중기업"], value="소기업")
797
+ tax_revenue = gr.Number(label="연매출 (백만원)", value=500, minimum=0)
798
+ tax_op_profit = gr.Number(label="영업이익 (백만원)", value=50, minimum=0)
799
+ tax_is_capital = gr.Checkbox(label="수도권 소재", value=True)
800
+ tax_establish_years = gr.Slider(label="업력 (년)", minimum=0, maximum=30, value=3, step=1)
801
+ tax_ceo_age = gr.Slider(label="대표자 나이", minimum=20, maximum=70, value=35, step=1)
802
+
803
+ with gr.Column():
804
+ gr.HTML('<div style="background:#12121e;color:#6495ed;padding:10px 16px;border-radius:10px;font-weight:600;margin-bottom:12px;">🔬 기술·인증·투자</div>')
805
+ tax_research_center = gr.Checkbox(label="기업부설연구소/전담부서 보유")
806
+ tax_rd_investment = gr.Number(label="연간 R&D 투자액 (백만원)", value=0, minimum=0)
807
+ tax_patents = gr.Number(label="보유 특허 수", value=0, minimum=0)
808
+ tax_has_venture = gr.Checkbox(label="벤처인증")
809
+ tax_has_innobiz = gr.Checkbox(label="이노비즈")
810
+ tax_is_female = gr.Checkbox(label="여성기업")
811
+ tax_is_disabled = gr.Checkbox(label="장애인기업")
812
+
813
+ with gr.Column():
814
+ gr.HTML('<div style="background:#12121e;color:#ffd700;padding:10px 16px;border-radius:10px;font-weight:600;margin-bottom:12px;">👥 고용·설비투자</div>')
815
+ tax_employees = gr.Number(label="총 직원 수", value=10, minimum=0)
816
+ tax_new_youth = gr.Number(label="신규 채용 - 청년 (전년 대비 증가)", value=0, minimum=0)
817
+ tax_new_general = gr.Number(label="신규 채용 - 일반 (전년 대비 증가)", value=0, minimum=0)
818
+ tax_facility_invest = gr.Number(label="설비투자액 (백만원)", value=0, minimum=0)
819
+
820
+ tax_btn = gr.Button("🧮 세금 절감 시뮬레이션 실행", variant="primary", size="lg")
821
+ tax_result = gr.HTML()
822
+
823
+ def run_tax_sim(ind, size, rev, op, cap, yrs, age, rc, rd, pat,
824
+ emp, ny, ng, fac, ven, inno, fem, dis):
825
+ results, total, corp_tax, taxable, best = simulate_tax_saving(
826
+ ind, size, rev, op, cap, yrs, age, rc, rd, pat,
827
+ emp, ny, ng, fac, ven, inno, fem, dis
828
+ )
829
+ return generate_tax_html(results, total, corp_tax, taxable, best)
830
+
831
+ tax_btn.click(
832
+ fn=run_tax_sim,
833
+ inputs=[
834
+ tax_industry, tax_company_size, tax_revenue, tax_op_profit,
835
+ tax_is_capital, tax_establish_years, tax_ceo_age,
836
+ tax_research_center, tax_rd_investment, tax_patents,
837
+ tax_employees, tax_new_youth, tax_new_general,
838
+ tax_facility_invest, tax_has_venture, tax_has_innobiz,
839
+ tax_is_female, tax_is_disabled
840
+ ],
841
+ outputs=[tax_result]
842
+ )
843
+
844
+ # ── 탭 2: R&D 예산 편성 계산기 ──
845
+ with gr.Tab("📊 R&D 예산 편성기"):
846
+ with gr.Row():
847
+ with gr.Column():
848
+ gr.HTML('<div style="background:#12121e;color:#6495ed;padding:10px 16px;border-radius:10px;font-weight:600;margin-bottom:12px;">💰 총괄 예산</div>')
849
+ rd_total = gr.Number(label="총 사업비 (백만원)", value=300, minimum=1)
850
+ rd_gov_ratio = gr.Slider(label="정부지원 비율 (%)", minimum=50, maximum=100, value=75, step=5)
851
+ rd_cash_ratio = gr.Slider(label="민간부담 중 현금 비율 (%)", minimum=0, maximum=100, value=50, step=10)
852
+
853
+ with gr.Column():
854
+ gr.HTML('<div style="background:#12121e;color:#6fd9a8;padding:10px 16px;border-radius:10px;font-weight:600;margin-bottom:12px;">📋 비목별 비율 (정부지원금 기준, %)</div>')
855
+ rd_personnel = gr.Slider(label="내부인건비", minimum=0, maximum=70, value=45, step=1)
856
+ rd_ext_personnel = gr.Slider(label="외부인건비", minimum=0, maximum=20, value=5, step=1)
857
+ rd_equipment = gr.Slider(label="연구장비·재료비", minimum=0, maximum=40, value=15, step=1)
858
+ rd_activity = gr.Slider(label="연구활동비", minimum=0, maximum=20, value=5, step=1)
859
+
860
+ with gr.Column():
861
+ gr.HTML('<div style="background:#12121e;color:#ffd700;padding:10px 16px;border-radius:10px;font-weight:600;margin-bottom:12px;">📋 비목별 비율 (계속)</div>')
862
+ rd_consign = gr.Slider(label="위탁연���비", minimum=0, maximum=40, value=10, step=1)
863
+ rd_facility = gr.Slider(label="연구시설활용비", minimum=0, maximum=20, value=5, step=1)
864
+ rd_overhead = gr.Slider(label="간접비", minimum=0, maximum=20, value=10, step=1)
865
+
866
+ gr.HTML('''
867
+ <div style="background:#1a1a2e;border-radius:10px;padding:14px;margin-top:12px;
868
+ border:1px solid rgba(255,215,0,0.15);font-size:12px;color:#8888a0;line-height:1.8;">
869
+ 💡 <strong style="color:#ffd700;">비율 가이드</strong><br>
870
+ · 인건비 합계: 40~60% 권장<br>
871
+ · 위탁연구비: 정부지원금의 40% 이내<br>
872
+ · 간접비: 10~15% 권장<br>
873
+ · 비율 합계가 100%가 아니면 자동 정규화
874
+ </div>
875
+ ''')
876
+
877
+ rd_btn = gr.Button("📊 예산 편성 계산", variant="primary", size="lg")
878
+ rd_result = gr.HTML()
879
+
880
+ def run_rd_calc(total, gov, cash, p1, p2, eq, act, con, fac, oh):
881
+ data = calculate_rd_budget(total, gov, cash, p1, p2, eq, act, con, fac, oh)
882
+ return generate_rd_budget_html(data)
883
+
884
+ rd_btn.click(
885
+ fn=run_rd_calc,
886
+ inputs=[
887
+ rd_total, rd_gov_ratio, rd_cash_ratio,
888
+ rd_personnel, rd_ext_personnel, rd_equipment,
889
+ rd_activity, rd_consign, rd_facility, rd_overhead
890
+ ],
891
+ outputs=[rd_result]
892
+ )
893
+
894
+
895
+ # ============================================================================
896
+ # 독립 실행용
897
+ # ============================================================================
898
+
899
+ def create_app():
900
+ """독립 실행"""
901
+ with gr.Blocks(title="세금·예산 계산기") as app:
902
+ gr.HTML("""
903
+ <div style="text-align:center;padding:30px;background:linear-gradient(135deg,#0d1117,#161b22);
904
+ border-radius:20px;margin-bottom:20px;">
905
+ <h1 style="font-size:36px;margin:0;
906
+ background:linear-gradient(135deg,#6fd9a8,#6495ed,#fff);
907
+ -webkit-background-clip:text;-webkit-text-fill-color:transparent;">
908
+ 🧮 CoBIZ 세금·예산 계산기
909
+ </h1>
910
+ </div>
911
+ """)
912
+ create_tax_calc_tab()
913
+ return app
914
+
915
+
916
+ if __name__ == "__main__":
917
+ app = create_app()
918
+ app.launch(server_name="0.0.0.0", server_port=7861)