parking_ticket 1.0.47 → 1.0.50

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/.vscode/settings.json +3 -0
  4. data/Gemfile +0 -15
  5. data/Gemfile.lock +72 -4
  6. data/Rakefile +2 -2
  7. data/bin/console +3 -3
  8. data/bin/tapioca +29 -0
  9. data/lib/clients/models/payment_method.rb +15 -0
  10. data/lib/clients/models/quote.rb +16 -0
  11. data/lib/clients/models/rate_option.rb +19 -0
  12. data/lib/clients/models/structuraly_comparable.rb +14 -0
  13. data/lib/clients/models/ticket.rb +19 -0
  14. data/lib/clients/models/vehicle.rb +17 -0
  15. data/lib/clients/pay_by_phone/adapter.rb +106 -50
  16. data/lib/clients/pay_by_phone/client.rb +101 -38
  17. data/lib/parking_ticket/configuration.rb +3 -0
  18. data/lib/parking_ticket/version.rb +2 -1
  19. data/lib/parking_ticket.rb +79 -54
  20. data/sorbet/config +4 -0
  21. data/sorbet/rbi/annotations/faraday.rbi +17 -0
  22. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  23. data/sorbet/rbi/annotations/webmock.rbi +9 -0
  24. data/sorbet/rbi/gems/addressable@2.8.1.rbi +2000 -0
  25. data/sorbet/rbi/gems/amazing_print@1.4.0.rbi +872 -0
  26. data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
  27. data/sorbet/rbi/gems/crack@0.4.5.rbi +144 -0
  28. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1079 -0
  29. data/sorbet/rbi/gems/faraday-net_http@3.0.2.rbi +146 -0
  30. data/sorbet/rbi/gems/faraday@2.7.2.rbi +2518 -0
  31. data/sorbet/rbi/gems/hashdiff@1.0.1.rbi +350 -0
  32. data/sorbet/rbi/gems/json@2.6.3.rbi +1541 -0
  33. data/sorbet/rbi/gems/json_matchers@0.11.1.rbi +133 -0
  34. data/sorbet/rbi/gems/json_schema@0.21.0.rbi +1165 -0
  35. data/sorbet/rbi/gems/netrc@0.11.0.rbi +161 -0
  36. data/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
  37. data/sorbet/rbi/gems/parser@3.2.2.0.rbi +7207 -0
  38. data/sorbet/rbi/gems/public_suffix@5.0.1.rbi +940 -0
  39. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +402 -0
  40. data/sorbet/rbi/gems/rake@13.0.6.rbi +2881 -0
  41. data/sorbet/rbi/gems/rbi@0.0.16.rbi +3008 -0
  42. data/sorbet/rbi/gems/regexp_parser@2.7.0.rbi +3600 -0
  43. data/sorbet/rbi/gems/rexml@3.2.5.rbi +4823 -0
  44. data/sorbet/rbi/gems/rspec-core@3.12.0.rbi +10826 -0
  45. data/sorbet/rbi/gems/rspec-expectations@3.12.1.rbi +8118 -0
  46. data/sorbet/rbi/gems/rspec-mocks@3.12.1.rbi +5300 -0
  47. data/sorbet/rbi/gems/rspec-support@3.12.0.rbi +1615 -0
  48. data/sorbet/rbi/gems/rspec@3.12.0.rbi +82 -0
  49. data/sorbet/rbi/gems/rubocop-ast@1.28.0.rbi +6985 -0
  50. data/sorbet/rbi/gems/rubocop-sorbet@0.7.0.rbi +1043 -0
  51. data/sorbet/rbi/gems/rubocop@1.48.1.rbi +54934 -0
  52. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1317 -0
  53. data/sorbet/rbi/gems/ruby2_keywords@0.0.5.rbi +8 -0
  54. data/sorbet/rbi/gems/spoom@1.2.1.rbi +2503 -0
  55. data/sorbet/rbi/gems/tapioca@0.11.4.rbi +3212 -0
  56. data/sorbet/rbi/gems/thor@1.2.1.rbi +3956 -0
  57. data/sorbet/rbi/gems/unicode-display_width@2.4.2.rbi +65 -0
  58. data/sorbet/rbi/gems/unparser@0.6.7.rbi +4515 -0
  59. data/sorbet/rbi/gems/vcr@6.1.0.rbi +3023 -0
  60. data/sorbet/rbi/gems/webmock@3.18.1.rbi +1728 -0
  61. data/sorbet/rbi/gems/webrick@1.7.0.rbi +2584 -0
  62. data/sorbet/rbi/gems/yard-sorbet@0.8.0.rbi +441 -0
  63. data/sorbet/rbi/gems/yard@0.9.28.rbi +17802 -0
  64. data/sorbet/tapioca/config.yml +13 -0
  65. data/sorbet/tapioca/require.rb +4 -0
  66. metadata +241 -4
  67. data/lib/clients/adapter.rb +0 -75
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47190c2379c7c918b9b1e523468356733a8e95f35f28b9f82a2b51e42711b6ff
4
- data.tar.gz: '03789c5ef1ddf7705635aa3a7fa8040c759ee6579e322343921a9401055718cb'
3
+ metadata.gz: bf677104f4a7521da8b2fd6f29067e05da2b6561f2a9ca66d548b38a85d4a7ae
4
+ data.tar.gz: 2a1f110540182ddfd469c0a6866cd9d080231f3d71b308e9009815a17458093c
5
5
  SHA512:
6
- metadata.gz: e42de2271ba5e618055f3d89cb1dc991eecbdaf3d3b5bc8a21badee98f962d7060c38143248bb8c00f8b60414a8b6ee20d62238a1ef6b1a595686f4326e09ae2
7
- data.tar.gz: ffdab5a02a2b4f826585ac8aa09f6e1d3c264ec6c0d47b6276d455cc410aa2b820f37280df16584655c15b24ddf5b1a3a3d887608063bfbead58ecbaa5ae0460
6
+ metadata.gz: 91b0d25a297292d067a76e77b67530410c5b82ad03a169049388c5b072e6056eeb27be51c684f690f998a6500e2e515209435b8edb354d8d5733601ad2af1bdf
7
+ data.tar.gz: '0983f1b743c0de20665039cc0058ce0db8a0954688c6c3674d6dc002d0ce5d6ba8d95a8beb9c8ec9c00ff1499ddba0f355d39f06db1537dd67226b0d7510baab'
data/.rubocop.yml ADDED
@@ -0,0 +1,4 @@
1
+ require:
2
+ - rubocop-sorbet
3
+ AllCops:
4
+ NewCops: enable
@@ -0,0 +1,3 @@
1
+ {
2
+ "ruby.rubocop.onSave": false
3
+ }
data/Gemfile CHANGED
@@ -1,19 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  source 'https://rubygems.org'
4
-
5
- # Specify your gem's dependencies in parking_ticket.gemspec
6
4
  gemspec
