"""記事 exempt-supplier-credit-70(免税事業者からの仕入れ、控除70%で負担はいくら増える?)の計算と図。
外部のデータは使わない。割合・期間・上限は国税庁 Q&A 問113・問113-3・問130(令和8年5月改訂)と「令和8年度税制改正特集」(2026-10-16 確認)。
  1. 年間の仕入額(税込)× 免税事業者等からの割合 の3×3 で、80%・70%・50%・30% のときに控除できない税額(国税と地方税の合計)
     控除できない税額 = 対象の仕入(税込)× 10/110 ×(1 − 控除割合)。すべて標準税率10%の仕入れと仮定(8%の品目は 8/108)
     国税だけなら 7.8/110(Q&A 問130 の式)。地方消費税は国税の 22/78 なので、合わせると 10/110 になる
  2. 1者あたり年1億円の上限:対象 = Σ min(A_i, 1億円)、上限を超えた部分 = Σ max(A_i − 1億円, 0) は0%
  3. 20日締めの請求(9/21〜10/20)を引渡日で80%と70%に分けた控除額
図は public/img/articles/ に SVG 3枚。
使い方: python scripts/figs/exempt_supplier_credit.py   (fields/sales-management-app で実行)
"""
import pathlib, json, html

ROOT = pathlib.Path(__file__).resolve().parents[2]
OUT = ROOT / 'public/img/articles'; OUT.mkdir(parents=True, exist_ok=True)

INK, INK2, MUTE, RULE, PAPER2 = '#111111', '#444444', '#6b6b6b', '#dcdcdc', '#f1f1f1'
AI, AI_TXT, AI_SOFT, SHU = '#678b2c', '#557323', '#dfe8cf', '#c23b22'   # 差し色は面だけ #678b2c、文字は #557323
FONT = "'Hiragino Sans','Yu Gothic','Meiryo',sans-serif"

RATES = [('80%', 0.8), ('70%', 0.7), ('50%', 0.5), ('30%', 0.3), ('0%', 0.0)]
TAX = 10 / 110


def lost(amount, r):
    return round(amount * TAX * (1 - r))


def svg(w, h, body):
    return (f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {h}" width="{w}" height="{h}" font-family="{FONT}">'
            f'<rect width="{w}" height="{h}" fill="#ffffff"/>{body}</svg>')


def t(x, y, s, size=14, fill=INK, anchor='start', weight=400):
    return f'<text x="{x}" y="{y}" font-size="{size}" fill="{fill}" text-anchor="{anchor}" font-weight="{weight}">{html.escape(str(s))}</text>'


def yen(v):
    return f'{v:,}円'


res = {}

# 1. 3×3 の表
totals = [100_000_000, 300_000_000, 1_000_000_000]
shares = [0.05, 0.10, 0.20]
rows = []
for T in totals:
    for s in shares:
        a = round(T * s)
        rows.append({'total': T, 'share': s, 'amount': a, 'lost': {k: lost(a, r) for k, r in RATES}})
res['table'] = rows
print('| 年間の仕入(税込) | 免税事業者等から | 80%のとき | 70%のとき | 50%のとき | 30%のとき |')
print('|---|---|---|---|---|---|')
for r in rows:
    L = r['lost']
    print(f"| {r['total'] // 10**8}億円 | {int(r['share'] * 100)}%({r['amount'] // 10**4:,}万円) | {L['80%']:,} | {L['70%']:,} | {L['50%']:,} | {L['30%']:,} |")

# 2. 1億円の上限
CAP = 100_000_000
suppliers = {'仕入先P': 120_000_000, '仕入先Q': 40_000_000, '仕入先R': 15_000_000}
eligible = sum(min(v, CAP) for v in suppliers.values())
excess = sum(max(v - CAP, 0) for v in suppliers.values())
res['cap'] = {'suppliers': suppliers, 'eligible': eligible, 'excess': excess,
              'excessLostAt70': round(excess * TAX * 0.7), 'excessTax': round(excess * TAX)}
print('cap', res['cap'])

# 3. 20日締めの請求を引渡日で分ける
sep, octo = 1_100_000, 2_200_000
split = round(sep * TAX * 0.8) + round(octo * TAX * 0.7)
res['cutoff'] = {'sep21_30': sep, 'oct1_20': octo, 'split': split,
                 'all80': round((sep + octo) * TAX * 0.8), 'all70': round((sep + octo) * TAX * 0.7)}
print('cutoff', res['cutoff'])

# 図1:段階の帯(期間と割合)
def fig_timeline():
    w, h = 860, 300
    b = t(24, 34, '免税事業者等からの仕入れで控除できる割合(改正後)', 18, INK, weight=700)
    segs = [('2023.10〜2026.9', '80%', 3.0, 0.8), ('2026.10〜2028.9', '70%', 2.0, 0.7), ('2028.10〜2030.9', '50%', 2.0, 0.5),
            ('2030.10〜2031.9', '30%', 1.0, 0.3), ('2031.10〜', '0%', 1.0, 0.0)]
    x0, x1, base, top = 40, 830, 220, 70
    unit = (x1 - x0) / sum(s[2] for s in segs)
    x = x0
    for i, (lab, pct, yrs, r) in enumerate(segs):
        wd = yrs * unit
        hh = (base - top) * r
        fill = AI if pct == '70%' else AI_SOFT
        if r > 0:
            b += f'<rect x="{x + 1:.1f}" y="{base - hh:.1f}" width="{wd - 2:.1f}" height="{hh:.1f}" fill="{fill}"/>'
        b += t(x + wd / 2, base - hh - 10, pct, 20, AI_TXT if pct == '70%' else INK, 'middle', 700)
        b += t(x + wd / 2, base + 22, lab, 13, INK2, 'middle')
        dur = {3.0: '3年', 2.0: '2年', 1.0: '1年'}[yrs] if pct != '0%' else ''
        if dur:
            b += t(x + wd / 2, base + 40, dur, 12, MUTE, 'middle')
        x += wd
    b += f'<line x1="{x0}" y1="{base}" x2="{x1}" y2="{base}" stroke="{INK2}" stroke-width="1"/>'
    b += t(24, 286, '出典:国税庁 Q&A 問113・問113-3(令和8年5月改訂)、令和8年度税制改正特集(2026年10月16日確認)。割合は課税仕入れの時期(商品は引渡しの日)で決まる', 12, INK2)
    return svg(w, h, b)


# 図2:3億円×10%(3,000万円)で控除できない税額
def fig_bars():
    case = next(r for r in rows if r['total'] == 300_000_000 and r['share'] == 0.10)
    w, h = 860, 360
    b = t(24, 34, '免税事業者等からの仕入れ 年3,000万円(税込)で控除できない税額', 18, INK, weight=700)
    b += t(24, 58, '年間の仕入3億円のうち10%。標準税率10%の仕入れと仮定、国税と地方税の合計(計算値)', 13, INK2)
    x0, bw, maxw = 120, 0, 640
    mx = case['amount'] * TAX
    for i, (k, r) in enumerate(RATES):
        v = case['lost'][k]
        y = 86 + i * 46
        b += t(x0 - 14, y + 22, f'控除{k}', 14, INK, 'end', 700 if k == '70%' else 400)
        b += f'<rect x="{x0}" y="{y}" width="{maxw}" height="30" fill="{PAPER2}"/>'
        b += f'<rect x="{x0}" y="{y}" width="{maxw * v / mx:.1f}" height="30" fill="{SHU if k == "70%" else AI}"/>'
        b += t(x0 + maxw * v / mx + 8, y + 21, yen(v), 14, SHU if k == '70%' else INK, 'start', 700)
    b += t(24, 336, '式:3,000万円 × 10/110 ×(1 − 控除割合)。出典:商いの帳場の試算(scripts/figs/exempt_supplier_credit.py)、割合は国税庁 Q&A 問113', 12, INK2)
    return svg(w, h, b)


# 図3:仕入先マスタ・仕入明細・年間累計
def fig_fields():
    w, h = 860, 330
    b = t(24, 34, '経過措置のために仕入側で持つ項目', 18, INK, weight=700)
    boxes = [
        (24, '仕入先マスタ', ['登録番号(T+13桁)', '区分(登録/免税事業者等)', '登録番号を確かめた日', '登録の開始日・取消日']),
        (304, '仕入明細', ['引渡日(検収日)', '税率(10%/8%)', '税込の金額', '控除割合(引渡日で決まる)']),
        (584, '年間の累計(仕入先ごと)', ['課税期間の開始日', '免税事業者等からの累計', '1億円を超えた額', '超えた部分は0%']),
    ]
    for x, head, items in boxes:
        b += f'<rect x="{x}" y="58" width="252" height="210" fill="{PAPER2}" stroke="{RULE}"/>'
        b += f'<rect x="{x}" y="58" width="252" height="38" fill="{AI}"/>'
        b += t(x + 14, 83, head, 15, '#ffffff', weight=700)
        for i, it in enumerate(items):
            b += t(x + 14, 126 + i * 36, '・' + it, 14, INK)
    for x in (276, 556):
        b += f'<path d="M{x + 4} 163 h20 m-7 -6 l7 6 l-7 6" fill="none" stroke="{INK2}" stroke-width="2"/>'
    b += t(24, 302, '帳簿には経過措置の対象である旨(「80%控除対象」「免」や記号)を書く(Q&A 問113)。1億円の上限は2026年10月1日以後に開始する課税期間から', 12, INK2)
    b += t(24, 320, '出典:国税庁 Q&A 問113・問113-2・問113-3・問130(令和8年5月改訂)。項目の選び方は商いの帳場の設計案', 12, INK2)
    return svg(w, h, b)


for name, f in [('exempt-supplier-credit-70-timeline', fig_timeline), ('exempt-supplier-credit-70-cost', fig_bars),
                ('exempt-supplier-credit-70-fields', fig_fields)]:
    (OUT / f'{name}.svg').write_text(f(), encoding='utf-8')
    print('wrote', name)
print(json.dumps(res, ensure_ascii=False))
