invoice_printer 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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