invoice_printer 2.0.0.beta3 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +7 -6
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +29 -16
  5. data/README.md +9 -3
  6. data/assets/fonts/opensans/OpenSans-Bold.ttf +0 -0
  7. data/assets/fonts/overpass/Overpass-Bold.ttf +0 -0
  8. data/assets/fonts/roboto/Roboto-Bold.ttf +0 -0
  9. data/benchmarks/render.yml +19 -13
  10. data/bin/invoice_printer +7 -0
  11. data/docs/COMMAND_LINE.md +122 -0
  12. data/docs/LIBRARY.md +16 -12
  13. data/docs/SERVER.md +8 -2
  14. data/examples/breakdown.rb +77 -0
  15. data/examples/international_invoice.rb +2 -2
  16. data/examples/long_invoice.rb +8 -8
  17. data/examples/picture.jpg +0 -0
  18. data/examples/promo.rb +19 -13
  19. data/examples/provider_purchaser_lines.rb +6 -15
  20. data/examples/simple_invoice.rb +15 -16
  21. data/examples/variable_field_invoice.rb +96 -0
  22. data/invoice_printer.gemspec +3 -2
  23. data/invoice_printer_fonts.gemspec +4 -1
  24. data/lib/invoice_printer.rb +27 -2
  25. data/lib/invoice_printer/document.rb +90 -148
  26. data/lib/invoice_printer/document/item.rb +34 -28
  27. data/lib/invoice_printer/pdf_document.rb +201 -208
  28. data/lib/invoice_printer/version.rb +1 -1
  29. data/test/api_test.rb +2 -2
  30. data/test/background_test.rb +1 -1
  31. data/test/cli_test.rb +1 -1
  32. data/test/dates_box_test.rb +4 -4
  33. data/test/examples_test.rb +2 -0
  34. data/test/inputs_test.rb +4 -4
  35. data/test/invoice_printer_test.rb +2 -2
  36. data/test/items_table_test.rb +2 -2
  37. data/test/labels_test.rb +2 -2
  38. data/test/notes_test.rb +1 -1
  39. data/test/page_numbers_test.rb +4 -4
  40. data/test/payment_box_test.rb +5 -5
  41. data/test/test_ext.rb +2 -1
  42. data/test/test_helper.rb +1 -1
  43. metadata +15 -15
  44. data/assets/logo.png +0 -0
  45. data/examples/background.png +0 -0
  46. data/examples/logo.png +0 -0
  47. data/examples/prawn.png +0 -0
  48. data/examples/stamp.png +0 -0
@@ -11,6 +11,7 @@ module InvoicePrinter
11
11
  # document: invoice,
12
12
  # labels: {},
13
13
  # font: 'font.ttf',
14
+ # bold_font: 'bold_font.ttf',
14
15
  # stamp: 'stamp.jpg',
15
16
  # logo: 'example.jpg'
16
17
  # )
@@ -20,7 +21,7 @@ module InvoicePrinter
20
21
  class StampFileNotFound < StandardError; end
21
22
  class InvalidInput < StandardError; end
22
23
 
23
- attr_reader :invoice, :labels, :file_name, :font, :stamp, :logo
24
+ attr_reader :invoice, :labels, :file_name, :font, :bold_font, :stamp, :logo
24
25
 
