module Dorsale module BillingMachine class InvoicePdf < Prawn::Document include Dorsale::Alexandrie::Prawn include ActionView::Helpers::NumberHelper attr_reader :main_document GREY = "808080" LIGHT_GREY = "C0C0C0" WHITE = "FFFFFF" DEBUG = false FRENCH_MONTH_NAMES = [nil, 'janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'] def main_document_type "Facture" end def initialize(main_document) super(:page_size => 'A4') @main_document = main_document @id_card = @main_document.id_card end def build build_logo build_legal_infos build_header build_contact_infos build_customer_infos build_label build_table build_comments build_footer end def build_logo image @main_document.id_card.logo.path , at: [45, 765], :width => 150 if @main_document.id_card.logo.present? end def build_legal_infos bounding_box [235, 735], :width => 235, :height => 110 do draw_bounds_debug font_size 8 text @id_card.entity_name, align: :right, style: :bold write_legal_line 'SIRET ' + @id_card.siret.to_s + ' APE ' + @id_card.ape_naf.to_s write_legal_line @id_card.legal_form.to_s + ' au capital de ' + number_with_delimiter(@id_card.capital, :delimiter => '.').to_s + ' euros' write_legal_line @id_card.registration_city.to_s + ' ' + @id_card.registration_number.to_s move_down 5 write_legal_line 'N° TVA ' + @id_card.intracommunity_vat.to_s move_down 15 write_legal_line @id_card.address1.to_s write_legal_line @id_card.zip.to_s + " " + @id_card.city.to_s end end def build_header bounding_box [300, 585], :width => 170, :height => 50 do draw_bounds_debug font_size 10 document_type = main_document_type text "#{document_type} N°" + @main_document.tracking_id, :inline_format => true, :align => :right font_size 11.5 text @id_card.city.to_s + ' le ' + french_date(@main_document.date), :align => :right end end def build_contact_infos bounding_box [50, 585], :width => 235, :height => 50 do draw_bounds_debug font_size 10 text 'Contact : ' + @id_card.contact_full_name.to_s, :inline_format => true text 'Tél : ' + @id_card.contact_phone.to_s, :inline_format => true text 'Fax: ' + @id_card.contact_fax.to_s, :inline_format => true text 'Email: ' + @id_card.contact_email.to_s, :inline_format => true end end def build_customer_infos unless @main_document.customer.nil? bounding_box [50, 530], :width => 420, :height => 105 do draw_bounds_debug font_size 11.5 text 'A l’attention de :', :style => :bold text @main_document.customer.name text @main_document.customer.address.street text @main_document.customer.address.street_bis text @main_document.customer.address.zip.to_s + ' ' + @main_document.customer.address.city.to_s text @main_document.customer.address.country end end end def build_label bounding_box [50, 425], :width => 350, :height => 30 do draw_bounds_debug font_size 11 text 'Objet : ' + @main_document.label, :inline_format => true end end def build_table bounding_box [50, 400], :width => 450 do @table_matrix = [['Prestation', 'Prix unitaire', 'Quantité', 'Total HT']] build_lines build_synthesis build_expiry build_payment_terms build_bank_infos end end def build_lines @main_document.lines.each do |line| @table_matrix.push [line.label, french_number(euros(line.unit_price), 2), french_number(line.quantity), french_number(euros(line.total), 2)] end end def build_synthesis font_size 10 if (@main_document.commercial_discount && @main_document.commercial_discount != 0.0) @table_matrix.push ['Remise commerciale', '', '', euros(@main_document.commercial_discount)] end @table_matrix.push ['Net HT', '', '', euros(@main_document.total_duty)] vat_rate = french_number(@main_document.vat_rate) @table_matrix.push ["TVA #{vat_rate} %", '', '', euros(@main_document.vat_amount)] @table_matrix.push ['Total TTC', '', '', euros(@main_document.total_all_taxes)] if (@main_document.advance && @main_document.advance != 0.0) @table_matrix.push ['Acompte reçu sur commande', '', '', euros(@main_document.advance)] @table_matrix.push ['Solde à payer', '', '', euros(@main_document.balance)] end write_table_from_matrix(@table_matrix) end def build_payment_terms move_down 15 text 'Conditions de paiement :' text @main_document.payment_term.try(:label) end def build_bank_infos move_down 10 text 'Coordonnées bancaires :' text 'IBAN : ' + @id_card.iban.to_s text 'BIC / SWIFT : ' + @id_card.bic_swift.to_s end def build_expiry end def build_comments end def build_footer bounding_box [50, 37], :width => 425 do font "Times-Roman" font_size 8.5 text @id_card.custom_info_1, :color => GREY end end def write_table_from_matrix matrix table matrix, :column_widths => [215, 65, 60, 80], :cell_style => {:align => :right, :border_width => 0.5} do row(0).style :background_color => LIGHT_GREY # make first row grey row(0).style :size => 11 # reduce font size of invoice lines invoice_lines_range = Range.new(1,(matrix.length - 6)) row(invoice_lines_range).style :size => 9 end end def draw_bounds_debug transparent(0.5) { stroke_bounds } if DEBUG end def write_legal_line text text text, :align => :right, :color => GREY end def french_date date french_month = FRENCH_MONTH_NAMES[date.month] return date.day.to_s + ' ' + french_month + ' ' + date.year.to_s end def euros amount amount ||= 0 french_number(amount, 2).to_s + " €" end def french_number amount, precision = -1 if precision >= 0 number_with_precision(amount, :precision => precision, :delimiter => '.', :separator => ",") else number_with_delimiter(amount, :delimiter => '.', :separator => ",") end end def number_without_trailling_zero number return ("%g" % number) end end # InvoicePdf end # BillingMachine end # Dorsale