3scale/porta

View on GitHub
app/lib/pdf/finance/invoice_generator.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true


module Pdf
  module Finance
    class InvoiceGenerator
      include Pdf::Printer

      # TODO: remove
      include ActionView::Helpers::NumberHelper
      include ThreeScale::MoneyHelper
      include ::Finance::InvoicesHelper

      def initialize(invoice_data)
        @data = invoice_data
        @coder = HTMLEntities.new

        # TODO: accept as parameter
        @style = Pdf::Styles::BlackAndWhite.new
        @pdf = Prawn::Document.new(page_size: 'A4',
                                   page_layout: :portrait,
                                   compress: true)

        set_default_font
      end

      # Generates PDF content and wraps it to envelope acceptable by Paperclip
      def generate_as_attachment
        InvoiceAttachment.new(@data, generate)
      end

      def generate
        print_header

        print_address_columns

        move_down(5)
        print_line_items
        move_down(5)

        print_total

        move_down(2)
        @pdf.text @data.invoice_footnote
        move_down

        @pdf.render
      end

      private

      def print_header
        two_columns do |column|
          print_logo if column == :left
          print_address(@data.buyer) if column == :right
        end

        move_down(14)
        @pdf.text "Invoice for #{@data.name}", size: 20, align: :center
        move_down(14)

        subtitle('Details')
        print_details
        move_down(3)
      end

      def print_logo
        @data.with_logo do |logo|
          @pdf.image(logo, fit: [200,50], position: :left) if logo
        end
      end

      def print_address_columns
        two_columns([0.mm, @pdf.cursor]) do |column|
          print_address(@data.provider, 'Issued by') if column == :left
          print_address(@data.buyer, 'For') if column == :right
        end
      end

      def print_address(person, name = nil)
        subtitle("#{name}") if name
        table_with_column_header(person, width: TABLE_HALF_WIDTH) do
          # prevent long addresses from wrapping header words
          # see https://github.com/prawnpdf/prawn-table/issues/67
          style(column(0), width: 58)
        end
      end

      def print_details
        details = [['Invoice ID', @data.friendly_id],
                   ['Issued on', @data.issued_on],
                   ['Billing period start', @data.period_start],
                   ['Billing period end', @data.period_end],
                   ['Due on', @data.due_on]]

        table_with_column_header(details)
      end

      def print_line_items
        subtitle('Line items')
        opts = { width: TABLE_FULL_WIDTH, header: true, cell_style: {align: :right} }
        table_with_header([InvoiceReportData::LINE_ITEMS_HEADING] + @data.line_items, opts) do
          column(0).style { |column| column.align = :left }
        end
        move_down
        @pdf.text(@data.vat_zero_text) if @data.vat_rate&.zero?
      end

      def print_total
        text = "AMOUNT DUE: #{@coder.decode(rounded_price_tag(@data.cost))}"
        format = {size: 13, align: :right, style: :bold}
        total_height = @pdf.height_of_formatted([{ text: text, **format }]) + move_amount(1)

        @pdf.start_new_page if @pdf.cursor < total_height

        print_line
        move_down(1)
        @pdf.text text, **format
      end
    end
  end
end