25
26
  DEFAULT_LABELS = {
26
27
  name: 'Invoice',
@@ -36,6 +37,7 @@ module InvoicePrinter
36
37
  iban: 'IBAN',
37
38
  issue_date: 'Issue date',
38
39
  due_date: 'Due date',
40
+ variable_symbol: 'Variable symbol',
39
41
  item: 'Item',
40
42
  variable: '',
41
43
  quantity: 'Quantity',
@@ -65,10 +67,20 @@ module InvoicePrinter
65
67
  @@labels = DEFAULT_LABELS.merge(labels)
66
68
  end
67
69
 
68
- def initialize(document: Document.new, labels: {}, font: nil, stamp: nil, logo: nil, background: nil, page_size: :letter)
70
+ def initialize(
71
+ document: Document.new,
72
+ labels: {},
73
+ font: nil,
74
+ bold_font: nil,
75
+ stamp: nil,
76
+ logo: nil,
77
+ background: nil,
78
+ page_size: :letter
79
+ )
69
80
  @document = document
70
81
  @labels = merge_custom_labels(labels)
71
82
  @font = font
83
+ @bold_font = bold_font
72
84
  @stamp = stamp
73
85
  @logo = logo
74
86
  @page_size = page_size ? PAGE_SIZES[page_size.to_sym] : PAGE_SIZES[:letter]
@@ -93,38 +105,10 @@ module InvoicePrinter
93
105
  end
94
106
  end
95
107
 
96
- if used? @font
97
- use_font(@font)
98
- end
99
-
100
- # Version 2.1 deprecation warnings
101
- warnings = [
102
- @document.provider_street,
103
- @document.provider_street_number,
104
- @document.provider_postcode,
105
- @document.provider_city,
106
- @document.provider_city_part,
107
- @document.provider_extra_address_line,
108
- @document.purchaser_street,
109
- @document.purchaser_street_number,
110
- @document.purchaser_postcode,
111
- @document.purchaser_city,
112
- @document.purchaser_city_part,
113
- @document.purchaser_extra_address_line
114
- ].delete_if(&:empty?)
115
-
116
- unless warnings.empty?
117
- warning = <<~WARN
118
- WARNING: Following values are used in deprecated fields and
119
- won't be rendered in future versions of InvoicePrinter:
120
-
121
- #{warnings.join(", ")}
122
-
123
- Use new provider_lines and purchaser_lines fields instead of
124
- the old address fields.
125
- WARN
126
-
127
- $stderr.puts warning
108
+ if used?(@font) && used?(@bold_font)
109
+ use_font(@font, @bold_font)
110
+ elsif used?(@font)
111
+ use_font(@font, @font)
128
112
  end
129
113
 
130
114
  build_pdf
@@ -142,11 +126,11 @@ module InvoicePrinter
142
126
 
143
127
  private
144
128
 
145
- def use_font(font)
146
- if File.exist?(@font)
147
- set_font_from_path(@font)
129
+ def use_font(font, bold_font)
130
+ if File.exist?(font) && File.exist?(bold_font)
131
+ set_font_from_path(font, bold_font)
148
132
  else
149
- set_builtin_font(@font)
133
+ set_builtin_font(font)
150
134
  end
151
135
  end
152
136
 
@@ -163,14 +147,14 @@ module InvoicePrinter
163
147
  end
164
148
 
165
149
  # Add font family in Prawn for a given +font+ file
166
- def set_font_from_path(font)
150
+ def set_font_from_path(font, bold_font)
167
151
  font_name = Pathname.new(font).basename
168
152
  @pdf.font_families.update(
169
153
  "#{font_name}" => {
170
154
  normal: font,
171
155
  italic: font,
172
- bold: font,
173
- bold_italic: font
156
+ bold: bold_font,
157
+ bold_italic: bold_font
174
158
  }
175
159
  )
176
160
  @pdf.font(font_name)
@@ -181,6 +165,7 @@ module InvoicePrinter
181
165
  @push_down = 0
182
166
  @push_items_table = 0
183
167
  @pdf.fill_color '000000'
168
+ @pdf.stroke_color 'aaaaaa'
184
169
  build_header
185
170
  build_provider_box
186
171
  build_purchaser_box
@@ -281,41 +266,6 @@ module InvoicePrinter
281
266
  width: x(240)
282
267
  )
283
268
  end
284
- else
285
- @pdf.text_box(
286
- "#{@document.provider_street} #{@document.provider_street_number}",
287
- size: 10,
288
- at: [10, y(620) - @push_down],
289
- width: x(240)
290
- )
291
- @pdf.text_box(
292
- @document.provider_postcode,
293
- size: 10,
294
- at: [10, y(605) - @push_down],
295
- width: x(240)
296
- )
297
- @pdf.text_box(
298
- @document.provider_city,
299
- size: 10,
300
- at: [60, y(605) - @push_down],
301
- width: x(240)
302
- )
303
- unless @document.provider_city_part.empty?
304
- @pdf.text_box(
305
- @document.provider_city_part,
306
- size: 10,
307
- at: [60, y(590) - @push_down],
308
- width: x(240)
309
- )
310
- end
311
- unless @document.provider_extra_address_line.empty?
312
- @pdf.text_box(
313
- @document.provider_extra_address_line,
314
- size: 10,
315
- at: [10, y(575) - @push_down],
316
- width: x(240)
317
- )
318
- end
319
269
  end
