invoice_printer 2.2.0.alpha1 → 2.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
  SHA256:
3
- metadata.gz: 73bc8cc15f44b26e3208614d83ee31dbb385b804e7a248723b07d6c9b60e7238
4
- data.tar.gz: 5d2ab37a9051dba8ddd0018a4d7bc3d2f6a14949f131679f77ac7a0cd9069981
3
+ metadata.gz: 2f98cb9145f19c42e95490c56afbb156408c5049c766d9ddcb1c776ee112c5fe
4
+ data.tar.gz: 77c6280ab4566b41ad6b040113f3ccf99b0c4bf5e2bccce28c3d0740644a1e57
5
5
  SHA512:
6
- metadata.gz: 3fb1d1f236410e510f79c30b9c817d63285ae9dd49a579ec4930e6596f1ab3c06d8d480c7e4c3f11f14873c14aa9d6b62bbd6e91687cafc052e6387244a791f3
7
- data.tar.gz: 2819f38b58b55ec97517c5521cee21a70ab33ad64303d6c71f92ae41186f5c7136f66a88ef8aad9eaea0144c632cc96d71244cff04264a642f8f0cd13437b52a
6
+ metadata.gz: c1be305d2988483f0912598cbcd523b3f8f020667f61cb253e7b5c3f455ed188efebcec20fe4d1f77148ce984c9866c723c3e645a9e4515b50a67aceb85d45a5
7
+ data.tar.gz: f4764ce73b9c8f696cdd8bfa975ab1f3cbd8d85bb62a3b335a321eb7fb860b08a03835cc875c3dd774b670af3baeffc48f590e53d0c763ccece20e9e22b74657
data/Dockerfile CHANGED
@@ -26,10 +26,10 @@ RUN apk update && apk upgrade
26
26
  RUN apk add build-base bash ruby ruby-etc ruby-dev
27
27
 
28
28
  # Install builtin fonts
29
- RUN gem install invoice_printer_fonts --version 2.1.0 --no-document
29
+ RUN gem install invoice_printer_fonts --version 2.3.0 --no-document
30
30
 
31
31
  # Install the gem from RubyGems.org
32
- RUN gem install invoice_printer_server --version 2.1.0 --no-document
32
+ RUN gem install invoice_printer_server --version 2.3.0 --no-document
33
33
 
34
34
  # Clean APK cache
