business-central 1.0.4 → 1.0.5

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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +58 -15
  3. data/lib/business_central.rb +4 -0
  4. data/lib/business_central/client.rb +5 -3
  5. data/lib/business_central/object/attachment.rb +30 -0
  6. data/lib/business_central/object/customer.rb +1 -0
  7. data/lib/business_central/object/default_dimension.rb +1 -1
  8. data/lib/business_central/object/general_ledger_entry.rb +13 -0
  9. data/lib/business_central/object/income_statement.rb +13 -0
  10. data/lib/business_central/object/irs1099_code.rb +16 -0
  11. data/lib/business_central/object/journal_line.rb +1 -1
  12. data/lib/business_central/object/picture.rb +1 -1
  13. data/lib/business_central/object/sales_credit_memo_line.rb +1 -1
  14. data/lib/business_central/object/sales_invoice_line.rb +1 -1
  15. data/lib/business_central/object/sales_order_line.rb +1 -1
  16. data/lib/business_central/object/sales_quote_line.rb +1 -1
  17. data/lib/business_central/version.rb +1 -1
  18. data/test/business_central/object/attachment_test.rb +117 -0
  19. data/test/business_central/object/customer_test.rb +44 -0
  20. data/test/business_central/object/general_ledger_entry_test.rb +82 -0
  21. data/test/business_central/object/income_statement_test.rb +82 -0
  22. data/test/business_central/object/irs1099_code_test.rb +124 -0
  23. data/test/business_central/object/journal_line_test.rb +8 -8
  24. data/test/business_central/object/journal_test.rb +20 -0
  25. data/test/business_central/object/sales_credit_memo_line_test.rb +8 -8
  26. data/test/business_central/object/sales_credit_memo_test.rb +1 -1
  27. data/test/business_central/object/sales_invoice_line_test.rb +8 -8
  28. data/test/business_central/object/sales_invoice_test.rb +22 -0
  29. data/test/business_central/object/sales_order_line_test.rb +8 -8
  30. data/test/business_central/object/sales_order_test.rb +1 -1
  31. data/test/business_central/object/sales_quote_line_test.rb +8 -8
  32. data/test/business_central/object/sales_quote_test.rb +1 -1
  33. metadata +18 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68fd68c7e0cf337b5f2c83ba5f08e21cdbab84b3c10a3515338a6d5241ab3c8d
4
- data.tar.gz: 14b3bcbe75143b2457c7ca2606a33926de4e89fd7001323c97911d557037301e
3
+ metadata.gz: eb391f19d6cbf2649ddbe7eb0cf937d2657c140de32d6f6a8c1f92483a353f57
4
+ data.tar.gz: c9ad222424c8b46bd9cdc4e282e5b583b2e795d1e1917c942b7da259e8380c92
5
5
  SHA512:
6
- metadata.gz: bfe06ca5d2427eaed0f8bcb6826e87635d72f02e456e7f4dba47bb19645edb757cc85af0436038f611821975fe43e39387238e180172e3ec09b95720ab45edcb
7
- data.tar.gz: 461aadc6e03b1a77bbe6737d69776d2c909baebd36c680a558320abc674f27824983cc1e3b1401b35f85b90fb9ba28f5ff7aaa93a0adbd79e50d8df828532fc6
6
+ metadata.gz: 3413af99b793f31b5913c726dd7fc3f5c48328f39321809b35da46f62100a12b529996eadfd3191d1581c52a718d749fa7eb2b808eb3f063f7a2e9c05975967e
7
+ data.tar.gz: 5e96d79316386187618b362f3ea365f2f510b50622a50f2436ec45feaa32d435e839fcbf4ac20b8c7bb8dc8b33e98a5a7295b2d9beeac7257bd4f1d5e6a4aca5
data/README.md CHANGED
@@ -26,6 +26,22 @@ This gem supports both authentication methods:
26
26
 
27
27
  https://docs.microsoft.com/en-us/dynamics-nav/api-reference/v1.0/endpoints-apis-for-dynamics