320
270
  unless @document.provider_tax_id.empty?
321
271
  @pdf.text_box(
@@ -386,41 +336,6 @@ module InvoicePrinter
386
336
  width: x(240)
387
337
  )
388
338
  end
389
- else
390
- @pdf.text_box(
391
- "#{@document.purchaser_street} #{@document.purchaser_street_number}",
392
- size: 10,
393
- at: [x(284), y(620) - @push_down],
394
- width: x(240)
395
- )
396
- @pdf.text_box(
397
- @document.purchaser_postcode,
398
- size: 10,
399
- at: [x(284), y(605) - @push_down],
400
- width: x(240)
401
- )
402
- @pdf.text_box(
403
- @document.purchaser_city,
404
- size: 10,
405
- at: [x(334), y(605) - @push_down],
406
- width: x(240)
407
- )
408
- unless @document.purchaser_city_part.empty?
409
- @pdf.text_box(
410
- @document.purchaser_city_part,
411
- size: 10,
412
- at: [x(334), y(590) - @push_down],
413
- width: x(240)
414
- )
415
- end
416
- unless @document.purchaser_extra_address_line.empty?
417
- @pdf.text_box(
418
- @document.purchaser_extra_address_line,
419
- size: 10,
420
- at: [x(284), y(575) - @push_down],
421
- width: x(240)
422
- )
423
- end
424
339
  end
425
340
  unless @document.purchaser_tax_id.empty?
426
341
  @pdf.text_box(
@@ -469,6 +384,10 @@ module InvoicePrinter
469
384
  end
470
385
  @payment_box_height = min_height
471
386
 
387
+ if big_info_box?
388
+ @payment_box_height = 110
389
+ end
390
+
472
391
  if @document.bank_account_number.empty?
473
392
  @pdf.text_box(
474
393
  @labels[:payment],
@@ -580,6 +499,7 @@ module InvoicePrinter
580
499
  @payment_box_height += 30
581
500
  @push_items_table += 18
582
501
  end
502
+
583
503
  if min_height > @payment_box_height
584
504
  @payment_box_height = min_height
585
505
  @push_items_table += 25
@@ -600,6 +520,8 @@ module InvoicePrinter
600
520
  # | Issue date sublabel |
601
521
  # | Due date: 03/03/2016|
602
522
  # | Due date sublabel |
523
+ # | Variable symbol: VS12345678|
524
+ # | Variable symbol sublabel |
603
525
  # --------------------------------
604
526
  #
605
527
  def build_info_box
@@ -619,17 +541,17 @@ module InvoicePrinter
619
541
  width: x(146),
620
542
  align: :right
621
543
  )
622
- end
623
544
 
624
- if used? @labels[:sublabels][:issue_date]
625
- position = issue_date_present ? 483 : 498
545
+ if used? @labels[:sublabels][:issue_date]
546
+ position = issue_date_present ? 483 : 498
626
547
 
627
- @pdf.text_box(
628
- @labels[:sublabels][:issue_date],
629
- size: 10,
630
- at: [x(284), y(position) - @push_down],
631
- width: x(240)
632
- )
548
+ @pdf.text_box(
549
+ @labels[:sublabels][:issue_date],
550
+ size: 10,
551
+ at: [x(284), y(position) - @push_down],
552
+ width: x(240)
553
+ )
554
+ end
633
555
  end
634
556
 
635
557
  due_date_present = !@document.due_date.empty?
@@ -651,29 +573,83 @@ module InvoicePrinter
651
573
  width: x(146),
652
574
  align: :right
653
575
  )
576
+
577
+ if used? @labels[:sublabels][:due_date]
578
+ position = issue_date_present ? 463 : 478
579
+ position -= 10 if used? @labels[:sublabels][:issue_date]
580
+
581
+ @pdf.text_box(
582
+ @labels[:sublabels][:due_date],
583
+ size: 10,
584
+ at: [x(284), y(position) - @push_down],
585
+ width: x(240)
586
+ )
587
+ end
654
588
  end
655
589
 
