class Dorsale::BillingMachine::InvoiceSingleVatPdf < Dorsale::ApplicationPdf
include Dorsale::Alexandrie::Prawn::RenderWithAttachments
DEBUG = false
BLACK = "000000"
WHITE = "FFFFFF"
GREY = "808080"
LIGHT_GREY = "C0C0C0"
attr_reader :main_document
def initialize(main_document)
super(page_size: "A4", margin: 1.cm)
@main_document = main_document
setup
end
def attachments
@main_document.try(:attachments) || []
end
def bm_currency(n)
currency(n, Dorsale::BillingMachine.default_currency)
end
# rubocop:disable Style/SingleLineMethods, Layout/EmptyLineBetweenDefs
def header_height; 90.mm; end
def logo_height; 32.mm; end
def logo_width; 50.mm; end
def contact_infos_height; 30.mm; end
def footer_height; 40.mm; end
def footer_top_height; 15.mm; end
def footer_bottom_height; 15.mm; end
def footer_pagination_height; 5.mm; end
def middle_height; 14.cm; end
def products_table_height; 90.mm; end
def first_column_width; 7.6.cm; end
def second_column_width; 2.4.cm; end
def third_column_width; 2.5.cm; end
def fourth_column_width; 2.9.cm; end
# rubocop:enable Style/SingleLineMethods, Layout/EmptyLineBetweenDefs
def last_column_width
bounds.width - first_column_width - second_column_width - third_column_width - fourth_column_width
end
def build
repeat :all do
build_header
build_footer
end
build_middle
build_page_numbers
end
def setup
font_root = ::Dorsale::Engine.root.join("app/assets/fonts")
font_families.update( # rubocop:disable Rails/SaveBang
"BryantPro" => {
normal: "#{font_root}/BryantPro-Regular.ttf",
bold: "#{font_root}/BryantPro-Bold.ttf",
},
)
font("BryantPro")
font_size 10
end
def build_header
bb height: header_height do
build_title
build_logo
build_contact_infos
build_subject
build_customer
end
end
def build_title
top = bounds.top - 1.5.cm
height = 1.cm
title = "#{main_document.t} n° #{main_document.tracking_id}"
bb top: top, height: height do
tb title, size: 20, align: :center
end
end
def logo_path
end
def build_logo
height = logo_height
width = logo_width
bb width: width, height: height do
image logo_path, fit: [width, height] if logo_path
end
end
def contact_infos_content
placeholder __method__
end
def build_contact_infos
top = bounds.top - 4.cm
width = bounds.width / 2 - 1.1.cm
height = contact_infos_height
bb top: top, width: width, height: height do
tb contact_infos_content.to_s, size: 9
end
end
def build_subject
top = bounds.top - 7.5.cm
width = bounds.width / 2 - 1.1.cm
height = 15.mm
bb top: top, width: width, height: height do
if main_document.label.present?
text "#{main_document.t(:label)} : #{main_document.label}", inline_format: true
end
if main_document.date.present?
move_down 3.mm
text "#{main_document.t(:date)} : #{date main_document.date}", inline_format: true
end
end
end
def customer_content
return if main_document.customer.nil?
content = []
content << main_document.customer.name
content << main_document.customer.address.street
content << main_document.customer.address.street_bis
content << "#{main_document.customer.address.zip} #{main_document.customer.address.city}"
content << main_document.customer.address.country
if main_document.customer.try(:european_union_vat_number).present?
content << main_document.customer.t(:european_union_vat_number) + " : "
content << main_document.customer.european_union_vat_number
end
content.select(&:present?).join("\n")
end
def build_customer
top = bounds.top - 4.cm
left = bounds.width / 2 + 1.1.cm
width = bounds.width / 2 - 1.1.cm
height = 4.5.cm
padding = 3.mm
bb top: top, left: left, height: height, width: width, padding: padding, background: LIGHT_GREY do
tb customer_content.to_s
end
end # def build_customer
def build_middle
top = bounds.top - header_height
height = middle_height
bb top: top, height: height do
build_table
build_total
build_document_infos
end
end
def has_advance
main_document.try(:advance) && main_document.advance.to_d != 0.0.to_d
end
def has_discount
main_document.try(:commercial_discount) && main_document.commercial_discount.to_d != 0.0.to_d
end
def build_table
height = products_table_height
# Empty table to draw lines
bb height: products_table_height do
repeat :all do
float do
table [["", "", "", "", ""]],
:column_widths => [
first_column_width,
second_column_width,
third_column_width,
fourth_column_width,
last_column_width,
],
:cell_style => {height: height} \
do
row(0).style :text_color => BLACK
row(0).style :font_style => :bold
column(0).style :align => :left
column(1..4).style :align => :right
end # table
end # float
end # repeat all
end # bb
# Products table
bb height: height do
table_products = [[
main_document.t(:designation).mb_chars.upcase.to_s,
main_document.t(:quantity).mb_chars.upcase.to_s,
main_document.t(:unit).mb_chars.upcase.to_s,
main_document.t(:unit_price).mb_chars.upcase.to_s,
main_document.t(:line_total).mb_chars.upcase.to_s,
]]
main_document.lines.each do |line|
table_products.push [
line.label,
number(line.quantity).gsub(",00", "").gsub(".00", ""),
line.unit,
bm_currency(line.unit_price),
bm_currency(line.total),
]
end
table table_products,
:column_widths => [
first_column_width,
second_column_width,
third_column_width,
fourth_column_width,
last_column_width,
],
:header => true,
:cell_style => {border_width: 0} \
do
row(0).font_style = :bold
row(0).border_width =
1,
cells.style { |c| c.align = c.column.zero? ? :left : :right }
end # table
end # bb
end # build_table
def build_total
top = bounds.top - products_table_height - 5.mm
height = middle_height - products_table_height - 5.mm
bb top: top, height: height do
table_totals = [[]]
if has_discount
table_totals.push [
main_document.t(:commercial_discount).mb_chars.upcase.to_s,
bm_currency(-main_document.commercial_discount),
]
end
table_totals.push [
main_document.t(:total_excluding_taxes).mb_chars.upcase.to_s,
bm_currency(main_document.total_excluding_taxes),
]
vat_rate = number(main_document.vat_rate)
table_totals.push [
"#{main_document.t(:vat).mb_chars.upcase} #{percentage vat_rate}",
bm_currency(main_document.vat_amount),
]
if has_advance
table_totals.push [
main_document.t(:advance).mb_chars.upcase.to_s,
bm_currency(main_document.advance),
]
table_totals.push [
main_document.t(:total_including_taxes).mb_chars.upcase.to_s,
bm_currency(main_document.balance),
]
else
table_totals.push [
main_document.t(:total_including_taxes).mb_chars.upcase.to_s,
bm_currency(main_document.total_including_taxes),
]
end
table table_totals,
:column_widths => [fourth_column_width, last_column_width],
:cell_style => {border_width: [0, 1, 0, 0]},
:position => :right do
row(-1).style :font_style => :bold
column(0).padding_right = 0.2.cm
row(-1).borders = [:top, :right]
row(-1).border_width = 1
cells.style do |c|
c.align = :right
end
end
stroke do
rectangle [(bounds.right - fourth_column_width - last_column_width), bounds.top], (fourth_column_width + last_column_width), (bounds.top-cursor)
end
end
end
def document_infos_content
txt = []
if main_document.try(:payment_term).present?
txt << "#{main_document.t :payment_term} : #{main_document.payment_term}"
end
if main_document.try(:expires_at).present?
txt << "#{main_document.t :expires_at} : #{date main_document.expires_at}"
end
txt << main_document.comments
txt.select(&:present?).join("\n\n")
end
def build_document_infos
top = bounds.top - products_table_height - 5.mm
height = middle_height - products_table_height - 5.mm
width = 10.cm
btb document_infos_content, top: top, height: height, width: width
end
def build_footer
top = bounds.bottom + footer_height
height = footer_height
bb top: top, height: height do
build_footer_top
build_footer_line
build_footer_bottom
end
end
# TODO
def footer_top_content
placeholder __method__
end
def build_footer_top
btb footer_top_content, height: footer_top_height, size: 9
end
def build_footer_line
top = bounds.top - footer_top_height - (footer_height - footer_top_height - footer_bottom_height - footer_pagination_height) / 2
stroke do
horizontal_line bounds.left, bounds.right, at: top
end
end
def footer_bottom_content
placeholder __method__
end
def build_footer_bottom
height = footer_bottom_height
top = bounds.bottom + height + footer_pagination_height
btb footer_bottom_content, top: top, height: height, size: 9
end
def build_page_numbers
height = footer_pagination_height
top = bounds.bottom + height
bb top: top, height: height do
number_pages "page /", align: :right, size: 9
end
end
end