vng 0.1.13 → 0.1.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cff4f73336138d9e2386b1273fd4e398c8d3e8e9c52fb60ba4f47fb7b98e3bf
4
- data.tar.gz: 6dbfa0fdad71e5fe35b113071e451a27e0150cde5ccffc7bc0676f191d433486
3
+ metadata.gz: de1ec03096db648933db7f9886eaa72b6c4af73e614e475bc0ad26126f35015e
4
+ data.tar.gz: 0adb9f129d030b78ec726f6a2a1cedd61ebc37c88a88df524aca23ff4d2583ca
5
5
  SHA512:
6
- metadata.gz: d76586e4271dc06bfe12ab3784f9534373f82e1953084c012ca79522ffbad4744486f55f66076b735bcafe7bddddc1465ef624f2af001aa0c183106a4403f0c4
7
- data.tar.gz: 5bb9df92265cf90e2e10a88efc2e5cbd4de6d0b4e80e38dc2faf597780ea9b759e951fe331ae453db38253df4c93a58bd04d8a6c299318f475a5c04f6b5d08c1
6
+ metadata.gz: ce83ddaea6c34121333fdaf15b5600b2486e51c2803b82a71826ca464b7c18f79f1c5d39e0837a0483ecda73512abae325fda7aea0b6ec7b4f8fac3ebcc201c4
7
+ data.tar.gz: 7efd6a2bc16eae79b5ecde44d85ec4ce4de4366a9c735bebc99350d1c743ccc4a6320d47a834e84a92205524761222d07e43a02b06878ff413ca5ff8219e7962
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.14] - 2024-11-17
4
+
5
+ - Adds Vng::Error
6
+
3
7
  ## [0.1.13] - 2024-11-15
4
8
 
5
9
  - Enable Vng.configuration.security_token
data/README.md CHANGED
@@ -5,8 +5,11 @@ Vng helps you write apps that need to interact with Vonigo.
5
5
 