28
28
 
29
+ ```Ruby
30
+ require 'business_central'
31
+
32
+ client = BusinessCentral::Client.new(
33
+ username: '<username>', # Basic authentication username
34
+ password: '<password>', # Basic authentication password
35
+ url: '<url>', # URL for API defaults to https://api.businesscentral.dynamics.com/v2.0/production/api/v1.0
36
+ web_service_url: '<url>', # URL for custom web services defaults to https://api.businesscentral.dynamics.com/v2.0/production/ODataV4
37
+ application_id: '<application_id>', # Oauth2 authentication application ID
38
+ secret_key: '<application_secret_key>', # OAuth2 authentication application secret key
39
+ oauth2_login_url: '<url>', # OAuth2 authentication login URL defaults to https://login.microsoftonline.com/common
40
+ default_company_id: '<company_id>', # Default company ID used in all requests (if required)
41
+ debug: false # Output requests to console
42
+ )
43
+ ```
44
+
29
45
  ### Basic Authentication:
30
46
 
31
47
  https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-develop-connect-apps#setting-up-basic-authentication
@@ -36,26 +52,27 @@ require 'business_central'
36
52
  client = BusinessCentral::Client.new(
37
53
  username: '<username>',
38
54
  password: '<password>',
39
- url: '<url>'
55
+ url: '<url>',
56
+ default_company_id: '11111111-2222-3333-4444-555555555555'
40
57
  )
41
58
 
42
59
  # Find all vendors
43
- vendors = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').find_all
60
+ vendors = client.vendor.all
44
61
 
45
62
  # Find vendor by ID
46
- vendor = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').find_by_id('3f445b08-2ffd-4f9d-81a0-b82f0d9714c4')
63
+ vendor = client.vendor.find('3f445b08-2ffd-4f9d-81a0-b82f0d9714c4')
47
64
 
48
65
  # Query vendor by display name
49
- vendor = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').where("displayName eq 'First Up Consultants'")
66
+ vendor = client.vendor.where("displayName eq 'First Up Consultants'")
50
67
 
51
68
  # Create a new vendor
52
- vendor = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').create({ display_name: 'hello testing new vendor' })
69
+ vendor = client.vendor.create({ display_name: 'hello testing new vendor' })
53
70
 
54
71
  # Update an existing vendor by ID
55
- vendor = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').update('3f445b08-2ffd-4f9d-81a0-b82f0d9714c4', { phone_number: '1112' })
72
+ vendor = client.vendor.update('3f445b08-2ffd-4f9d-81a0-b82f0d9714c4', { phone_number: '1112' })
56
73
 
57
74
  # Delete a vendor
