Class: AddressLabelsPdf

Inherits:
Prawn::Document
  • Object
show all
Defined in:
app/pdfs/address_labels_pdf.rb

Instance Method Summary collapse

Constructor Details

#initialize(address_labels, options = {title: '', updated_at: Time.zone.now, sender: '', book_rate: false}) ⇒ AddressLabelsPdf

address_label: Array of AddressLabel objects. When calling ‘addresses.to_s`, the i-th

address is returned as String.

options:

- title:        The title of the document, e.g. "Addresses of all CEOs".
- updated_at:   Timestamp that indicates the date of last modification.
- sender:       Sender line of the address label.
- book_rate:    Whether the package is to be sent as "press and books".
                When sent to Germany, this results in the badge "Büchersendung".
                When sent to other countries, the international "Envois à taxe réduite" is used.


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/pdfs/address_labels_pdf.rb', line 15

def initialize(address_labels, options = {title: '', updated_at: Time.zone.now, sender: '', book_rate: false})
  super(page_size: 'A4', top_margin: 8.mm, bottom_margin: 8.mm, left_margin: 10.mm, right_margin: 10.mm)
  
  @document_title = options[:title]
  @document_updated_at = options[:updated_at]
  @required_page_count = (address_labels.count / 24).round + 1
  @sender = options[:sender]
  @book_rate = options[:book_rate]
  
  define_grid columns: 3, rows: 8, gutter: 10.mm
  
  for p in (0..(@required_page_count - 1))
    page_header
    page_footer
    
    for y in 0..7
     for x in 0..2
       grid(y, x).bounding_box do
         address_label = address_labels[p * 24 + y * 3 + x]
         address = address_label.to_s.gsub(", ", "\n")
         book_rate_line(address_label) if @book_rate and address_label
         sender_line if @sender and address.to_s.present?
         address.gsub!("\nDeutschland", "") if I18n.locale == :de # in order to save space for in-country deliveries.
         text address.to_s, size: text_size(address.to_s, @book_rate), fallback_fonts: fallback_fonts
       end
     end
    end
    start_new_page if p < (@required_page_count - 1)
  end
  
  # grid.show_all
end

Instance Method Details

#book_rate_line(address_label) ⇒ Object



48
49
50
51
52
53
54
# File 'app/pdfs/address_labels_pdf.rb', line 48

def book_rate_line(address_label)
  move_up 2.mm
  address_label.kind_of?(AddressLabel) || raise('Expected AddressLabel, got String. This might be caused by a change of interface. Please call `uncached(:members_postal_addresses)` on all Groups.')
  book_rate_text = (address_label.country_code == "DE") ? "BÜCHERSENDUNG" : "ENVOIS À TAXE RÉDUITE"
  text "<b>#{book_rate_text}</b>", size: 12.pt, inline_format: true
  move_down 1.mm
end

#define_fontsObject



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'app/pdfs/address_labels_pdf.rb', line 119

def define_fonts
  # The idea to use fallback fonts to have chinese characters supported along
  # with other UTF-8 characters, was taken from:
  # http://stackoverflow.com/a/11097644/2066546
  
  kai = "#{Prawn::BASEDIR}/data/fonts/gkai00mp.ttf"
  # action_man_path = "#{Prawn::BASEDIR}/data/fonts/Action Man.dfont"
  dejavu = "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"

  font_families.update("dejavu" => {
    :normal      => dejavu,
    :italic      => dejavu,
    :bold        => dejavu,
    :bold_italic => dejavu
  })

  #Times is defined in prawn
  font_families.update("times" => {
    :normal => "Times-Roman",
    :italic      => "Times-Italic",
    :bold        => "Times-Bold",
    :bold_italic => "Times-BoldItalic"
  })

  # font_families.update("action_man" => {
  #   :normal      => { :file => action_man_path, :font => "ActionMan" },
  #   :italic      => { :file => action_man_path, :font => "ActionMan-Italic" },
  #   :bold        => { :file => action_man_path, :font => "ActionMan-Bold" },
  #   :bold_italic => { :file => action_man_path, :font => "ActionMan-BoldItalic" }
  # })

  font_families.update("kai" => {
    :normal => { :file => kai, :font => "Kai" },
    :bold   => kai,
    :italic => kai,
    :bold_italic => kai
  })
end

#fallback_fontsObject



114
115
116
117
# File 'app/pdfs/address_labels_pdf.rb', line 114

def fallback_fonts
  define_fonts
  ["dejavu", "times", 'kai']
end

#num_of_lines_required(str, font_size = 12.pt) ⇒ Object

This method estimates the number of lines required for the given string. Some lines are longer than 35 characters and they will broken into the new line in the PDF. Therefore we need this estimate.



88
89
90
91
92
93
94
95
# File 'app/pdfs/address_labels_pdf.rb', line 88

def num_of_lines_required(str, font_size = 12.pt)
  @available_width ||= (210.mm - 20.mm - 2 * 10.mm)/3
  if str.present?
    str.lines.collect { |line| (width_of(line, size: font_size) / @available_width).floor + 1 }.sum
  else
    0
  end
end


108
109
110
111
112
# File 'app/pdfs/address_labels_pdf.rb', line 108

def page_footer
  bounding_box([0, -0.5.cm], width: 18.5.cm, height: 0.5.cm) do
    text page_footer_text, size: 8.pt, align: :center
  end
end


105
106
107
# File 'app/pdfs/address_labels_pdf.rb', line 105

def page_footer_text
  "#{Rails.application.class.parent_name}: #{@document_title}, Datenstand: #{I18n.localize(@document_updated_at)}, Seite #{page_number} von #{@required_page_count}"
end

#page_headerObject



100
101
102
103
104
# File 'app/pdfs/address_labels_pdf.rb', line 100

def page_header
  bounding_box([0, 28.85.cm], width: 18.5.cm, height: 0.5.cm) do
    text page_header_text, size: 8.pt, align: :center
  end
end

#page_header_textObject



97
98
99
# File 'app/pdfs/address_labels_pdf.rb', line 97

def page_header_text
  "Druck auf Zweckform 3475, 70x36 mm², 24 Stk pro Blatt, DIN-A4. Skalierung auf 100% stellen!"
end

#sender_lineObject



56
57
58
59
# File 'app/pdfs/address_labels_pdf.rb', line 56

def sender_line
  text "<u>#{@sender}</u>", size: 5.pt, inline_format: true
  move_down 2.mm
end

#text_size(str, book_rate = false) ⇒ Object

This method is to adjust the font size according to the number of lines required in order to have all addresses fit into their box, but have the font as large as possible.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'app/pdfs/address_labels_pdf.rb', line 65

def text_size(str, book_rate = false)
  if book_rate
    # If there is a "book rate" badge, the actual address text needs to be smaller.
    if str.present?
      return 10.pt if num_of_lines_required(str, 12.pt) < 5
      return 8.pt if num_of_lines_required(str, 10.pt) < 6
      return 6.pt if num_of_lines_required(str, 8.pt) < 8
    end
    return 5.pt
  else
    if str.present?
      return 12.pt if num_of_lines_required(str, 12.pt) < 5
      return 10.pt if num_of_lines_required(str, 10.pt) < 6
      return 8.pt if num_of_lines_required(str, 8.pt) < 8
    end
    return 7.pt
  end
end