invoice_printer 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ddd0a166f35069b45db3f5c65500c8266944d76
4
- data.tar.gz: a40efb4a2f1dabf24979ec48e55687ef372f8800
3
+ metadata.gz: 327ecc31f48a1b7a25b413c9423c47ce335c1a1b
4
+ data.tar.gz: bb454cbed1da8260b3f73c8f6ede4db3328326e5
5
5
  SHA512:
6
- metadata.gz: 5c3f7dd04900eb6c8f9dc8d33af717a8478b67b8e0102e1ff16a884572ba72a9539b8da828cbd87a87bef8a684c051e865e5394fd549b3da461b8d77c353a78b
7
- data.tar.gz: 941c1108dd6881bb4a6712070da699074dd34c430eb782409a01efb79d9453e884dc235eacf1a42a74a17ac67eb2005f0b8506855563eaa5d3fdcccef6ba32f1
6
+ metadata.gz: 1aa09af511628b9dba7d3d5aa3497c33f5927c0d96b55964b5cf0a9b24219582dde29e3a8d8855fc8806ab99c77b4e69f4f34ad0cda1e52a520d8a3a5f362c95
7
+ data.tar.gz: 8de19983830a6263597e6799fd6c7738c81b5ee1b73dff6e44a504ef5b80c093da19eb7cbf25f73161987a9388314972df12f9e80e43f6f69be4a81aeecadbaa
data/.gitignore CHANGED
@@ -1,6 +1,5 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
- /Gemfile.lock
4
3
  /_yardoc/
5
4
  /coverage/
6
5
  /doc/
data/Gemfile CHANGED
@@ -8,3 +8,9 @@ group :test do
8
8
  gem 'minitest'
9
9
  gem 'rack-test', require: 'rack/test'
10
10
  end
11
+
12
+ group :benchmark do
13
+ gem 'benchmark_driver', '0.14.11'
14
+ # For generating benchmark reports with --output gruff
15
+ gem 'benchmark_driver-output-gruff'
16
+ end
@@ -0,0 +1,63 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ invoice_printer (1.2.0)
5
+ json (~> 2.1)
6
+ prawn (= 2.1.0)
7
+ prawn-layout (= 0.8.4)
8
+ puma (~> 3.9)
9
+ roda (= 3.5.0)
10
+
11
+ GEM
12
+ remote: https://rubygems.org/
13
+ specs:
14
+ Ascii85 (1.0.3)
15
+ afm (0.2.2)
16
+ benchmark_driver (0.14.11)
17
+ benchmark_driver-output-gruff (0.3.1)
18
+ benchmark_driver (>= 0.12.0)
19
+ gruff
20
+ gruff (0.7.0)
21
+ rmagick (~> 2.13, >= 2.13.4)
22
+ hashery (2.1.2)
23
+ json (2.1.0)
24
+ minitest (5.11.3)
25
+ pdf-core (0.6.1)
26
+ pdf-inspector (1.3.0)
27
+ pdf-reader (>= 1.0, < 3.0.a)
28
+ pdf-reader (2.2.0)
29
+ Ascii85 (~> 1.0.0)
30
+ afm (~> 0.2.1)
31
+ hashery (~> 2.0)
32
+ ruby-rc4
33
+ ttfunk
34
+ prawn (2.1.0)
35
+ pdf-core (~> 0.6.1)
36
+ ttfunk (~> 1.4.0)
37
+ prawn-layout (0.8.4)
38
+ puma (3.12.0)
39
+ rack (2.0.6)
40
+ rack-test (1.1.0)
41
+ rack (>= 1.0, < 3)
42
+ rake (10.5.0)
43
+ rmagick (2.16.0)
44
+ roda (3.5.0)
45
+ rack
46
+ ruby-rc4 (0.1.5)
47
+ ttfunk (1.4.0)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ benchmark_driver (= 0.14.11)
54
+ benchmark_driver-output-gruff
55
+ bundler (~> 1.7)
56
+ invoice_printer!
57
+ minitest
58
+ pdf-inspector
59
+ rack-test
60
+ rake (~> 10.0)
61
+
62
+ BUNDLED WITH
63
+ 1.16.1
data/README.md CHANGED
@@ -48,6 +48,4 @@ See more usecases in the `examples/` directory.
48
48
 
