parking_ticket 1.0.46 → 1.0.49
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/.vscode/settings.json +3 -0
- data/Gemfile +0 -15
- data/Gemfile.lock +72 -4
- data/Rakefile +2 -2
- data/bin/console +3 -3
- data/bin/tapioca +29 -0
- data/lib/clients/models/payment_method.rb +15 -0
- data/lib/clients/models/quote.rb +16 -0
- data/lib/clients/models/rate_option.rb +19 -0
- data/lib/clients/models/structuraly_comparable.rb +14 -0
- data/lib/clients/models/ticket.rb +19 -0
- data/lib/clients/models/vehicle.rb +17 -0
- data/lib/clients/pay_by_phone/adapter.rb +107 -53
- data/lib/clients/pay_by_phone/client.rb +101 -38
- data/lib/parking_ticket/configuration.rb +3 -0
- data/lib/parking_ticket/version.rb +2 -1
- data/lib/parking_ticket.rb +79 -54
- data/sorbet/config +4 -0
- data/sorbet/rbi/annotations/faraday.rbi +17 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/annotations/webmock.rbi +9 -0
- data/sorbet/rbi/gems/addressable@2.8.1.rbi +2000 -0
- data/sorbet/rbi/gems/amazing_print@1.4.0.rbi +872 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
- data/sorbet/rbi/gems/crack@0.4.5.rbi +144 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1079 -0
- data/sorbet/rbi/gems/faraday-net_http@3.0.2.rbi +146 -0
- data/sorbet/rbi/gems/faraday@2.7.2.rbi +2518 -0
- data/sorbet/rbi/gems/hashdiff@1.0.1.rbi +350 -0
- data/sorbet/rbi/gems/json@2.6.3.rbi +1541 -0
- data/sorbet/rbi/gems/json_matchers@0.11.1.rbi +133 -0
- data/sorbet/rbi/gems/json_schema@0.21.0.rbi +1165 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +161 -0
- data/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
- data/sorbet/rbi/gems/parser@3.2.2.0.rbi +7207 -0
- data/sorbet/rbi/gems/public_suffix@5.0.1.rbi +940 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +402 -0
- data/sorbet/rbi/gems/rake@13.0.6.rbi +2881 -0
- data/sorbet/rbi/gems/rbi@0.0.16.rbi +3008 -0
- data/sorbet/rbi/gems/regexp_parser@2.7.0.rbi +3600 -0
- data/sorbet/rbi/gems/rexml@3.2.5.rbi +4823 -0
- data/sorbet/rbi/gems/rspec-core@3.12.0.rbi +10826 -0
- data/sorbet/rbi/gems/rspec-expectations@3.12.1.rbi +8118 -0
- data/sorbet/rbi/gems/rspec-mocks@3.12.1.rbi +5300 -0
- data/sorbet/rbi/gems/rspec-support@3.12.0.rbi +1615 -0
- data/sorbet/rbi/gems/rspec@3.12.0.rbi +82 -0
- data/sorbet/rbi/gems/rubocop-ast@1.28.0.rbi +6985 -0
- data/sorbet/rbi/gems/rubocop-sorbet@0.7.0.rbi +1043 -0
- data/sorbet/rbi/gems/rubocop@1.48.1.rbi +54934 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1317 -0
- data/sorbet/rbi/gems/ruby2_keywords@0.0.5.rbi +8 -0
- data/sorbet/rbi/gems/spoom@1.2.1.rbi +2503 -0
- data/sorbet/rbi/gems/tapioca@0.11.4.rbi +3212 -0
- data/sorbet/rbi/gems/thor@1.2.1.rbi +3956 -0
- data/sorbet/rbi/gems/unicode-display_width@2.4.2.rbi +65 -0
- data/sorbet/rbi/gems/unparser@0.6.7.rbi +4515 -0
- data/sorbet/rbi/gems/vcr@6.1.0.rbi +3023 -0
- data/sorbet/rbi/gems/webmock@3.18.1.rbi +1728 -0
- data/sorbet/rbi/gems/webrick@1.7.0.rbi +2584 -0
- data/sorbet/rbi/gems/yard-sorbet@0.8.0.rbi +441 -0
- data/sorbet/rbi/gems/yard@0.9.28.rbi +17802 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +4 -0
- metadata +241 -4
- data/lib/clients/adapter.rb +0 -75
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b46304973466b46ffd135627aa9ed02e08d0165275e3d309d07fa7cdd4f043a
|
4
|
+
data.tar.gz: b1b7d77658c9ffb2ca0886b0ec4e056e843d5ff662223b64f7cd2a37d9b3b31d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86469cd585d95b63a7366a61081159a6e800aa3c4bb046adad5ad51cf0d5d3a9e7c9964c2f58d4c3e8af296a57cf61c986b26d378df215255a25f29b96aa9506
|
7
|
+
data.tar.gz: 45f94644040eb191fb0d44ec90e565de09fa8f00daa4387eea31dbfbcc5d55100db0cd480bde2ae67cadce4b4d7f7dc9b8b3a0a2c34f57e6ce1ddf0ef052b995
|
data/.rubocop.yml
ADDED
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.
|
5
|
-
faraday
|
4
|
+
parking_ticket (1.0.48)
|
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.
|
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
|
-
|
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
data/bin/console
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
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
|
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,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,108 +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
|
5
|
-
|
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
|
-
|
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
|
-
|
24
|
-
|
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(
|
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
|
-
|
35
|
-
|
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
|
-
|
40
|
-
{
|
71
|
+
ParkingTicket::Clients::Models::RateOption.new(
|
41
72
|
client_internal_id: rate_option['rateOptionId'],
|
42
73
|
name: rate_option['name'],
|
43
74
|
type: rate_option['type'],
|
44
|
-
accepted_time_units: mapped_time_units
|
45
|
-
|
46
|
-
}
|
75
|
+
accepted_time_units: mapped_time_units
|
76
|
+
)
|
47
77
|
end
|
48
78
|
end
|
49
79
|
|
50
|
-
|
51
|
-
|
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|
|
52
86
|
ticket.dig('vehicle', 'licensePlate') == license_plate && ticket['locationId'] == zipcode
|
53
87
|
end.map do |ticket|
|
54
|
-
|
88
|
+
ParkingTicket::Clients::Models::Ticket.new(
|
55
89
|
client_internal_id: ticket['parkingSessionId'],
|
56
90
|
starts_on: DateTime.parse(ticket['startTime']),
|
57
91
|
ends_on: DateTime.parse(ticket['expireTime']),
|
58
92
|
license_plate: ticket.dig('vehicle', 'licensePlate'),
|
59
93
|
cost: ticket.dig('segments', 0, 'cost'),
|
60
94
|
client: 'PayByPhone'
|
61
|
-
|
95
|
+
)
|
62
96
|
end.first
|
63
97
|
end
|
64
98
|
|
65
|
-
|
66
|
-
|
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
|
67
112
|
|
68
|
-
|
69
|
-
|
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)
|
70
121
|
|
71
|
-
|
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(
|
72
144
|
license_plate: license_plate,
|
73
145
|
zipcode: zipcode,
|
74
146
|
rate_option_client_internal_id: rate_option_client_internal_id,
|
75
147
|
quantity: quantity,
|
76
148
|
time_unit: mapped_time_unit,
|
77
|
-
quote_client_internal_id: quote
|
78
|
-
starts_on: quote
|
149
|
+
quote_client_internal_id: quote.client_internal_id,
|
150
|
+
starts_on: quote.starts_on.to_s,
|
79
151
|
payment_method_id: payment_method_id
|
80
152
|
)
|
81
153
|
end
|
82
154
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
client_internal_id: payment_method['id'],
|
87
|
-
anonymised_card_number: payment_method['maskedCardNumber'][-4..],
|
88
|
-
payment_card_type: PAYMENT_CARD_TYPE_MAPPER[payment_method['paymentCardType']]
|
89
|
-
}
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def fetch_and_map_quote(rate_option_id, zipcode, license_plate, quantity, time_unit)
|
94
|
-
mapped_time_unit = ACCEPTED_TIME_UNIT_MAPPER.key(time_unit)
|
95
|
-
fetched_quote = client.quote(rate_option_id, zipcode, license_plate, quantity, mapped_time_unit)
|
96
|
-
|
97
|
-
{
|
98
|
-
client_internal_id: fetched_quote['quoteId'],
|
99
|
-
starts_on: fetched_quote['parkingStartTime'],
|
100
|
-
ends_on: fetched_quote['parkingExpiryTime'],
|
101
|
-
cost: fetched_quote.dig('totalCost', 'amount')
|
102
|
-
}
|
155
|
+
sig { void }
|
156
|
+
def raise_invalid_credentials!
|
157
|
+
raise Error, 'Adapter credentials are not valid'
|
103
158
|
end
|
104
159
|
end
|
105
160
|
end
|
106
161
|
end
|
107
162
|
end
|
108
|
-
|