656
- if used? @labels[:sublabels][:due_date]
657
- position = issue_date_present ? 463 : 478
590
+ variable_symbol_present = !@document.variable_symbol.empty?
591
+
592
+ if variable_symbol_present
593
+ position = (issue_date_present || due_date_present) ? 483 : 498
594
+ position = issue_date_present && due_date_present ? 458 : 463
658
595
  position -= 10 if used? @labels[:sublabels][:issue_date]
596
+ position -= 10 if used? @labels[:sublabels][:due_date]
659
597
 
660
598
  @pdf.text_box(
661
- @labels[:sublabels][:due_date],
662
- size: 10,
599
+ @labels[:variable_symbol],
600
+ size: 11,
663
601
  at: [x(284), y(position) - @push_down],
664
602
  width: x(240)
665
603
  )
604
+ @pdf.text_box(
605
+ @document.variable_symbol,
606
+ size: 13,
607
+ at: [x(384), y(position) - @push_down],
608
+ width: x(146),
609
+ align: :right
610
+ )
611
+
612
+ if used? @labels[:sublabels][:variable_symbol]
613
+ position = issue_date_present ? 443 : 458
614
+ position -= 10 if used? @labels[:sublabels][:issue_date]
615
+ position -= 10 if used? @labels[:sublabels][:due_date]
616
+
617
+ @pdf.text_box(
618
+ @labels[:sublabels][:variable_symbol],
619
+ size: 10,
620
+ at: [x(284), y(position) - @push_down],
621
+ width: x(240)
622
+ )
623
+ end
666
624
  end
667
625
 
668
- if issue_date_present || due_date_present
626
+ if issue_date_present || due_date_present || variable_symbol_present
627
+ big_box = (issue_date_present && due_date_present && variable_symbol_present && info_box_sublabels_used?)
669
628
  height = (issue_date_present && due_date_present) ? 75 : 60
629
+ height = big_box ? 110 : height
670
630
  height = @payment_box_height if @payment_box_height > height
671
631
 
672
632
  @pdf.stroke_rounded_rectangle([x(274), y(508) - @push_down], x(266), height, 6)
673
- @push_items_table += 12 if @push_items_table <= 18
633
+ @push_items_table += 23 if @push_items_table <= 18
634
+ @push_items_table += 24 if big_box
635
+
636
+ #@push_items_table += 30
674
637
  end
675
638
  end
676
639
 
640
+ def big_info_box?
641
+ !@document.issue_date.empty? &&
642
+ !@document.due_date.empty? &&
643
+ !@document.variable_symbol.empty? &&
644
+ info_box_sublabels_used?
645
+ end
646
+
647
+ def info_box_sublabels_used?
648
+ used?(@labels[:sublabels][:issue_date]) ||
649
+ used?(@labels[:sublabels][:due_date]) ||
650
+ used?(@labels[:sublabels][:variable_symbol])
651
+ end
652
+
677
653
  # Build the following table for document items:
678
654
  #
679
655
  # =================================================================
@@ -700,26 +676,28 @@ module InvoicePrinter
700
676
  items_params = determine_items_structure
701
677
  items = build_items_data(items_params)
702
678
  headers = build_items_header(items_params)
679
+ data = items.prepend(headers)
703
680
 
