bollettino 1.0.0 → 1.0.1
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 +5 -5
- data/.rubocop.yml +103 -0
- data/.travis.yml +3 -3
- data/CHANGELOG.md +31 -3
- data/README.md +8 -8
- data/bollettino.gemspec +10 -7
- data/lib/bollettino.rb +15 -12
- data/lib/bollettino/generator.rb +24 -20
- data/lib/bollettino/model/address.rb +22 -0
- data/lib/bollettino/model/base.rb +9 -0
- data/lib/bollettino/model/payee.rb +21 -0
- data/lib/bollettino/model/payer.rb +20 -0
- data/lib/bollettino/model/payment_order.rb +24 -0
- data/lib/bollettino/model/slip.rb +25 -0
- data/lib/bollettino/renderer/address.rb +32 -0
- data/lib/bollettino/renderer/base.rb +46 -0
- data/lib/bollettino/renderer/errors.rb +14 -0
- data/lib/bollettino/renderer/payee.rb +34 -0
- data/lib/bollettino/renderer/payer.rb +28 -0
- data/lib/bollettino/renderer/payment_order.rb +45 -0
- data/lib/bollettino/renderer/slip.rb +29 -0
- data/lib/bollettino/version.rb +3 -1
- data/spec/integration/generation_spec.rb +8 -9
- data/spec/spec_helper.rb +9 -1
- data/spec/unit/bollettino/generator_spec.rb +8 -35
- data/spec/unit/bollettino/model/address_spec.rb +20 -0
- data/spec/unit/bollettino/model/payee_spec.rb +18 -0
- data/spec/unit/bollettino/model/payer_spec.rb +24 -0
- data/spec/unit/bollettino/model/payment_order_spec.rb +19 -0
- data/spec/unit/bollettino/model/slip_spec.rb +29 -0
- data/spec/unit/bollettino/renderer/address_spec.rb +28 -0
- data/spec/unit/bollettino/renderer/payee_spec.rb +39 -0
- data/spec/unit/bollettino/renderer/payer_spec.rb +41 -0
- data/spec/unit/bollettino/renderer/payment_order_spec.rb +40 -0
- data/spec/unit/bollettino/renderer/slip_spec.rb +54 -0
- metadata +81 -51
- data/lib/bollettino/models/address.rb +0 -18
- data/lib/bollettino/models/payee.rb +0 -17
- data/lib/bollettino/models/payer.rb +0 -16
- data/lib/bollettino/models/payment_order.rb +0 -20
- data/lib/bollettino/models/slip.rb +0 -21
- data/lib/bollettino/renderer.rb +0 -47
- data/lib/bollettino/renderers/address_renderer.rb +0 -24
- data/lib/bollettino/renderers/payee_renderer.rb +0 -26
- data/lib/bollettino/renderers/payer_renderer.rb +0 -20
- data/lib/bollettino/renderers/payment_order_renderer.rb +0 -37
- data/lib/bollettino/renderers/slip_renderer.rb +0 -21
- data/spec/unit/bollettino/models/address_spec.rb +0 -12
- data/spec/unit/bollettino/models/payee_spec.rb +0 -10
- data/spec/unit/bollettino/models/payer_spec.rb +0 -12
- data/spec/unit/bollettino/models/payment_order_spec.rb +0 -11
- data/spec/unit/bollettino/models/slip_spec.rb +0 -15
- data/spec/unit/bollettino/renderers/address_renderer_spec.rb +0 -23
- data/spec/unit/bollettino/renderers/payee_renderer_spec.rb +0 -37
- data/spec/unit/bollettino/renderers/payer_renderer_spec.rb +0 -27
- data/spec/unit/bollettino/renderers/payment_order_renderer_spec.rb +0 -39
- data/spec/unit/bollettino/renderers/slip_renderer_spec.rb +0 -34
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Renderer
|
5
|
+
class Address < Base
|
6
|
+
class << self
|
7
|
+
def render(image, address)
|
8
|
+
render_street(image, address)
|
9
|
+
render_zip(image, address)
|
10
|
+
render_location(image, address)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def render_street(image, address)
|
16
|
+
write_text(image, [85, 267], address.street[0..29], KERNING_NORMAL, FONT_SIZE_SMALL)
|
17
|
+
write_text(image, [1508, 267], address.street[0..22], KERNING_BOX_SMALLEST)
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_zip(image, address)
|
21
|
+
write_text(image, [85, 223], address.zip[0..29], KERNING_NORMAL, FONT_SIZE_SMALL)
|
22
|
+
write_text(image, [1508, 200], address.zip[0..4], KERNING_BOX_SMALLEST)
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_location(image, address)
|
26
|
+
write_text(image, [85, 180], address.location[0..29], KERNING_NORMAL, FONT_SIZE_SMALL)
|
27
|
+
write_text(image, [1713, 200], address.location[0..16], KERNING_BOX_SMALLEST)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Renderer
|
5
|
+
# Base renderer
|
6
|
+
#
|
7
|
+
# @abstract Subclass and override {.render} to create a renderer
|
8
|
+
#
|
9
|
+
# @author Alessandro Desantis <desa.alessandro@gmail.com>
|
10
|
+
class Base
|
11
|
+
class << self
|
12
|
+
KERNING_NORMAL = 1
|
13
|
+
|
14
|
+
KERNING_BOX = 17.5
|
15
|
+
KERNING_BOX_SMALLER = 17
|
16
|
+
KERNING_BOX_SMALLEST = 16
|
17
|
+
|
18
|
+
FONT_SIZE_NORMAL = 30
|
19
|
+
FONT_SIZE_SMALL = 25
|
20
|
+
|
21
|
+
# Renders the given model on the image.
|
22
|
+
#
|
23
|
+
# @param image [MiniMagick::Image]
|
24
|
+
# @param model
|
25
|
+
#
|
26
|
+
# @abstract This method must be overridden by the renderers
|
27
|
+
def render(_image, _model)
|
28
|
+
fail NotImplementedError
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def write_text(image, coords, text, kerning = KERNING_NORMAL, font_size = FONT_SIZE_NORMAL)
|
34
|
+
image.combine_options do |c|
|
35
|
+
c.font 'courier'
|
36
|
+
c.fill 'black'
|
37
|
+
c.pointsize font_size
|
38
|
+
c.gravity 'southwest'
|
39
|
+
c.kerning kerning
|
40
|
+
c.draw %(text #{coords.join(',')} "#{text.to_s.upcase.gsub('"', '\"')}")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Renderer
|
5
|
+
# Rendering error
|
6
|
+
#
|
7
|
+
# This error is usually raised when some data can't be renderered because
|
8
|
+
# it's malformed.
|
9
|
+
#
|
10
|
+
# @author Alessandro Desantis <desa.alessandro@gmail.com>
|
11
|
+
class RenderingError < StandardError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Renderer
|
5
|
+
class Payee < Base
|
6
|
+
class << self
|
7
|
+
def render(image, payee)
|
8
|
+
render_account_number(image, payee)
|
9
|
+
render_name(image, payee)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def render_account_number(image, payee)
|
15
|
+
if payee.account_number.length > 10
|
16
|
+
fail RenderingError, "Account number can't be longer than 10 characters"
|
17
|
+
end
|
18
|
+
|
19
|
+
[[265, 695], [1310, 695]].each do |coords|
|
20
|
+
write_text(image, coords, payee.account_number, KERNING_BOX)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def render_name(image, payee)
|
25
|
+
write_text(image, [90, 585], payee.name[0..46])
|
26
|
+
write_text(image, [90, 545], payee.name[47..93])
|
27
|
+
|
28
|
+
write_text(image, [1105, 590], payee.name[0..33], KERNING_BOX_SMALLER)
|
29
|
+
write_text(image, [1105, 545], payee.name[34..67], KERNING_BOX_SMALLER)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Renderer
|
5
|
+
class Payer < Base
|
6
|
+
class << self
|
7
|
+
def render(image, payer)
|
8
|
+
render_name(image, payer)
|
9
|
+
render_address(image, payer)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def render_name(image, payer)
|
15
|
+
write_text(image, [85, 360], payer.name[0..24])
|
16
|
+
write_text(image, [85, 315], payer.name[25..49])
|
17
|
+
|
18
|
+
write_text(image, [1508, 375], payer.name[0..22], KERNING_BOX_SMALLEST)
|
19
|
+
write_text(image, [1508, 330], payer.name[23..45], KERNING_BOX_SMALLEST)
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_address(image, payer)
|
23
|
+
Address.render(image, payer.address)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Renderer
|
5
|
+
class PaymentOrder < Base
|
6
|
+
class << self
|
7
|
+
def render(image, payment_order)
|
8
|
+
render_numeric_amount(image, payment_order)
|
9
|
+
render_text_amount(image, payment_order)
|
10
|
+
render_reason(image, payment_order)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def render_numeric_amount(image, payment_order)
|
16
|
+
numeric_amount = payment_order.numeric_amount
|
17
|
+
numeric_amount = format('%.2f', numeric_amount).delete('.')
|
18
|
+
|
19
|
+
if numeric_amount.length > 7
|
20
|
+
fail RenderingError, "Numeric amount can't be longer than 7 total digits"
|
21
|
+
end
|
22
|
+
|
23
|
+
numeric_amount_x = 1000 - 35 * numeric_amount.length.to_i
|
24
|
+
|
25
|
+
[[numeric_amount_x, 690], [numeric_amount_x + 1315, 690]].each do |coords|
|
26
|
+
write_text(image, coords, numeric_amount, KERNING_BOX)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def render_reason(image, payment_order)
|
31
|
+
write_text(image, [90, 475], payment_order.reason[0..46])
|
32
|
+
write_text(image, [90, 435], payment_order.reason[47..93])
|
33
|
+
|
34
|
+
write_text(image, [1110, 475], payment_order.reason[0..60])
|
35
|
+
write_text(image, [1110, 435], payment_order.reason[61..121])
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_text_amount(image, payment_order)
|
39
|
+
write_text(image, [245, 650], payment_order.text_amount[0..38])
|
40
|
+
write_text(image, [1435, 650], payment_order.text_amount[0..44])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Renderer
|
5
|
+
class Slip < Base
|
6
|
+
class << self
|
7
|
+
def render(image, slip)
|
8
|
+
render_payment_order(image, slip)
|
9
|
+
render_payee(image, slip)
|
10
|
+
render_payer(image, slip)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def render_payment_order(image, slip)
|
16
|
+
PaymentOrder.render(image, slip.payment_order)
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_payee(image, slip)
|
20
|
+
Payee.render(image, slip.payee)
|
21
|
+
end
|
22
|
+
|
23
|
+
def render_payer(image, slip)
|
24
|
+
Payer.render(image, slip.payer)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/bollettino/version.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe 'The generation' do
|
4
4
|
let(:payee) do
|
5
|
-
Bollettino::Payee.new(
|
5
|
+
Bollettino::Model::Payee.new(
|
6
6
|
account_number: '0123456789',
|
7
7
|
name: 'Acme Inc.'
|
8
8
|
)
|
9
9
|
end
|
10
10
|
|
11
11
|
let(:payer) do
|
12
|
-
Bollettino::Payer.new(
|
12
|
+
Bollettino::Model::Payer.new(
|
13
13
|
name: 'John Doe',
|
14
|
-
address: Bollettino::Address.new(
|
14
|
+
address: Bollettino::Model::Address.new(
|
15
15
|
street: '3681 Foggy Moor',
|
16
16
|
zip: '19147-0834',
|
17
17
|
location: 'Grayson'
|
@@ -20,16 +20,15 @@ RSpec.describe 'The generation' do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
let(:payment_order) do
|
23
|
-
Bollettino::PaymentOrder.new(
|
23
|
+
Bollettino::Model::PaymentOrder.new(
|
24
24
|
numeric_amount: 54.31,
|
25
25
|
text_amount: 'Cinquantaquattro/31',
|
26
26
|
reason: 'Invoice INV-1391'
|
27
27
|
)
|
28
|
-
|
29
28
|
end
|
30
29
|
|
31
30
|
let(:slip) do
|
32
|
-
Bollettino::Slip.new(
|
31
|
+
Bollettino::Model::Slip.new(
|
33
32
|
payee: payee,
|
34
33
|
payer: payer,
|
35
34
|
payment_order: payment_order
|
@@ -38,13 +37,13 @@ RSpec.describe 'The generation' do
|
|
38
37
|
|
39
38
|
let(:slip_path) { File.expand_path('../../../tmp/slip.png', __FILE__) }
|
40
39
|
|
41
|
-
before
|
40
|
+
before do
|
42
41
|
FileUtils.rm(slip_path) if File.exist?(slip_path)
|
43
42
|
end
|
44
43
|
|
45
44
|
it 'creates the slip' do
|
46
45
|
expect {
|
47
46
|
Bollettino::Generator.new.generate!(slip, slip_path)
|
48
|
-
}.to change{File.exist?(slip_path)}.from(false).to(true)
|
47
|
+
}.to change { File.exist?(slip_path) }.from(false).to(true)
|
49
48
|
end
|
50
49
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'coveralls'
|
2
|
+
Coveralls.wear!
|
3
|
+
|
1
4
|
require 'bollettino'
|
2
5
|
|
3
6
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
@@ -33,7 +36,12 @@ RSpec.configure do |config|
|
|
33
36
|
|
34
37
|
# rspec-mocks config goes here. You can use an alternate test double
|
35
38
|
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
36
|
-
config.mock_with :
|
39
|
+
config.mock_with :rspec do |mocks|
|
40
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
41
|
+
# a real object. This is generally recommended, and will default to
|
42
|
+
# `true` in RSpec 4.
|
43
|
+
mocks.verify_partial_doubles = true
|
44
|
+
end
|
37
45
|
|
38
46
|
# These two settings work together to allow you to limit a spec run
|
39
47
|
# to individual examples or groups you care about by tagging them with
|
@@ -1,49 +1,22 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe Bollettino::Generator do
|
4
4
|
subject { described_class.new }
|
5
5
|
|
6
6
|
describe '#generate!' do
|
7
|
-
let(:slip)
|
8
|
-
|
7
|
+
let(:slip) { instance_double('Bollettino::Model::Slip') }
|
8
|
+
let(:image) { instance_double('MiniMagick::Image') }
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
name: rs
|
14
|
-
),
|
15
|
-
payment_order: stub(
|
16
|
-
numeric_amount: 1,
|
17
|
-
text_amount: rs,
|
18
|
-
reason: rs
|
19
|
-
),
|
20
|
-
payer: stub(
|
21
|
-
name: rs,
|
22
|
-
address: stub(
|
23
|
-
street: rs,
|
24
|
-
location: rs,
|
25
|
-
zip: rs
|
26
|
-
)
|
27
|
-
)
|
28
|
-
)
|
10
|
+
before do
|
11
|
+
allow(MiniMagick::Image).to receive(:open).and_return(image)
|
12
|
+
allow(Bollettino::Renderer::Slip).to receive(:render)
|
29
13
|
end
|
30
14
|
|
31
|
-
it '
|
32
|
-
image
|
33
|
-
image
|
34
|
-
.expects(:write)
|
15
|
+
it 'creates the image' do
|
16
|
+
expect(image).to receive(:write)
|
35
17
|
.with('slip.png')
|
36
18
|
.once
|
37
19
|
|
38
|
-
MiniMagick::Image
|
39
|
-
.expects(:open)
|
40
|
-
.once
|
41
|
-
.returns(image)
|
42
|
-
|
43
|
-
Bollettino::Renderer::SlipRenderer
|
44
|
-
.expects(:render)
|
45
|
-
.once
|
46
|
-
|
47
20
|
subject.generate!(slip, 'slip.png')
|
48
21
|
end
|
49
22
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Model
|
5
|
+
RSpec.describe Address do
|
6
|
+
subject do
|
7
|
+
described_class.new(
|
8
|
+
street: '3681 Foggy Moor',
|
9
|
+
zip: '19147-0834',
|
10
|
+
city: 'Grayson',
|
11
|
+
state: 'Pennsylvania'
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'is instantiated correctly' do
|
16
|
+
expect { subject }.not_to raise_error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Model
|
5
|
+
RSpec.describe Payee do
|
6
|
+
subject do
|
7
|
+
described_class.new(
|
8
|
+
account_number: '0123456789',
|
9
|
+
name: 'Acme Inc.'
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'is instantiated correctly' do
|
14
|
+
expect { subject }.not_to raise_error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bollettino
|
4
|
+
module Model
|
5
|
+
RSpec.describe Payer do
|
6
|
+
subject do
|
7
|
+
described_class.new(
|
8
|
+
name: 'John Doe',
|
9
|
+
address: address
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:address) { instance_double('Bollettino::Model::Address') }
|
14
|
+
|
15
|
+
before do
|
16
|
+
allow(address).to receive(:to_hash).and_return({})
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'is instantiated correctly' do
|
20
|
+
expect { subject }.not_to raise_error
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|