|
|
|
|
|
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) |
|
|
|