Gem prown を使用して請求書を作成する。

はじめに
---
本記事は　オリジナルアプリ　Kiyoraの続編となります。
プログラミングスクールで作成したオリジナルアプリケーションで作成した
Ruby on Railsでのpdf出力について取り上げます。

----

実行環境
rails 6.0.3
ruby 3.0.1
psql (PostgreSQL) 14.2

前提
rails newでアプリ作成
rails db:create を実行済み。


prawnの導入 
---
gemファイルに以下を追加します。
テーブルも表示させたいのでprawn-tableもインストールします。
```
gem 'prawn'
gem 'prawn-table'
```

実行コマンド
```
bundle install
```

モデル作成
----
```
rails g model invoice_pdf
```
コントローラーを作成
---
```
rails g controller invoice_pdfs
```

ルーティングの設定
---
showの画面でPDFを表示

```ruby
resources :invoice_pdfs, only: %i[show]
```

pdfを実装させる


```ruby:invoice_pdf.rb
class InvoicePdf < Prawn::Document
  FONT_PATH = Rails.root + '/Users/workspace/kiyora/app/assets/fonts/ipaexg.ttf'

  def initialize(record,customer)

    super(
      page_size: 'A4',
      top_margin: 40,
      bottom_margin: 30,
      left_margin: 20,
      right_margin: 20
    )

    @record = record
    @customer = customer
   
    font 'app/assets/fonts/ipaexg.ttf'
    header
    move_down 50
    contents
  end

  # コンポーネント作成
  def header
    text '請求書', size: 20, align: :center
    move_down 20

    text "作成日: #{Date.today}",align: :right, size: 10
    text "株式会社　良好建築設備",align: :right, size: 10
    text "住所　東京都台東区花川戸3丁目1-1-1",align: :right, size: 10
    text "電話: 03-333-3333",align: :right, size: 10
    text "info: contact@center.com",align: :right, size: 10
    image 'app/assets/images/sqe_rei.jpeg',align: :right, width: 40, height: 40,at: [400, 700]
    
    text "#{@customer.name} 様",align: :left, size: 12
    text "郵便番号: #{@customer.zip} ",align: :left, size: 12
    text "住所: #{@customer.address} ",align: :left, size: 12
  end

  def contents
    move_down 10
    text "作業日:#{@record.support_at.strftime("%Y年%m月%d日").to_s}"
    text '下記の通りご請求申し上げます。',align: :center
 
      bounding_box([0, 555], width: 310, height: 65) do
       move_down 10
      text "合計金額 #{@record.sales+(@record.sales*0.1).round}", size: 16, align: :left
      end

      rows = [['詳細', '数量', '単価', '金額'], 
      ["#{@record.category}", '1',"#{@record.sales}", "#{@record.sales+(@record.sales*0.1).round}"]
      ]
      #テーブルの作成。カラムが４つ。それぞれの幅を指定。
      table(rows, column_widths: [370, 30, 60, 60], position: :center) do |table|
      table.cells.size = 10
      table.row(0).align = :center
      end

      bounding_box([373, 300], width: 150, height: 100) do
        table [['小計', "#{@record.sales}"], ['消費税', "#{(@record.sales*0.1).round}"], 
        ['合計金額', "#{@record.sales+(@record.sales*0.1).round}"]],
        column_widths: [50, 100], position: :right do |table|
        table.cells.size = 10
        end
      move_down 10
      text "お振込期日  #{Date.today+14}", size: 12, align: :left
      end
  end
end 
```

# フォントのダウンロード

クラス名にはPrawn::Documentを継承させます。

フォントをダウンロードします。prawnは日本語には対応していない為。
こちらのページからダウンロード。

https://moji.or.jp/ipafont/ipaex00401/

ダウンロードしたファイルを　/app/assets/fonts以下に配置。
# コードの説明

```
def initialize
```
pdfには顧客情報に紐づいた情報とタスク情報を出力したいので
(下記に説明あり）
def initialize(record,customer)と記述。

superで外枠となるサイズを指定。
引数にrecord customerを設定。

```ruby:controller show
@record = Task.find(params[:id])
@customer = @customers.find_by(task_id: @record.id)
```
コントローラーファイルで上記をあらかじめ設定し、recordにはTaskモデル、
customerにはcustomerモデルの情報が格納される。


```
move_down 50
```

headerとcontentsの間にどれくらい余白を入れるかmove_downによって数値設定。
値が大きいほど、空間ができる

名前の表示

```ruby
text "#{@customer.name} 様",align: :left, size: 12
```
@customerのnameカラムに入っている情報を取得したい場合、"#{}"で展開させる。
sizeはフォントサイズのこと

```
bounding_box([0, 555], width: 310, height: 65)
```
pdfの中にボックスを作成します。始点となる座標点を指定します。
[横, 縦]、単位はポイント(pt)になります。そこから、幅310高さ65のボックスを作ります。

公式ドキュメント

https://prawnpdf.org/docs/0.11.1/Prawn/Document/BoundingBox.html

```ruby
table(rows, column_widths: [370, 30, 60, 60], position: :center) do |table|
      table.cells.size = 10
      table.row(0).align = :center
end
```
 セルのサイズと文字の大きさ
```ruby
 table.cells.size = 10 
```

枠線を特定箇所のみ付けることも可能。
```ruby
 table.cells.borders = %i[right top]
```
今日の請求書発行日から14日後に日付を設定。
```ruby
text "お振込期日  #{Date.today+14}", size: 12, align: :left
```

コントローラーファイル
```ruby:invoice_pdfs_controller.rb
class InvoicePdfsController < ApplicationController
  def show
    @records = Task.all # pdf上で使用するレコードのインスタンスを作成
    @record = Task.find(params[:id])
    @customers = Customer.all
    @customer = @customers.find_by(task_id: @record.id)

    respond_to do |format|
      format.html
      format.pdf do

        # pdfを新規作成。引数にインスタンス変数を渡す。
        pdf = InvoicePdf.new(@record, @customer)
        send_data pdf.render,
          filename:    "invoice.pdf",
          type:        "application/pdf",
          disposition: "inline" # 画面に表示。外すとダウンロードされる。
      end
    end
  end
  private
  def set_show
    params.permit(:name,:dispatch,
      properties_attributes:[:name, :zip, :prefecture, :city , :address, :tel,:_destroy ],
      partners_attributes:[{id:[]},:name,:worker,:contact,:sales,:_destroy],
      agents_attributes:[:id,:manager_name, :name, :zip, :prefecture, :city, :address,:_destroy],
      customer_attributes:[:id,:name,:zip,:address,:tel,:_destroy]
    )
  end
end
```

新規作成を行う。
```ruby
pdf = InvoicePdf.new(@record, @customer)
```
```ruby
disposition: "inline"
```
PDFをブラウザ上に出力する際に必要なオプション。外すとダウンロードになる。

他にもprawnには図形を出力したりする機能もあり、公式ドキュメントを見ると
利用用途が広がりそうです。

ブラウザでの表示
---

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530703/70d5558d-2b92-411d-6137-304c92b2823f.png">

PDF版マニュアル

https://prawnpdf.org/manual.pdf


参考にさせて頂いた記事
--------
https://techtechmedia.com/prawn-pdf-rails/
https://qiita.com/yacci/items/61a26ddd3f6eb2494121
https://qiita.com/ayies128/items/7262b771fdae5b7f0098

---

エンジニアのスタートラインにようやく立てたところです。
未熟な点が多々あるかとは思いますが、温かく見守って頂ければと思います。