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.
- checksums.yaml +4 -4
- data/Dockerfile +7 -6
- data/Gemfile +1 -1
- data/Gemfile.lock +29 -16
- data/README.md +9 -3
- data/assets/fonts/opensans/OpenSans-Bold.ttf +0 -0
- data/assets/fonts/overpass/Overpass-Bold.ttf +0 -0
- data/assets/fonts/roboto/Roboto-Bold.ttf +0 -0
- data/benchmarks/render.yml +19 -13
- data/bin/invoice_printer +7 -0
- data/docs/COMMAND_LINE.md +122 -0
- data/docs/LIBRARY.md +16 -12
- data/docs/SERVER.md +8 -2
- data/examples/breakdown.rb +77 -0
- data/examples/international_invoice.rb +2 -2
- data/examples/long_invoice.rb +8 -8
- data/examples/picture.jpg +0 -0
- data/examples/promo.rb +19 -13
- data/examples/provider_purchaser_lines.rb +6 -15
- data/examples/simple_invoice.rb +15 -16
- data/examples/variable_field_invoice.rb +96 -0
- data/invoice_printer.gemspec +3 -2
- data/invoice_printer_fonts.gemspec +4 -1
- data/lib/invoice_printer.rb +27 -2
- data/lib/invoice_printer/document.rb +90 -148
- data/lib/invoice_printer/document/item.rb +34 -28
- data/lib/invoice_printer/pdf_document.rb +201 -208
- data/lib/invoice_printer/version.rb +1 -1
- data/test/api_test.rb +2 -2
- data/test/background_test.rb +1 -1
- data/test/cli_test.rb +1 -1
- data/test/dates_box_test.rb +4 -4
- data/test/examples_test.rb +2 -0
- data/test/inputs_test.rb +4 -4
- data/test/invoice_printer_test.rb +2 -2
- data/test/items_table_test.rb +2 -2
- data/test/labels_test.rb +2 -2
- data/test/notes_test.rb +1 -1
- data/test/page_numbers_test.rb +4 -4
- data/test/payment_box_test.rb +5 -5
- data/test/test_ext.rb +2 -1
- data/test/test_helper.rb +1 -1
- metadata +15 -15
- data/assets/logo.png +0 -0
- data/examples/background.png +0 -0
- data/examples/logo.png +0 -0
- data/examples/prawn.png +0 -0
- 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(
|
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? @
|
97
|
-
use_font(@font)
|
98
|
-
|
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?(
|
147
|
-
set_font_from_path(
|
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(
|
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:
|
173
|
-
bold_italic:
|
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
|
-
|
625
|
-
|
545
|
+
if used? @labels[:sublabels][:issue_date]
|
546
|
+
position = issue_date_present ? 483 : 498
|
626
547
|
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
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
|
-
|
657
|
-
|
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[:
|
662
|
-
size:
|
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 +=
|
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
|
-
|
705
|
-
|
706
|
-
row_colors: ['
|
681
|
+
options = {
|
682
|
+
header: true,
|
683
|
+
row_colors: [nil, 'ededed'],
|
707
684
|
width: x(540, 2),
|
708
|
-
|
709
|
-
|
710
|
-
|
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
|
-
|
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
|
747
|
-
line << item.
|
748
|
-
line << item.
|
749
|
-
line << item.
|
750
|
-
line << item.
|
751
|
-
line << item.
|
752
|
-
line << item.
|
753
|
-
line << item.
|
754
|
-
line << item.
|
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 << {
|
763
|
-
headers << {
|
764
|
-
headers << {
|
765
|
-
headers << {
|
766
|
-
headers << {
|
767
|
-
headers << {
|
768
|
-
headers << {
|
769
|
-
headers << {
|
770
|
-
headers << {
|
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
|
-
|
828
|
-
@
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
)
|
834
|
-
|
835
|
-
|
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
|
-
|
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 :
|
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,
|
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(
|