vng 3.0.0 → 3.1.0

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: 3ce0b4bfa1bc71ea60e74d3ded65c3a610a5a9bd02d867fab27d0e59c7272a24
4
- data.tar.gz: 85345a62558558d22899adcdf1f052d42ef19b61d160dc0d49a87604f1292695
3
+ metadata.gz: 44bfc4eff4a138fc21a6058eb634d08e8be4bca032b43807c15fea355dfa5fe1
4
+ data.tar.gz: 414e83652f42d05171fc1413c17d9a817ab02bcd49d340164338e682b886d028
5
5
  SHA512:
6
- metadata.gz: a1d3770ed3fe0ef347ec57deb447af38ac3b93885fee6f20e557a61c7ea788001dd1d01485b4c95b9232ca7ae3e74397aaf382b77a21fb05304a33c20c6dd34a
7
- data.tar.gz: 53d11a0458c95f71a557531821141ec120b58dafe266952a06149fac84e348c0cd1e0a80d86298dfb242a20bfeb69010f8fad53f9e026fc7cb6418c123bd7666
6
+ metadata.gz: c64946b9ea2609929eb2b89b241dc93fa221df17c081e3548357eb94187d3d58215c59a6522a27d248c53c9009c5df7ec2fe64047b53367748be71988e653d60
7
+ data.tar.gz: 917f9edb608a9488bd95896fad8e11803494f5598236f8271abc08853159b5a6821c328d99c4db5c9f5fcb138fb4632c99fa5349569e87355edc2a09f013d45f
data/CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
- ## [3.0.0] - 2024-12-26
1
+ ## [3.1.0] - 2025-01-11
2
+
3
+ - Add Client.find(id)
4
+
5
+ ## [3.0.1] - 2025-01-10
6
+
7
+ - Make Contact.edited_since lazy
8
+
9
+ ## [3.0.0] - 2025-01-09
2
10
 
3
11
  - Add Contact.edited_since(timestamp)
4
12
 
data/lib/vng/client.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'vng/availability'
2
+
3
+ module Vng
4
+ # Provides methods to interact with Vonigo clients.
5
+ class Client < Resource
6
+ PATH = '/api/v1/data/Clients/'
7
+
8
+ attr_reader :id, :email
9
+
10
+ def initialize(id:, email:)
11
+ @id = id
12
+ @email = email
13
+ end
14
+
15
+
16
+ def self.find(contact_id)
17
+ body = {
18
+ method: '1',
19
+ objectID: contact_id,
20
+ }
21
+
22
+ data = request path: PATH, body: body
23
+
24
+ email = value_for_field data, 238
25
+ new id: contact_id, email: email
26
+ end
27
+ end
28
+ end
data/lib/vng/contact.rb CHANGED
@@ -1,40 +1,65 @@
1
1
  require 'vng/resource'
2
2
 
3
+ require ENV['VNG_MOCK'] ? 'vng/mock_request' : 'vng/http_request'
4
+ require 'vng/relation'
5
+
3
6
  module Vng
4
7
  # Provides methods to interact with Vonigo contacts.
5
8
  class Contact < Resource
6
9
  PATH = '/api/v1/data/Contacts/'
7
10
 
8
- attr_reader :id, :first_name, :last_name, :email, :phone, :client_id, :edited_at
11
+ # @param [Hash<Symbol, String>] data the options to initialize a resource.
12
+ # @option data [String] :object_id The unique ID of a Vonigo resource.
13
+ # @option data [Array] :fields The fields of a Vonigo resource.
14
+ def initialize(data = {})
15
+ @data = data
16
+ end
9
17
 
10
- def initialize(id:, first_name:, last_name:, email:, phone:, client_id:, edited_at: nil)
11
- @id = id
12
- @first_name = first_name
13
- @last_name = last_name
14
- @email = email
15
- @phone = phone
16
- @client_id = client_id
17
- @edited_at = edited_at
18
+ # @return [String] the resource’s unique ID.
19
+ def id
20
+ @data['objectID']
18
21
  end
19
22
 
20
- def self.edited_since(timestamp)
21
- body = { isCompleteObject: 'true', dateStart: timestamp.to_i, dateMode: 2 }
23
+ def active?
24
+ @data['isActive'] != 'false'
25
+ end
26
+
27
+ def first_name
28
+ self.class.value_for_field @data, 127
29
+ end
30
+
31
+ def last_name
32
+ self.class.value_for_field @data, 128
33
+ end
34
+
35
+ def email
36
+ self.class.value_for_field @data, 97
37
+ end
22
38
 