58
- client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').destroy('f0730ada-b315-ea11-a813-000d3ad21e99')
75
+ client.vendor.destroy('f0730ada-b315-ea11-a813-000d3ad21e99')
59
76
  ```
60
77
 
61
78
  ### Oauth2 Authentication
@@ -67,10 +84,10 @@ require 'business_central'
67
84
 
68
85
  # Create client - used to connect to the API
69
86
  client = BusinessCentral::Client.new(
70
- tenant_id: '<tenant_id>',
71
87
  application_id: '<application_id>',
72
88
  secret_key: '<application_secret_key>',
73
- url: '<url>'
89
+ url: '<url>',
90
+ default_company_id: '11111111-2222-3333-4444-555555555555'
74
91
  )
75
92
 
76
93
  # Controller endpoint 1
@@ -87,22 +104,48 @@ client.authorize_from_token(
87
104
  )
88
105
 
89
106
  # Find all vendors
90
- vendors = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').find_all
107
+ vendors = client.vendor.all
91
108
 
92
109
  # Find vendor by ID
93
- vendor = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').find_by_id('3f445b08-2ffd-4f9d-81a0-b82f0d9714c4')
110
+ vendor = client.vendor.find('3f445b08-2ffd-4f9d-81a0-b82f0d9714c4')
94
111
 
95
112
  # Query vendor by display name
96
- vendor = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').where("displayName eq 'First Up Consultants'")
113
+ vendor = client.vendor.where("displayName eq 'First Up Consultants'")
97
114
 
98
115
  # Create a new vendor
99
- vendor = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').create({ display_name: 'hello testing' })
116
+ vendor = client.vendor.create({ display_name: 'hello testing' })
100
117
 
101
118
  # Update an existing vendor by ID
102
- vendor = client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').update('3f445b08-2ffd-4f9d-81a0-b82f0d9714c4', { phone_number: '1112' })
119
+ vendor = client.vendor.update('3f445b08-2ffd-4f9d-81a0-b82f0d9714c4', { phone_number: '1112' })
103
120
 
104
121
  # Delete a vendor
105
- client.vendor(company_id: '3a502065-2a08-4c3b-9468-fb83642d3d3a').destroy('f0730ada-b315-ea11-a813-000d3ad21e99')
122
+ client.vendor.destroy('f0730ada-b315-ea11-a813-000d3ad21e99')
123
+ ```
124
+
125
+ ### OData Web Services
126
+
127
+ https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/webservices/odata-web-services
128
+
129
+ ```Ruby
130
+ require 'business_central'
131
+
132
+ client = BusinessCentral::Client.new(
133
+ username: '<username>',
134
+ password: '<password>',
135
+ web_service_url: '<url>'
136
+ )
137
+
138
+ # Query a record
139
+ company = client.web_service.object("Company('?')/Purchase_Order", 'My Company').get
140
+
141
+ # Create a record
142
+ client.web_service.object("Company('?')/Purchase_Order", 'My Company').post({})
143
+
144
+ # Update a record
145
+ client.web_service.object("Company('?')/Purchase_Order", 'My Company').patch({})
146
+
147
+ # Delete a record
148
+ client.web_service.object("Company('?')/Purchase_Order", 'My Company').delete
106
149
  ```
107
150
 
108
151
  ## Development
@@ -19,6 +19,7 @@ require 'business_central/object/url_builder'
19
19
  require 'business_central/object/account'
20
20
  require 'business_central/object/aged_account_payable'
21
21
  require 'business_central/object/aged_account_receivable'
22
+ require 'business_central/object/attachment'
22
23
  require 'business_central/object/cash_flow_statement'
23
24
  require 'business_central/object/balance_sheet'
24
25
  require 'business_central/object/company'
@@ -35,6 +36,9 @@ require 'business_central/object/dimension'
35
36
  require 'business_central/object/dimension_line'
36
37
  require 'business_central/object/dimension_value'
37
38
  require 'business_central/object/employee'
39
+ require 'business_central/object/general_ledger_entry'
40
+ require 'business_central/object/income_statement'
41
+ require 'business_central/object/irs1099_code'
38
42
  require 'business_central/object/item'
39
43
  require 'business_central/object/item_category'
40
44
  require 'business_central/object/journal'
@@ -8,8 +8,7 @@ module BusinessCentral
8
8
 
9
9
  DEFAULT_URL = 'https://api.businesscentral.dynamics.com/v2.0/production/api/v1.0'
10
10
 
11
- attr_reader :tenant_id,
12
- :username,
11
+ attr_reader :username,
13
12
  :password,
14
13
  :application_id,
15
14
  :secret_key,
@@ -25,6 +24,7 @@ module BusinessCentral
25
24
  object :account
26
25
  object :aged_account_payable
27
26
  object :aged_account_receivable
27
+ object :attachment
28
28
  object :balance_sheet
29
29
  object :cash_flow_statement
30
30
  object :company
@@ -41,6 +41,9 @@ module BusinessCentral
41
41
  object :dimension_line
42
42
  object :dimension_value
43
43
  object :employee
44
+ object :general_ledger_entry
45
+ object :income_statement
46
+ object :irs1099_code
44
47
  object :purchase_invoice
45
48
  object :purchase_invoice_line
46
49
  object :item
