vng 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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