invoice_printer 2.4.0 → 2.5.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 +4 -4
- data/.github/workflows/ci.yml +3 -2
- data/bin/invoice_printer +7 -0
- data/docs/COMMAND_LINE.md +1 -0
- data/docs/SERVER.md +2 -0
- data/examples/qr_invoice.rb +57 -0
- data/invoice_printer.gemspec +4 -0
- data/lib/invoice_printer/pdf_document.rb +35 -2
- data/lib/invoice_printer/version.rb +1 -1
- data/lib/invoice_printer.rb +7 -0
- data/test/cli_test.rb +8 -0
- data/test/inputs_test.rb +8 -0
- metadata +18 -6
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0b0c25298ec6af636229e5502e0e80bfdf7675bc46d4f6a8fbec3a81c215dbd
|
4
|
+
data.tar.gz: 80bb84c5081ece73c5f77ed6597e987267c64f90cdc76c547ee123e417c878ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68978f3d5badd98537e2c3c287c4bbca474de49db7b02210e0d388e764935f612fe10b72a53e689d29643466fd8ffce6d122202f55860876609d2f01dab4a2b8
|
7
|
+
data.tar.gz: f3d1d0a824c9c1ba9528a564a497e5709d118ab0d91e97f9910d369b448a45536097b60370255d6751d3bb2ce253eb751807bf1a73461b27ab68902d6d3016a8
|
data/.github/workflows/ci.yml
CHANGED
@@ -22,12 +22,13 @@ jobs:
|
|
22
22
|
ruby:
|
23
23
|
- "3.1"
|
24
24
|
- "3.2"
|
25
|
-
|
25
|
+
- "3.3"
|
26
|
+
- "3.4"
|
26
27
|
steps:
|
27
28
|
- name: Install system dependencies
|
28
29
|
run: sudo apt-get install imagemagick libmagickwand-dev
|
29
30
|
- name: Check out code
|
30
|
-
uses: actions/checkout@
|
31
|
+
uses: actions/checkout@v5
|
31
32
|
- name: Install Ruby dependencies
|
32
33
|
uses: ruby/setup-ruby@v1
|
33
34
|
with:
|
data/bin/invoice_printer
CHANGED
@@ -22,6 +22,7 @@ def show_help
|
|
22
22
|
--bold-font path to bold font or builtin font name
|
23
23
|
-s, --stamp path to stamp
|
24
24
|
--logo path to logotype
|
25
|
+
--qr path to QR image
|
25
26
|
--background path to background image
|
26
27
|
--page-size letter or a4 (letter is the default)
|
27
28
|
-f, --filename output path
|
@@ -60,6 +61,10 @@ parser = OptionParser.new do|opts|
|
|
60
61
|
options[:logo] = path
|
61
62
|
end
|
62
63
|
|
64
|
+
opts.on('--qr PATH') do |path|
|
65
|
+
options[:qr] = path
|
66
|
+
end
|
67
|
+
|
63
68
|
opts.on('--background PATH') do |path|
|
64
69
|
options[:background] = path
|
65
70
|
end
|
@@ -124,6 +129,7 @@ begin
|
|
124
129
|
bold_font: options[:bold_font],
|
125
130
|
stamp: options[:stamp],
|
126
131
|
logo: options[:logo],
|
132
|
+
qr: options[:qr],
|
127
133
|
background: options[:background],
|
128
134
|
page_size: options[:page_size]
|
129
135
|
)
|
@@ -139,6 +145,7 @@ begin
|
|
139
145
|
bold_font: options[:bold_font],
|
140
146
|
stamp: options[:stamp],
|
141
147
|
logo: options[:logo],
|
148
|
+
qr: options[:qr],
|
142
149
|
file_name: options[:filename],
|
143
150
|
background: options[:background],
|
144
151
|
page_size: options[:page_size]
|
data/docs/COMMAND_LINE.md
CHANGED
@@ -16,6 +16,7 @@ Options:
|
|
16
16
|
--bold-font path to bold font or builtin font name
|
17
17
|
-s, --stamp path to stamp
|
18
18
|
--logo path to logotype
|
19
|
+
--qr path to QR image
|
19
20
|
--background path to background image
|
20
21
|
--page-size letter or a4 (letter is the default)
|
21
22
|
-f, --filename output path
|
data/docs/SERVER.md
CHANGED
@@ -64,6 +64,7 @@ Options:
|
|
64
64
|
- `bold_font` - path to bold font file or builtin font name
|
65
65
|
- `stamp` - path to stamp file
|
66
66
|
- `logo` - path to logotype file
|
67
|
+
- `qr` - path to QR image file
|
67
68
|
- `background` - path to background file
|
68
69
|
- `page_size` - letter or A4 page size
|
69
70
|
|
@@ -107,6 +108,7 @@ Options:
|
|
107
108
|
- `bold_font` - path to bold font file or builtin font name
|
108
109
|
- `stamp` - path to stamp file
|
109
110
|
- `logo` - path to logotype file
|
111
|
+
- `qr` - path to QR image file
|
110
112
|
- `background` - path to background file
|
111
113
|
- `page_size` - letter or A4 page size
|
112
114
|
- `filename` - path for saving the generated output PDF
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Example demonstrating adding a QR image to the invoice (bottom-right)
|
3
|
+
|
4
|
+
lib = File.expand_path('../../lib', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
require 'invoice_printer'
|
7
|
+
|
8
|
+
provider_address = <<ADDRESS
|
9
|
+
5th Avenue
|
10
|
+
747 05 NYC
|
11
|
+
ADDRESS
|
12
|
+
|
13
|
+
purchaser_address = <<ADDRESS
|
14
|
+
7th Avenue
|
15
|
+
747 70 NYC
|
16
|
+
ADDRESS
|
17
|
+
|
18
|
+
item = InvoicePrinter::Document::Item.new(
|
19
|
+
name: 'Programming',
|
20
|
+
quantity: '10',
|
21
|
+
unit: 'hr',
|
22
|
+
price: '$ 90',
|
23
|
+
amount: '$ 900'
|
24
|
+
)
|
25
|
+
|
26
|
+
invoice = InvoicePrinter::Document.new(
|
27
|
+
number: 'NO. 202500000001',
|
28
|
+
provider_name: 'John White',
|
29
|
+
provider_lines: provider_address,
|
30
|
+
purchaser_name: 'Will Black',
|
31
|
+
purchaser_lines: purchaser_address,
|
32
|
+
issue_date: '10/20/2025',
|
33
|
+
due_date: '11/03/2025',
|
34
|
+
total: '$ 900',
|
35
|
+
bank_account_number: '156546546465',
|
36
|
+
description: "Invoice with QR image example.",
|
37
|
+
items: [item],
|
38
|
+
note: "Scan the QR code for payment or details."
|
39
|
+
)
|
40
|
+
|
41
|
+
qr_path = File.expand_path('../qr.png', __FILE__)
|
42
|
+
logo_path = File.expand_path('../prawn.png', __FILE__)
|
43
|
+
|
44
|
+
InvoicePrinter.print(
|
45
|
+
document: invoice,
|
46
|
+
logo: logo_path,
|
47
|
+
qr: qr_path,
|
48
|
+
file_name: 'qr_invoice.pdf'
|
49
|
+
)
|
50
|
+
|
51
|
+
InvoicePrinter.print(
|
52
|
+
document: invoice,
|
53
|
+
logo: logo_path,
|
54
|
+
qr: qr_path,
|
55
|
+
file_name: 'qr_invoice_a4.pdf',
|
56
|
+
page_size: :a4
|
57
|
+
)
|
data/invoice_printer.gemspec
CHANGED
@@ -11,10 +11,13 @@ ONLY_FONTS_FILES = [
|
|
11
11
|
'FONTS_LICENSE.txt',
|
12
12
|
'assets/fonts/overpass/OFL-1.1.txt',
|
13
13
|
'assets/fonts/overpass/Overpass-Regular.ttf',
|
14
|
+
'assets/fonts/overpass/Overpass-Bold.ttf',
|
14
15
|
'assets/fonts/opensans/Apache-2.0.txt',
|
15
16
|
'assets/fonts/opensans/OpenSans-Regular.ttf',
|
17
|
+
'assets/fonts/opensans/OpenSans-Bold.ttf',
|
16
18
|
'assets/fonts/roboto/Apache-2.0.txt',
|
17
19
|
'assets/fonts/roboto/Roboto-Regular.ttf',
|
20
|
+
'assets/fonts/roboto/Roboto-Bold.ttf',
|
18
21
|
'lib/invoice_printer/fonts.rb'
|
19
22
|
]
|
20
23
|
|
@@ -49,6 +52,7 @@ Gem::Specification.new do |spec|
|
|
49
52
|
spec.add_dependency 'prawn-table', '~> 0.2.2'
|
50
53
|
spec.add_dependency 'matrix'
|
51
54
|
spec.add_dependency 'e2mmap'
|
55
|
+
spec.add_dependency 'base64'
|
52
56
|
|
53
57
|
spec.add_development_dependency 'bundler', '>= 1.7'
|
54
58
|
spec.add_development_dependency 'rake', '>= 10.0'
|
@@ -13,15 +13,17 @@ module InvoicePrinter
|
|
13
13
|
# font: 'font.ttf',
|
14
14
|
# bold_font: 'bold_font.ttf',
|
15
15
|
# stamp: 'stamp.jpg',
|
16
|
-
# logo: 'example.jpg'
|
16
|
+
# logo: 'example.jpg',
|
17
|
+
# qr: 'qr.png'
|
17
18
|
# )
|
18
19
|
class PDFDocument
|
19
20
|
class FontFileNotFound < StandardError; end
|
20
21
|
class LogoFileNotFound < StandardError; end
|
21
22
|
class StampFileNotFound < StandardError; end
|
23
|
+
class QRFileNotFound < StandardError; end
|
22
24
|
class InvalidInput < StandardError; end
|
23
25
|
|
24
|
-
attr_reader :invoice, :labels, :file_name, :font, :bold_font, :stamp, :logo
|
26
|
+
attr_reader :invoice, :labels, :file_name, :font, :bold_font, :stamp, :logo, :qr
|
25
27
|
|
26
28
|
DEFAULT_LABELS = {
|
27
29
|
name: 'Invoice',
|
@@ -74,6 +76,7 @@ module InvoicePrinter
|
|
74
76
|
bold_font: nil,
|
75
77
|
stamp: nil,
|
76
78
|
logo: nil,
|
79
|
+
qr: nil,
|
77
80
|
background: nil,
|
78
81
|
page_size: :letter
|
79
82
|
)
|
@@ -83,6 +86,7 @@ module InvoicePrinter
|
|
83
86
|
@bold_font = bold_font
|
84
87
|
@stamp = stamp
|
85
88
|
@logo = logo
|
89
|
+
@qr = qr
|
86
90
|
@page_size = page_size ? PAGE_SIZES[page_size.to_sym] : PAGE_SIZES[:letter]
|
87
91
|
@pdf = Prawn::Document.new(background: background, page_size: @page_size.name)
|
88
92
|
|
@@ -105,6 +109,14 @@ module InvoicePrinter
|
|
105
109
|
end
|
106
110
|
end
|
107
111
|
|
112
|
+
if used? @qr
|
113
|
+
if File.exist?(@qr)
|
114
|
+
@qr = qr
|
115
|
+
else
|
116
|
+
raise QRFileNotFound, "QR image file not found at #{@qr}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
108
120
|
if used?(@font) && used?(@bold_font)
|
109
121
|
use_font(@font, @bold_font)
|
110
122
|
elsif used?(@font)
|
@@ -176,6 +188,7 @@ module InvoicePrinter
|
|
176
188
|
build_total
|
177
189
|
build_stamp
|
178
190
|
build_logo
|
191
|
+
build_qr
|
179
192
|
build_note
|
180
193
|
build_footer
|
181
194
|
end
|
@@ -855,6 +868,26 @@ module InvoicePrinter
|
|
855
868
|
end
|
856
869
|
end
|
857
870
|
|
871
|
+
# Insert a QR image at the right bottom of the document
|
872
|
+
#
|
873
|
+
# If a note is present, position it on top of it.
|
874
|
+
def build_qr
|
875
|
+
if @qr && !@qr.empty?
|
876
|
+
bottom = @document.note.empty? ? 75 : (75 + note_height)
|
877
|
+
# Place QR at page width minus its fit width to keep it at the right edge.
|
878
|
+
|
879
|
+
image_info = Prawn::Images::PNG.new(File.read(@qr))
|
880
|
+
image_width = image_info.width.to_f
|
881
|
+
|
882
|
+
if image_width > x(50)
|
883
|
+
image_width = x(50)
|
884
|
+
end
|
885
|
+
|
886
|
+
left = @pdf.bounds.right - image_width
|
887
|
+
@pdf.image(@qr, at: [left, bottom], fit: [x(50), y(50)])
|
888
|
+
end
|
889
|
+
end
|
890
|
+
|
858
891
|
# Insert a stamp (with signature) after the total table
|
859
892
|
def build_stamp
|
860
893
|
if @stamp && !@stamp.empty?
|
data/lib/invoice_printer.rb
CHANGED
@@ -18,6 +18,7 @@ Prawn::Font::AFM.hide_m17n_warning = true
|
|
18
18
|
# bold_font: 'path-to-font-file.ttf',
|
19
19
|
# stamp: 'stamp.jpg',
|
20
20
|
# logo: 'logo.jpg',
|
21
|
+
# qr: 'qr.png',
|
21
22
|
# file_name: 'invoice.pdf'
|
22
23
|
# )
|
23
24
|
module InvoicePrinter
|
@@ -69,6 +70,7 @@ module InvoicePrinter
|
|
69
70
|
# bold_font - bold font file to use
|
70
71
|
# stamp - stamp & signature (image)
|
71
72
|
# logo - logotype (image)
|
73
|
+
# qr - QR image (image)
|
72
74
|
# background - background (image)
|
73
75
|
# page_size - :letter or :a4
|
74
76
|
# file_name - output file
|
@@ -79,6 +81,7 @@ module InvoicePrinter
|
|
79
81
|
bold_font: nil,
|
80
82
|
stamp: nil,
|
81
83
|
logo: nil,
|
84
|
+
qr: nil,
|
82
85
|
background: nil,
|
83
86
|
page_size: :letter,
|
84
87
|
file_name:
|
@@ -90,6 +93,7 @@ module InvoicePrinter
|
|
90
93
|
bold_font: bold_font,
|
91
94
|
stamp: stamp,
|
92
95
|
logo: logo,
|
96
|
+
qr: qr,
|
93
97
|
background: background,
|
94
98
|
page_size: page_size
|
95
99
|
).print(file_name)
|
@@ -103,6 +107,7 @@ module InvoicePrinter
|
|
103
107
|
# bold_font - bold font file to use
|
104
108
|
# stamp - stamp & signature (image)
|
105
109
|
# logo - logotype (image)
|
110
|
+
# qr - QR image (image)
|
106
111
|
# background - background (image)
|
107
112
|
# page_size - :letter or :a4
|
108
113
|
def self.render(
|
@@ -112,6 +117,7 @@ module InvoicePrinter
|
|
112
117
|
bold_font: nil,
|
113
118
|
stamp: nil,
|
114
119
|
logo: nil,
|
120
|
+
qr: nil,
|
115
121
|
background: nil,
|
116
122
|
page_size: :letter
|
117
123
|
)
|
@@ -122,6 +128,7 @@ module InvoicePrinter
|
|
122
128
|
bold_font: bold_font,
|
123
129
|
stamp: stamp,
|
124
130
|
logo: logo,
|
131
|
+
qr: qr,
|
125
132
|
background: background,
|
126
133
|
page_size: page_size
|
127
134
|
).render
|
data/test/cli_test.rb
CHANGED
@@ -22,6 +22,7 @@ class CLITest < Minitest::Test
|
|
22
22
|
"--document '#{@invoice_as_json}' " +
|
23
23
|
"--labels '#{labels_hash.to_json}' " +
|
24
24
|
"--logo '#{logo_path}' " +
|
25
|
+
"--qr '#{qr_path}' " +
|
25
26
|
"--background '#{background_path}' " +
|
26
27
|
"--filename #{@output_path}"
|
27
28
|
|
@@ -44,6 +45,7 @@ class CLITest < Minitest::Test
|
|
44
45
|
document: @invoice,
|
45
46
|
labels: labels_hash,
|
46
47
|
logo: logo_path,
|
48
|
+
qr: qr_path,
|
47
49
|
background: background_path,
|
48
50
|
page_size: :letter,
|
49
51
|
file_name: expected_pdf_path
|
@@ -60,6 +62,7 @@ class CLITest < Minitest::Test
|
|
60
62
|
"--document '#{@invoice_as_json}' " +
|
61
63
|
"--labels '#{labels_hash.to_json}' " +
|
62
64
|
"--logo '#{logo_path}' " +
|
65
|
+
"--qr '#{qr_path}' " +
|
63
66
|
"--background '#{background_path}' " +
|
64
67
|
"--page-size a4 " +
|
65
68
|
"--filename #{@output_path}"
|
@@ -83,6 +86,7 @@ class CLITest < Minitest::Test
|
|
83
86
|
document: @invoice,
|
84
87
|
labels: labels_hash,
|
85
88
|
logo: logo_path,
|
89
|
+
qr: qr_path,
|
86
90
|
background: background_path,
|
87
91
|
page_size: :a4,
|
88
92
|
file_name: expected_pdf_path
|
@@ -107,6 +111,10 @@ class CLITest < Minitest::Test
|
|
107
111
|
File.expand_path('../../examples/logo.png', __FILE__)
|
108
112
|
end
|
109
113
|
|
114
|
+
def qr_path
|
115
|
+
File.expand_path('../../assets/qr.png', __FILE__)
|
116
|
+
end
|
117
|
+
|
110
118
|
def background_path
|
111
119
|
File.expand_path('../../examples/background.png', __FILE__)
|
112
120
|
end
|
data/test/inputs_test.rb
CHANGED
@@ -55,4 +55,12 @@ class InputsTest < Minitest::Test
|
|
55
55
|
InvoicePrinter.render(document: invoice, stamp: 'missing.png')
|
56
56
|
end
|
57
57
|
end
|
58
|
+
|
59
|
+
def test_missing_qr_raises_an_exception
|
60
|
+
invoice = InvoicePrinter::Document.new(**default_document_params)
|
61
|
+
|
62
|
+
assert_raises(InvoicePrinter::PDFDocument::QRFileNotFound) do
|
63
|
+
InvoicePrinter.render(document: invoice, qr: 'missing.png')
|
64
|
+
end
|
65
|
+
end
|
58
66
|
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: 2.
|
4
|
+
version: 2.5.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:
|
11
|
+
date: 2025-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: base64
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: bundler
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,9 +137,6 @@ files:
|
|
123
137
|
- LICENSE.txt
|
124
138
|
- README.md
|
125
139
|
- Rakefile
|
126
|
-
- assets/fonts/opensans/OpenSans-Bold.ttf
|
127
|
-
- assets/fonts/overpass/Overpass-Bold.ttf
|
128
|
-
- assets/fonts/roboto/Roboto-Bold.ttf
|
129
140
|
- benchmarks/render.yml
|
130
141
|
- bin/invoice_printer
|
131
142
|
- docs/COMMAND_LINE.md
|
@@ -142,6 +153,7 @@ files:
|
|
142
153
|
- examples/picture.jpg
|
143
154
|
- examples/promo.rb
|
144
155
|
- examples/provider_purchaser_lines.rb
|
156
|
+
- examples/qr_invoice.rb
|
145
157
|
- examples/simple_invoice.rb
|
146
158
|
- examples/variable_field_invoice.rb
|
147
159
|
- invoice_printer.gemspec
|
@@ -186,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
198
|
- !ruby/object:Gem::Version
|
187
199
|
version: '0'
|
188
200
|
requirements: []
|
189
|
-
rubygems_version: 3.
|
201
|
+
rubygems_version: 3.5.22
|
190
202
|
signing_key:
|
191
203
|
specification_version: 4
|
192
204
|
summary: Super simple PDF invoicing in pure Ruby
|
Binary file
|
Binary file
|
Binary file
|