35
35
  RUN rm -rf /var/cache/apk/*
data/Gemfile.lock CHANGED
@@ -1,12 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- invoice_printer (2.1.0.rc1)
4
+ invoice_printer (2.2.0)
5
+ e2mmap
5
6
  json (~> 2.1)
6
- prawn (~> 2.2)
7
+ matrix
8
+ prawn (~> 2.4)
7
9
  prawn-table (~> 0.2.2)
8
- invoice_printer_server (2.1.0.rc1)
9
- invoice_printer (= 2.1.0.rc1)
10
+ invoice_printer_server (2.2.0)
11
+ invoice_printer (= 2.2.0)
10
12
  json (~> 2.1)
11
13
  puma (>= 3.9.0)
12
14
  roda (~> 3.5)
@@ -14,48 +16,52 @@ PATH
14
16
  GEM
15
17
  remote: https://rubygems.org/
16
18
  specs:
17
- Ascii85 (1.0.3)
19
+ Ascii85 (1.1.0)
18
20
  afm (0.2.2)
19
21
  benchmark_driver (0.15.17)
20
22
  benchmark_driver-output-gruff (0.3.1)
21
23
  benchmark_driver (>= 0.12.0)
22
24
  gruff
23
- gruff (0.11.0)
25
+ e2mmap (0.1.0)
26
+ gruff (0.14.0)
24
27
  histogram
25
28
  rmagick
26
29
  hashery (2.1.2)
27
30
  histogram (0.2.4.1)
28
- json (2.3.1)
29
- minitest (5.14.2)
30
- nio4r (2.5.4)
31
+ json (2.6.3)
32
+ matrix (0.1.0)
33
+ minitest (5.15.0)
34
+ nio4r (2.5.8)
31
35
  pdf-core (0.9.0)
32
36
  pdf-inspector (1.3.0)
33
37
  pdf-reader (>= 1.0, < 3.0.a)
34
- pdf-reader (2.4.1)
35
- Ascii85 (~> 1.0.0)
38
+ pdf-reader (2.11.0)
39
+ Ascii85 (~> 1.0)
36
40
  afm (~> 0.2.1)
37
41
  hashery (~> 2.0)
38
42
  ruby-rc4
39
43
  ttfunk
44
+ pkg-config (1.5.1)
40
45
  prawn (2.4.0)
41
46
  pdf-core (~> 0.9.0)
42
47
  ttfunk (~> 1.7)
43
48
  prawn-table (0.2.2)
44
49
  prawn (>= 1.3.0, < 3.0.0)
45
- puma (5.0.2)
50
+ puma (6.0.2)
46
51
  nio4r (~> 2.0)
47
- rack (2.2.3)
48
- rack-test (1.1.0)
49
- rack (>= 1.0, < 3)
50
- rake (13.0.1)
51
- rmagick (4.1.2)
52
- roda (3.36.0)
52
+ rack (3.0.4.1)
53
+ rack-test (2.0.2)
54
+ rack (>= 1.3)
55
+ rake (13.0.6)
56
+ rmagick (5.1.0)
57
+ pkg-config (~> 1.4)
58
+ roda (3.64.0)
53
59
  rack
54
60
  ruby-rc4 (0.1.5)
55
61
  ttfunk (1.7.0)
56
62
 
57
63
  PLATFORMS
58
- ruby
64
+ x86_64-linux
59
65
 
60
66
  DEPENDENCIES
61
67
  benchmark_driver (= 0.15.17)
@@ -68,4 +74,4 @@ DEPENDENCIES
68
74
  rake (>= 10.0)
69
75
 
70
76
  BUNDLED WITH
71
- 2.1.4
77
+ 2.4.3
data/README.md CHANGED
@@ -25,7 +25,7 @@ See more usecases in the `examples/` directory.
25
25
  - Purchaser and provider boxes with addresses and identificaton numbers
26
26
  - Payment method box showing banking details including SWIFT and IBAN fields
27
27
  - Issue/due dates box
28
- - Configurable items' table with item description, quantity, unit, price per unit, tax and item's total amount fields
28
+ - Configurable items' table with item description, breakdown, quantity, unit, price per unit, tax and item's total amount fields
29
29
  - Final subtotal/tax/total info box
30
30
  - Page numbers
31
31
  - Configurable field labels & sublabels (optional little labels)
Binary file
data/bin/invoice_printer CHANGED
@@ -19,6 +19,7 @@ def show_help
19
19
  -d, --document document as JSON
20
20
  -l, --labels labels as JSON
21
21
  --font path to font or builtin font name
22
+ --bold-font path to bold font or builtin font name
22
23
  -s, --stamp path to stamp
23
24
  --logo path to logotype
24
25
  --background path to background image
@@ -47,6 +48,10 @@ parser = OptionParser.new do|opts|
47
48
  options[:font] = path
48
49
  end
49
50
 
51
+ opts.on('--bold-font PATH') do |path|
52
+ options[:bold_font] = path
53
+ end
54
+
50
55
  opts.on('-s', '--stamp PATH') do |path|
51
56
  options[:stamp] = path
52
57
  end
@@ -116,6 +121,7 @@ begin
116
121
  document: document,
117
122
  labels: labels,
118
123
  font: options[:font],
124
+ bold_font: options[:bold_font],
119
125
  stamp: options[:stamp],
120
126
  logo: options[:logo],
121
127
  background: options[:background],
@@ -130,6 +136,7 @@ begin
130
136
  document: document,
131
137
  labels: labels,
132
138
  font: options[:font],
139
+ bold_font: options[:bold_font],
133
140
  stamp: options[:stamp],
134
141
  logo: options[:logo],
135
142
  file_name: options[:filename],
data/docs/COMMAND_LINE.md CHANGED
@@ -13,6 +13,7 @@ Options:
13
13
  -d, --document document as JSON
14
14
  -l, --labels labels as JSON
15
15
  --font path to font or builtin font name
16
+ --bold-font path to bold font or builtin font name
16
17
  -s, --stamp path to stamp
17
18
  --logo path to logotype
18
19
  --background path to background image
@@ -48,6 +49,7 @@ JSON document with all possible fields filled:
48
49
  "bank_account_number":"156546546465",
49
50
  "account_iban":"IBAN464545645",
50
51
  "account_swift":"SWIFT5456",
52
+ "description": "We are invoicing the following items:",
51
53
  "items":[
52
54
  {
53
55
  "name":"Konzultace",
@@ -139,7 +141,7 @@ All labels:
139
141
 
140
142
  ## Built-in fonts
141
143
 
142
- Supported builtin fonts are: `overpass`, `opensans`, and `roboto`.
144
+ Supported builtin fonts are: `overpass`, `opensans`, and `roboto`. They ship with bold versions.
143
145
 
144
146
  ## Examples
145
147
 
data/docs/LIBRARY.md CHANGED
@@ -31,6 +31,7 @@ Here is an full example for creating the document object:
31
31
  ```ruby
32
32
  item = InvoicePrinter::Document::Item.new(
33
33
  name: 'Web consultation',
34
+ breakdown: 'Excludes 1h free consultation',
34
35
  quantity: nil,
35
36
  unit: 'hours',
36
37
  price: '$ 25',
@@ -64,6 +65,7 @@ invoice = InvoicePrinter::Document.new(
64
65
  bank_account_number: '156546546465',
65
66
  account_iban: 'IBAN464545645',
66
67
  account_swift: 'SWIFT5456',
68
+ description: 'We are invoicing the following items:',
67
69
  items: [item],
68
70
  note: 'A note...'
69
71
  )
data/docs/SERVER.md CHANGED
@@ -61,6 +61,7 @@ Options:
61
61
  - `document` - JSON representation of the document
62
62
  - `labels` - JSON for labels
63
63
  - `font` - path to font file or builtin font name
64
+ - `bold_font` - path to bold font file or builtin font name
64
65
  - `stamp` - path to stamp file
65
66
  - `logo` - path to logotype file
66
67
  - `background` - path to background file
@@ -103,6 +104,7 @@ Options:
103
104
  - `document` - JSON representation of the document
104
105
  - `labels` - JSON for labels
105
106
  - `font` - path to font file or builtin font name
107
+ - `bold_font` - path to bold font file or builtin font name
106
108
  - `stamp` - path to stamp file
107
109
  - `logo` - path to logotype file
108
110
  - `background` - path to background file
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+ # This is an example of a longer invoice.
3
+
4
+ lib = File.expand_path('../../lib', __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require 'invoice_printer'
7
+
8
+ labels = {
9
+ tax: '10% VAT'
10
+ }
11
+
12
+ item = InvoicePrinter::Document::Item.new(
13
+ name: 'Programming',
14
+ quantity: '10',
15
+ unit: 'h',
16
+ price: '$ 60',
17
+ tax: '$ 60',
18
+ amount: '$ 600'
19
+ )
20
+
21
+ item2 = InvoicePrinter::Document::Item.new(
22
+ name: 'Consulting',
23
+ breakdown: "Excludes 1 hour free consultation",
24
+ quantity: '10',
25
+ unit: 'h',
26
+ price: '$ 30',
27
+ tax: '$ 30',
28
+ amount: '$ 300'
29
+ )
30
+
31
+ breakdown = <<BREAKDOWN
32
+ Issue 404: 15h
33
+ Issue 505: 5h
34
+ BREAKDOWN
35
+
36
+ item3 = InvoicePrinter::Document::Item.new(
37
+ name: 'Support',
38
+ breakdown: breakdown,
39
+ quantity: '20',
40
+ unit: 'h',
41
+ price: '$ 15',
42
+ tax: '$ 30',
43
+ amount: '$ 330'
44
+ )
45
+
46
+ invoice = InvoicePrinter::Document.new(
47
+ number: 'NO. 198900000001',
48
+ provider_name: 'John White',
49
+ provider_lines: "79 Stonybrook St.\nBronx, NY 10457",
50
+ purchaser_name: 'Will Black',
51
+ purchaser_lines: "8648 Acacia Rd.\nBrooklyn, NY 11203",
52
+ issue_date: '05/03/2016',
53
+ due_date: '19/03/2016',
54
+ subtotal: '$ 1,000',
55
+ tax: '$ 100',
56
+ total: '$ 1,100',
57
+ bank_account_number: '156546546465',
58
+ items: [item, item2, item3],
59
+ note: 'This is a note at the end.'
60
+ )
61
+
62
+ InvoicePrinter.print(
63
+ document: invoice,
64
+ labels: labels,
65
+ stamp: File.expand_path('../stamp.png', __FILE__),
66
+ logo: File.expand_path('../prawn.png', __FILE__),
67
+ file_name: 'breakdown.pdf'
68
+ )
69
+
70
+ InvoicePrinter.print(
71
+ document: invoice,
72
+ labels: labels,
73
+ stamp: File.expand_path('../stamp.png', __FILE__),
74
+ logo: File.expand_path('../prawn.png', __FILE__),
75
+ file_name: 'breakdown_a4.pdf',
76
+ page_size: :a4
77
+ )
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # This is an example of a very simple invoice.
2
+ # This is an example of a longer invoice.
3
3
 
4
4
  lib = File.expand_path('../../lib', __FILE__)
5
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -12,7 +12,7 @@ labels = {
12
12
  item = InvoicePrinter::Document::Item.new(
13
13
  name: 'Programming',
14
14
  quantity: '10',
15
- unit: 'hr',
15
+ unit: 'h',
16
16
  price: '$ 60',
17
17
  tax: '$ 60',
18
18
  amount: '$ 600'
@@ -21,7 +21,7 @@ item = InvoicePrinter::Document::Item.new(
21
21
  item2 = InvoicePrinter::Document::Item.new(
22
22
  name: 'Consulting',
23
23
  quantity: '10',
24
- unit: 'hr',
24
+ unit: 'h',
25
25
  price: '$ 30',
26
26
  tax: '$ 30',
27
27
  amount: '$ 300'
@@ -30,7 +30,7 @@ item2 = InvoicePrinter::Document::Item.new(
30
30
  item3 = InvoicePrinter::Document::Item.new(
31
31
  name: 'Support',
32
32
  quantity: '20',
33
- unit: 'hr',
33
+ unit: 'h',
34
34
  price: '$ 15',
35
35
  tax: '$ 30',
36
36
  amount: '$ 330'
data/examples/promo.rb CHANGED
@@ -80,6 +80,7 @@ InvoicePrinter.print(
80
80
  document: invoice,
81
81
  labels: labels,
82
82
  font: File.expand_path('../../assets/fonts/overpass/Overpass-Regular.ttf', __FILE__),
83
+ bold_font: File.expand_path('../../assets/fonts/overpass/Overpass-Bold.ttf', __FILE__),
83
84
  logo: File.expand_path('../logo.png', __FILE__),
84
85
  file_name: 'promo.pdf'
85
86
  )
@@ -88,6 +89,7 @@ InvoicePrinter.print(
88
89
  document: invoice,
89
90
  labels: labels,
90
91
  font: File.expand_path('../../assets/fonts/overpass/Overpass-Regular.ttf', __FILE__),
92
+ bold_font: File.expand_path('../../assets/fonts/overpass/Overpass-Bold.ttf', __FILE__),
91
93
  logo: File.expand_path('../logo.png', __FILE__),
92
94
  file_name: 'promo_a4.pdf',
93
95
  page_size: :a4
@@ -27,11 +27,13 @@ invoice = InvoicePrinter::Document.new(
27
27
  number: 'NO. 198900000001',
28
28
  provider_name: 'John White',
29
29
  provider_lines: provider_address,
30
+ purchaser_name: 'Will Black',
30
31
  purchaser_lines: purchaser_address,
31
32
  issue_date: '05/03/2016',
32
33
  due_date: '19/03/2016',
33
34
  total: '$ 900',
34
35
  bank_account_number: '156546546465',
36
+ description: "You can use 20% discount for the next order with the code:\nDISCOUNT",
35
37
  items: [item],
36
38
  note: "This is a note at the end.\nA note with two lines."
37
39
  )
@@ -45,8 +45,10 @@ Gem::Specification.new do |spec|
45
45
  spec.required_ruby_version = '>= 2.4'
46
46
 
47
47
  spec.add_dependency 'json', '~> 2.1'
48
- spec.add_dependency 'prawn', '~> 2.2'
48
+ spec.add_dependency 'prawn', '~> 2.4'
49
49
  spec.add_dependency 'prawn-table', '~> 0.2.2'
50
+ spec.add_dependency 'matrix'
51
+ spec.add_dependency 'e2mmap'
50
52
 
51
53
  spec.add_development_dependency 'bundler', '>= 1.7'
52
54
  spec.add_development_dependency 'rake', '>= 10.0'
@@ -7,10 +7,13 @@ FONTS_FILES = [
7
7
  'FONTS_LICENSE.txt',
8
8
  'assets/fonts/overpass/OFL-1.1.txt',
9
9
  'assets/fonts/overpass/Overpass-Regular.ttf',
10
+ 'assets/fonts/overpass/Overpass-Bold.ttf',
10
11
  'assets/fonts/opensans/Apache-2.0.txt',
11
12
  'assets/fonts/opensans/OpenSans-Regular.ttf',
13
+ 'assets/fonts/opensans/OpenSans-Bold.ttf',
12
14
  'assets/fonts/roboto/Apache-2.0.txt',
13
15
  'assets/fonts/roboto/Roboto-Regular.ttf',
16
+ 'assets/fonts/roboto/Roboto-Bold.ttf',
14
17
  'lib/invoice_printer/fonts.rb'
15
18
  ]
16
19
 
@@ -6,6 +6,7 @@ module InvoicePrinter
6
6
  #
7
7
  # item = InvoicePrinter::Document::Item.new(
8
8
  # name: 'UX consultation',
9
+ # breakdown: "Monday 3h\nTuesday 1h"
9
10
  # variable: 'June 2008',
10
11
  # quantity: '4',
11
12
  # unit: 'hours',
@@ -18,6 +19,7 @@ module InvoicePrinter
18
19
  # but this is not enforced.
19
20
  class Item
20
21
  attr_reader :name,
22
+ :breakdown,
21
23
  :variable, # for anything required
22
24
  :quantity,
23
25
  :unit,
@@ -30,51 +32,55 @@ module InvoicePrinter
30
32
  class << self
31
33
  def from_json(json)
32
34
  new(
33
- name: json['name'],
35
+ name: json['name'],
36
+ breakdown: json['breakdown'],
34
37
  variable: json['variable'],
35
38
  quantity: json['quantity'],
36
- unit: json['unit'],
37
- price: json['price'],
38
- tax: json['tax'],
39
- tax2: json['tax2'],
40
- tax3: json['tax3'],
41
- amount: json['amount']
39
+ unit: json['unit'],
40
+ price: json['price'],
41
+ tax: json['tax'],
42
+ tax2: json['tax2'],
43
+ tax3: json['tax3'],
44
+ amount: json['amount']
42
45
  )
43
46
  end
44
47
  end
45
48
 
46
- def initialize(name: nil,
49
+ def initialize(name: nil,
50
+ breakdown: nil,
47
51
  variable: nil,
48
52
  quantity: nil,
49
- unit: nil,
50
- price: nil,
51
- tax: nil,
52
- tax2: nil,
53
- tax3: nil,
54
- amount: nil)
53
+ unit: nil,
54
+ price: nil,
55
+ tax: nil,
56
+ tax2: nil,
57
+ tax3: nil,
58
+ amount: nil)
55
59
 
56
- @name = String(name)
60
+ @name = String(name)
61
+ @breakdown = String(breakdown)
57
62
  @variable = String(variable)
58
63
  @quantity = String(quantity)
59
- @unit = String(unit)
60
- @price = String(price)
61
- @tax = String(tax)
62
- @tax2 = String(tax2)
63
- @tax3 = String(tax3)
64
- @amount = String(amount)
64
+ @unit = String(unit)
65
+ @price = String(price)
66
+ @tax = String(tax)
67
+ @tax2 = String(tax2)
68
+ @tax3 = String(tax3)
69
+ @amount = String(amount)
65
70
  end
66
71
 
67
72
  def to_h
68
73
  {
69
- 'name': @name,
74
+ 'name': @name,
75
+ 'breakdown': @breakdown,
70
76
  'variable': @variable,
71
77
  'quantity': @quantity,
72
- 'unit': @unit,
73
- 'price': @price,
74
- 'tax': @tax,
75
- 'tax2': @tax2,
76
- 'tax3': @tax3,
77
- 'amount': @amount,
78
+ 'unit': @unit,
79
+ 'price': @price,
80
+ 'tax': @tax,
81
+ 'tax2': @tax2,
82
+ 'tax3': @tax3,
83
+ 'amount': @amount,
78
84
  }
79
85
  end
80
86
 
@@ -22,6 +22,7 @@ module InvoicePrinter
22
22
  # bank_account_number: '156546546465',
23
23
  # account_iban: 'IBAN464545645',
24
24
  # account_swift: 'SWIFT5456',
25
+ # description: "We are invoicing you the following items:",
25
26
  # items: [
26
27
  # InvoicePrinter::Document::Item.new,
27
28
  # InvoicePrinter::Document::Item.new
@@ -57,6 +58,7 @@ module InvoicePrinter
57
58
  :bank_account_number,
58
59
  :account_iban,
59
60
  :account_swift,
61
+ :description,
60
62
  # Collection of InvoicePrinter::Invoice::Items
61
63
  :items,
62
64
  :note
@@ -84,6 +86,7 @@ module InvoicePrinter
84
86
  bank_account_number: json['bank_account_number'],
85
87
  account_iban: json['account_iban'],
86
88
  account_swift: json['account_swift'],
89
+ description: json['description'],
87
90
  note: json['note'],
88
91
 
89
92
  items: (json['items'] || []).map { |item_json| Item.from_json(item_json) }
@@ -111,6 +114,7 @@ module InvoicePrinter
111
114
  bank_account_number: nil,
112
115
  account_iban: nil,
113
116
  account_swift: nil,
117
+ description: nil,
114
118
  items: nil,
115
119
  note: nil)
116
120
 
@@ -134,6 +138,7 @@ module InvoicePrinter
134
138
  @bank_account_number = String(bank_account_number)
135
139
  @account_iban = String(account_iban)
136
140
  @account_swift = String(account_swift)
141
+ @description = String(description)
137
142
  @items = items
138
143
  @note = String(note)
139
144
 
@@ -163,6 +168,7 @@ module InvoicePrinter
163
168
  'bank_account_number': @bank_account_number,
164
169
  'account_iban': @account_iban,
165
170
  'account_swift': @account_swift,
171
+ 'description': @description,
166
172
  'items': @items.map(&:to_h),
167
173
  'note': @note
168
174
  }
@@ -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',
@@ -66,10 +67,20 @@ module InvoicePrinter
66
67
  @@labels = DEFAULT_LABELS.merge(labels)
67
68
  end
68
69
 
69
- 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
+ )
70
80
  @document = document
71
81
  @labels = merge_custom_labels(labels)
72
82
  @font = font
83
+ @bold_font = bold_font
73
84
  @stamp = stamp
74
85
  @logo = logo
75
86
  @page_size = page_size ? PAGE_SIZES[page_size.to_sym] : PAGE_SIZES[:letter]
@@ -94,8 +105,10 @@ module InvoicePrinter
94
105
  end
95
106
  end
96
107
 
97
- if used? @font
98
- use_font(@font)
108
+ if used?(@font) && used?(@bold_font)
109
+ use_font(@font, @bold_font)
110
+ elsif used?(@font)
111
+ use_font(@font, @font)
99
112
  end
100
113
 
101
114
  build_pdf
@@ -113,11 +126,11 @@ module InvoicePrinter
113
126
 
114
127
  private
115
128
 
116
- def use_font(font)
117
- if File.exist?(@font)
118
- 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)
119
132
  else
120
- set_builtin_font(@font)
133
+ set_builtin_font(font)
121
134
  end
122
135
  end
123
136
 
@@ -134,14 +147,14 @@ module InvoicePrinter
134
147
  end
135
148
 
136
149
  # Add font family in Prawn for a given +font+ file
137
- def set_font_from_path(font)
150
+ def set_font_from_path(font, bold_font)
138
151
  font_name = Pathname.new(font).basename
139
152
  @pdf.font_families.update(
140
153
  "#{font_name}" => {
141
154
  normal: font,
142
155
  italic: font,
143
- bold: font,
144
- bold_italic: font
156
+ bold: bold_font,
157
+ bold_italic: bold_font
145
158
  }
146
159
  )
147
160
  @pdf.font(font_name)
@@ -158,6 +171,7 @@ module InvoicePrinter
158
171
  build_purchaser_box
159
172
  build_payment_method_box
160
173
  build_info_box
174
+ build_description
161
175
  build_items
162
176
  build_total
163
177
  build_stamp
@@ -241,18 +255,14 @@ module InvoicePrinter
241
255
  end
242
256
  # Render provider_lines if present
243
257
  if !@document.provider_lines.empty?
244
- lines = @document.provider_lines.split("\n")
245
- line_y = 618
246
- lines.each_with_index do |line, index|
247
- next if index > 3
248
-
249
- @pdf.text_box(
250
- "#{line}",
251
- size: 10,
252
- at: [10, y(line_y - index*15) - @push_down],
253
- width: x(240)
254
- )
255
- end
258
+ @pdf.text_box(
259
+ @document.provider_lines,
260
+ size: 10,
261
+ at: [x(10), y(618) - @push_down],
262
+ width: x(246),
263
+ height: y(68),
264
+ leading: 3,
265
+ )
256
266
  end
257
267
  unless @document.provider_tax_id.empty?
258
268
  @pdf.text_box(
@@ -311,18 +321,14 @@ module InvoicePrinter
311
321
  end
312
322
  # Render purchaser_lines if present
313
323
  if !@document.purchaser_lines.empty?
314
- lines = @document.purchaser_lines.split("\n")
315
- line_y = 618
316
- lines.each_with_index do |line, index|
317
- next if index > 3
318
-
319
- @pdf.text_box(
320
- "#{line}",
321
- size: 10,
322
- at: [x(284), y(line_y - index*15) - @push_down],
323
- width: x(240)
324
- )
325
- end
324
+ @pdf.text_box(
325
+ @document.purchaser_lines,
326
+ size: 10,
327
+ at: [x(284), y(618) - @push_down],
328
+ width: x(246),
329
+ height: y(68),
330
+ leading: 3,
331
+ )
326
332
  end
327
333
  unless @document.purchaser_tax_id.empty?
328
334
  @pdf.text_box(
@@ -637,6 +643,25 @@ module InvoicePrinter
637
643
  used?(@labels[:sublabels][:variable_symbol])
638
644
  end
639
645
 
646
+ def build_description
647
+ unless @document.description.empty?
648
+ @pdf.text_box(
649
+ @document.description,
650
+ size: 11,
651
+ align: :left,
652
+ at: [0, y(450) - @push_down - 26]
653
+ )
654
+ @push_items_table += description_height + 8
655
+ end
656
+ end
657
+
658
+ def description_height
659
+ @description_height ||= begin
660
+ num_of_lines = @document.description.lines.count
661
+ (num_of_lines * 13)
662
+ end
663
+ end
664
+
640
665
  # Build the following table for document items:
641
666
  #
642
667
  # =================================================================
@@ -708,7 +733,8 @@ module InvoicePrinter
708
733
  def build_items_data(items_params)
709
734
  @document.items.map do |item|
710
735
  line = []
711
- line << { content: item.name, borders: [:bottom], align: :left } if items_params[:names]
736
+ line << { content: name_cell(item), borders: [:bottom] } if items_params[:names]
737
+ #line << { content: item.name, borders: [:bottom], align: :left } if items_params[:names]
712
738
  line << { content: item.variable, align: :right } if items_params[:variables]
713
739
  line << { content: item.quantity, align: :right } if items_params[:quantities]
714
740
  line << { content: item.unit, align: :right } if items_params[:units]
@@ -721,6 +747,27 @@ module InvoicePrinter
721
747
  end
722
748
  end
723
749
 
750
+ # Display item's name and breakdown if present
751
+ def name_cell(item)
752
+ data = if used?(item.breakdown)
753
+ data = [
754
+ [{ content: item.name, padding: [5, 0, 0, 5] }],
755
+ [{ content: item.breakdown, size: 8, padding: [2, 0, 5, 5] }]
756
+ ]
757
+
758
+ options = {
759
+ cell_style: {
760
+ borders: []
761
+ },
762
+ position: :left
763
+ }
764
+
765
+ @pdf.make_table(data, options)
766
+ else
767
+ item.name
768
+ end
769
+ end
770
+
724
771
  # Include only relevant headers
725
772
  def build_items_header(items_params)
726
773
  headers = []
@@ -759,52 +806,40 @@ module InvoicePrinter
759
806
  @pdf.move_down(25)
760
807
 
761
808
  items = []
762
- items << [{ content: "#{@labels[:subtotal]}:#{build_sublabel_for_total_table(:subtotal)}", align: :right }, @document.subtotal] \
763
- unless @document.subtotal.empty?
764
- items << [{ content: "#{@labels[:tax]}:#{build_sublabel_for_total_table(:tax)}", align: :right }, @document.tax] \
765
- unless @document.tax.empty?
766
- items << [{ content: "#{@labels[:tax2]}:#{build_sublabel_for_total_table(:tax2)}", align: :right }, @document.tax2] \
767
- unless @document.tax2.empty?
768
- items << [{ content: "#{@labels[:tax3]}:#{build_sublabel_for_total_table(:tax3)}", align: :right }, @document.tax3] \
769
- unless @document.tax3.empty?
770
-
771
- width = [
772
- "#{@labels[:subtotal]}#{@document.subtotal}".size,
773
- "#{@labels[:tax]}#{@document.tax}".size,
774
- "#{@labels[:tax2]}#{@document.tax2}".size,
775
- "#{@labels[:tax3]}#{@document.tax3}".size
776
- ].max * 8
777
809
 
778
- options = {
779
- cell_style: {
780
- borders: []
781
- }
782
- }
810
+ items << [
811
+ { content: "#{@labels[:subtotal]}:#{build_sublabel_for_total_table(:subtotal)}", align: :left },
812
+ { content: @document.subtotal, align: :right }
813
+ ] unless @document.subtotal.empty?
783
814
 
784
- @pdf.span(x(width), position: :right) do
785
- @pdf.table(items, options) unless items.empty?
786
- end
815
+ items << [
816
+ { content: "#{@labels[:tax]}:#{build_sublabel_for_total_table(:tax)}", align: :left },
817
+ { content: @document.tax, align: :right }
818
+ ] unless @document.tax.empty?
787
819
 
788
- @pdf.move_down(15)
820
+ items << [
821
+ { content: "#{@labels[:tax2]}:#{build_sublabel_for_total_table(:tax2)}", align: :left },
822
+ { content: @document.tax2, align: :right }
823
+ ] unless @document.tax2.empty?
789
824
 
790
- unless @document.total.empty?
791
- @pdf.text(
792
- "#{@labels[:total]}: #{@document.total}",
793
- size: 16,
794
- align: :right,
795
- style: :bold
796
- )
825
+ items << [
826
+ { content: "#{@labels[:tax3]}:#{build_sublabel_for_total_table(:tax3)}", align: :left },
827
+ { content: @document.tax3, align: :right }
828
+ ] unless @document.tax3.empty?
797
829
 
798
- @pdf.move_down(5)
830
+ items << [
831
+ { content: "\n#{@labels[:total]}:#{build_sublabel_for_total_table(:total)}", align: :left, font_style: :bold, size: 16 },
832
+ { content: "\n#{@document.total}", align: :right, font_style: :bold, size: 16 }
833
+ ] unless @document.total.empty?
799
834
 
800
- if used? @labels[:sublabels][:total]
801
- @pdf.text(
802
- "#{@labels[:sublabels][:total]}: #{@document.total}",
803
- size: 12,
804
- align: :right
805
- )
806
- end
807
- end
835
+ options = {
836
+ cell_style: {
837
+ borders: []
838
+ },
839
+ position: :right
840
+ }
841
+
842
+ @pdf.table(items, options) unless items.empty?
808
843
  end
809
844
 
810
845
  # Return sublabel on a new line or empty string
@@ -822,7 +857,7 @@ module InvoicePrinter
822
857
  def build_logo
823
858
  if @logo && !@logo.empty?
824
859
  bottom = @document.note.empty? ? 75 : (75 + note_height)
825
- @pdf.image(@logo, at: [0, bottom], fit: [200, 50])
860
+ @pdf.image(@logo, at: [0, bottom], fit: [x(200), y(50)])
826
861
  end
827
862
  end
828
863
 
@@ -830,7 +865,7 @@ module InvoicePrinter
830
865
  def build_stamp
831
866
  if @stamp && !@stamp.empty?
832
867
  @pdf.move_down(15)
833
- @pdf.image(@stamp, position: :right)
868
+ @pdf.image(@stamp, position: :right, fit: [x(200), y(40)])
834
869
  end
835
870
  end
836
871
 
@@ -1,3 +1,3 @@
1
1
  module InvoicePrinter
2
- VERSION = '2.2.0.alpha1'
2
+ VERSION = '2.3.0'
3
3
  end
@@ -15,6 +15,7 @@ Prawn::Font::AFM.hide_m17n_warning = true
15
15
  # InvoicePrinter.print(
16
16
  # document: invoice,
17
17
  # font: 'path-to-font-file.ttf',
18
+ # bold_font: 'path-to-font-file.ttf',
18
19
  # stamp: 'stamp.jpg',
19
20
  # logo: 'logo.jpg',
20
21
  # file_name: 'invoice.pdf'
@@ -65,16 +66,28 @@ module InvoicePrinter
65
66
  # document - InvoicePrinter::Document object
66
67
  # labels - labels to override
67
68
  # font - font file to use
69
+ # bold_font - bold font file to use
68
70
  # stamp - stamp & signature (image)
69
71
  # logo - logotype (image)
70
72
  # background - background (image)
71
73
  # page_size - :letter or :a4
72
74
  # file_name - output file
73
- def self.print(document:, labels: {}, font: nil, stamp: nil, logo: nil, background: nil, page_size: :letter, file_name:)
75
+ def self.print(
76
+ document:,
77
+ labels: {},
78
+ font: nil,
79
+ bold_font: nil,
80
+ stamp: nil,
81
+ logo: nil,
82
+ background: nil,
83
+ page_size: :letter,
84
+ file_name:
85
+ )
74
86
  PDFDocument.new(
75
87
  document: document,
76
88
  labels: labels,
77
89
  font: font,
90
+ bold_font: bold_font,
78
91
  stamp: stamp,
79
92
  logo: logo,
80
93
  background: background,
@@ -87,15 +100,26 @@ module InvoicePrinter
87
100
  # document - InvoicePrinter::Document object
88
101
  # labels - labels to override
89
102
  # font - font file to use
103
+ # bold_font - bold font file to use
90
104
  # stamp - stamp & signature (image)
91
105
  # logo - logotype (image)
92
106
  # background - background (image)
93
107
  # page_size - :letter or :a4
94
- def self.render(document:, labels: {}, font: nil, stamp: nil, logo: nil, background: nil, page_size: :letter)
108
+ def self.render(
109
+ document:,
110
+ labels: {},
111
+ font: nil,
112
+ bold_font: nil,
113
+ stamp: nil,
114
+ logo: nil,
115
+ background: nil,
116
+ page_size: :letter
117
+ )
95
118
  PDFDocument.new(
96
119
  document: document,
97
120
  labels: labels,
98
121
  font: font,
122
+ bold_font: bold_font,
99
123
  stamp: stamp,
100
124
  logo: logo,
101
125
  background: background,
data/regenerate.rb ADDED
@@ -0,0 +1,10 @@
1
+ # Script to regenerate all examples
2
+ examples_directory = File.expand_path('../examples', __FILE__)
3
+ @examples = Dir.glob("#{examples_directory}/*.rb")
4
+
5
+ @examples.each do |example|
6
+ puts "Running #{example}"
7
+ Dir.chdir(examples_directory) do
8
+ `ruby #{example}`
9
+ end
10
+ end
@@ -4,10 +4,12 @@ require 'test_helper'
4
4
  class ExamplesTest < Minitest::Test
5
5
  def setup
6
6
  examples_directory = File.expand_path('../../examples', __FILE__)
7
+ assets_directory = File.expand_path('../../assets', __FILE__)
7
8
  @examples = Dir.glob("#{examples_directory}/*.rb")
8
9
  @test_dir = File.absolute_path('./tmp/invoice_printer_examples')
9
10
  FileUtils.mkdir_p @test_dir
10
11
  FileUtils.copy_entry examples_directory, @test_dir
12
+ FileUtils.cp_r assets_directory, File.absolute_path('./tmp/')
11
13
  end
12
14
 
13
15
  def teardown
data/test/test_ext.rb CHANGED
@@ -101,7 +101,8 @@ module InvoicePrinter
101
101
  strings << @document.tax2
102
102
  strings << "#{@labels[:tax3]}:"
103
103
  strings << @document.tax3
104
- strings << "#{@labels[:total]}: #{@document.total}"
104
+ strings << "#{@labels[:total]}:"
105
+ strings << @document.total
105
106
  strings
106
107
  end
107
108
 
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: 2.2.0.alpha1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josef Strzibny
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-16 00:00:00.000000000 Z
11
+ date: 2023-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.2'
33
+ version: '2.4'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.2'
40
+ version: '2.4'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: prawn-table
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.2.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: matrix
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: e2mmap
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: bundler
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -95,12 +123,16 @@ files:
95
123
  - LICENSE.txt
96
124
  - README.md
97
125
  - Rakefile
126
+ - assets/fonts/opensans/OpenSans-Bold.ttf
127
+ - assets/fonts/overpass/Overpass-Bold.ttf
128
+ - assets/fonts/roboto/Roboto-Bold.ttf
98
129
  - benchmarks/render.yml
99
130
  - bin/invoice_printer
100
131
  - docs/COMMAND_LINE.md
101
132
  - docs/INSTALLATION.md
102
133
  - docs/LIBRARY.md
103
134
  - docs/SERVER.md
135
+ - examples/breakdown.rb
104
136
  - examples/clients/node.js
105
137
  - examples/complex_invoice.rb
106
138
  - examples/czech_invoice.rb
@@ -120,6 +152,7 @@ files:
120
152
  - lib/invoice_printer/document/item.rb
121
153
  - lib/invoice_printer/pdf_document.rb
122
154
  - lib/invoice_printer/version.rb
155
+ - regenerate.rb
123
156
  - test/api_test.rb
124
157
  - test/background_test.rb
125
158
  - test/cli_test.rb
@@ -138,7 +171,7 @@ homepage: https://github.com/strzibny/invoice_printer
138
171
  licenses:
139
172
  - MIT
140
173
  metadata: {}
141
- post_install_message:
174
+ post_install_message:
142
175
  rdoc_options: []
143
176
  require_paths:
144
177
  - lib
@@ -149,12 +182,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
182
  version: '2.4'
150
183
  required_rubygems_version: !ruby/object:Gem::Requirement
151
184
  requirements:
152
- - - ">"
185
+ - - ">="
153
186
  - !ruby/object:Gem::Version
154
- version: 1.3.1
187
+ version: '0'
155
188
  requirements: []
156
- rubygems_version: 3.2.0.rc.1
157
- signing_key:
189
+ rubygems_version: 3.3.3
190
+ signing_key:
158
191
  specification_version: 4
159
192
  summary: Super simple PDF invoicing in pure Ruby
160
193
  test_files: