dynamics_crm 0.8.0 → 0.9.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
  SHA1:
3
- metadata.gz: 98498eb29f5847c9e344859c2a728367d4e5227a
4
- data.tar.gz: a6621ceb97f27de1298c7afba4b99cfd6f5fa44b
3
+ metadata.gz: f9b5b7d4367ee302f2a1e925b08b24f946c5c778
4
+ data.tar.gz: 105acef89d7636ed35fefecbf5e775f1d81f42d6
5
5
  SHA512:
6
- metadata.gz: 1773ffbe9669459911e9c08bc44f241fa825ca14858f738084e7179cb5b46b965b8c01222c3c6c0b98651da0da0dbdd3f59d52c4cfe304197950e9473379b666
7
- data.tar.gz: 261c9ae185cfdd0151ff118a56f78bb873ca69ef866dfbee46b9bc4e85265292c1cd1d5dad7ef1b18c143668fb9798938bf90089d92cb4dae3bb37d7a071e4a9
6
+ metadata.gz: 21555819445cc0def2c009775539fa497f927d81f635d57aa1b0a3f40a38cd344ca1b81fcbfb930e758d08689455c9f16b8ed4c58c200bbbebbac636ebd5de98
7
+ data.tar.gz: a7f4ed37563e4eae82536c63e4770820621d91bc520b8bbbddf3381db3cac92303a99b20ba2c4ed4208e14f9a0e6dfcc781dbca5fd6d7da33bca97ac0b117366
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.9.0 (March 13, 2017)
2
+ * Adds Filters support to Query Criteria #60
3
+ * Improve GUID attribute regex.
4
+ * Fix logging for non-200 response codes.
5
+
1
6
  ## 0.8.0 (January 4, 2017)
2
7
  * Support ArrayOfEntity so one can create bound entities like ActivityParties on create #41
3
8
  * Add special case for nil value #43
data/README.md CHANGED
@@ -70,6 +70,32 @@ while result.MoreRecords
70
70
  end
71
71
  ```
72
72
 
73
+ ### retrieve_multiple using complex Filters
74
+
75
+ ```ruby
76
+ # Build QueryExpression
77
+ query = DynamicsCRM::XML::QueryExpression.new('account')
78
+ query.columns = %w(accountid name telephone1)
79
+ # Switch to Or criteria
80
+ query.criteria.filter_operator = 'Or'
81
+
82
+ filter1 = DynamicsCRM::XML::FilterExpression.new('And')
83
+ filter1.add_condition('name', 'Equal', 'Integration Specialists')
84
+ filter1.add_condition('telephone1', 'In', ['(317) 845-2212', '3178452212'])
85
+
86
+ filter2 = DynamicsCRM::XML::FilterExpression.new('And')
87
+ filter2.add_condition('name', 'Equal', 'Thematics Development Inc.')
88
+ filter2.add_condition('telephone1', 'Null')
89
+
90
+ # Add Filters to criteria
91
+ query.criteria.add_filter(filter1)
92
+ query.criteria.add_filter(filter2)
93
+
94
+
95
+ result = client.retrieve_multiple(query)
96
+ ```
97
+
98
+
73
99
  ### fetch (FetchXml)
74
100
 
75
101
  ```ruby
data/lib/dynamics_crm.rb CHANGED
@@ -8,6 +8,7 @@ require "dynamics_crm/xml/condition_expression"
8
8
  require "dynamics_crm/xml/column_set"
9
9
  require "dynamics_crm/xml/criteria"
10
10
  require "dynamics_crm/xml/query_expression"
11
+ require "dynamics_crm/xml/filter_expression"
11
12
  require "dynamics_crm/xml/fetch_expression"
12
13
  require "dynamics_crm/xml/entity"
13
14
  require "dynamics_crm/xml/entity_reference"
@@ -64,7 +64,6 @@ module DynamicsCRM
64
64
  #
65
65
  # Returns true on success or raises Fault
66
66
  def authenticate(username, password)
67
-
68
67
  @username = username
69
68
  @password = password
70
69
 
@@ -108,37 +107,34 @@ module DynamicsCRM
108
107
  end
109
108
  end
110
109
 
111
-
112
110
  true
113
111
  end
114
112
 
115
113
  # These are all the operations defined by the Dynamics WSDL.
116
114
  # Tag names are case-sensitive.
117
115
  def create(entity_name, attributes)
118
-
119
116
  entity = XML::Entity.new(entity_name)
120
117
  entity.attributes = XML::Attributes.new(attributes)
121
118
 
122
119
  xml_response = post(organization_endpoint, create_request(entity))
123
- return Response::CreateResult.new(xml_response)
120
+ Response::CreateResult.new(xml_response)
124
121
  end
125
122
 
126
123
  # http://crmtroubleshoot.blogspot.com.au/2013/07/dynamics-crm-2011-php-and-soap-calls.html
127
124
  def retrieve(entity_name, guid, columns=[])
128
-
129
125
  column_set = XML::ColumnSet.new(columns)
130
126
  request = retrieve_request(entity_name, guid, column_set)
131
127
 
132
128
  xml_response = post(organization_endpoint, request)
133
- return Response::RetrieveResult.new(xml_response)
129
+ Response::RetrieveResult.new(xml_response)
134
130
  end
135
131
 
136
132
  def rollup(target_entity, query, rollup_type="Related")
137
- self.execute("Rollup", {
138
- Target: target_entity,
139
- Query: query,
140
- RollupType: rollup_type
141
- })
133
+ self.execute("Rollup", {
134
+ Target: target_entity,
135
+ Query: query,
136
+ RollupType: rollup_type
137
+ })
142
138
  end
143
139
 
144
140
  # Suports parameter list or QueryExpression object.
@@ -172,14 +168,14 @@ module DynamicsCRM
172
168
 
173
169
  request = update_request(entity)
174
170
  xml_response = post(organization_endpoint, request)
175
- return Response::UpdateResponse.new(xml_response)
171
+ Response::UpdateResponse.new(xml_response)
176
172
  end
177
173
 
178
174
  def delete(entity_name, guid)
179
175
  request = delete_request(entity_name, guid)
180
176
 
181
177
  xml_response = post(organization_endpoint, request)
182
- return Response::DeleteResponse.new(xml_response)
178
+ Response::DeleteResponse.new(xml_response)
183
179
  end
184
180
 
185
181
  def execute(action, parameters={}, response_class=nil)
@@ -187,19 +183,19 @@ module DynamicsCRM
187
183
  xml_response = post(organization_endpoint, request)
188
184
 
189
185
  response_class ||= Response::ExecuteResult
190
- return response_class.new(xml_response)
186
+ response_class.new(xml_response)
191
187
  end
192
188
 
193
189
  def associate(entity_name, guid, relationship, related_entities)
194
190
  request = associate_request(entity_name, guid, relationship, related_entities)
195
191
  xml_response = post(organization_endpoint, request)
196
- return Response::AssociateResponse.new(xml_response)
192
+ Response::AssociateResponse.new(xml_response)
197
193
  end
198
194
 
199
195
  def disassociate(entity_name, guid, relationship, related_entities)
200
196
  request = disassociate_request(entity_name, guid, relationship, related_entities)
201
197
  xml_response = post(organization_endpoint, request)
202
- return Response::DisassociateResponse.new(xml_response)
198
+ Response::DisassociateResponse.new(xml_response)
203
199
  end
204
200
 
205
201
  def create_attachment(entity_name, entity_id, options={})
@@ -324,28 +320,23 @@ module DynamicsCRM
324
320
  end
325
321
 
326
322
  def post(url, request)
327
- log_xml("REQUEST", request)
323
+ log_xml('REQUEST', request)
328
324
  uri = URI.parse(url)
329
325
 
330
326
  http = Net::HTTP.new uri.host, uri.port
331
327
  http.use_ssl = true
332
328
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
333
329
 
334
- req = Net::HTTP::Post.new(uri.request_uri, {
335
- "Connection" => "Keep-Alive",
336
- "Content-type" => "application/soap+xml; charset=UTF-8",
337
- "Content-length" => request.bytesize.to_s
338
- })
330
+ req = Net::HTTP::Post.new(uri.request_uri,
331
+ 'Connection' => 'Keep-Alive',
332
+ 'Content-type' => 'application/soap+xml; charset=UTF-8',
333
+ 'Content-length' => request.bytesize.to_s
334
+ )
339
335
  req.body = request
340
336
  response = http.request(req)
341
337
 
342
- if response.code.to_i == 200
343
- response_body = response.body
344
- else
345
- # Do something here on error.
346
- end
347
-
348
- log_xml("RESPONSE", response_body)
338
+ response_body = response.body
339
+ log_xml('RESPONSE', response_body)
349
340
 
350
341
  response_body
351
342
  end
@@ -354,6 +345,7 @@ module DynamicsCRM
354
345
  return unless logger
355
346
 
356
347
  logger.debug(title)
348
+
357
349
  doc = REXML::Document.new(xml)
358
350
  formatter.write(doc.root, logger)
359
351
  logger.debug("\n")
@@ -1,13 +1,10 @@
1
1
  module DynamicsCRM
2
2
  module Response
3
-
4
3
  class Result < Hash
5
-
6
4
  attr_reader :document
7
5
  attr_reader :result_response
8
6
 
9
7
  def initialize(xml)
10
-
11
8
  @document = REXML::Document.new(xml)
12
9
 
13
10
  fault_xml = @document.get_elements("//[local-name() = 'Fault']")
@@ -24,7 +21,7 @@ module DynamicsCRM
24
21
 
25
22
  # Returns base element of the response document to parse.
26
23
  def response_element
27
- class_name = self.class.to_s.split("::").last
24
+ class_name = self.class.to_s.split('::').last
28
25
  end
29
26
 
30
27
  # Invoked by constructor, should be implemented in sub-classes.
@@ -35,7 +32,6 @@ module DynamicsCRM
35
32
 
36
33
  # Allows method-like access to the hash using camelcase field names.
37
34
  def method_missing(method, *args, &block)
38
-
39
35
  # First return local hash entry for symbol or string.
40
36
  return self[method] if self.has_key?(method)
41
37
 
@@ -50,13 +46,12 @@ module DynamicsCRM
50
46
  end
51
47
 
52
48
  # Finally return nil.
53
- return value
49
+ value
54
50
  end
55
51
 
56
52
  def respond_to_missing?(method_name, include_private = false)
57
53
  self.has_key?(method_name.to_s) || self.has_key?(method_name) || super
58
54
  end
59
-
60
55
  end
61
56
 
62
57
  # There's nothing to parse in the UpdateResult
@@ -73,6 +68,5 @@ module DynamicsCRM
73
68
 
74
69
  class DisassociateResponse < Result
75
70
  end
76
-
77
71
  end
78
72
  end
@@ -1,3 +1,3 @@
1
1
  module DynamicsCRM
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -51,8 +51,8 @@ module DynamicsCRM
51
51
  end
52
52
  end
53
53
 
54
- if type == "string" && value =~ /\w+{8}-\w+{4}-\w+{4}-\w+{4}-\w+{12}/
55
- type = "guid"
54
+ if type == 'string' && value =~ /\A\{?\w{8}-\w{4}-\w{4}-\w{4}-\w{12}\}?\z/
55
+ type = 'guid'
56
56
  end
57
57
 
58
58
  type
@@ -4,9 +4,11 @@ module DynamicsCRM
4
4
  # Creates a ConditionExpression element to be used in retrieve calls.
5
5
  class ConditionExpression
6
6
  attr_accessor :attr_name, :operator, :value, :type
7
- def initialize(attr_name, operator, value, type: nil)
7
+
8
+ def initialize(attr_name, operator, value = nil, type: nil)
8
9
  @attr_name = attr_name
9
10
  @operator = operator
11
+ # value can be optional to support Null and NotNull operators
10
12
  @value = value
11
13
  @values = Array(value)
12
14
  @type = type
@@ -2,6 +2,7 @@ module DynamicsCRM
2
2
  module XML
3
3
  class Criteria < Array
4
4
  SUPPORTED_OPERATORS = %w(And Or)
5
+ attr_accessor :filter_operator
5
6
 
6
7
  def initialize(tuples = [], filter_operator: nil)
7
8
  filter_operator ||= 'And'
@@ -15,31 +16,59 @@ module DynamicsCRM
15
16
  attr_name, operator, value, data_type = *tuple
16
17
  ConditionExpression.new(attr_name, operator, value, type: data_type)
17
18
  end
19
+
20
+ @filters = []
18
21
  end
19
22
 
20
- def add_condition(attr_name, operator, value, type: nil)
23
+ def add_condition(attr_name, operator, value = nil, type: nil)
21
24
  @expressions << ConditionExpression.new(attr_name, operator, value, type: type)
22
25
  end
23
26
 
27
+ def add_filter(filter)
28
+ @filters << filter
29
+ end
30
+
24
31
  # ConditionExpression can be repeated multiple times
25
32
  # Operator: can be lots of values such as: eq (Equals), neq (Not Equals), gt (Greater Than)
26
33
  # get the values from a fetch xml query
27
34
  # Values -> Value can be repeated multiple times
28
35
  # FilterOperator: and OR or depending on the filter requirements
36
+ # Filters: can contain FilterExpressions to support complex logical statements.
29
37
  def to_xml(options = {})
30
38
  ns = options[:namespace] ? options[:namespace] : 'a'
31
39
 
32
- xml_expression = @expressions.map do |conditional|
33
- conditional.to_xml(options)
34
- end.join('')
35
-
36
40
  %(<#{ns}:Criteria>
37
- <#{ns}:Conditions>
38
- #{xml_expression}
39
- </#{ns}:Conditions>
41
+ #{conditions_xml(options)}
40
42
  <#{ns}:FilterOperator>#{@filter_operator}</#{ns}:FilterOperator>
43
+ #{filters_xml(options)}
41
44
  </#{ns}:Criteria>)
42
45
  end
46
+
47
+ def conditions_xml(options)
48
+ ns = options[:namespace] ? options[:namespace] : 'a'
49
+
50
+ if @expressions.empty?
51
+ "<#{ns}:Conditions />"
52
+ else
53
+ xml_expression = @expressions.map do |conditional|
54
+ conditional.to_xml(options)
55
+ end.join('')
56
+
57
+ %(<#{ns}:Conditions>
58
+ #{xml_expression}
59
+ </#{ns}:Conditions>)
60
+ end
61
+ end
62
+
63
+ def filters_xml(options)
64
+ ns = options[:namespace] ? options[:namespace] : 'a'
65
+ if @filters.empty?
66
+ "<#{ns}:Filters />"
67
+ else
68
+ fx = @filters.map { |f| f.to_xml(options) }.join('')
69
+ %(<#{ns}:Filters>#{fx}</#{ns}:Filters>)
70
+ end
71
+ end
43
72
  end
44
73
  # Criteria
45
74
  end
@@ -0,0 +1,65 @@
1
+ module DynamicsCRM
2
+ module XML
3
+ # Represents FilterExpression XML fragment.
4
+ class FilterExpression
5
+ attr_accessor :conditions, :filters, :filter_operator
6
+
7
+ def initialize(operator = 'And')
8
+ @filter_operator = operator
9
+ @conditions = []
10
+ @filters = []
11
+ end
12
+
13
+ def add_condition(field, operator, value=nil)
14
+ conditions << ConditionExpression.new(field, operator, value)
15
+ end
16
+
17
+ def add_filter(filter)
18
+ filters << filter
19
+ end
20
+
21
+ def to_xml(options = {})
22
+ ns = options[:namespace] ? options[:namespace] : 'b'
23
+
24
+ query_xml = %(
25
+ <#{ns}:FilterExpression>
26
+ #{conditions_xml(options)}
27
+ <#{ns}:FilterOperator>#{@filter_operator}</#{ns}:FilterOperator>
28
+ #{filters_xml(options)}
29
+ </#{ns}:FilterExpression>
30
+ )
31
+
32
+ query_xml
33
+ end
34
+
35
+ protected
36
+
37
+ def conditions_xml(options)
38
+ ns = options[:namespace] ? options[:namespace] : 'b'
39
+
40
+ if conditions.empty?
41
+ "<#{ns}:Conditions />"
42
+ else
43
+ xml = conditions.map { |c| c.to_xml(options) }.join('')
44
+ %(<#{ns}:Conditions>
45
+ #{xml}
46
+ </#{ns}:Conditions>)
47
+ end
48
+ end
49
+
50
+ def filters_xml(options)
51
+ ns = options[:namespace] ? options[:namespace] : 'b'
52
+
53
+ if filters.empty?
54
+ "<#{ns}:Filters />"
55
+ else
56
+ sub_filters = filters.map { |f| f.to_xml(options) }.join('')
57
+ %(<#{ns}:Filters>
58
+ #{sub_filters}
59
+ </#{ns}:Filters>)
60
+ end
61
+ end
62
+ end
63
+ # FilterExpression
64
+ end
65
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe DynamicsCRM::XML::ConditionExpression do
4
+ it 'generates base ConditionExpresion' do
5
+ subject = DynamicsCRM::XML::ConditionExpression.new('name', 'Equal', 'GitHub')
6
+
7
+ fragment = %(
8
+ <b:ConditionExpression>
9
+ <b:AttributeName>name</b:AttributeName>
10
+ <b:Operator>Equal</b:Operator>
11
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
12
+ <d:anyType i:type="s:string" xmlns:s="http://www.w3.org/2001/XMLSchema">GitHub</d:anyType>
13
+ </b:Values>
14
+ </b:ConditionExpression>)
15
+
16
+ expect(subject.to_xml(namespace: 'b')).to match_xml fragment
17
+ end
18
+
19
+ it 'supports boolean values' do
20
+ subject = DynamicsCRM::XML::ConditionExpression.new('isactive', 'Equal', true)
21
+
22
+ fragment = %(
23
+ <b:ConditionExpression>
24
+ <b:AttributeName>isactive</b:AttributeName>
25
+ <b:Operator>Equal</b:Operator>
26
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
27
+ <d:anyType i:type="s:boolean" xmlns:s="http://www.w3.org/2001/XMLSchema">true</d:anyType>
28
+ </b:Values>
29
+ </b:ConditionExpression>)
30
+
31
+ expect(subject.to_xml(namespace: 'b')).to match_xml fragment
32
+ end
33
+
34
+ it 'supports Array values' do
35
+ subject = DynamicsCRM::XML::ConditionExpression.new('salesstage', 'In', [0, 1, 2])
36
+
37
+ fragment = %(
38
+ <b:ConditionExpression>
39
+ <b:AttributeName>salesstage</b:AttributeName>
40
+ <b:Operator>In</b:Operator>
41
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
42
+ <d:anyType i:type="s:int" xmlns:s="http://www.w3.org/2001/XMLSchema">0</d:anyType>
43
+ <d:anyType i:type="s:int" xmlns:s="http://www.w3.org/2001/XMLSchema">1</d:anyType>
44
+ <d:anyType i:type="s:int" xmlns:s="http://www.w3.org/2001/XMLSchema">2</d:anyType>
45
+ </b:Values>
46
+ </b:ConditionExpression>)
47
+
48
+ expect(subject.to_xml(namespace: 'b')).to match_xml fragment
49
+ end
50
+
51
+ it 'supports Null operator without value' do
52
+ subject = DynamicsCRM::XML::ConditionExpression.new('telephone1', 'Null')
53
+
54
+ fragment = %(
55
+ <b:ConditionExpression>
56
+ <b:AttributeName>telephone1</b:AttributeName>
57
+ <b:Operator>Null</b:Operator>
58
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
59
+ </b:Values>
60
+ </b:ConditionExpression>)
61
+
62
+ expect(subject.to_xml(namespace: 'b')).to match_xml fragment
63
+ end
64
+ end
@@ -8,9 +8,9 @@ describe DynamicsCRM::XML::Criteria do
8
8
 
9
9
  it 'generates empty Criteria fragment' do
10
10
  expected = %(<a:Criteria>
11
- <a:Conditions>
12
- </a:Conditions>
11
+ <a:Conditions />
13
12
  <a:FilterOperator>And</a:FilterOperator>
13
+ <a:Filters />
14
14
  </a:Criteria>)
15
15
 
16
16
  expect(subject.to_xml).to match_xml(expected)
@@ -33,6 +33,7 @@ describe DynamicsCRM::XML::Criteria do
33
33
  </a:ConditionExpression>
34
34
  </a:Conditions>
35
35
  <a:FilterOperator>And</a:FilterOperator>
36
+ <a:Filters />
36
37
  </a:Criteria>)
37
38
  }
38
39
 
@@ -77,6 +78,7 @@ describe DynamicsCRM::XML::Criteria do
77
78
  </a:ConditionExpression>
78
79
  </a:Conditions>
79
80
  <a:FilterOperator>And</a:FilterOperator>
81
+ <a:Filters />
80
82
  </a:Criteria>)
81
83
  end
82
84
  end
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+
3
+ describe DynamicsCRM::XML::FilterExpression do
4
+ describe 'initialization' do
5
+ subject {
6
+ DynamicsCRM::XML::FilterExpression.new('And')
7
+ }
8
+
9
+ it 'generates empty FilterExpression fragment' do
10
+ fragment = %(<b:FilterExpression>
11
+ <b:Conditions />
12
+ <b:FilterOperator>And</b:FilterOperator>
13
+ <b:Filters />
14
+ </b:FilterExpression>)
15
+
16
+ expect(subject.to_xml).to match_xml fragment
17
+ end
18
+
19
+ it 'generates FilterExpression with condition' do
20
+ subject.add_condition('name', 'Equal', 'Integration Specialists')
21
+
22
+ fragment = %(
23
+ <b:FilterExpression>
24
+ <b:Conditions>
25
+ <b:ConditionExpression>
26
+ <b:AttributeName>name</b:AttributeName>
27
+ <b:Operator>Equal</b:Operator>
28
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
29
+ <d:anyType i:type="s:string" xmlns:s="http://www.w3.org/2001/XMLSchema">Integration Specialists</d:anyType>
30
+ </b:Values>
31
+ </b:ConditionExpression>
32
+ </b:Conditions>
33
+ <b:FilterOperator>And</b:FilterOperator>
34
+ <b:Filters />
35
+ </b:FilterExpression>)
36
+
37
+ expect(subject.to_xml(namespace: 'b')).to match_xml fragment
38
+ end
39
+
40
+ it 'generates FilterExpression with sub-Filter' do
41
+ subject.add_condition('name', 'Equal', 'Integration Specialists')
42
+
43
+ filter = DynamicsCRM::XML::FilterExpression.new('And')
44
+ filter.add_condition('name', 'NotEqual', 'Bob')
45
+
46
+ subject.add_filter(filter)
47
+
48
+ fragment = %(
49
+ <b:FilterExpression>
50
+ <b:Conditions>
51
+ <b:ConditionExpression>
52
+ <b:AttributeName>name</b:AttributeName>
53
+ <b:Operator>Equal</b:Operator>
54
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
55
+ <d:anyType i:type="s:string" xmlns:s="http://www.w3.org/2001/XMLSchema">Integration Specialists</d:anyType>
56
+ </b:Values>
57
+ </b:ConditionExpression>
58
+ </b:Conditions>
59
+ <b:FilterOperator>And</b:FilterOperator>
60
+ <b:Filters>
61
+ <b:FilterExpression>
62
+ <b:Conditions>
63
+ <b:ConditionExpression>
64
+ <b:AttributeName>name</b:AttributeName>
65
+ <b:Operator>NotEqual</b:Operator>
66
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
67
+ <d:anyType i:type="s:string" xmlns:s="http://www.w3.org/2001/XMLSchema">Bob</d:anyType>
68
+ </b:Values>
69
+ </b:ConditionExpression>
70
+ </b:Conditions>
71
+ <b:FilterOperator>And</b:FilterOperator>
72
+ <b:Filters />
73
+ </b:FilterExpression>
74
+ </b:Filters>
75
+ </b:FilterExpression>)
76
+
77
+ expect(subject.to_xml(namespace: 'b')).to match_xml fragment
78
+ end
79
+ end
80
+
81
+ describe 'Criteria' do
82
+ subject do
83
+ criteria = DynamicsCRM::XML::Criteria.new
84
+ criteria.filter_operator = 'Or'
85
+
86
+ filter1 = DynamicsCRM::XML::FilterExpression.new('And')
87
+ filter1.add_condition('name', 'Equal', 'Integration Specialists')
88
+ filter1.add_condition('name', 'NotEqual', 'Bob')
89
+
90
+ filter2 = DynamicsCRM::XML::FilterExpression.new('And')
91
+ filter2.add_condition('name', 'Equal', 'Thematics Development Inc.')
92
+ filter2.add_condition('name', 'NotEqual', 'Bob')
93
+
94
+ criteria.add_filter(filter1)
95
+ criteria.add_filter(filter2)
96
+
97
+ criteria
98
+ end
99
+
100
+ it 'generates Criteria with Or Filters' do
101
+ expect(subject.to_xml(namespace: 'b')).to match_xml criteria_with_or_filters
102
+ end
103
+
104
+ def criteria_with_or_filters
105
+ %(<b:Criteria>
106
+ <b:Conditions />
107
+ <b:FilterOperator>Or</b:FilterOperator>
108
+ <b:Filters>
109
+ <b:FilterExpression>
110
+ <b:Conditions>
111
+ <b:ConditionExpression>
112
+ <b:AttributeName>name</b:AttributeName>
113
+ <b:Operator>Equal</b:Operator>
114
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
115
+ <d:anyType i:type="s:string" xmlns:s="http://www.w3.org/2001/XMLSchema">Integration Specialists</d:anyType>
116
+ </b:Values>
117
+ </b:ConditionExpression>
118
+ <b:ConditionExpression>
119
+ <b:AttributeName>name</b:AttributeName>
120
+ <b:Operator>NotEqual</b:Operator>
121
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
122
+ <d:anyType i:type="s:string" xmlns:s="http://www.w3.org/2001/XMLSchema">Bob</d:anyType>
123
+ </b:Values>
124
+ </b:ConditionExpression>
125
+ </b:Conditions>
126
+ <b:FilterOperator>And</b:FilterOperator>
127
+ <b:Filters />
128
+ </b:FilterExpression>
129
+ <b:FilterExpression>
130
+ <b:Conditions>
131
+ <b:ConditionExpression>
132
+ <b:AttributeName>name</b:AttributeName>
133
+ <b:Operator>Equal</b:Operator>
134
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
135
+ <d:anyType i:type="s:string" xmlns:s="http://www.w3.org/2001/XMLSchema">Thematics Development Inc.</d:anyType>
136
+ </b:Values>
137
+ </b:ConditionExpression>
138
+ <b:ConditionExpression>
139
+ <b:AttributeName>name</b:AttributeName>
140
+ <b:Operator>NotEqual</b:Operator>
141
+ <b:Values xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
142
+ <d:anyType i:type="s:string" xmlns:s="http://www.w3.org/2001/XMLSchema">Bob</d:anyType>
143
+ </b:Values>
144
+ </b:ConditionExpression>
145
+ </b:Conditions>
146
+ <b:FilterOperator>And</b:FilterOperator>
147
+ <b:Filters />
148
+ </b:FilterExpression>
149
+ </b:Filters>
150
+ </b:Criteria>)
151
+ end
152
+ end
153
+ end
@@ -9,7 +9,8 @@ describe DynamicsCRM::XML::QueryExpression do
9
9
 
10
10
  context "generate empty QueryExpression fragment" do
11
11
  it { expect(subject.to_xml).to include("<b:ColumnSet ") }
12
- it { expect(subject.to_xml).to match(/<b:Conditions>\s+<\/b:Conditions>/) }
12
+ it { expect(subject.to_xml).to include("<b:Criteria>") }
13
+ it { expect(subject.to_xml).to include("<b:Conditions />") }
13
14
  it { expect(subject.to_xml).to include("<b:AllColumns>true</b:AllColumns>") }
14
15
  it { expect(subject.to_xml).to include("<b:Distinct>false</b:Distinct>") }
15
16
  it { expect(subject.to_xml).to include("<b:EntityName>opportunity</b:EntityName>") }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamics_crm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Heth
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-22 00:00:00.000000000 Z
11
+ date: 2017-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mimemagic
@@ -190,6 +190,7 @@ files:
190
190
  - lib/dynamics_crm/xml/entity_reference.rb
191
191
  - lib/dynamics_crm/xml/fault.rb
192
192
  - lib/dynamics_crm/xml/fetch_expression.rb
193
+ - lib/dynamics_crm/xml/filter_expression.rb
193
194
  - lib/dynamics_crm/xml/message_builder.rb
194
195
  - lib/dynamics_crm/xml/message_parser.rb
195
196
  - lib/dynamics_crm/xml/money.rb
@@ -235,10 +236,12 @@ files:
235
236
  - spec/lib/response/retrieve_result_spec.rb
236
237
  - spec/lib/xml/attributes_spec.rb
237
238
  - spec/lib/xml/column_set_spec.rb
239
+ - spec/lib/xml/condition_expression_spec.rb
238
240
  - spec/lib/xml/criteria_spec.rb
239
241
  - spec/lib/xml/entity_reference_spec.rb
240
242
  - spec/lib/xml/entity_spec.rb
241
243
  - spec/lib/xml/fault_spec.rb
244
+ - spec/lib/xml/filter_expression_spec.rb
242
245
  - spec/lib/xml/message_builder_spec.rb
243
246
  - spec/lib/xml/money_spec.rb
244
247
  - spec/lib/xml/query_expression_spec.rb
@@ -309,10 +312,12 @@ test_files:
309
312
  - spec/lib/response/retrieve_result_spec.rb
310
313
  - spec/lib/xml/attributes_spec.rb
311
314
  - spec/lib/xml/column_set_spec.rb
315
+ - spec/lib/xml/condition_expression_spec.rb
312
316
  - spec/lib/xml/criteria_spec.rb
313
317
  - spec/lib/xml/entity_reference_spec.rb
314
318
  - spec/lib/xml/entity_spec.rb
315
319
  - spec/lib/xml/fault_spec.rb
320
+ - spec/lib/xml/filter_expression_spec.rb
316
321
  - spec/lib/xml/message_builder_spec.rb
317
322
  - spec/lib/xml/money_spec.rb
318
323
  - spec/lib/xml/query_expression_spec.rb