@@ -71,7 +74,6 @@ module BusinessCentral
71
74
 
72
75
  def initialize(options = {})
73
76
  opts = options.dup
74
- @tenant_id = opts.delete(:tenant_id)
75
77
  @username = opts.delete(:username)
76
78
  @password = opts.delete(:password)
77
79
  @url = opts.delete(:url) || DEFAULT_URL
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class Attachment < Base
6
+ OBJECT = 'attachments'
7
+
8
+ OBJECT_METHODS = %i[
9
+ get
10
+ post
11
+ patch
12
+ delete
13
+ ].freeze
14
+
15
+ def update(parent_id:, attachment_id:, **params)
16
+ url = "#{build_url(child_path: OBJECT)}(parentId=#{parent_id},id=#{attachment_id})/content"
17
+ Request.call(:patch, @client, url, etag: '', params: {}) do |request|
18
+ request['Content-Type'] = 'application/json'
19
+ request['If-Match'] = 'application/json'
20
+ request.body = Request.convert(params)
21
+ end
22
+ end
23
+
24
+ def destroy(parent_id:, attachment_id:)
25
+ url = "#{build_url(child_path: OBJECT)}(#{parent_id},#{attachment_id})"
26
+ Request.call(:delete, @client, url, etag: '')
27
+ end
28
+ end
29
+ end
30
+ end
@@ -27,6 +27,7 @@ module BusinessCentral
27
27
  delete
28
28
  ].freeze
29
29
 
30
+ navigation :default_dimension
30
31
  navigation :picture
31
32
  end
32
33
  end
@@ -36,7 +36,7 @@ module BusinessCentral
36
36
 
37
37
  super(client, args)
38
38
  @parent_path << {
39
- path: parent.downcase,
39
+ path: parent,
40
40
  id: parent_id
41
41
  }
42
42
  @parent_id = parent_id
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class GeneralLedgerEntry < Base
6
+ OBJECT = 'generalLedgerEntries'
7
+
8
+ OBJECT_METHODS = %i[
9
+ get
10
+ ].freeze
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class IncomeStatement < Base
6
+ OBJECT = 'incomeStatement'
7
+
8
+ OBJECT_METHODS = %i[
9
+ get
10
+ ].freeze
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class Irs1099Code < Base
6
+ OBJECT = 'irs1099Codes'
7
+
8
+ OBJECT_METHODS = %i[
9
+ get
10
+ post
11
+ patch
12
+ delete
13
+ ].freeze
14
+ end
15
+ end
16
+ end
@@ -39,7 +39,7 @@ module BusinessCentral
39
39
 
40
40
  super(client, args)
41
41
  @parent_path << {
42
- path: parent.downcase,
42
+ path: parent,
43
43
  id: parent_id
44
44
  }
45
45
  end
@@ -24,7 +24,7 @@ module BusinessCentral
24
24
 
25
25
  super(client, args)
26
26
  @parent_path << {
27
- path: parent.downcase,
27
+ path: parent,
28
28
  id: parent_id
29
29
  }
30
30
  @parent_id = parent_id
@@ -21,7 +21,7 @@ module BusinessCentral
21
21
 
22
22
  super(client, args)
23
23
  @parent_path << {
24
- path: parent.downcase,
24
+ path: parent,
25
25
  id: parent_id
26
26
  }
27
27
  end
@@ -21,7 +21,7 @@ module BusinessCentral
21
21
 
22
22
  super(client, args)
23
23
  @parent_path << {
24
- path: parent.downcase,
24
+ path: parent,
25
25
  id: parent_id
26
26
  }
27
27
  end
@@ -21,7 +21,7 @@ module BusinessCentral
21
21
 
22
22
  super(client, args)
23
23
  @parent_path << {
24
- path: parent.downcase,
24
+ path: parent,
25
25
  id: parent_id
26
26
  }
27
27
  end
@@ -21,7 +21,7 @@ module BusinessCentral
21
21
 
22
22
  super(client, args)
