module Receipts class Base < Prawn::Document attr_accessor :title, :company class << self attr_reader :title end def initialize(attributes = {}) super(page_size: attributes.delete(:page_size) || "LETTER") setup_fonts attributes.fetch(:font, Receipts.default_font) @title = attributes.fetch(:title, self.class.title) generate_from(attributes) end def generate_from(attributes) return if attributes.empty? company = attributes.fetch(:company) header company: company, height: attributes.fetch(:logo_height, 16) render_details attributes.fetch(:details) render_billing_details company: company, recipient: attributes.fetch(:recipient) render_line_items( line_items: attributes.fetch(:line_items), column_widths: attributes[:column_widths] ) render_footer attributes.fetch(:footer, default_message(company: company)) end def setup_fonts(custom_font = nil) if !!custom_font font_families.update "Primary" => custom_font font "Primary" end font_size 8 end def load_image(logo) if logo.is_a? String logo.start_with?("http") ? URI.parse(logo).open : File.open(logo) else logo end end def header(company: {}, height: 16) logo = company[:logo] if logo.nil? text company.fetch(:name), align: :right, style: :bold, size: 16, color: "4b5563" else image load_image(logo), height: height, position: :right end move_up height text title, style: :bold, size: 16 end def render_details(details, margin_top: 16) move_down margin_top table(details, cell_style: {borders: [], inline_format: true, padding: [0, 8, 2, 0]}) end def render_billing_details(company:, recipient:, margin_top: 16) move_down margin_top company_details = [ company[:address], company[:phone], company[:email] ].compact.join("\n") line_items = [ [ {content: "#{company.fetch(:name)}\n#{company_details}", padding: [0, 12, 0, 0]}, {content: Array(recipient).join("\n"), padding: [0, 12, 0, 0]} ] ] table(line_items, width: bounds.width, cell_style: {borders: [], inline_format: true, overflow: :expand}) end def render_line_items(line_items:, margin_top: 30, column_widths: nil) move_down margin_top borders = line_items.length - 2 table_options = { width: bounds.width, cell_style: {border_color: "eeeeee", inline_format: true}, column_widths: column_widths }.compact table(line_items, table_options) do cells.padding = 6 cells.borders = [] row(0..borders).borders = [:bottom] end end def render_footer(message, margin_top: 30) move_down margin_top text message, inline_format: true end def default_message(company:) "For questions, contact us anytime at #{company.fetch(:email)}." end end end