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.
Files changed (57) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +103 -0
  3. data/.travis.yml +3 -3
  4. data/CHANGELOG.md +31 -3
  5. data/README.md +8 -8
  6. data/bollettino.gemspec +10 -7
  7. data/lib/bollettino.rb +15 -12
  8. data/lib/bollettino/generator.rb +24 -20
  9. data/lib/bollettino/model/address.rb +22 -0
  10. data/lib/bollettino/model/base.rb +9 -0
  11. data/lib/bollettino/model/payee.rb +21 -0
  12. data/lib/bollettino/model/payer.rb +20 -0
  13. data/lib/bollettino/model/payment_order.rb +24 -0
  14. data/lib/bollettino/model/slip.rb +25 -0
  15. data/lib/bollettino/renderer/address.rb +32 -0
  16. data/lib/bollettino/renderer/base.rb +46 -0
  17. data/lib/bollettino/renderer/errors.rb +14 -0
  18. data/lib/bollettino/renderer/payee.rb +34 -0
  19. data/lib/bollettino/renderer/payer.rb +28 -0
  20. data/lib/bollettino/renderer/payment_order.rb +45 -0
  21. data/lib/bollettino/renderer/slip.rb +29 -0
  22. data/lib/bollettino/version.rb +3 -1
  23. data/spec/integration/generation_spec.rb +8 -9
  24. data/spec/spec_helper.rb +9 -1
  25. data/spec/unit/bollettino/generator_spec.rb +8 -35
  26. data/spec/unit/bollettino/model/address_spec.rb +20 -0
  27. data/spec/unit/bollettino/model/payee_spec.rb +18 -0
  28. data/spec/unit/bollettino/model/payer_spec.rb +24 -0
  29. data/spec/unit/bollettino/model/payment_order_spec.rb +19 -0
  30. data/spec/unit/bollettino/model/slip_spec.rb +29 -0
  31. data/spec/unit/bollettino/renderer/address_spec.rb +28 -0
  32. data/spec/unit/bollettino/renderer/payee_spec.rb +39 -0
  33. data/spec/unit/bollettino/renderer/payer_spec.rb +41 -0
  34. data/spec/unit/bollettino/renderer/payment_order_spec.rb +40 -0
  35. data/spec/unit/bollettino/renderer/slip_spec.rb +54 -0
  36. metadata +81 -51
  37. data/lib/bollettino/models/address.rb +0 -18
  38. data/lib/bollettino/models/payee.rb +0 -17
  39. data/lib/bollettino/models/payer.rb +0 -16
  40. data/lib/bollettino/models/payment_order.rb +0 -20
  41. data/lib/bollettino/models/slip.rb +0 -21
  42. data/lib/bollettino/renderer.rb +0 -47
  43. data/lib/bollettino/renderers/address_renderer.rb +0 -24
  44. data/lib/bollettino/renderers/payee_renderer.rb +0 -26
  45. data/lib/bollettino/renderers/payer_renderer.rb +0 -20
  46. data/lib/bollettino/renderers/payment_order_renderer.rb +0 -37
  47. data/lib/bollettino/renderers/slip_renderer.rb +0 -21
  48. data/spec/unit/bollettino/models/address_spec.rb +0 -12
  49. data/spec/unit/bollettino/models/payee_spec.rb +0 -10
  50. data/spec/unit/bollettino/models/payer_spec.rb +0 -12
  51. data/spec/unit/bollettino/models/payment_order_spec.rb +0 -11
  52. data/spec/unit/bollettino/models/slip_spec.rb +0 -15
  53. data/spec/unit/bollettino/renderers/address_renderer_spec.rb +0 -23
  54. data/spec/unit/bollettino/renderers/payee_renderer_spec.rb +0 -37
  55. data/spec/unit/bollettino/renderers/payer_renderer_spec.rb +0 -27
  56. data/spec/unit/bollettino/renderers/payment_order_renderer_spec.rb +0 -39
  57. 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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bollettino
2
- VERSION = '1.0.0'
4
+ VERSION = '1.0.1'
3
5
  end
@@ -1,17 +1,17 @@
1
- require 'spec_helper'
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(:each) do
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 :mocha
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
- require 'spec_helper'
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) do
8
- rs = (('A'..'Z').to_a * 10).join('')
7
+ let(:slip) { instance_double('Bollettino::Model::Slip') }
8
+ let(:image) { instance_double('MiniMagick::Image') }
9
9
 
10
- stub(
11
- payee: stub(
12
- account_number: '0123456789',
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 'writes the image' do
32
- image = mock()
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