File size: 3,065 Bytes
9f4d112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# pdf_export.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib import colors
from reportlab.pdfgen import canvas
from reportlab.platypus import Table, TableStyle, SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet

def write_invoice_pdf(path, invoice, items, customer, totals):
    doc = SimpleDocTemplate(path, pagesize=A4,
                            rightMargin=20*mm, leftMargin=20*mm,
                            topMargin=20*mm, bottomMargin=20*mm)
    styles = getSampleStyleSheet()
    story = []

    title = "請求書" if invoice.status != "draft" else "請求書(下書き)"
    story.append(Paragraph(title, styles["Title"]))
    story.append(Spacer(1, 6))

    # ヘッダ情報
    header = [
        ["請求書番号", str(invoice.id)],
        ["発行日", str(invoice.issue_date)],
        ["支払期日", str(invoice.due_date or "記載なし")],
        ["ステータス", invoice.status],
    ]
    t = Table(header, colWidths=[30*mm, 120*mm])
    t.setStyle(TableStyle([("BOX", (0,0), (-1,-1), 0.25, colors.black),
                           ("BACKGROUND", (0,0), (0,-1), colors.whitesmoke),
                           ("VALIGN",(0,0),(-1,-1),"MIDDLE")]))
    story.append(t)
    story.append(Spacer(1, 8))

    # 請求先
    to_table = [
        ["請求先", customer.name if customer else f"Customer #{invoice.customer_id}"],
        ["住所", (customer.address or "") if customer else ""],
        ["メール", (customer.email or "") if customer else ""],
    ]
    tt = Table(to_table, colWidths=[30*mm, 120*mm])
    tt.setStyle(TableStyle([("BOX", (0,0), (-1,-1), 0.25, colors.black),
                            ("BACKGROUND", (0,0), (0,-1), colors.whitesmoke)]))
    story.append(tt)
    story.append(Spacer(1, 8))

    # 明細
    data = [["内容", "数量", "単価", "税率", "金額"]]
    for it in items:
        line = it.quantity * it.unit_price
        data.append([it.description, f"{it.quantity}", f"{it.unit_price:.2f}", f"{it.tax_rate*100:.0f}%", f"{line:.2f}"])

    tbl = Table(data, colWidths=[70*mm, 20*mm, 25*mm, 20*mm, 35*mm])
    tbl.setStyle(TableStyle([
        ("GRID", (0,0), (-1,-1), 0.25, colors.black),
        ("BACKGROUND", (0,0), (-1,0), colors.lightgrey),
        ("ALIGN", (1,1), (-1,-1), "RIGHT"),
        ("ALIGN", (0,0), (0,-1), "LEFT"),
    ]))
    story.append(tbl)
    story.append(Spacer(1, 8))

    # 合計
    sum_table = [
        ["小計", f"{totals.subtotal:.2f}"],
        ["税額", f"{totals.tax:.2f}"],
        ["合計", f"{totals.total:.2f}"],
    ]
    st = Table(sum_table, colWidths=[40*mm, 35*mm])
    st.setStyle(TableStyle([
        ("GRID", (0,0), (-1,-1), 0.25, colors.black),
        ("BACKGROUND", (0,2), (-1,2), colors.yellow),
        ("ALIGN", (1,0), (1,-1), "RIGHT"),
    ]))
    story.append(st)

    # 備考
    if invoice.notes:
        story.append(Spacer(1, 8))
        story.append(Paragraph(f"備考:{invoice.notes}", styles["Normal"]))

    doc.build(story)