49
49
  ## Copyright
50
50
 
51
- Copyright 2015-2018 &copy; [Josef Strzibny](http://strzibny.name/). MIT licensed.
52
-
53
- Originally extracted from and created for an open source single-entry invoicing app [InvoiceBar](https://github.com/strzibny/invoicebar).
51
+ Copyright 2015-2019 &copy; [Josef Strzibny](http://strzibny.name/). MIT licensed.
@@ -0,0 +1,44 @@
1
+ # Run the benchmark with benchmark_driver as:
2
+ #
3
+ # $ benchmark-driver benchmarks/render.yml --output gruff --runner ips -e '/path/to/bin/ruby;/path/to/bin/ruby-2.6.0 --jit'
4
+ # $ benchmark-driver benchmarks/render.yml --output compare --runner memory -e '/path/to/bin/ruby;/path/to/bin/ruby-2.6.0 --jit--jit'
5
+ loop_count: 10000
6
+ prelude: |
7
+ lib = File.expand_path('../lib', __FILE__)
8
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
9
+ require 'invoice_printer'
10
+
11
+ item = InvoicePrinter::Document::Item.new(
12
+ name: 'Programming',
13
+ quantity: '10',
14
+ unit: 'hr',
15
+ price: '$ 90',
16
+ amount: '$ 900'
17
+ )
18
+
19
+ invoice = InvoicePrinter::Document.new(
20
+ number: 'NO. 198900000001',
21
+ provider_name: 'John White',
22
+ provider_street: '5th Avenue',
23
+ provider_street_number: '1',
24
+ provider_postcode: '747 05',
25
+ provider_city: 'NYC',
26
+ purchaser_name: 'Will Black',
27
+ purchaser_street: '7th Avenue',
28
+ purchaser_street_number: '1',
29
+ purchaser_postcode: '747 70',
30
+ purchaser_city: 'NYC',
31
+ issue_date: '05/03/2016',
32
+ due_date: '19/03/2016',
33
+ total: '$ 900',
34
+ bank_account_number: '156546546465',
35
+ items: [item],
36
+ note: 'This is a note at the end.'
37
+ )
38
+ benchmark:
39
+ render: |
40
+ InvoicePrinter.print(
41
+ document: invoice,
42
+ file_name: 'simple_invoice_a4.pdf',
43
+ page_size: :a4
44
+ )
@@ -16,11 +16,12 @@ def show_help
16
16
 
17
17
  Options:
18
18
 
19
- -l, --labels labels as JSON
20
19
  -d, --document document as JSON
20
+ -l, --labels labels as JSON
21
+ --font path to font
21
22
  -s, --stamp path to stamp
22
23
  --logo path to logotype
23
- --font path to font
24
+ --background path to background image
24
25
  --page-size letter or a4 (letter is the default)
25
26
  -f, --filename output path
26
27
  -r, --render directly render PDF stream (filename option will be ignored)
@@ -33,12 +34,16 @@ end
33
34
  options = {}
34
35
 
35
36
  parser = OptionParser.new do|opts|
37
+ opts.on('-d', '--document JSON') do |json|
38
+ options[:document] = json
39
+ end
40
+
36
41
  opts.on('-l', '--labels JSON') do |json|
37
42
  options[:labels] = json
38
43
  end
39
44
 
40
- opts.on('-d', '--document JSON') do |json|
41
- options[:document] = json
45
+ opts.on('--font PATH') do |path|
46
+ options[:font] = path
42
47
  end
43
48
 
44
49
  opts.on('-s', '--stamp PATH') do |path|
@@ -49,8 +54,8 @@ parser = OptionParser.new do|opts|
49
54
  options[:logo] = path
50
55
  end
51
56
 
52
- opts.on('--font PATH') do |path|
53
- options[:font] = path
57
+ opts.on('--background PATH') do |path|
58
+ options[:background] = path
54
59
  end
55
60
 
56
61
  opts.on('--page-size OPTION') do |option|
@@ -89,8 +94,10 @@ begin
89
94
  raise '--document not provided' unless options[:document]
90
95
 
91
96
  begin
92
- json = JSON.parse options[:document]
97
+ json = JSON.parse(options[:document])
93
98
  document = InvoicePrinter::Document.from_json(json)
99
+ labels = options[:labels] ? JSON.parse(options[:labels]) : {}
100
+
94
101
  rescue => e
95
102
  STDERR.puts "ERROR: parsing JSON failed. Invalid JSON?"
96
103
 
@@ -105,11 +112,13 @@ begin
105
112
 
106
113
  if options[:render]
107
114
  stream = InvoicePrinter.render(
108
- document: document,
109
- font: options[:font],
110
- stamp: options[:stamp],
111
- logo: options[:logo],
112
- page_size: options[:page_size]
115
+ document: document,
116
+ labels: labels,
117
+ font: options[:font],
118
+ stamp: options[:stamp],
119
+ logo: options[:logo],
120
+ background: options[:background],
121
+ page_size: options[:page_size]
113
122
  )
114
123
 
115
124
  puts stream
@@ -117,12 +126,14 @@ begin
117
126
  raise '--filename not provided. Use --render if you with to render to STDOUT.' unless options[:filename]
118
127
 
119
128
  InvoicePrinter.print(
120
- document: document,
121
- font: options[:font],
122
- stamp: options[:stamp],
123
- logo: options[:logo],
124
- file_name: options[:filename],
125
- page_size: options[:page_size]
129
+ document: document,
130
+ labels: labels,
131
+ font: options[:font],
132
+ stamp: options[:stamp],
133
+ logo: options[:logo],
134
+ file_name: options[:filename],
135
+ background: options[:background],
136
+ page_size: options[:page_size]
126
137
  )
127
138
  end
128
139
  rescue => e
@@ -10,12 +10,14 @@ Usage: invoice_printer [options]
10
10
 
11
11
  Options:
12
12
 
13
- -l, --labels labels as JSON
14
13
  -d, --document document as JSON
14
+ -l, --labels labels as JSON
15
+ --font path to font
15
16
  -s, --stamp path to stamp
16
17
  --logo path to logotype
17
- --font path to font
18
- --page_size letter or a4 (letter is the default)
18
+ --background path to background image
19
+ --page-size letter or a4 (letter is the default)
19
20
  -f, --filename output path
20
21
  -r, --render directly render PDF stream (filename option will be ignored)
22
+
21
23
  ```
@@ -73,6 +73,10 @@ invoice = InvoicePrinter::Document.new(
73
73
  )
74
74
  ```
75
75
 
76
+ **Note**: There is `variable` field that can be used for any
77
+ extra column. `tax2` and `tax3` for more complex taxes are
78
+ available as well.
79
+
76
80
  ### Ruby on Rails
77
81
 
78
82
  If you want to use InvoicePrinter for printing PDF documents directly from Rails
@@ -170,6 +174,7 @@ InvoicePrinter.labels = {
170
174
  issue_date: 'Issue date',
171
175
  due_date: 'Due date',
172
176
  item: 'Item',
177
+ variable: '',
173
178
  quantity: 'Quantity',
174
179
  unit: 'Unit',
175
180
  price_per_item: 'Price per item',
@@ -181,6 +186,7 @@ InvoicePrinter.labels = {
181
186
  total: 'Total'
182
187
  }
183
188
  ```
189
+ **Note:** `variable` fields lack default label. You should provide one.
184
190
 
185
191
  You can also use sublabels feature to provide the document in two languages:
186
192
 
@@ -201,6 +207,7 @@ sublabels = {
201
207
  issue_date: 'Datum vydání',
202
208
  due_date: 'Datum splatnosti',
203
209
  item: 'Položka',
210
+ variable: '',
204
211
  quantity: 'Počet',
205
212
  unit: 'MJ',
206
213
  price_per_item: 'Cena za položku',
@@ -215,7 +222,7 @@ labels.merge!({ sublabels: sublabels })
215
222
  ...
216
223
  ```
217
224
 
218
- Now the document will have a little sublabels next to the original labels in Czech.
225
+ Now the document will have little sublabels next to the original labels in Czech.
219
226
 
220
227
  ### Font
221
228
 
@@ -46,9 +46,11 @@ Options:
46
46
 
47
47
  - `document` - JSON representation of the document
48
48
  - `labels` - JSON for labels
49
+ - `font` - path to font file
49
50
  - `stamp` - path to stamp file
50
51
  - `logo` - path to logotype file
51
- - `font` - path to font file
52
+ - `background` - path to background file
53
+ - `page_size` - letter or A4 page size
52
54
 
53
55
  On success a `200` response is returned:
54
56
 
@@ -84,9 +86,11 @@ Options:
84
86
 
85
87
  - `document` - JSON representation of the document
86
88
  - `labels` - JSON for labels
89
+ - `font` - path to font file
87
90
  - `stamp` - path to stamp file
88
91
  - `logo` - path to logotype file
89
- - `font` - path to font file
92
+ - `background` - path to background file
93
+ - `page_size` - letter or A4 page size
90
94
  - `filename` - path for saving the generated output PDF
91
95
 
92
96
  On success a `200` response is returned:
@@ -6,11 +6,16 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
6
  require 'invoice_printer'
7
7
 
8
8
  labels = {
9
- tax: '10% VAT'
9
+ variable: 'Date',
10
+ tax: '10% VAT',
11
+ sublabels: {
12
+ variable: 'of work done'
13
+ }
10
14
  }
11
15
 
12
16
  item = InvoicePrinter::Document::Item.new(
13
17
  name: 'Programming',
18
+ variable: 'June 2018',
14
19
  quantity: '10',
15
20
  unit: 'hr',
16
21
  price: '$ 60',
@@ -20,6 +25,7 @@ item = InvoicePrinter::Document::Item.new(
20
25
 
21
26
  item2 = InvoicePrinter::Document::Item.new(
22
27
  name: 'Consulting',
28
+ variable: 'July 2018',
23
29
  quantity: '10',
24
30
  unit: 'hr',
25
31
  price: '$ 30',
@@ -29,6 +35,7 @@ item2 = InvoicePrinter::Document::Item.new(
29
35
 
30
36
  item3 = InvoicePrinter::Document::Item.new(
31
37
  name: 'Support',
38
+ variable: 'September 2018',
32
39
  quantity: '20',
33
40
  unit: 'hr',
34
41
  price: '$ 15',
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+ # This is an example of a Czech invoice.
3
+ #
4
+ # Due to the special characters it requires Overpass-Regular.ttf font to be
5
+ # present in this directory.
6
+
7
+ lib = File.expand_path('../../lib', __FILE__)
8
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
9
+ require 'invoice_printer'
10
+
11
+ labels = {
12
+ name: 'Faktura',
13
+ provider: 'Prodejce',
14
+ purchaser: 'Kupující',
15
+ tax_id: 'IČ',
16
+ tax_id2: 'DIČ',
17
+ payment: 'Forma úhrady',
18
+ payment_by_transfer: 'Platba na následující účet:',
19
+ account_number: 'Číslo účtu',
20
+ issue_date: 'Datum vydání',
21
+ due_date: 'Datum splatnosti',
22
+ item: 'Položka',
23
+ quantity: 'Počet',
24
+ unit: 'MJ',
25
+ price_per_item: 'Cena za položku',
26
+ amount: 'Celkem bez daně',
27
+ subtotal: 'Cena bez daně',
28
+ tax: 'DPH 21 %',
29
+ total: 'Celkem'
30
+ }
31
+
32
+ first_item = InvoicePrinter::Document::Item.new(
33
+ name: 'Konzultace',
34
+ quantity: '2',
35
+ unit: 'hod',
36
+ price: 'Kč 500',
37
+ amount: 'Kč 1.000'
38
+ )
39
+
40
+ second_item = InvoicePrinter::Document::Item.new(
41
+ name: 'Programování',
42
+ quantity: '10',
43
+ unit: 'hod',
44
+ price: 'Kč 900',
45
+ amount: 'Kč 9.000'
46
+ )
47
+
48
+ invoice = InvoicePrinter::Document.new(
49
+ number: 'č. 198900000001',
50
+ provider_name: 'Petr Nový',
51
+ provider_tax_id: '56565656',
52
+ provider_tax_id2: 'CZ56565656',
53
+ provider_street: 'Rolnická',
54
+ provider_street_number: '1',
55
+ provider_postcode: '747 05',
56
+ provider_city: 'Opava',
57
+ provider_city_part: 'Kateřinky',
58
+ purchaser_name: 'Adam Černý',
59
+ purchaser_street: 'Ostravská',
60
+ purchaser_street_number: '1',
61
+ purchaser_postcode: '747 70',
62
+ purchaser_city: 'Opava',
63
+ purchaser_tax_id: '56565656',
64
+ purchaser_tax_id2: 'CZ56565656',
65
+ issue_date: '05/03/2016',
66
+ due_date: '19/03/2016',
67
+ subtotal: 'Kč 10.000',
68
+ tax: 'Kč 2.100',
69
+ total: 'Kč 12.100,-',
70
+ bank_account_number: '156546546465',
71
+ account_iban: 'IBAN464545645',
72
+ account_swift: 'SWIFT5456',
73
+ items: [first_item, second_item] * 20,
74
+ note: 'Osoba je zapsána v živnostenském rejstříku.'
75
+ )
76
+
77
+ InvoicePrinter.print(
78
+ document: invoice,
79
+ labels: labels,
80
+ font: File.expand_path('../Overpass-Regular.ttf', __FILE__),
81
+ logo: 'prawn.png',
82
+ file_name: 'czech_invoice_long.pdf'
83
+ )
84
+
85
+ InvoicePrinter.print(
86
+ document: invoice,
87
+ labels: labels,
88
+ font: File.expand_path('../Overpass-Regular.ttf', __FILE__),
89
+ logo: 'prawn.png',
90
+ file_name: 'czech_invoice_long_a4.pdf',
91
+ page_size: :a4
92
+ )
@@ -62,12 +62,14 @@ module InvoicePrinter
62
62
  # Print the given InvoicePrinter::Document to PDF file named +file_name+
63
63
  #
64
64
  # document - InvoicePrinter::Document object
65
- # file_name - output file
66
65
  # labels - labels to override
67
66
  # font - font file to use
68
67
  # stamp - stamp & signature (image)
69
68
  # logo - logotype (image)
70
- def self.print(document:, file_name:, labels: {}, font: nil, stamp: nil, logo: nil, background: nil, page_size: :letter)
69
+ # background - background (image)
70
+ # page_size - :letter or :a4
71
+ # file_name - output file
72
+ def self.print(document:, labels: {}, font: nil, stamp: nil, logo: nil, background: nil, page_size: :letter, file_name:)
71
73
  PDFDocument.new(
72
74
  document: document,
73
75
  labels: labels,
@@ -86,6 +88,8 @@ module InvoicePrinter
86
88
  # font - font file to use
87
89
  # stamp - stamp & signature (image)
88
90
  # logo - logotype (image)
91
+ # background - background (image)
92
+ # page_size - :letter or :a4
89
93
  def self.render(document:, labels: {}, font: nil, stamp: nil, logo: nil, background: nil, page_size: :letter)
90
94
  PDFDocument.new(
91
95
  document: document,
@@ -6,6 +6,7 @@ module InvoicePrinter
6
6
  #
7
7
  # item = InvoicePrinter::Document::Item.new(
8
8
  # name: 'UX consultation',
9
+ # variable: 'June 2008',
9
10
  # quantity: '4',
10
11
  # unit: 'hours',
11
12
  # price: '$ 25',
@@ -17,6 +18,7 @@ module InvoicePrinter
17
18
  # but this is not enforced.
18
19
  class Item
19
20
  attr_reader :name,
21
+ :variable, # for anything required
20
22
  :quantity,
21
23
  :unit,
22
24
  :price,
@@ -29,6 +31,7 @@ module InvoicePrinter
29
31
  def from_json(json)
30
32
  new(
31
33
  name: json['name'],
34
+ variable: json['variable'],
32
35
  quantity: json['quantity'],
33
36
  unit: json['unit'],
34
37
  price: json['price'],
@@ -41,6 +44,7 @@ module InvoicePrinter
41
44
  end
42
45
 
43
46
  def initialize(name: nil,
47
+ variable: nil,
44
48
  quantity: nil,
45
49
  unit: nil,
46
50
  price: nil,
@@ -50,6 +54,7 @@ module InvoicePrinter
50
54
  amount: nil)
51
55
 
52
56
  @name = String(name)
57
+ @variable = String(variable)
53
58
  @quantity = String(quantity)
54
59
  @unit = String(unit)
55
60
  @price = String(price)
@@ -62,6 +67,7 @@ module InvoicePrinter
62
67
  def to_h
63
68
  {
64
69
  'name': @name,
70
+ 'variable': @variable,
65
71
  'quantity': @quantity,
66
72
  'unit': @unit,
67
73
  'price': @price,
@@ -37,6 +37,7 @@ module InvoicePrinter
37
37
  issue_date: 'Issue date',
38
38
  due_date: 'Due date',
39
39
  item: 'Item',
40
+ variable: '',
40
41
  quantity: 'Quantity',
41
42
  unit: 'Unit',
42
43
  price_per_item: 'Price per item',
@@ -46,7 +47,7 @@ module InvoicePrinter
46
47
  amount: 'Amount',
47
48
  subtotal: 'Subtotal',
48
49
  total: 'Total',
49
- sublabels: {},
50
+ sublabels: {}
50
51
  }
51
52
 
52
53
  PageSize = Struct.new(:name, :width, :height)
@@ -66,12 +67,12 @@ module InvoicePrinter
66
67
 
67
68
  def initialize(document: Document.new, labels: {}, font: nil, stamp: nil, logo: nil, background: nil, page_size: :letter)
68
69
  @document = document
69
- @labels = PDFDocument.labels.merge(labels)
70
- @page_size = PAGE_SIZES[page_size.to_sym]
71
- @pdf = Prawn::Document.new(background: background, page_size: @page_size.name)
70
+ @labels = merge_custom_labels(labels)
72
71
  @font = font
73
72
  @stamp = stamp
74
73
  @logo = logo
74
+ @page_size = page_size ? PAGE_SIZES[page_size.to_sym] : PAGE_SIZES[:letter]
75
+ @pdf = Prawn::Document.new(background: background, page_size: @page_size.name)
75
76
 
76
77
  raise InvalidInput, 'document is not a type of InvoicePrinter::Document' \
77
78
  unless @document.is_a?(InvoicePrinter::Document)
@@ -602,8 +603,9 @@ module InvoicePrinter
602
603
  # |x | 2| hr| $2| $1| $4|
603
604
  # =================================================================
604
605
  #
606
+ # variable (2nd position), tax2 and tax3 (after tax) fields can be added
607
+ # as well if necessary. variable does not come with any default label.
605
608
  # If a specific column miss data, it's omittted.
606
- # tax2 and tax3 fields can be added as well if necessary.
607
609
  #
608
610
  # Using sublabels one can change the table to look as:
609
611
  #
@@ -632,7 +634,8 @@ module InvoicePrinter
632
634
  4 => :right,
633
635
  5 => :right,
634
636
  6 => :right,
635
- 7 => :right
637
+ 7 => :right,
638
+ 8 => :right
636
639
  },
637
640
  font_size: 10
638
641
  }
@@ -645,6 +648,7 @@ module InvoicePrinter
645
648
  items_params = {}
646
649
  @document.items.each do |item|
647
650
  items_params[:names] = true unless item.name.empty?
651
+ items_params[:variables] = true unless item.variable.empty?
648
652
  items_params[:quantities] = true unless item.quantity.empty?
649
653
  items_params[:units] = true unless item.unit.empty?
650
654
  items_params[:prices] = true unless item.price.empty?
@@ -661,6 +665,7 @@ module InvoicePrinter
661
665
  @document.items.map do |item|
662
666
  line = []
663
667
  line << item.name if items_params[:names]
668
+ line << item.variable if items_params[:variables]
664
669
  line << item.quantity if items_params[:quantities]
665
670
  line << item.unit if items_params[:units]
666
671
  line << item.price if items_params[:prices]
@@ -676,6 +681,7 @@ module InvoicePrinter
676
681
  def build_items_header(items_params)
677
682
  headers = []
678
683
  headers << { text: label_with_sublabel(:item) } if items_params[:names]
684
+ headers << { text: label_with_sublabel(:variable) } if items_params[:variables]
679
685
  headers << { text: label_with_sublabel(:quantity) } if items_params[:quantities]
680
686
  headers << { text: label_with_sublabel(:unit) } if items_params[:units]
681
687
  headers << { text: label_with_sublabel(:price_per_item) } if items_params[:prices]
@@ -831,5 +837,24 @@ module InvoicePrinter
831
837
  width_ratio = value / PAGE_SIZES[:letter].height
832
838
  width_ratio * @page_size.height
833
839
  end
840
+
841
+ def merge_custom_labels(labels = {})
842
+ custom_labels = if labels
843
+ hash_keys_to_symbols(labels)
844
+ else
845
+ {}
846
+ end
847
+
848
+ PDFDocument.labels.merge(custom_labels)
849
+ end
850
+
851
+ def hash_keys_to_symbols(value)
852
+ return value unless value.is_a? Hash
853
+
854
+ value.inject({}) do |memo, (k, v)|
855
+ memo[k.to_sym] = hash_keys_to_symbols(v)
856
+ memo
857
+ end
858
+ end
834
859
  end
835
860
  end
@@ -16,11 +16,13 @@ class InvoicePrinter::Server < Roda
16
16
  r.halt
17
17
  end
18
18
 
19
- labels = params[:labels]
20
- document = params[:document]
21
- stamp = params[:stamp]
22
- logo = params[:logo]
23
- font = params[:font]
19
+ document = params[:document]
20
+ labels = params[:labels]
21
+ font = params[:font]
22
+ stamp = params[:stamp]
23
+ logo = params[:logo]
24
+ background = params[:background]
25
+ page_size = params[:page_size]
24
26
  else
25
27
  response.status = 400
26
28
  response.write({ result: 'error', error: 'No JSON. Did you set Content-Type to application/json?' }.to_json)
@@ -46,11 +48,14 @@ class InvoicePrinter::Server < Roda
46
48
 
47
49
  begin
48
50
  InvoicePrinter.print(
49
- document: document,
50
- font: font,
51
- stamp: stamp,
52
- logo: logo,
53
- file_name: filename
51
+ document: document,
52
+ labels: labels,
53
+ font: font,
54
+ stamp: stamp,
55
+ logo: logo,
56
+ background: background,
57
+ page_size: page_size,
58
+ file_name: filename
54
59
  )
55
60
 
56
61
  { result: 'ok', path: filename }.to_json
@@ -65,10 +70,13 @@ class InvoicePrinter::Server < Roda
65
70
  r.post 'render' do
66
71
  begin
67
72
  stream = InvoicePrinter.render(
68
- document: document,
69
- font: font,
70
- stamp: stamp,
71
- logo: logo
73
+ document: document,
74
+ labels: labels,
75
+ font: font,
76
+ stamp: stamp,
77
+ logo: logo,
78
+ background: background,
79
+ page_size: page_size
72
80
  )
73
81
 
74
82
  { result: 'ok', data: Base64.encode64(stream) }.to_json
@@ -79,4 +87,4 @@ class InvoicePrinter::Server < Roda
79
87
  end
80
88
  end
81
89
  end
82
- end
90
+ end
@@ -1,3 +1,3 @@
1
1
  module InvoicePrinter
2
- VERSION = '1.2.0'
2
+ VERSION = '1.3.0'
3
3
  end
@@ -15,7 +15,7 @@ class ApiTest < Minitest::Test
15
15
  end
16
16
 
17
17
  def teardown
18
- FileUtils.rm_rf @test_dir if File.exists?(@test_dir)
18
+ FileUtils.rm_rf @test_dir if File.exist?(@test_dir)
19
19
  end
20
20
 
21
21
  # Test POST /print
@@ -15,7 +15,12 @@ class CLITest < Minitest::Test
15
15
  end
16
16
 
17
17
  def test_print_to_file
18
- command = "bin/invoice_printer --filename #{@output_path} --document '#{@invoice_as_json}'"
18
+ command = "bin/invoice_printer " +
19
+ "--document '#{@invoice_as_json}' " +
20
+ "--labels '#{labels_hash.to_json}' " +
21
+ "--logo '#{logo_path}' " +
22
+ "--background '#{background_path}' " +
23
+ "--filename #{@output_path}"
19
24
 
20
25
  exit_status, command_stdout, command_stderr = nil
21
26
 
@@ -33,9 +38,12 @@ class CLITest < Minitest::Test
33
38
  expected_pdf_path = "#{@output_path}.expected_letter"
34
39
 
35
40
  InvoicePrinter.print(
36
- document: @invoice,
37
- file_name: expected_pdf_path,
38
- page_size: :letter
41
+ document: @invoice,
42
+ labels: labels_hash,
43
+ logo: logo_path,
44
+ background: background_path,
45
+ page_size: :letter,
46
+ file_name: expected_pdf_path
39
47
  )
40
48
 
41
49
  similarity = (File.read(expected_pdf_path) == File.read(@output_path))
@@ -45,7 +53,13 @@ class CLITest < Minitest::Test
45
53
  end
46
54
 
47
55
  def test_print_to_file_a4
48
- command = "bin/invoice_printer --filename #{@output_path} --page-size a4 --document '#{@invoice_as_json}'"
56
+ command = "bin/invoice_printer " +
57
+ "--document '#{@invoice_as_json}' " +
58
+ "--labels '#{labels_hash.to_json}' " +
59
+ "--logo '#{logo_path}' " +
60
+ "--background '#{background_path}' " +
61
+ "--page-size a4 " +
62
+ "--filename #{@output_path}"
49
63
 
50
64
  exit_status, command_stdout, command_stderr = nil
51
65
 
@@ -63,9 +77,12 @@ class CLITest < Minitest::Test
63
77
  expected_pdf_path = "#{@output_path}.expected_a4"
64
78
 
65
79
  InvoicePrinter.print(
66
- document: @invoice,
67
- file_name: expected_pdf_path,
68
- page_size: :a4
80
+ document: @invoice,
81
+ labels: labels_hash,
82
+ logo: logo_path,
83
+ background: background_path,
84
+ page_size: :a4,
85
+ file_name: expected_pdf_path
69
86
  )
70
87
 
71
88
  similarity = (File.read(expected_pdf_path) == File.read(@output_path))
@@ -73,4 +90,21 @@ class CLITest < Minitest::Test
73
90
 
74
91
  File.unlink expected_pdf_path
75
92
  end
93
+
94
+ private
95
+
96
+ def labels_hash
97
+ sublabels = { sublabels: { name: 'Sublabel name' } }
98
+
99
+ { provider: 'Default Provider',
100
+ purchaser: 'Default Purchaser' }.merge!(sublabels)
101
+ end
102
+
103
+ def logo_path
104
+ File.expand_path('../../examples/logo.png', __FILE__)
105
+ end
106
+
107
+ def background_path
108
+ File.expand_path('../../examples/background.png', __FILE__)
109
+ end
76
110
  end
@@ -55,5 +55,4 @@ class InputsTest < Minitest::Test
55
55
  InvoicePrinter.render(document: invoice, stamp: 'missing.png')
56
56
  end
57
57
  end
58
-
59
58
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: invoice_printer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josef Strzibny
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-13 00:00:00.000000000 Z
11
+ date: 2019-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -119,10 +119,12 @@ extra_rdoc_files: []
119
119
  files:
120
120
  - ".gitignore"
121
121
  - Gemfile
122
+ - Gemfile.lock
122
123
  - LICENSE.txt
123
124
  - README.md
124
125
  - Rakefile
125
126
  - assets/logo.png
127
+ - benchmarks/render.yml
126
128
  - bin/invoice_printer
127
129
  - bin/invoice_printer_server
128
130
  - docs/COMMAND_LINE.md
@@ -133,6 +135,7 @@ files:
133
135
  - examples/clients/node.js
134
136
  - examples/complex_invoice.rb
135
137
  - examples/czech_invoice.rb
138
+ - examples/czech_invoice_long.rb
136
139
  - examples/international_invoice.rb
137
140
  - examples/logo.png
138
141
  - examples/long_invoice.rb