704
- styles = {
705
- headers: headers,
706
- row_colors: ['F5F5F5', nil],
681
+ options = {
682
+ header: true,
683
+ row_colors: [nil, 'ededed'],
707
684
  width: x(540, 2),
708
- align: {
709
- 0 => :left,
710
- 1 => :right,
711
- 2 => :right,
712
- 3 => :right,
713
- 4 => :right,
714
- 5 => :right,
715
- 6 => :right,
716
- 7 => :right,
717
- 8 => :right
718
- },
719
- font_size: 10
685
+ cell_style: {
686
+ borders: []
687
+ }
720
688
  }
721
689
 
722
- @pdf.table(items, styles) unless items.empty?
690
+ unless items.empty?
691
+ @pdf.font_size(10) do
692
+ @pdf.table(data, options) do
693
+ row(0).background_color = 'e3e3e3'
694
+ row(0).border_color = 'aaaaaa'
695
+ row(0).borders = [:bottom]
696
+ row(items.size - 1).borders = [:bottom]
697
+ row(items.size - 1).border_color = 'd9d9d9'
698
+ end
699
+ end
700
+ end
723
701
  end
724
702
 
725
703
  # Determine sections of the items table to show based on provided data
@@ -743,31 +721,53 @@ module InvoicePrinter
743
721
  def build_items_data(items_params)
744
722
  @document.items.map do |item|
745
723
  line = []
746
- line << item.name if items_params[:names]
747
- line << item.variable if items_params[:variables]
748
- line << item.quantity if items_params[:quantities]
749
- line << item.unit if items_params[:units]
750
- line << item.price if items_params[:prices]
751
- line << item.tax if items_params[:taxes]
752
- line << item.tax2 if items_params[:taxes2]
753
- line << item.tax3 if items_params[:taxes3]
754
- line << item.amount if items_params[:amounts]
724
+ line << { content: name_cell(item), borders: [:bottom] } if items_params[:names]
725
+ #line << { content: item.name, borders: [:bottom], align: :left } if items_params[:names]
726
+ line << { content: item.variable, align: :right } if items_params[:variables]
727
+ line << { content: item.quantity, align: :right } if items_params[:quantities]
728
+ line << { content: item.unit, align: :right } if items_params[:units]
729
+ line << { content: item.price, align: :right } if items_params[:prices]
730
+ line << { content: item.tax, align: :right } if items_params[:taxes]
731
+ line << { content: item.tax2, align: :right } if items_params[:taxes2]
732
+ line << { content: item.tax3, align: :right } if items_params[:taxes3]
733
+ line << { content: item.amount, align: :right } if items_params[:amounts]
755
734
  line
756
735
  end
757
736
  end
758
737
 
738
+ # Display item's name and breakdown if present
739
+ def name_cell(item)
740
+ data = if used?(item.breakdown)
741
+ data = [
742
+ [{ content: item.name, padding: [5, 0, 0, 5] }],
743
+ [{ content: item.breakdown, size: 8, padding: [2, 0, 5, 5] }]
744
+ ]
745
+
746
+ options = {
747
+ cell_style: {
748
+ borders: []
749
+ },
750
+ position: :left
751
+ }
752
+
753
+ @pdf.make_table(data, options)
754
+ else
755
+ item.name
756
+ end
757
+ end
758
+
759
759
  # Include only relevant headers
760
760
  def build_items_header(items_params)
761
761
  headers = []
762
- headers << { text: label_with_sublabel(:item) } if items_params[:names]
763
- headers << { text: label_with_sublabel(:variable) } if items_params[:variables]
764
- headers << { text: label_with_sublabel(:quantity) } if items_params[:quantities]
765
- headers << { text: label_with_sublabel(:unit) } if items_params[:units]
766
- headers << { text: label_with_sublabel(:price_per_item) } if items_params[:prices]
767
- headers << { text: label_with_sublabel(:tax) } if items_params[:taxes]
768
- headers << { text: label_with_sublabel(:tax2) } if items_params[:taxes2]
769
- headers << { text: label_with_sublabel(:tax3) } if items_params[:taxes3]
770
- headers << { text: label_with_sublabel(:amount) } if items_params[:amounts]
762
+ headers << { content: label_with_sublabel(:item), align: :left } if items_params[:names]
763
+ headers << { content: label_with_sublabel(:variable), align: :right } if items_params[:variables]
764
+ headers << { content: label_with_sublabel(:quantity), align: :right } if items_params[:quantities]
765
+ headers << { content: label_with_sublabel(:unit), align: :right } if items_params[:units]
766
+ headers << { content: label_with_sublabel(:price_per_item), align: :right } if items_params[:prices]
767
+ headers << { content: label_with_sublabel(:tax), align: :right } if items_params[:taxes]
768
+ headers << { content: label_with_sublabel(:tax2), align: :right } if items_params[:taxes2]
769
+ headers << { content: label_with_sublabel(:tax3), align: :right } if items_params[:taxes3]
770
+ headers << { content: label_with_sublabel(:amount), align: :right } if items_params[:amounts]
771
771
  headers
772
772
  end
773
773
 
@@ -794,54 +794,40 @@ module InvoicePrinter
794
794
  @pdf.move_down(25)
795
795
 
796
796
  items = []
797
- items << ["#{@labels[:subtotal]}:#{build_sublabel_for_total_table(:subtotal)}", @document.subtotal] \
798
- unless @document.subtotal.empty?
799
- items << ["#{@labels[:tax]}:#{build_sublabel_for_total_table(:tax)}", @document.tax] \
800
- unless @document.tax.empty?
801
- items << ["#{@labels[:tax2]}:#{build_sublabel_for_total_table(:tax2)}", @document.tax2] \
802
- unless @document.tax2.empty?
803
- items << ["#{@labels[:tax3]}:#{build_sublabel_for_total_table(:tax3)}", @document.tax3] \
804
- unless @document.tax3.empty?
805
-
806
- width = [
807
- "#{@labels[:subtotal]}#{@document.subtotal}".size,
808
- "#{@labels[:tax]}#{@document.tax}".size,
809
- "#{@labels[:tax2]}#{@document.tax2}".size,
810
- "#{@labels[:tax3]}#{@document.tax3}".size
811
- ].max * 8
812
-
813
- styles = {
814
- border_width: 0,
815
- align: {
816
- 0 => :right,
817
- 1 => :left
818
- }
819
- }
820
-
821
- @pdf.span(x(width), position: :right) do
822
- @pdf.table(items, styles) unless items.empty?
823
- end
824
-
825
- @pdf.move_down(15)
826
797
 
827
- unless @document.total.empty?
828
- @pdf.text(
829
- "#{@labels[:total]}: #{@document.total}",
830
- size: 16,
831
- align: :right,
832
- style: :bold
833
- )
834
-
835
- @pdf.move_down(5)
798
+ items << [
799
+ { content: "#{@labels[:subtotal]}:#{build_sublabel_for_total_table(:subtotal)}", align: :left },
800
+ { content: @document.subtotal, align: :right }
801
+ ] unless @document.subtotal.empty?
802
+
803
+ items << [
804
+ { content: "#{@labels[:tax]}:#{build_sublabel_for_total_table(:tax)}", align: :left },
805
+ { content: @document.tax, align: :right }
806
+ ] unless @document.tax.empty?
807
+
808
+ items << [
809
+ { content: "#{@labels[:tax2]}:#{build_sublabel_for_total_table(:tax2)}", align: :left },
810
+ { content: @document.tax2, align: :right }
811
+ ] unless @document.tax2.empty?
812
+
813
+ items << [
814
+ { content: "#{@labels[:tax3]}:#{build_sublabel_for_total_table(:tax3)}", align: :left },
815
+ { content: @document.tax3, align: :right }
816
+ ] unless @document.tax3.empty?
817
+
818
+ items << [
819
+ { content: "\n#{@labels[:total]}:#{build_sublabel_for_total_table(:total)}", align: :left, font_style: :bold, size: 16 },
820
+ { content: "\n#{@document.total}", align: :right, font_style: :bold, size: 16 }
821
+ ] unless @document.total.empty?
822
+
823
+ options = {
824
+ cell_style: {
825
+ borders: []
826
+ },
827
+ position: :right
828
+ }
836
829
 
837
- if used? @labels[:sublabels][:total]
838
- @pdf.text(
839
- "#{@labels[:sublabels][:total]}: #{@document.total}",
840
- size: 12,
841
- align: :right
842
- )
843
- end
844
- end
830
+ @pdf.table(items, options) unless items.empty?
845
831
  end
846
832
 
847
833
  # Return sublabel on a new line or empty string
@@ -858,7 +844,7 @@ module InvoicePrinter
858
844
  # If a note is present, position it on top of it.
859
845
  def build_logo
860
846
  if @logo && !@logo.empty?
861
- bottom = @document.note.empty? ? 75 : 85
847
+ bottom = @document.note.empty? ? 75 : (75 + note_height)
862
848
  @pdf.image(@logo, at: [0, bottom], fit: [200, 50])
863
849
  end
864
850
  end
@@ -876,12 +862,19 @@ module InvoicePrinter
876
862
  @pdf.text_box(
877
863
  "#{@document.note}",
878
864
  size: 10,
879
- at: [0, 10],
865
+ at: [0, note_height],
880
866
  width: x(450),
881
867
  align: :left
882
868
  )
883
869
  end
884
870
 
871
+ def note_height
872
+ @note_height ||= begin
873
+ num_of_lines = @document.note.lines.count
874
+ (num_of_lines * 11)
875
+ end
876
+ end
877
+
885
878
  # Include page numbers if we got more than one page
886
879
  def build_footer
887
880
  @pdf.number_pages(