class PdfGenerator def initialize(invoice) @invoice = invoice end def build(options={}) options[:site] ||= 'wpul' @owner = Configuration.get(:owner, options[:site]) pdf = PDF::Writer.new(:paper => 'LETTER', :version => '1.3', :orientation => :portrait) pdf.margins_in(1.5, 0.5, 0.5, 0.75) pdf.select_font 'Times-Roman' File.open(File.join(RAILS_ROOT, 'public', 'images', "#{options[:site]}-logo.jpg"), 'rb') do |logo| pdf.open_object do |header| pdf.save_state pdf.add_image_from_file logo, pdf.in2pts(0.5), pdf.in2pts(10), pdf.in2pts(3) pdf.add_text pdf.in2pts(0.5), pdf.in2pts(9.85), "#{@owner.main_address.format.join(', ')} - Phone: #{@owner.main_phone.number}", 10 text = "#{options[:type].to_s.capitalize} No: #{@invoice.no}" font_size = 10 text_width = pdf.text_width(text, font_size) pdf.add_text pdf.in2pts(8.5) - pdf.in2pts(0.5) - text_width, pdf.in2pts(9.85), text, font_size pdf.move_to pdf.in2pts(0.5), pdf.in2pts(10) - 16 pdf.line_to pdf.in2pts(8.5) - pdf.in2pts(0.5), pdf.in2pts(10) - 16 pdf.stroke pdf.restore_state pdf.close_object pdf.add_object(header, :all_pages) end pdf.open_object do |footer| pdf.save_state font_size = 10 if @owner then text = "#{@owner.company_name} - #{@owner.main_address.format.join(', ')} - Phone: #{@owner.main_phone.number}" else text = "NO CUSTOMER !!!" end text_size = pdf.text_width(text, font_size) pdf.add_text pdf.margin_x_middle - text_size/2.0, pdf.in2pts(0.5), text, font_size pdf.move_to pdf.in2pts(0.5), pdf.in2pts(0.5) + 16 pdf.line_to pdf.in2pts(8.5) - pdf.in2pts(0.5), pdf.in2pts(0.5) + 16 pdf.stroke pdf.restore_state pdf.close_object pdf.add_object(footer, :all_pages) end pdf.start_columns(2, pdf.in2pts(0.5)) pdf.text "Sold To:" if @invoice.customer then pdf.text "#{@invoice.customer.company_name}" unless @invoice.customer.company_name.blank? pdf.text "#{@invoice.customer.name}" pdf.text(@invoice.customer.main_address.format) if @invoice.customer.main_address pdf.text "\nPhone: #{@invoice.customer.main_phone.number}" \ unless @invoice.customer.main_phone.blank? || \ @invoice.customer.main_phone.number.blank? else pdf.text "No Customer" end pdf.start_new_page # Starts a new column, instead pdf.text "Date: #{(@invoice.date || Time.now).to_time.strftime('%d/%m/%Y')}", :justification => :right pdf.text "#{options[:type].to_s.capitalize} No: #{@invoice.no}", :justification => :right pdf.text "Our GST #: #{Configuration.get(:company_gst_number)}", :justification => :right pdf.text "Our PST #: #{Configuration.get(:company_pst_number)}", :justification => :right pdf.stop_columns if :quote == options[:type] then pdf.text "\nThis is an estimate - the final amount billed will be based upon the number of strands of lights and ancillary products actually used to complete the work.", :font_size => 12, :justification => :center, :left => pdf.in2pts(0.5), :right => pdf.in2pts(0.5) end pdf.text "\n" PDF::SimpleTable.new do |table| table.width = pdf.in2pts(8.5 - 1.25) table.position = :center table.bold_headings = true table.minimum_space = 50 table.protect_rows = 2 table.column_order = %w(description product_no unit_price quantity extension_price) table.columns['description'] = PDF::SimpleTable::Column.new('description') {|col| col.heading = 'Description' } table.columns['product_no'] = PDF::SimpleTable::Column.new('product_no') {|col| col.heading = 'Product No' } table.columns['unit_price'] = PDF::SimpleTable::Column.new('unit_price') {|col| col.heading = 'Unit Price'; col.justification = :right } table.columns['quantity'] = PDF::SimpleTable::Column.new('quantity') {|col| col.heading = 'Quantity'; col.justification = :right } table.columns['extension_price'] = PDF::SimpleTable::Column.new('extension_price') {|col| col.heading = 'Extension'; col.justification = :right } data = @invoice.lines.map do |item| row = {'description' => item.description} case when item.product? row.merge!( 'product_no' => item.no, 'unit_price' => item.unit_price.format(:html), 'quantity' => item.quantity, 'extension_price' => item.extension_price.format(:html), 'description' => " #{row['description']}") when item.manhours? row.merge!( 'unit_price' => item.unit_price.format(:html), 'quantity' => item.quantity, 'extension_price' => item.extension_price.format(:html), 'description' => " #{row['description']}") when item.comment? row['description'] = "#{row['description']}" end row end data << {'quantity' => 'Subtotal:', 'extension_price' => @invoice.subtotal} data << {'quantity' => 'Equipment Fee:', 'extension_price' => @invoice.equipment_fee} unless @invoice.equipment_fee.zero? data << {'quantity' => 'Transportation:', 'extension_price' => @invoice.transport_fee} unless @invoice.transport_fee.zero? data << {'quantity' => 'Shipping Fee:', 'extension_price' => @invoice.shipping_fee} unless @invoice.shipping_fee.zero? data << {'quantity' => "#{@invoice.fst_name} (#{@invoice.fst_subtotal} x #{@invoice.fst_rate / 1000}%):", 'extension_price' => @invoice.fst_amount} if @invoice.fst? data << {'quantity' => "#{@invoice.pst_name} (#{@invoice.pst_subtotal} x #{@invoice.pst_rate / 1000}%):", 'extension_price' => @invoice.pst_amount} if @invoice.pst? data << {'quantity' => "Total:", 'extension_price' => @invoice.total.format(:with_currency)} data << {'quantity' => "Balance due:", 'extension_price' => @invoice.balance.format(:with_currency)} unless @invoice.balance.zero? table.data = data table.render_on(pdf) end unless @invoice.payments.empty? then pdf.text "\nPayment History", :font_size => 14 pdf.text "", :font_size => 8 PDF::SimpleTable.new do |table| table.width = pdf.in2pts(8.5 - 1.25) table.position = :center table.bold_headings = true table.minimum_space = 50 table.protect_rows = 2 table.column_order = %w(date method reason status amount) table.columns['date'] = PDF::SimpleTable::Column.new('date') {|col| col.heading = 'Date'; col.justification = :right } table.columns['method'] = PDF::SimpleTable::Column.new('method') {|col| col.heading = 'Method' } table.columns['reason'] = PDF::SimpleTable::Column.new('reason') {|col| col.heading = 'Reason' } table.columns['status'] = PDF::SimpleTable::Column.new('status') {|col| col.heading = 'Status' } table.columns['amount'] = PDF::SimpleTable::Column.new('amount') {|col| col.heading = 'Amount'; col.justification = :right } table.data = @invoice.payments.map do |payment| { 'date' => payment.updated_at.to_time.strftime('%d/%m/%Y %H:%M'), 'method' => payment.method_name, 'reason' => payment.reason, 'status' => payment.status, 'amount' => payment.amount.format(:with_currency)} end table.render_on(pdf) end end unless @invoice.notes.blank? then pdf.text "\nNotes", :font_size => 14 pdf.text @invoice.notes, :font_size => 11 end upcoming_jobs = @invoice.upcoming_jobs(@invoice.created_at) unless upcoming_jobs.empty? then pdf.text "\nUpcoming jobs", :font_size => 14 pdf.text 'We have the following jobs scheduled with you:', :font_size => 11 upcoming_jobs.each do |job| text = "* #{job.job_date.to_time.strftime('%d/%m/%Y %H:%M')}" text << " (#{job.duration} hours)" if job.duration != 0 text << " - #{job.description}" pdf.text text, :font_size => 11, :left => pdf.in2pts(0.25) end end return pdf.render end end end