6
6
  The **source code** is available on [GitHub](https://github.com/HouseAccountEng/vng) and the **documentation** on [RubyDoc](http://www.rubydoc.info/gems/vng/frames).
7
7
 
8
+ [![Code Climate](https://codeclimate.com/github/HouseAccountEng/vng.png)](https://codeclimate.com/github/HouseAccountEng/vng)
9
+
8
10
  After [registering your app](#configuring-your-app), you can run commands like:
9
11
 
12
+
10
13
  ```ruby
11
14
  Vng::Zip.all
12
15
  Vng::Franchise.all
@@ -42,15 +45,6 @@ indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
42
45
  guarantees that your project won’t occur in any error when you `bundle update`
43
46
  and a new version of Vng is released.
44
47
 
45
- Available resources
46
- ===================
47
-
48
- Vng::Zip
49
- -------
50
-
51
- TODO
52
-
53
-
54
48
  Configuring your app
55
49
  ====================
56
50
 
@@ -95,8 +89,8 @@ How to release new versions
95
89
 
96
90
  If you are a manager of this project, remember to upgrade the [Vng gem](http://rubygems.org/gems/vng)
97
91
  whenever a new feature is added or a bug gets fixed.
98
- Make sure all the tests are passing ,
99
- document the changes in CHANGELOG.md and README.md, bump the version, then run
92
+ Make sure all the tests are passing and the code is 100% test-covered.
93
+ Document the changes in CHANGELOG.md and README.md, bump the version, then run:
100
94
 
101
95
  rake release
102
96
 
data/lib/vng/asset.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo assets.
3
- class Asset
5
+ class Asset < Resource
6
+ PATH = '/api/v1/data/Assets/'
7
+
4
8
  attr_reader :id
5
9
 
6
10
  def initialize(id:)
@@ -9,7 +13,6 @@ module Vng
9
13
 
10
14
  def self.create(name:, weight:, breed_option_id:, client_id:)
11
15
  body = {
12
- securityToken: Vng.configuration.security_token,
13
16
  method: '3',
14
17
  clientID: client_id,
15
18
  Fields: [
@@ -19,15 +22,7 @@ module Vng
19
22
  ]
20
23
  }
21
24
 
22
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Assets/'
23
-
24
- request = Net::HTTP::Post.new(uri.request_uri)
25
- request.initialize_http_header 'Content-Type' => 'application/json'
26
- request.body = body.to_json
27
-
28
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
29
- http.request request
30
- end
25
+ data = request path: PATH, body: body
31
26
 
32
27
  # curl = 'curl'.tap do |curl|
33
28
  # curl << ' -X POST'
@@ -37,25 +32,16 @@ module Vng
37
32
  # end
38
33
  # puts curl
39
34
 
40
- new id: JSON(response.body)['Asset']['objectID']
35
+ new id: data['Asset']['objectID']
41
36
  end
42
37
 
43
38
  def destroy
44
39
  body = {
45
- securityToken: Vng.configuration.security_token,
46
40
  method: '4',
47
41
  objectID: id,
48
42
  }
49
43
 
50
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Assets/'
51
-
52
- request = Net::HTTP::Post.new(uri.request_uri)
53
- request.initialize_http_header 'Content-Type' => 'application/json'
54
- request.body = body.to_json
55
-
56
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
57
- http.request request
58
- end
44
+ data = self.class.request path: PATH, body: body
59
45
  end
60
46
  end
61
47
  end
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo availabilities.
3
- class Availability
5
+ class Availability < Resource
6
+ PATH = '/api/v1/resources/availability/'
7
+
4
8
  attr_reader :route_id, :date, :minutes
5
9
 
6
10
  def initialize(route_id:, date:, minutes:)
@@ -11,29 +15,20 @@ module Vng
11
15
 
12
16
  def self.where(location_id:, duration:, from_time:, to_time:)
13
17
  body = {
14
- securityToken: Vng.configuration.security_token,
15
18
  method: '0',
16
19
  serviceTypeID: '14', # only return items of serviceType 'Pet Grooming'
17
20
  locationID: location_id,
18
- duration: duration.to_i,
21
+ duration: [duration.to_i, 30].max, # or 'duration is not provided'
19
22
  dateStart: from_time.to_i,
20
23
  dateEnd: to_time.to_i,
21
24
  }
22
25
 
23
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/resources/availability/'
24
-
25
- request = Net::HTTP::Post.new(uri.request_uri)
26
- request.initialize_http_header 'Content-Type' => 'application/json'
27
- request.body = body.to_json
28
-
29
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
30
- http.request request
31
- end
26
+ data = request path: PATH, body: body
32
27
 
33
- JSON(response.body)['Availability'].map do |body|
34
- route_id = body['routeID']
35
- date = Date.strptime body['dayID'], '%Y%m%d'
36
- minutes = body['startTime'].to_i
28
+ data['Availability'].map do |availability|
29
+ route_id = availability['routeID']
30
+ date = Date.strptime availability['dayID'], '%Y%m%d'
31
+ minutes = availability['startTime'].to_i
37
32
 
38
33
  new route_id: route_id, date: date, minutes: minutes
39
34
  end
data/lib/vng/breed.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo breeds.
3
- class Breed
5
+ class Breed < Resource
6
+ PATH = '/api/v1/resources/breeds/'
7
+
4
8
  attr_reader :id, :name, :species, :option_id, :low_weight, :high_weight
5
9
 
6
10
  def initialize(id:, name:, species:, option_id:, low_weight:, high_weight:)
@@ -14,27 +18,15 @@ module Vng
14
18
 
15
19
  # TODO: Needs pagination
16
20
  def self.all
17
- body = {
18
- securityToken: Vng.configuration.security_token,
19
- }
20
-
21
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/resources/breeds/'
22
-
23
- request = Net::HTTP::Post.new(uri.request_uri)
24
- request.initialize_http_header 'Content-Type' => 'application/json'
25
- request.body = body.to_json
26
-
27
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
28
- http.request request
29
- end
21
+ data = request path: PATH
30
22
 
31
- JSON(response.body)['Breeds'].map do |body|
32
- id = body['breedID']
33
- name = body['breed']
34
- species = body['species']
35
- option_id = body['optionID']
36
- low_weight = body['breedLowWeight']
37
- high_weight = body['breedHighWeight']
23
+ data['Breeds'].map do |breed|
24
+ id = breed['breedID']
25
+ name = breed['breed']
26
+ species = breed['species']
27
+ option_id = breed['optionID']
28
+ low_weight = breed['breedLowWeight']
29
+ high_weight = breed['breedHighWeight']
38
30
 
39
31
  new id: id, name: name, species: species, option_id: option_id, low_weight: low_weight, high_weight: high_weight
40
32
  end
data/lib/vng/case.rb CHANGED
@@ -1,53 +1,44 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo cases.
3
- class Case
5
+ class Case < Resource
6
+ PATH = '/api/v1/data/Cases/'
7
+
4
8
  attr_reader :id
5
9
 
6
10
  def initialize(id:)
7
11
  @id = id
8
12
  end
9
13
 
10
- def self.create(client_id:, summary:, comments:)
14
+ def self.create(client_id:, summary:, comments:, phone:, email:, zip:)
11
15
  body = {
12
- securityToken: Vng.configuration.security_token,
13
16
  method: '3',
14
- objectID: client_id,
17
+ clientID: client_id,
15
18
  Fields: [
16
19
  {fieldID: 219, optionID: 239}, # Status: open
17
- {fieldID: 220, fieldValue: summary},
18
- {fieldID: 230, fieldValue: comments},
20
+ {fieldID: 220, fieldValue: summary}, # Summary:
21
+ {fieldID: 230, fieldValue: comments}, # Comments:
22
+ {fieldID: 226, optionID: 227}, # Type: 'General request'
23
+ {fieldID: 227, optionID: 232}, # Preferred Contact Method: 'Phone'
24
+ {fieldID: 228, fieldValue: phone}, # Phone Me Back at:
25
+ {fieldID: 229, fieldValue: email}, # Email:
26
+ {fieldID: 1023, fieldValue: zip}, # Zip Code:
19
27
  ]
20
28
  }
21
29
 
22
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Cases/'
23
-
24
- request = Net::HTTP::Post.new(uri.request_uri)
25
- request.initialize_http_header 'Content-Type' => 'application/json'
26
- request.body = body.to_json
30
+ data = request path: PATH, body: body
27
31
 
28
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
29
- http.request request
30
- end
31
-
32
- new id: JSON(response.body)['Case']['objectID']
32
+ new id: data['Case']['objectID']
33
33
  end
34
34
 
35
35
  def destroy
36
36
  body = {
37
- securityToken: Vng.configuration.security_token,
38
37
  method: '4',
39
38
  objectID: id,
40
39
  }
41
40
 
42
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Cases/'
43
-
44
- request = Net::HTTP::Post.new(uri.request_uri)
45
- request.initialize_http_header 'Content-Type' => 'application/json'
46
- request.body = body.to_json
47
-
48
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
49
- http.request request
50
- end
41
+ self.class.request path: PATH, body: body
51
42
  end
52
43
  end
53
44
  end
@@ -0,0 +1,5 @@
1
+ module Vng
2
+ # A wrapper around StandardError.
3
+ class ConnectionError < StandardError
4
+ end
5
+ end
data/lib/vng/contact.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo contacts.
3
- class Contact
5
+ class Contact < Resource
6
+ PATH = '/api/v1/data/Contacts/'
7
+
4
8
  attr_reader :id, :first_name, :last_name, :email, :phone
5
9
 
6
10
  def initialize(id:, first_name:, last_name:, email:, phone:)
@@ -13,7 +17,6 @@ module Vng
13
17
 
14
18
  def self.create(first_name:, last_name:, email:, phone:, client_id:)
15
19
  body = {
16
- securityToken: Vng.configuration.security_token,
17
20
  method: '3',
18
21
  clientID: client_id,
19
22
  Fields: [
@@ -24,44 +27,26 @@ module Vng
24
27
  ]
25
28
  }
26
29
 
27
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Contacts/'
28
-
29
- request = Net::HTTP::Post.new(uri.request_uri)
30
- request.initialize_http_header 'Content-Type' => 'application/json'
31
- request.body = body.to_json
30
+ data = request path: PATH, body: body
32
31
 
33
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
34
- http.request request
35
- end
36
-
37
- body = JSON response.body
38
-
39
- id = body['Contact']['objectID']
40
- first_name = body['Fields'].find{|field| field['fieldID'] == 127}['fieldValue']
41
- last_name = body['Fields'].find{|field| field['fieldID'] == 128}['fieldValue']
42
- email = body['Fields'].find{|field| field['fieldID'] == 97}['fieldValue']
43
- phone = body['Fields'].find{|field| field['fieldID'] == 96}['fieldValue']
32
+ id = data['Contact']['objectID']
33
+ first_name = data['Fields'].find{|field| field['fieldID'] == 127}['fieldValue']
34
+ last_name = data['Fields'].find{|field| field['fieldID'] == 128}['fieldValue']
35
+ email = data['Fields'].find{|field| field['fieldID'] == 97}['fieldValue']
36
+ phone = data['Fields'].find{|field| field['fieldID'] == 96}['fieldValue']
44
37
 
45
38
  new id: id, first_name: first_name, last_name: last_name, email: email, phone: phone
46
39
  end
47
40
 
48
- def destroy
49
- body = {
50
- securityToken: Vng.configuration.security_token,
51
- method: '4',
52
- objectID: id,
53
- }
54
-
55
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Contacts/'
56
-
57
- request = Net::HTTP::Post.new(uri.request_uri)
58
- request.initialize_http_header 'Content-Type' => 'application/json'
59
- request.body = body.to_json
60
-
61
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
62
- http.request request
63
- end
64
- end
41
+ # Data validation failed. [{"fieldID"=>0, "fieldName"=>nil, "errNo"=>-1408, "errMsg"=>"Primary contact cannot be deleted."}]
42
+ # def destroy
43
+ # body = {
44
+ # method: '4',
45
+ # objectID: id,
46
+ # }
47
+ #
48
+ # self.class.request path: PATH, body: body
49
+ # end
65
50
  end
66
51
  end
67
52
 
data/lib/vng/error.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Vng
2
+ # A wrapper around StandardError.
3
+ class Error < StandardError
4
+ end
5
+ end
data/lib/vng/franchise.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'vng/availability'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo franchises.
3
- class Franchise
5
+ class Franchise < Resource
6
+ PATH = '/api/v1/resources/franchises/'
7
+
4
8
  attr_reader :id, :name, :gmt_offset
5
9
 
6
10
  def initialize(id:, name: nil, gmt_offset: nil)
@@ -12,46 +16,25 @@ module Vng
12
16
 
13
17
  def self.find_by(zip:)
14
18
  body = {
15
- securityToken: Vng.configuration.security_token,
16
19
  method: '1',
17
20
  zip: zip,
18
21
  }
19
22
 
20
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/resources/availability/'
21
-
22
- request = Net::HTTP::Post.new(uri.request_uri)
23
- request.initialize_http_header 'Content-Type' => 'application/json'
24
- request.body = body.to_json
23
+ data = request path: Vng::Availability::PATH, body: body
25
24
 
26
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
27
- http.request request
28
- end
29
-
30
- franchise_id = JSON(response.body)['Ids']['franchiseID']
25
+ franchise_id = data['Ids']['franchiseID']
31
26
  new(id: franchise_id) unless franchise_id == '0'
32
27
  end
33
28
 
34
29
  def self.all
35
- body = {
36
- securityToken: Vng.configuration.security_token,
37
- }
38
-
39
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/resources/franchises/'
40
-
41
- request = Net::HTTP::Post.new(uri.request_uri)
42
- request.initialize_http_header 'Content-Type' => 'application/json'
43
- request.body = body.to_json
44
-
45
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
46
- http.request request
47
- end
48
-
49
- JSON(response.body)['Franchises'].filter do |body|
50
- body['isActive']
51
- end.map do |body|
52
- id = body['franchiseID']
53
- name = body['franchiseName']
54
- gmt_offset = body['gmtOffsetFranchise']
30
+ data = request path: PATH
31
+
32
+ data['Franchises'].filter do |franchise|
33
+ franchise['isActive']
34
+ end.map do |franchise|
35
+ id = franchise['franchiseID']
36
+ name = franchise['franchiseName']
37
+ gmt_offset = franchise['gmtOffsetFranchise']
55
38
 
56
39
  new id: id, name: name, gmt_offset: gmt_offset
57
40
  end
data/lib/vng/lead.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo leads.
3
- class Lead
5
+ class Lead < Resource
6
+ PATH = '/api/v1/data/Leads/'
7
+
4
8
  attr_reader :id, :name, :email, :phone
5
9
 
6
10
  def initialize(id:, name:, email:, phone:)
@@ -12,7 +16,6 @@ module Vng
12
16
 
13
17
  def self.create(name:, email:, phone:)
14
18
  body = {
15
- securityToken: Vng.configuration.security_token,
16
19
  method: '3',
17
20
  Fields: [
18
21
  {fieldID: 121, optionID: '59'},
@@ -22,51 +25,25 @@ module Vng
22
25
  ]
23
26
  }
24
27
 
25
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Leads/'
26
-
27
- request = Net::HTTP::Post.new(uri.request_uri)
28
- request.initialize_http_header 'Content-Type' => 'application/json'
29
- request.body = body.to_json
30
-
31
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
32
- http.request request
33
- end
34
-
35
- body = JSON response.body
36
-
37
- if body['errNo']
38
- # 'errNo'=>-600,
39
- # 'errMsg'=>'Data validation failed.',
40
- # 'dateNow'=>'1731342482',
41
- # 'Errors'=>[{"fieldID"=>1024, "fieldName"=>"Phone # to Reach You", "errNo"=>-602, "errMsg"=>"Field data is in incorrect format."}]}
42
-
43
- # raise Vng::Error
44
- end
28
+ data = request path: PATH, body: body
45
29
 
46
- id = body['Client']['objectID']
47
- name = body['Fields'].find{|field| field['fieldID'] == 126}['fieldValue']
48
- email = body['Fields'].find{|field| field['fieldID'] == 238}['fieldValue']
49
- phone = body['Fields'].find{|field| field['fieldID'] == 1024}['fieldValue']
30
+ id = data['Client']['objectID']
31
+ name = data['Fields'].find{|field| field['fieldID'] == 126}['fieldValue']
32
+ email = data['Fields'].find{|field| field['fieldID'] == 238}['fieldValue']
33
+ phone = data['Fields'].find{|field| field['fieldID'] == 1024}['fieldValue']
50
34
 
51
35
  new id: id, name: name, email: email, phone: phone
52
36
  end
53
37
 
54
- def destroy
55
- body = {
56
- securityToken: Vng.configuration.security_token,
57
- method: '4',
58
- objectID: id,
59
- }
60
-
61
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Leads/'
62
-
63
- request = Net::HTTP::Post.new(uri.request_uri)
64
- request.initialize_http_header 'Content-Type' => 'application/json'
65
- request.body = body.to_json
66
-
67
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
68
- http.request request
69
- end
70
- end
38
+ # Data validation failed. [{"fieldID"=>0, "fieldName"=>nil, "errNo"=>-1201, "errMsg"=>"Lead ID does not exist."}]
39
+ # TODO: has become an account meanwhile!! so this doesn't work
40
+ # def destroy
41
+ # body = {
42
+ # method: '4',
43
+ # objectID: id,
44
+ # }
45
+ #
46
+ # self.class.request path: PATH, body: body
47
+ # end
71
48
  end
72
49
  end
data/lib/vng/location.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo locations.
3
- class Location
5
+ class Location < Resource
6
+ PATH = '/api/v1/data/Locations/'
7
+
4
8
  # TODO: fetch from /system/objects/ method: 1, objectID: 20
5
9
  STATES_OPTION_ID = {
6
10
  AK: 9879, AL: 9878, AR: 9877, AZ: 9880, CA: 9883, CO: 9876, CT: 9875,
@@ -21,7 +25,6 @@ module Vng
21
25
 
22
26
  def self.create(address:, city:, zip:, state:, client_id:)
23
27
  body = {
24
- securityToken: Vng.configuration.security_token,
25
28
  method: '3',
26
29
  clientID: client_id,
27
30
  Fields: [
@@ -33,36 +36,20 @@ module Vng
33
36
  ]
34
37
  }
35
38
 
36
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Locations/'
37
-
38
- request = Net::HTTP::Post.new(uri.request_uri)
39
- request.initialize_http_header 'Content-Type' => 'application/json'
40
- request.body = body.to_json
39
+ data = request path: PATH, body: body
41
40
 
42
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
43
- http.request request
44
- end
45
-
46
- new id: JSON(response.body)['Location']['objectID']
41
+ new id: data['Location']['objectID']
47
42
  end
48
43
 
49
- def destroy
50
- body = {
51
- securityToken: Vng.configuration.security_token,
52
- method: '4',
53
- objectID: id,
54
- }
55
-
56
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/Locations/'
57
-
58
- request = Net::HTTP::Post.new(uri.request_uri)
59
- request.initialize_http_header 'Content-Type' => 'application/json'
60
- request.body = body.to_json
61
-
62
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
63
- http.request request
64
- end
65
- end
44
+ # Data validation failed. [{"fieldID"=>0, "fieldName"=>"", "errNo"=>-1809, "errMsg"=>"Primary location cannot be deleted."}]
45
+ # def destroy
46
+ # body = {
47
+ # method: '4',
48
+ # objectID: id,
49
+ # }
50
+ #
51
+ # self.class.request path: PATH, body: body
52
+ # end
66
53
  end
67
54
  end
68
55
 
data/lib/vng/lock.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'vng/availability'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo locks.
3
- class Lock
5
+ class Lock < Resource
6
+ PATH = '/api/v1/resources/availability/'
7
+
4
8
  attr_reader :id
5
9
 
6
10
  def initialize(id:)
@@ -9,7 +13,6 @@ module Vng
9
13
 
10
14
  def self.create(duration:, location_id:, date:, minutes:, route_id:)
11
15
  body = {
12
- securityToken: Vng.configuration.security_token,
13
16
  method: '2',
14
17
  serviceTypeID: '14', # only create items of serviceType 'Pet Grooming'
15
18
  duration: duration.to_i,
@@ -19,36 +22,18 @@ module Vng
19
22
  startTime: minutes,
20
23
  }
21
24
 
22
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/resources/availability/'
23
-
24
- request = Net::HTTP::Post.new(uri.request_uri)
25
- request.initialize_http_header 'Content-Type' => 'application/json'
26
- request.body = body.to_json
25
+ data = request path: Vng::Availability::PATH, body: body
27
26
 
28
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
29
- http.request request
30
- end
31
-
32
- id = JSON(response.body)['Ids']['lockID']
33
- new id: id
27
+ new id: data['Ids']['lockID']
34
28
  end
35
29
 
36
- def destroy
37
- body = {
38
- securityToken: Vng.configuration.security_token,
39
- method: '4',
40
- objectID: id,
41
- }
42
-
43
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/resources/availability/'
44
-
45
- request = Net::HTTP::Post.new(uri.request_uri)
46
- request.initialize_http_header 'Content-Type' => 'application/json'
47
- request.body = body.to_json
48
-
49
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
50
- http.request request
51
- end
52
- end
30
+ # def destroy
31
+ # body = {
32
+ # method: '4',
33
+ # lockID: id,
34
+ # }
35
+ #
36
+ # self.class.request path: PATH, body: body
37
+ # end
53
38
  end
54
39
  end
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo price items.
3
- class PriceItem
5
+ class PriceItem < Resource
6
+ PATH = '/api/v1/data/priceLists/'
7
+
4
8
  attr_reader :id, :price_item, :value, :tax_id, :duration_per_unit, :service_badge, :service_category
5
9
 
6
10
  def initialize(id:, price_item:, value:, tax_id:, duration_per_unit:, service_badge:, service_category:)
@@ -15,25 +19,15 @@ module Vng
15
19
 
16
20
  def self.where(location_id:, asset_id:)
17
21
  body = {
18
- securityToken: Vng.configuration.security_token,
19
22
  method: '2',
20
23
  serviceTypeID: '14', # only return items of serviceType 'Pet Grooming'
21
24
  locationID: location_id,
22
25
  assetID: asset_id,
23
26
  }
24
27
 
25
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/priceLists/'
26
-
27
- request = Net::HTTP::Post.new(uri.request_uri)
28
- request.initialize_http_header 'Content-Type' => 'application/json'
29
- request.body = body.to_json
30
-
31
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
32
- http.request request
33
- end
28
+ data = request path: PATH, body: body
34
29
 
35
- JSON(response.body)['PriceItems'].filter do |body|
36
- # TODO: body['serviceBadge'] != 'Not Offered'
30
+ data['PriceItems'].filter do |body|
37
31
  body['isOnline'] && body['isActive']
38
32
  end.map do |body|
39
33
  id = body['priceItemID']
@@ -0,0 +1,40 @@
1
+ require 'vng/connection_error'
2
+ require 'vng/error'
3
+
4
+ module Vng
5
+ # Provides an abstract class for every Vonigo resource.
6
+ class Resource
7
+ private
8
+ def self.request(path:, body: {}, query: {}, include_security_token: true)
9
+ uri = URI::HTTPS.build host: host, path: path
10
+ uri.query = URI.encode_www_form(query) if query.any?
11
+
12
+ method = query.any? ? Net::HTTP::Get : Net::HTTP::Post
13
+ request = method.new uri.request_uri
14
+ request.initialize_http_header 'Content-Type' => 'application/json'
15
+
16
+ if query.none?
17
+ body = body.merge(securityToken: security_token) if include_security_token
18
+ request.body = body.to_json
19
+ end
20
+
21
+ response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
22
+ http.request request
23
+ end
24
+
25
+ JSON(response.body).tap do |data|
26
+ raise Vng::Error, "#{data['errMsg']} #{data['Errors']}" unless data['errNo'].zero?
27
+ end
28
+ rescue Errno::ECONNREFUSED, SocketError => e
29
+ raise Vng::ConnectionError, e.message
30
+ end
31
+
32
+ def self.host
33
+ Vng.configuration.host
34
+ end
35
+
36
+ def self.security_token
37
+ Vng.configuration.security_token
38
+ end
39
+ end
40
+ end
@@ -1,51 +1,51 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo work security tokens.
3
- class SecurityToken
5
+ class SecurityToken < Resource
6
+ PATH = '/api/v1/security/login/'
7
+
4
8
  attr_reader :token
5
9
 
6
- def initialize(token:, host:)
10
+ def initialize(token:)
7
11
  @token = token
8
- @host = host
9
12
  end
10
13
 
11
- def self.create(host:, username:, password:)
14
+ def self.create
12
15
  body = {
13
16
  app_version: '1',
14
17
  company: 'Vonigo',
15
- host: host,
16
- password: Digest::MD5.hexdigest(password),
17
- username: username,
18
+ username: Vng.configuration.username,
19
+ password: Digest::MD5.hexdigest(Vng.configuration.password),
18
20
  }
19
21
 
20
- uri = URI::HTTPS.build host: host, path: '/api/v1/security/login/'
21
-
22
- request = Net::HTTP::Get.new(uri.request_uri)
23
- request.initialize_http_header 'Content-Type' => 'application/json; charset=utf-8'
24
- request.body = body.to_json
25
-
26
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
27
- http.request request
28
- end
29
-
30
- token = JSON(response.body)['securityToken']
22
+ data = request path: PATH, body: body, include_security_token: false
31
23
 
32
- new token: token, host: host
24
+ new token: data['securityToken']
33
25
  end
34
26
 
35
- def destroy
27
+ # TODO: Check if it's not the correct one already or catch
28
+ # Data validation failed. [{"fieldID"=>0, "fieldName"=>nil, "errNo"=>-5213, "errMsg"=>"Same franchise ID supplied."}]
29
+ def assign_to(franchise_id:)
36
30
  body = {
37
31
  securityToken: @token,
32
+ method: "2",
33
+ franchiseID: franchise_id,
38
34
  }
39
35
 
40
- uri = URI::HTTPS.build host: @host, path: '/api/v1/security/login/'
41
-
42
- request = Net::HTTP::Post.new(uri.request_uri)
43
- request.initialize_http_header 'Content-Type' => 'application/json'
44
- request.body = body.to_json
36
+ self.class.request path: '/api/v1/security/session/', body: body, include_security_token: false
37
+ rescue Vng::Error => e
38
+ # TODO: improve: ignore if the token was already assigned to the franchise
39
+ raise unless e.message.include? 'Same franchise ID supplied'
40
+ end
45
41
 
46
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
47
- http.request request
48
- end
42
+ def destroy
43
+ query = { securityToken: @token }
44
+ self.class.request path: '/api/v1/security/logout/', query: query
45
+ rescue Vng::Error => e
46
+ p "Vng:Error! #{e}"
47
+ # TODO: improve: ignore if the token was already destroyed
48
+ raise unless e.message.include?('Session expired') || e.message.include?('Session does not exist')
49
49
  end
50
50
  end
51
51
  end
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo service types.
3
- class ServiceType
5
+ class ServiceType < Resource
6
+ PATH = '/api/v1/resources/serviceTypes/'
7
+
4
8
  attr_reader :id, :type, :duration
5
9
 
6
10
  def initialize(id:, type:, duration:)
@@ -11,21 +15,9 @@ module Vng
11
15
 
12
16
  # TODO: Needs pagination
13
17
  def self.all
14
- body = {
15
- securityToken: Vng.configuration.security_token,
16
- }
17
-
18
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/resources/serviceTypes/'
19
-
20
- request = Net::HTTP::Post.new(uri.request_uri)
21
- request.initialize_http_header 'Content-Type' => 'application/json'
22
- request.body = body.to_json
18
+ data = request path: PATH
23
19
 
24
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
25
- http.request request
26
- end
27
-
28
- JSON(response.body)['ServiceTypes'].map do |body|
20
+ data['ServiceTypes'].map do |body|
29
21
  id = body['serviceTypeID']
30
22
  type = body['serviceType']
31
23
  duration = body['duration']
@@ -36,21 +28,12 @@ module Vng
36
28
 
37
29
  def self.where(zip:)
38
30
  body = {
39
- securityToken: Vng.configuration.security_token,
40
31
  zip: zip,
41
32
  }
42
33
 
43
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/resources/serviceTypes/'
44
-
45
- request = Net::HTTP::Post.new(uri.request_uri)
46
- request.initialize_http_header 'Content-Type' => 'application/json'
47
- request.body = body.to_json
48
-
49
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
50
- http.request request
51
- end
34
+ data = request path: PATH, body: body
52
35
 
53
- JSON(response.body)['ServiceTypes'].filter do |body|
36
+ data.fetch('ServiceTypes', []).filter do |body|
54
37
  body['isActive']
55
38
  end.map do |body|
56
39
  id = body['serviceTypeID']
data/lib/vng/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Vng
2
- VERSION = '0.1.13'
2
+ VERSION = '0.1.14'
3
3
  end
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo work orders.
3
- class WorkOrder
5
+ class WorkOrder < Resource
6
+ PATH = '/api/v1/data/WorkOrders/'
7
+
4
8
  attr_reader :id
5
9
 
6
10
  def initialize(id:)
@@ -8,20 +12,7 @@ module Vng
8
12
  end
9
13
 
10
14
  def self.create(lock_id:, client_id:, contact_id:, location_id:, duration:, summary:, line_items:)
11
- charges = line_items.map do |line_item|
12
- {
13
- priceItemID: line_item[:price_item_id],
14
- taxID: line_item[:tax_id],
15
- assetID: line_item[:asset_id],
16
- Fields: [
17
- {fieldID: 9289, fieldValue: line_item[:description]},
18
- {fieldID: 9287, fieldValue: line_item[:price]}
19
- ]
20
- }
21
- end
22
-
23
15
  body = {
24
- securityToken: Vng.configuration.security_token,
25
16
  method: '3',
26
17
  serviceTypeID: '14', # only return items of serviceType 'Pet Grooming'
27
18
  lockID: lock_id,
@@ -33,39 +24,47 @@ module Vng
33
24
  {fieldID: 186, fieldValue: duration.to_i},
34
25
  {fieldID: 201, optionID: '9537'} # label: Online Tentative
35
26
  ],
36
- Charges: charges
27
+ Charges: charges_for(line_items)
37
28
  }
38
29
 
39
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/WorkOrders/'
40
-
41
- request = Net::HTTP::Post.new(uri.request_uri)
42
- request.initialize_http_header 'Content-Type' => 'application/json'
43
- request.body = body.to_json
44
-
45
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
46
- http.request request
47
- end
30
+ data = request path: PATH, body: body
48
31
 
49
- id = JSON(response.body)['WorkOrder']['objectID']
50
- new id: id
32
+ new id: data['WorkOrder']['objectID']
51
33
  end
52
34
 
53
- def destroy
54
- body = {
55
- securityToken: Vng.configuration.security_token,
56
- method: '4',
57
- objectID: id,
58
- }
59
-
60
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/data/WorkOrders/'
35
+ # TODO: This moves to "archived". actual cancelation is different
36
+ # def destroy
37
+ # body = {
38
+ # method: '8',
39
+ # objectID: id,
40
+ # }
41
+ #
42
+ # data = self.class.request path: PATH, body: body
43
+ # end
61
44
 
62
- request = Net::HTTP::Post.new(uri.request_uri)
63
- request.initialize_http_header 'Content-Type' => 'application/json'
64
- request.body = body.to_json
45
+ private
65
46
 
66
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
67
- http.request request
47
+ def self.charges_for(line_items)
48
+ line_items.map do |line_item|
49
+ {
50
+ priceItemID: line_item[:price_item_id],
51
+ taxID: line_item[:tax_id],
52
+ assetID: line_item[:asset_id],
53
+ Fields: charge_fields_for(line_item)
54
+ }
68
55
  end
69
56
  end
57
+
58
+ def self.charge_fields_for(line_item)
59
+ [
60
+ {fieldID: 9289, fieldValue: line_item[:description]},
61
+ {fieldID: 9287, fieldValue: line_item[:price]}, # Unit price
62
+ {fieldID: 8673, fieldValue: line_item[:price]}, # Price item
63
+ {fieldID: 813, fieldValue: line_item[:price]}, # Price
64
+ {fieldID: 9286, fieldValue: line_item[:price]}, # Subtotal
65
+ {fieldID: 9283, fieldValue: line_item[:price]}, # Total
66
+ {fieldID: 9288, fieldValue: 1}, # Qty
67
+ ]
68
+ end
70
69
  end
71
70
  end
data/lib/vng/zip.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'vng/resource'
2
+
1
3
  module Vng
2
4
  # Provides methods to interact with Vonigo ZIP codes.
3
- class Zip
5
+ class Zip < Resource
6
+ PATH = '/api/v1/resources/zips/'
7
+
4
8
  attr_reader :zip, :state, :zone_name
5
9
 
6
10
  def initialize(zip:, state:, zone_name:)
@@ -11,21 +15,9 @@ module Vng
11
15
 
12
16
  # TODO: Needs pagination
13
17
  def self.all
14
- body = {
15
- securityToken: Vng.configuration.security_token,
16
- }
17
-
18
- uri = URI::HTTPS.build host: 'aussiepetmobileusatraining2.vonigo.com', path: '/api/v1/resources/zips/'
19
-
20
- request = Net::HTTP::Post.new(uri.request_uri)
21
- request.initialize_http_header 'Content-Type' => 'application/json'
22
- request.body = body.to_json
23
-
24
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
25
- http.request request
26
- end
18
+ data = request path: PATH
27
19
 
28
- JSON(response.body)['Zips'].map do |body|
20
+ data['Zips'].map do |body|
29
21
  zip = body['zip']
30
22
  state = body['state']
31
23
  zone_name = body['zoneName']
data/lib/vng.rb CHANGED
@@ -9,6 +9,7 @@ require_relative 'vng/availability'
9
9
  require_relative 'vng/breed'
10
10
  require_relative 'vng/case'
11
11
  require_relative 'vng/config'
12
+ require_relative 'vng/connection_error'
12
13
  require_relative 'vng/contact'
13
14
  require_relative 'vng/franchise'
14
15
  require_relative 'vng/lead'
@@ -20,8 +21,3 @@ require_relative 'vng/service_type'
20
21
  require_relative 'vng/version'
21
22
  require_relative 'vng/work_order'
22
23
  require_relative 'vng/zip'
23
-
24
- module Vng
25
- class Error < StandardError; end
26
- # Your code goes here...
27
- end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vng
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - claudiob
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-16 00:00:00.000000000 Z
11
+ date: 2024-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simplecov
@@ -43,12 +43,15 @@ files:
43
43
  - lib/vng/case.rb
44
44
  - lib/vng/config.rb
45
45
  - lib/vng/configuration.rb
46
+ - lib/vng/connection_error.rb
46
47
  - lib/vng/contact.rb
48
+ - lib/vng/error.rb
47
49
  - lib/vng/franchise.rb
48
50
  - lib/vng/lead.rb
49
51
  - lib/vng/location.rb
50
52
  - lib/vng/lock.rb
51
53
  - lib/vng/price_item.rb
54
+ - lib/vng/resource.rb
52
55
  - lib/vng/security_token.rb
53
56
  - lib/vng/service_type.rb
54
57
  - lib/vng/version.rb