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