7
-
8
- gem 'rake', '~> 13.0'
9
-
10
- gem 'rspec', '~> 3.0'
11
-
12
- # VCR, save test suite's http requests and replay them
13
- gem 'vcr', '~> 6.0'
14
- # Mock web requests in tests
15
- gem 'webmock', '~> 3.12'
16
-
17
- gem 'faraday', '~> 2.7', '>= 2.7.2'
18
-
19
- gem 'json_matchers'
data/Gemfile.lock CHANGED
@@ -1,27 +1,42 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parking_ticket (1.0.46)
5
- faraday
4
+ parking_ticket (1.0.49)
5
+ faraday (>= 2.7.2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  addressable (2.8.1)
11
11
  public_suffix (>= 2.0.2, < 6.0)
12
+ amazing_print (1.4.0)
13
+ ast (2.4.2)
14
+ byebug (11.1.3)
12
15
  crack (0.4.5)
13
16
  rexml
14
17
  diff-lcs (1.5.0)
15
- faraday (2.7.2)
18
+ faraday (2.7.4)
16
19
  faraday-net_http (>= 2.0, < 3.1)
17
20
  ruby2_keywords (>= 0.0.4)
18
21
  faraday-net_http (3.0.2)
19
22
  hashdiff (1.0.1)
23
+ json (2.6.3)
20
24
  json_matchers (0.11.1)
21
25
  json_schema
22
26
  json_schema (0.21.0)
27
+ netrc (0.11.0)
28
+ parallel (1.22.1)
29
+ parser (3.2.2.0)
30
+ ast (~> 2.4.1)
23
31
  public_suffix (5.0.1)
32
+ rainbow (3.1.1)
24
33
  rake (13.0.6)
34
+ rbi (0.0.16)
35
+ ast
36
+ parser (>= 2.6.4.0)
37
+ sorbet-runtime (>= 0.5.9204)
38
+ unparser
39
+ regexp_parser (2.7.0)
25
40
  rexml (3.2.5)
26
41
  rspec (3.12.0)
27
42
  rspec-core (~> 3.12.0)
@@ -36,23 +51,76 @@ GEM
36
51
  diff-lcs (>= 1.2.0, < 2.0)
37
52
  rspec-support (~> 3.12.0)
38
53
  rspec-support (3.12.0)
54
+ rubocop (1.48.1)
55
+ json (~> 2.3)
56
+ parallel (~> 1.10)
57
+ parser (>= 3.2.0.0)
58
+ rainbow (>= 2.2.2, < 4.0)
59
+ regexp_parser (>= 1.8, < 3.0)
60
+ rexml (>= 3.2.5, < 4.0)
61
+ rubocop-ast (>= 1.26.0, < 2.0)
62
+ ruby-progressbar (~> 1.7)
63
+ unicode-display_width (>= 2.4.0, < 3.0)
64
+ rubocop-ast (1.28.0)
65
+ parser (>= 3.2.1.0)
66
+ rubocop-sorbet (0.7.0)
67
+ rubocop (>= 0.90.0)
68
+ ruby-progressbar (1.13.0)
39
69
  ruby2_keywords (0.0.5)
70
+ sorbet (0.5.10746)
71
+ sorbet-static (= 0.5.10746)
72
+ sorbet-runtime (0.5.10746)
73
+ sorbet-static (0.5.10746-universal-darwin-20)
74
+ sorbet-static-and-runtime (0.5.10746)
75
+ sorbet (= 0.5.10746)
76
+ sorbet-runtime (= 0.5.10746)
77
+ spoom (1.2.1)
78
+ sorbet (>= 0.5.10187)
79
+ sorbet-runtime (>= 0.5.9204)
80
+ thor (>= 0.19.2)
81
+ tapioca (0.11.4)
82
+ bundler (>= 2.2.25)
83
+ netrc (>= 0.11.0)
84
+ parallel (>= 1.21.0)
85
+ rbi (~> 0.0.0, >= 0.0.16)
86
+ sorbet-static-and-runtime (>= 0.5.10187)
87
+ spoom (~> 1.2.0, >= 1.2.0)
88
+ thor (>= 1.2.0)
89
+ yard-sorbet
90
+ thor (1.2.1)
91
+ unicode-display_width (2.4.2)
92
+ unparser (0.6.7)
93
+ diff-lcs (~> 1.3)
94
+ parser (>= 3.2.0)
40
95
  vcr (6.1.0)
41
96
  webmock (3.18.1)
42
97
  addressable (>= 2.8.0)
43
98
  crack (>= 0.3.2)
44
99
  hashdiff (>= 0.4.0, < 2.0.0)
100
+ webrick (1.7.0)
101
+ yard (0.9.28)
102
+ webrick (~> 1.7.0)
103
+ yard-sorbet (0.8.0)
104
+ sorbet-runtime (>= 0.5)
105
+ yard (>= 0.9)
45
106
 
46
107
  PLATFORMS
47
108
  arm64-darwin-20
48
109
  x86_64-linux
49
110
 
50
111
  DEPENDENCIES
51
- faraday (~> 2.7, >= 2.7.2)
112
+ amazing_print
113
+ byebug
52
114
  json_matchers
53
115
  parking_ticket!
54
116
  rake (~> 13.0)
55
117
  rspec (~> 3.0)
118
+ rubocop
119
+ rubocop-sorbet
120
+ sorbet
121
+ sorbet-runtime
122
+ tapioca
123
+ unparser
56
124
  vcr (~> 6.0)
57
125
  webmock (~> 3.12)
58
126
 
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
data/bin/console CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require "parking_ticket"
4
+ require 'bundler/setup'
5
+ require 'parking_ticket'
6
6
 
7
7
  # You can add fixtures and/or initialization code here to make experimenting
8
8
  # with your gem easier. You can also use a different console, if you like.
@@ -11,5 +11,5 @@ require "parking_ticket"
11
11
  # require "pry"
12
12
  # Pry.start
13
13
 
14
- require "irb"
14
+ require 'irb'
15
15
  IRB.start(__FILE__)
data/bin/tapioca ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'tapioca' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path('bundle', __dir__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require 'rubygems'
27
+ require 'bundler/setup'
28
+
29
+ load Gem.bin_path('tapioca', 'tapioca')
@@ -0,0 +1,15 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module ParkingTicket
5
+ module Clients
6
+ module Models
7
+ class PaymentMethod < T::Struct
8
+ include ParkingTicket::Clients::Models::StructuralyComparable
9
+ const :client_internal_id, String
10
+ const :anonymised_card_number, String
11
+ const :payment_card_type, String
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module ParkingTicket
5
+ module Clients
6
+ module Models
7
+ class Quote < T::Struct
8
+ include ParkingTicket::Clients::Models::StructuralyComparable
9
+ const :client_internal_id, String
10
+ const :starts_on, DateTime
11
+ const :ends_on, DateTime
12
+ const :cost, Float
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module ParkingTicket
5
+ module Clients
6
+ module Models
7
+ class RateOption < T::Struct
8
+ include ParkingTicket::Clients::Models::StructuralyComparable
9
+
10
+ const :client_internal_id, String
11
+ const :name, String
12
+ const :type, String
13
+ const :accepted_time_units, T::Array[String]
14
+
15
+ prop :free, T.nilable(T::Boolean)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ module ParkingTicket
5
+ module Clients
6
+ module Models
7
+ module StructuralyComparable
8
+ def ==(other)
9
+ serialize == other.serialize
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module ParkingTicket
5
+ module Clients
6
+ module Models
7
+ class Ticket < T::Struct
8
+ include ParkingTicket::Clients::Models::StructuralyComparable
9
+
10
+ const :client_internal_id, String
11
+ const :starts_on, DateTime
12
+ const :ends_on, DateTime
13
+ const :license_plate, String
14
+ const :cost, Float
15
+ const :client, String
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module ParkingTicket
5
+ module Clients
6
+ module Models
7
+ class Vehicle < T::Struct
8
+ include ParkingTicket::Clients::Models::StructuralyComparable
9
+
10
+ const :client_internal_id, String
11
+ const :license_plate, String
12
+ const :vehicle_type, String
13
+ const :vehicle_description, T.nilable(String)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,106 +1,162 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
1
4
  module ParkingTicket
2
5
  module Clients
3
6
  module PayByPhone
4
- class Adapter < Clients::Adapter
5
- ACCEPTED_TIME_UNIT_MAPPER = {
7
+ class Adapter
8
+ extend T::Sig
9
+
10
+ class << self
11
+ extend T::Sig
12
+ sig { returns(T.class_of(ParkingTicket::Clients::PayByPhone::Client)) }
13
+ def client_class
14
+ ParkingTicket::Clients::PayByPhone::Client
15
+ end
16
+
17
+ sig { params(username: String, password: String).returns(T::Boolean) }
18
+ def valid_credentials?(username, password)
19
+ client_class.auth(username, password).status == 200
20
+ end
21
+ end
22
+
23
+ ACCEPTED_TIME_UNIT_MAPPER = T.let({
6
24
  'Days' => 'days',
7
25
  'Minutes' => 'minutes',
8
26
  'Hours' => 'hours'
9
- }.freeze
27
+ }.freeze, T::Hash[String, String])
10
28
 
11
- PAYMENT_CARD_TYPE_MAPPER = {
29
+ PAYMENT_CARD_TYPE_MAPPER = T.let({
12
30
  'MasterCard' => 'master_card',
13
31
  'Visa' => 'visa'
14
- }.freeze
32
+ }.freeze, T::Hash[String, String])
15
33
 
16
- VEHICLE_TYPE_MAPPER = {
34
+ VEHICLE_TYPE_MAPPER = T.let({
17
35
  'Car' => 'combustion_car',
18
36
  'ElectricMotorcycle' => 'electric_motorcycle'
19
- }.freeze
37
+ }.freeze, T::Hash[String, String])
20
38
 
21
- private
39
+ class Error < StandardError; end
40
+
41
+ sig { params(username: String, password: String).void }
42
+ def initialize(username, password)
43
+ @username = username
44
+ @password = password
45
+ @valid_credentials = T.let(self.class.valid_credentials?(username, password), T::Boolean)
46
+ @client = T.let(self.class.client_class.new(@username, @password), ParkingTicket::Clients::PayByPhone::Client)
47
+ end
22
48
 
23
- def fetch_and_map_vehicles
24
- client.vehicles.map do |vehicle|
25
- {
49
+ sig { returns(T::Array[ParkingTicket::Clients::Models::Vehicle]) }
50
+ def vehicles
51
+ raise_invalid_credentials! unless @valid_credentials
52
+ @client.vehicles.map do |vehicle|
53
+ ParkingTicket::Clients::Models::Vehicle.new(
26
54
  client_internal_id: vehicle['vehicleId'],
27
55
  license_plate: vehicle['licensePlate'],
28
- vehicle_type: VEHICLE_TYPE_MAPPER[vehicle['type']],
29
- vehicle_description: vehicle.dig("profile", "description"),
30
- }
56
+ vehicle_type: T.must(VEHICLE_TYPE_MAPPER[vehicle['type']]),
57
+ vehicle_description: vehicle.dig('profile', 'description')
58
+ )
31
59
  end
32
60
  end
33
61
 
34
- def fetch_and_map_rate_options(zipcode, license_plate)
35
- client.rate_options(zipcode, license_plate).map do |rate_option|
62
+ sig do
63
+ params(zipcode: String, license_plate: String).returns(T::Array[ParkingTicket::Clients::Models::RateOption])
64
+ end
65
+ def rate_options(zipcode, license_plate)
66
+ raise_invalid_credentials! unless @valid_credentials
67
+ @client.rate_options(zipcode, license_plate).map do |rate_option|
36
68
  mapped_time_units = rate_option['acceptedTimeUnits'].map do |accepted_time_unit|
37
69
  ACCEPTED_TIME_UNIT_MAPPER[accepted_time_unit]
38
70
  end
39
- {
71
+ ParkingTicket::Clients::Models::RateOption.new(
40
72
  client_internal_id: rate_option['rateOptionId'],
41
73
  name: rate_option['name'],
42
74
  type: rate_option['type'],
43
75
  accepted_time_units: mapped_time_units
44
- }
76
+ )
45
77
  end
46
78
  end
47
79
 
48
- def fetch_and_map_running_ticket(license_plate, zipcode)
49
- client.running_tickets.filter do |ticket|
80
+ sig do
81
+ params(license_plate: String, zipcode: String).returns(T.nilable(ParkingTicket::Clients::Models::Ticket))
82
+ end
83
+ def running_ticket(license_plate, zipcode)
84
+ raise_invalid_credentials! unless @valid_credentials
85
+ @client.running_tickets.filter do |ticket|
50
86
  ticket.dig('vehicle', 'licensePlate') == license_plate && ticket['locationId'] == zipcode
51
87
  end.map do |ticket|
52
- {
88
+ ParkingTicket::Clients::Models::Ticket.new(
53
89
  client_internal_id: ticket['parkingSessionId'],
54
90
  starts_on: DateTime.parse(ticket['startTime']),
55
91
  ends_on: DateTime.parse(ticket['expireTime']),
56
92
  license_plate: ticket.dig('vehicle', 'licensePlate'),
57
93
  cost: ticket.dig('segments', 0, 'cost'),
58
94
  client: 'PayByPhone'
59
- }
95
+ )
60
96
  end.first
61
97
  end
62
98
 
63
- def request_new_ticket(license_plate:, zipcode:, rate_option_client_internal_id:, quantity:, time_unit:, payment_method_id:)
64
- mapped_time_unit = ACCEPTED_TIME_UNIT_MAPPER.key(time_unit)
99
+ sig do
100
+ returns(T::Array[ParkingTicket::Clients::Models::PaymentMethod])
101
+ end
102
+ def payment_methods
103
+ raise_invalid_credentials! unless @valid_credentials
104
+ @client.payment_methods.fetch('items').map do |payment_method|
105
+ ParkingTicket::Clients::Models::PaymentMethod.new(
106
+ client_internal_id: payment_method['id'],
107
+ anonymised_card_number: payment_method['maskedCardNumber'][-4..],
108
+ payment_card_type: PAYMENT_CARD_TYPE_MAPPER.fetch(payment_method['paymentCardType'])
109
+ )
110
+ end
111
+ end
65
112
 
66
- quote = fetch_and_map_quote(rate_option_client_internal_id, zipcode, license_plate, quantity,
67
- time_unit)
113
+ sig do
114
+ params(rate_option_id: String, zipcode: String, license_plate: String, quantity: Integer,
115
+ time_unit: String).returns(ParkingTicket::Clients::Models::Quote)
116
+ end
117
+ def quote(rate_option_id, zipcode, license_plate, quantity, time_unit)
118
+ raise_invalid_credentials! unless @valid_credentials
119
+ mapped_time_unit = T.must(ACCEPTED_TIME_UNIT_MAPPER.key(time_unit))
120
+ fetched_quote = @client.quote(rate_option_id, zipcode, license_plate, quantity, mapped_time_unit)
68
121
 
69
- client.new_ticket(
122
+ ParkingTicket::Clients::Models::Quote.new(
123
+ client_internal_id: fetched_quote['quoteId'],
124
+ starts_on: DateTime.parse(fetched_quote['parkingStartTime']),
125
+ ends_on: DateTime.parse(fetched_quote['parkingExpiryTime']),
126
+ cost: fetched_quote.dig('totalCost', 'amount').to_f
127
+ )
128
+ end
129
+
130
+ sig do
131
+ params(license_plate: String, zipcode: String, rate_option_client_internal_id: String, quantity: Integer,
132
+ time_unit: String, payment_method_id: T.nilable(String)).void
133
+ end
134
+ def new_ticket(license_plate:, zipcode:, rate_option_client_internal_id:, quantity:, time_unit:,
135
+ payment_method_id:)
136
+ raise_invalid_credentials! unless @valid_credentials
137
+
138
+ mapped_time_unit = ACCEPTED_TIME_UNIT_MAPPER.invert.fetch(time_unit)
139
+
140
+ quote = quote(rate_option_client_internal_id, zipcode, license_plate, quantity,
141
+ time_unit)
142
+
143
+ @client.new_ticket(
70
144
  license_plate: license_plate,
71
145
  zipcode: zipcode,
72
146
  rate_option_client_internal_id: rate_option_client_internal_id,
73
147
  quantity: quantity,
74
148
  time_unit: mapped_time_unit,
75
- quote_client_internal_id: quote[:client_internal_id],
76
- starts_on: quote[:starts_on],
149
+ quote_client_internal_id: quote.client_internal_id,
150
+ starts_on: quote.starts_on,
77
151
  payment_method_id: payment_method_id
78
152
  )
79
153
  end
80
154
 
81
- def fetch_and_map_payment_methods
82
- client.payment_methods['items'].map do |payment_method|
83
- {
84
- client_internal_id: payment_method['id'],
85
- anonymised_card_number: payment_method['maskedCardNumber'][-4..],
86
- payment_card_type: PAYMENT_CARD_TYPE_MAPPER[payment_method['paymentCardType']]
87
- }
88
- end
89
- end
90
-
91
- def fetch_and_map_quote(rate_option_id, zipcode, license_plate, quantity, time_unit)
92
- mapped_time_unit = ACCEPTED_TIME_UNIT_MAPPER.key(time_unit)
93
- fetched_quote = client.quote(rate_option_id, zipcode, license_plate, quantity, mapped_time_unit)
94
-
95
- {
96
- client_internal_id: fetched_quote['quoteId'],
97
- starts_on: fetched_quote['parkingStartTime'],
98
- ends_on: fetched_quote['parkingExpiryTime'],
99
- cost: fetched_quote.dig('totalCost', 'amount')
100
- }
155
+ sig { void }
156
+ def raise_invalid_credentials!
157
+ raise Error, 'Adapter credentials are not valid'
101
158
  end
102
159
  end
103
160
  end
104
161
  end
105
162
  end
106
-