23
23
  @parent_path << {
24
- path: parent.downcase,
24
+ path: parent,
25
25
  id: parent_id
26
26
  }
27
27
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BusinessCentral
4
- VERSION = '1.0.4'
4
+ VERSION = '1.0.5'
5
5
  end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ # rake test TEST=test/business_central/object/attachment_test.rb
5
+
6
+ class BusinessCentral::Object::AttachmentTest < Minitest::Test
7
+ def setup
8
+ @company_id = '123456'
9
+ @client = BusinessCentral::Client.new
10
+ @attachment = @client.attachment(company_id: @company_id)
11
+ end
12
+
13
+ def test_find_all
14
+ stub_request(:get, /attachments/)
15
+ .to_return(
16
+ status: 200,
17
+ body: {
18
+ 'value': [
19
+ {
20
+ id: '111',
21
+ fileName: 'attachment1.pdf'
22
+ }
23
+ ]
24
+ }.to_json
25
+ )
26
+
27
+ response = @attachment.find_all
28
+ assert_equal response.first[:file_name], 'attachment1.pdf'
29
+ end
30
+
31
+ def test_find_by_id
32
+ test_id = '09876'
33
+ stub_request(:get, /attachments\(#{test_id}\)/)
34
+ .to_return(
35
+ status: 200,
36
+ body: {
37
+ id: '222',
38
+ fileName: 'attachment2.jpg'
39
+ }.to_json
40
+ )
41
+
42
+ response = @attachment.find_by_id(test_id)
43
+ assert_equal response[:file_name], 'attachment2.jpg'
44
+ end
45
+
46
+ def test_where
47
+ test_filter = "fileName eq 'attachment3.png'"
48
+ stub_request(:get, /attachments\?\$filter=#{test_filter}/)
49
+ .to_return(
50
+ status: 200,
51
+ body: {
52
+ 'value': [
53
+ {
54
+ id: '333',
55
+ fileName: 'attachment3.png'
56
+ }
57
+ ]
58
+ }.to_json
59
+ )
60
+
61
+ response = @attachment.where(test_filter)
62
+ assert_equal response.first[:file_name], 'attachment3.png'
63
+ end
64
+
65
+ def test_create
66
+ stub_request(:post, /attachments/)
67
+ .to_return(
68
+ status: 200,
69
+ body: {
70
+ fileName: 'attachment4.gif'
71
+ }.to_json
72
+ )
73
+
74
+ response = @attachment.create(
75
+ file_name: 'attachment4.gif'
76
+ )
77
+ assert_equal response[:file_name], 'attachment4.gif'
78
+ end
79
+
80
+ def test_update
81
+ test_parent_id = '011123'
82
+ test_attachment_id = '11123'
83
+ stub_request(:get, /attachments\(parentId=#{test_parent_id},id=#{test_attachment_id}\)/)
84
+ .to_return(
85
+ status: 200,
86
+ body: {
87
+ etag: '112',
88
+ fileName: 'attachment5.pdf'
89
+ }.to_json
90
+ )
91
+
92
+ stub_request(:patch, /attachments\(parentId=#{test_parent_id},id=#{test_attachment_id}\)/)
93
+ .to_return(
94
+ status: 200,
95
+ body: {
96
+ fileName: 'attachment6.pdf'
97
+ }.to_json
98
+ )
99
+
100
+ response = @attachment.update(
101
+ parent_id: test_parent_id,
102
+ attachment_id: test_attachment_id,
103
+ file_name: 'attachment6.pdf'
104
+ )
105
+ assert_equal response[:file_name], 'attachment6.pdf'
106
+ end
107
+
108
+ def test_delete
109
+ test_parent_id = '011124'
110
+ test_attachment_id = '11124'
111
+
112
+ stub_request(:delete, /attachments\(#{test_parent_id},#{test_attachment_id}\)/)
113
+ .to_return(status: 204)
114
+
115
+ assert @attachment.destroy(parent_id: test_parent_id, attachment_id: test_attachment_id)
116
+ end
117
+ end