23
- data = request path: PATH, body: body, returning: 'Contacts'
39
+ def phone
40
+ self.class.value_for_field @data, 96
41
+ end
24
42
 
25
- data.filter_map do |body|
26
- next unless body['isActive']
43
+ def client_id
44
+ self.class.value_for_relation @data, 'client'
45
+ end
27
46
 
28
- id = body['objectID']
29
- first_name = value_for_field body, 127
30
- last_name = value_for_field body, 128
31
- email = value_for_field body, 97
32
- phone = value_for_field body, 96
33
- client_id = value_for_relation body, 'client'
34
- edited_at = Time.at Integer(body['dateLastEdited']), in: 'UTC'
47
+ def edited_at
48
+ Time.at Integer(@data['dateLastEdited']), in: 'UTC'
49
+ end
35
50
 
36
- new id: id, first_name: first_name, last_name: last_name, email: email, phone: phone, client_id: client_id, edited_at: edited_at
37
- end
51
+ # @return [Vng::Relation] the resources matching the conditions.
52
+ def self.where(conditions = {})
53
+ @where ||= Relation.new
54
+ @where.where conditions
55
+ end
56
+
57
+ def self.edited_since(timestamp)
58
+ contacts = where isCompleteObject: 'true', dateStart: timestamp.to_i, dateMode: 2
59
+ # TODO: select should accept sub-hash, e.g.
60
+ # .select :date_last_edited, fields: [134, 1036], relations: ['client']
61
+ contacts = contacts.select 'dateLastEdited', 'Fields', 'Relations'
62
+ contacts.lazy.filter(&:active?)
38
63
  end
39
64
 
40
65
  def self.create(first_name:, last_name:, email:, phone:, client_id:)
@@ -50,14 +75,7 @@ module Vng
50
75
  }
51
76
 
52
77
  data = request path: PATH, body: body
53
-
54
- id = data['Contact']['objectID']
55
- first_name = value_for_field data, 127
56
- last_name = value_for_field data, 128
57
- email = value_for_field data, 97
58
- phone = value_for_field data, 96
59
-
60
- new id: id, first_name: first_name, last_name: last_name, email: email, phone: phone, client_id: client_id
78
+ new data['Contact']
61
79
  end
62
80
  end
63
81
  end
@@ -130,7 +130,14 @@ module Vng
130
130
  {"fieldID"=>96, "fieldValue"=>"8648648640" },
131
131
  ], "Relations" => [
132
132
  {"objectID" => 915738, "relationType" => "client", "isActive" => "true"},
133
- ]}
133
+ ]},
134
+ {"objectID" => "2201008", "dateLastEdited" => "1736479081", "isActive" => "true", "Fields" => [
135
+ {"fieldID"=>127, "fieldValue"=>"No" },
136
+ {"fieldID"=>128, "fieldValue"=>"Email" },
137
+ {"fieldID"=>96, "fieldValue"=>"8648648640" },
138
+ ], "Relations" => [
139
+ {"objectID" => 916758, "relationType" => "client", "isActive" => "true"},
140
+ ]},
134
141
  ]}
135
142
  elsif @body[:pageNo].nil?
136
143
  { "Contact"=>{ "objectID"=>"2201007" }, "Fields"=> [
@@ -144,6 +151,10 @@ module Vng
144
151
  end
145
152
  when '/api/v1/data/Locations/'
146
153
  { "Location"=>{ "objectID"=>995681 } }
154
+ when '/api/v1/data/Clients/'
155
+ { "Client" => { "objectID" => "916758" }, "Fields" => [
156
+ { "fieldID" => 238, "fieldValue" => "vng@example.com", "optionID" => 0 }
157
+ ] }
147
158
  when '/api/v1/data/Assets/'
148
159
  if @body[:method].eql? '3'
149
160
  if @body[:Fields].find{|field| field[:fieldID] == 1014}[:optionID].eql? 304
@@ -0,0 +1,89 @@
1
+ module Vng
2
+ # Provides methods to iterate through collections of Vonigo resources.
3
+ # @private
4
+ class Relation
5
+ include Enumerable
6
+
7
+ # @yield [Hash] the options to change which items to iterate through.
8
+ def initialize(options = {}, &item_block)
9
+ @options = {parts: ['objectID', 'isActive'], next_page: 1}
10
+ @options.merge! options
11
+ @item_block = item_block
12
+ end
13
+
14
+ # Specifies which items to fetch when hitting the data API.
15
+ # @param [Hash<Symbol, String>] conditions The conditions for the items.
16
+ # @return [Vng::Relation] itself.
17
+ def where(conditions = {})
18
+ if @options[:conditions] != conditions
19
+ @items = []
20
+ @options.merge! conditions: conditions
21
+ end
22
+ self
23
+ end
24
+
25
+ # Specifies which parts of the resource to fetch when hitting the data API.
26
+ # @param [Array<Symbol>] parts The parts to fetch.
27
+ # @return [Vng::Relation] itself.
28
+ def select(*parts)
29
+ if @options[:parts] != parts + ['objectID', 'isActive']
30
+ @items = nil
31
+ @options.merge! parts: (parts + ['objectID', 'isActive'])
32
+ end
33
+ self
34
+ end
35
+
36
+ def each
37
+ @last_index = 0
38
+ while next_item = find_next
39
+ yield next_item
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def request(path:, body: {}, query: {}, include_security_token: true)
46
+ if query.none? && include_security_token
47
+ body = body.merge securityToken: Vng.configuration.security_token
48
+ end
49
+
50
+ response_for path:, body:, query:
51
+ end
52
+
53
+ def response_for(path:, body: {}, query: {})
54
+ instrument do |data|
55
+ Request.new(host: Vng.configuration.host, path: path, query: query, body: body).run
56
+ end
57
+ end
58
+
59
+ def find_next
60
+ @items ||= []
61
+ if @items[@last_index].nil? && more_pages?
62
+ body = @options[:conditions].merge pageSize: 500, pageNo: @options[:next_page], sortMode: 3, sortDirection: 0
63
+
64
+ response_body = request path: '/api/v1/data/Contacts/', body: body
65
+
66
+ more_items = response_body['Contacts'].map do |contact_data|
67
+ Vng::Contact.new contact_data.slice(*@options[:parts])
68
+ end
69
+ @options.merge! next_page: (more_items.size == 500 ? @options[:next_page] + 1 : 1)
70
+ @items.concat more_items
71
+ end
72
+ @items[(@last_index +=1) -1]
73
+ end
74
+
75
+ def more_pages?
76
+ @last_index.zero? || @options[:next_page] > 1
77
+ end
78
+
79
+ # Provides instrumentation to ActiveSupport listeners
80
+ def instrument(&block)
81
+ data = { class_name: 'Vng::Contact' }
82
+ if defined?(ActiveSupport::Notifications)
83
+ ActiveSupport::Notifications.instrument 'Vng.request', data, &block
84
+ else
85
+ block.call data
86
+ end
87
+ end
88
+ end
89
+ end
data/lib/vng/resource.rb CHANGED
@@ -29,7 +29,7 @@ module Vng
29
29
  end
30
30
 
31
31
  def self.response_for(path:, body: {}, query: {})
32
- instrument do |data|
32
+ instrument do
33
33
  Request.new(host: host, path: path, query: query, body: body).run
34
34
  end
35
35
  end
@@ -55,10 +55,10 @@ module Vng
55
55
  # Provides instrumentation to ActiveSupport listeners
56
56
  def self.instrument(&block)
57
57
  data = { class_name: name }
58
- if defined?(ActiveSupport::Notifications)
58
+ if defined? ActiveSupport::Notifications
59
59
  ActiveSupport::Notifications.instrument 'Vng.request', data, &block
60
60
  else
61
- block.call data
61
+ block.call
62
62
  end
63
63
  end
64
64
  end
data/lib/vng/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Vng
2
- VERSION = '3.0.0'
2
+ VERSION = '3.1.0'
3
3
  end
data/lib/vng.rb CHANGED
@@ -10,6 +10,7 @@ require_relative 'vng/availability'
10
10
  require_relative 'vng/breed'
11
11
  require_relative 'vng/case'
12
12
  require_relative 'vng/connection_error'
13
+ require_relative 'vng/client'
13
14
  require_relative 'vng/contact'
14
15
  require_relative 'vng/franchise'
15
16
  require_relative 'vng/lead'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vng
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - claudiob
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-01-10 00:00:00.000000000 Z
10
+ date: 2025-01-11 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: simplecov
@@ -69,6 +69,7 @@ files:
69
69
  - lib/vng/availability.rb
70
70
  - lib/vng/breed.rb
71
71
  - lib/vng/case.rb
72
+ - lib/vng/client.rb
72
73
  - lib/vng/config.rb
73
74
  - lib/vng/configuration.rb
74
75
  - lib/vng/connection_error.rb
@@ -83,6 +84,7 @@ files:
83
84
  - lib/vng/price_block.rb
84
85
  - lib/vng/price_item.rb
85
86
  - lib/vng/price_list.rb
87
+ - lib/vng/relation.rb
86
88
  - lib/vng/resource.rb
87
89
  - lib/vng/route.rb
88
90
  - lib/vng/security_token.rb