business-central 1.0.1 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +58 -15
  3. data/lib/business_central.rb +47 -2
  4. data/lib/business_central/client.rb +82 -39
  5. data/lib/business_central/exceptions.rb +30 -10
  6. data/lib/business_central/object/account.rb +4 -12
  7. data/lib/business_central/object/aged_account_payable.rb +4 -12
  8. data/lib/business_central/object/aged_account_receivable.rb +4 -12
  9. data/lib/business_central/object/argument_helper.rb +22 -0
  10. data/lib/business_central/object/attachment.rb +30 -0
  11. data/lib/business_central/object/balance_sheet.rb +4 -12
  12. data/lib/business_central/object/base.rb +100 -49
  13. data/lib/business_central/object/cash_flow_statement.rb +4 -12
  14. data/lib/business_central/object/company.rb +9 -2
  15. data/lib/business_central/object/company_information.rb +7 -15
  16. data/lib/business_central/object/country_region.rb +26 -0
  17. data/lib/business_central/object/currency.rb +29 -0
  18. data/lib/business_central/object/customer.rb +34 -0
  19. data/lib/business_central/object/customer_financial_detail.rb +13 -0
  20. data/lib/business_central/object/customer_payment.rb +43 -0
  21. data/lib/business_central/object/customer_payment_journal.rb +25 -0
  22. data/lib/business_central/object/customer_sale.rb +13 -0
  23. data/lib/business_central/object/default_dimension.rb +51 -0
  24. data/lib/business_central/object/dimension.rb +20 -0
  25. data/lib/business_central/object/dimension_line.rb +37 -0
  26. data/lib/business_central/object/dimension_value.rb +28 -0
  27. data/lib/business_central/object/employee.rb +21 -0
  28. data/lib/business_central/object/filter_query.rb +18 -0
  29. data/lib/business_central/object/general_ledger_entry.rb +13 -0
  30. data/lib/business_central/object/income_statement.rb +13 -0
  31. data/lib/business_central/object/irs1099_code.rb +16 -0
  32. data/lib/business_central/object/item.rb +16 -19
  33. data/lib/business_central/object/item_category.rb +16 -0
  34. data/lib/business_central/object/journal.rb +29 -0
  35. data/lib/business_central/object/journal_line.rb +48 -0
  36. data/lib/business_central/object/object_helper.rb +49 -0
  37. data/lib/business_central/object/payment_method.rb +16 -0
  38. data/lib/business_central/object/payment_term.rb +16 -0
  39. data/lib/business_central/object/picture.rb +53 -0
  40. data/lib/business_central/object/purchase_invoice.rb +8 -16
  41. data/lib/business_central/object/purchase_invoice_line.rb +14 -18
  42. data/lib/business_central/object/request.rb +61 -50
  43. data/lib/business_central/object/response.rb +31 -23
  44. data/lib/business_central/object/retained_earning_statement.rb +13 -0
  45. data/lib/business_central/object/sales_credit_memo.rb +20 -0
  46. data/lib/business_central/object/sales_credit_memo_line.rb +30 -0
  47. data/lib/business_central/object/sales_invoice.rb +62 -0
  48. data/lib/business_central/object/sales_invoice_line.rb +30 -0
  49. data/lib/business_central/object/sales_order.rb +20 -0
  50. data/lib/business_central/object/sales_order_line.rb +30 -0
  51. data/lib/business_central/object/sales_quote.rb +20 -0
  52. data/lib/business_central/object/sales_quote_line.rb +30 -0
  53. data/lib/business_central/object/shipment_method.rb +16 -0
  54. data/lib/business_central/object/subscription.rb +16 -0
  55. data/lib/business_central/object/tax_area.rb +16 -0
  56. data/lib/business_central/object/tax_group.rb +16 -0
  57. data/lib/business_central/object/time_registration_entry.rb +16 -0
  58. data/lib/business_central/object/trial_balance.rb +13 -0
  59. data/lib/business_central/object/units_of_measure.rb +16 -0
  60. data/lib/business_central/object/url_builder.rb +59 -0
  61. data/lib/business_central/object/url_helper.rb +44 -0
  62. data/lib/business_central/object/validation.rb +10 -7
  63. data/lib/business_central/object/vendor.rb +12 -15
  64. data/lib/business_central/object/vendor_purchase.rb +13 -0
  65. data/lib/business_central/version.rb +4 -2
  66. data/lib/business_central/web_service.rb +78 -0
  67. data/lib/core_ext/string.rb +18 -12
  68. data/test/business_central/client_test.rb +49 -7
  69. data/test/business_central/object/account_test.rb +6 -5
  70. data/test/business_central/object/aged_account_payable_test.rb +6 -5
  71. data/test/business_central/object/aged_account_receivable_test.rb +6 -5
  72. data/test/business_central/object/attachment_test.rb +117 -0
  73. data/test/business_central/object/balance_sheet_test.rb +6 -5
  74. data/test/business_central/object/base_test.rb +41 -0
  75. data/test/business_central/object/cash_flow_statement_test.rb +6 -5
  76. data/test/business_central/object/company_information_test.rb +9 -10
  77. data/test/business_central/object/company_test.rb +6 -5
  78. data/test/business_central/object/country_region_test.rb +129 -0
  79. data/test/business_central/object/currency_test.rb +150 -0
  80. data/test/business_central/object/customer_financial_detail_test.rb +68 -0
  81. data/test/business_central/object/customer_payment_journal_test.rb +134 -0
  82. data/test/business_central/object/customer_payment_test.rb +141 -0
  83. data/test/business_central/object/customer_sale_test.rb +72 -0
  84. data/test/business_central/object/customer_test.rb +168 -0
  85. data/test/business_central/object/default_dimension_test.rb +170 -0
  86. data/test/business_central/object/dimension_line_test.rb +165 -0
  87. data/test/business_central/object/dimension_test.rb +65 -0
  88. data/test/business_central/object/dimension_value_test.rb +68 -0
  89. data/test/business_central/object/employee_test.rb +141 -0
  90. data/test/business_central/object/filter_query_test.rb +36 -0
  91. data/test/business_central/object/general_ledger_entry_test.rb +82 -0
  92. data/test/business_central/object/income_statement_test.rb +82 -0
  93. data/test/business_central/object/irs1099_code_test.rb +124 -0
  94. data/test/business_central/object/item_category_test.rb +122 -0
  95. data/test/business_central/object/item_test.rb +16 -17
  96. data/test/business_central/object/journal_line_test.rb +152 -0
  97. data/test/business_central/object/journal_test.rb +144 -0
  98. data/test/business_central/object/payment_method_test.rb +134 -0
  99. data/test/business_central/object/payment_term_test.rb +134 -0
  100. data/test/business_central/object/picture_test.rb +74 -0
  101. data/test/business_central/object/purchase_invoice_line_test.rb +15 -15
  102. data/test/business_central/object/purchase_invoice_test.rb +15 -15
  103. data/test/business_central/object/request_test.rb +75 -12
  104. data/test/business_central/object/response_test.rb +34 -9
  105. data/test/business_central/object/retained_earning_statement_test.rb +52 -0
  106. data/test/business_central/object/sales_credit_memo_line_test.rb +134 -0
  107. data/test/business_central/object/sales_credit_memo_test.rb +146 -0
  108. data/test/business_central/object/sales_invoice_line_test.rb +164 -0
  109. data/test/business_central/object/sales_invoice_test.rb +156 -0
  110. data/test/business_central/object/sales_order_line_test.rb +134 -0
  111. data/test/business_central/object/sales_order_test.rb +146 -0
  112. data/test/business_central/object/sales_quote_line_test.rb +134 -0
  113. data/test/business_central/object/sales_quote_test.rb +146 -0
  114. data/test/business_central/object/shipment_method_test.rb +133 -0
  115. data/test/business_central/object/subscription_test.rb +126 -0
  116. data/test/business_central/object/tax_area_test.rb +126 -0
  117. data/test/business_central/object/tax_group_test.rb +126 -0
  118. data/test/business_central/object/time_registration_entry_test.rb +126 -0
  119. data/test/business_central/object/trial_balance_test.rb +82 -0
  120. data/test/business_central/object/units_of_measure_test.rb +126 -0
  121. data/test/business_central/object/validation_test.rb +5 -4
  122. data/test/business_central/object/vendor_purchase_test.rb +82 -0
  123. data/test/business_central/object/vendor_test.rb +16 -16
  124. data/test/business_central/web_service_test.rb +100 -0
  125. data/test/business_central_test.rb +3 -1
  126. data/test/test_helper.rb +16 -6
  127. metadata +188 -37
  128. data/lib/business_central/object/helper.rb +0 -15
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class ItemCategory < Base
6
+ OBJECT = 'itemCategories'
7
+
8
+ OBJECT_METHODS = %i[
9
+ get
10
+ post
11
+ patch
12
+ delete
13
+ ].freeze
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class Journal < Base
6
+ extend BusinessCentral::Object::ObjectHelper
7
+
8
+ OBJECT = 'journals'
9
+
10
+ OBJECT_VALIDATION = {
11
+ code: {
12
+ maximum_length: 10
13
+ },
14
+ display_name: {
15
+ maximum_length: 50
16
+ }
17
+ }.freeze
18
+
19
+ OBJECT_METHODS = %i[
20
+ get
21
+ post
22
+ patch
23
+ delete
24
+ ].freeze
25
+
26
+ navigation :journal_line
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class JournalLine < Base
6
+ OBJECT = 'journalLines'
7
+
8
+ OBJECT_VALIDATION = {
9
+ account_number: {
10
+ maximum_length: 20
11
+ },
12
+ document_number: {
13
+ maximum_length: 20
14
+ },
15
+ external_document_number: {
16
+ maximum_length: 20
17
+ },
18
+ description: {
19
+ maximum_length: 50
20
+ },
21
+ comment: {
22
+ maximum_length: 250
23
+ }
24
+ }.freeze
25
+
26
+ OBJECT_METHODS = %i[
27
+ get
28
+ post
29
+ patch
30
+ delete
31
+ ].freeze
32
+
33
+ OBJECT_PARENTS = %w[
34
+ journals
35
+ ].freeze
36
+
37
+ def initialize(client, parent: 'journals', parent_id:, **args)
38
+ return if !valid_parent?(parent)
39
+
40
+ super(client, args)
41
+ @parent_path << {
42
+ path: parent,
43
+ id: parent_id
44
+ }
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ module ObjectHelper
6
+ include ArgumentHelper
7
+
8
+ def object(object_name, *_params)
9
+ define_method(object_name) do |argument = nil|
10
+ object = "@#{object_name}_cache".to_sym
11
+ if argument.nil?
12
+ if !instance_variable_defined?(object)
13
+ instance_variable_set(
14
+ object,
15
+ BusinessCentral::Object.const_get(
16
+ object_name.to_s.to_camel_case(true).to_s.to_sym
17
+ ).new(self, argument)
18
+ )
19
+ else
20
+ instance_variable_get(object)
21
+ end
22
+ else
23
+ instance_variable_set(
24
+ object,
25
+ BusinessCentral::Object.const_get(
26
+ object_name.to_s.to_camel_case(true).to_s.to_sym
27
+ ).new(self, argument)
28
+ )
29
+ end
30
+ end
31
+ end
32
+
33
+ def navigation(object_name, *_params)
34
+ define_method(object_name) do |argument = nil|
35
+ object = "@#{object_name}_cache".to_sym
36
+ instance_variable_set(
37
+ object,
38
+ BusinessCentral::Object.const_get(object_name.to_s.to_camel_case(true).to_s.to_sym).new(
39
+ client,
40
+ company_id: company_id(argument),
41
+ parent: self.class.const_get(:OBJECT),
42
+ parent_id: id(argument)
43
+ )
44
+ )
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class PaymentMethod < Base
6
+ OBJECT = 'paymentMethods'
7
+
8
+ OBJECT_METHODS = %i[
9
+ get
10
+ post
11
+ patch
12
+ delete
13
+ ].freeze
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class PaymentTerm < Base
6
+ OBJECT = 'paymentTerms'
7
+
8
+ OBJECT_METHODS = %i[
9
+ get
10
+ post
11
+ patch
12
+ delete
13
+ ].freeze
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BusinessCentral
4
+ module Object
5
+ class Picture < Base
6
+ OBJECT = 'picture'
7
+
8
+ OBJECT_METHODS = %i[
9
+ get
10
+ post
11
+ patch
12
+ delete
13
+ ].freeze
14
+
15
+ OBJECT_PARENTS = %w[
16
+ items
17
+ customers
18
+ vendors
19
+ employees
20
+ ].freeze
21
+
22
+ def initialize(client, parent:, parent_id:, **args)
23
+ return if !valid_parent?(parent)
24
+
25
+ super(client, args)
26
+ @parent_path << {
27
+ path: parent,
28
+ id: parent_id
29
+ }
30
+ @parent_id = parent_id
31
+ end
32
+
33
+ def create(data)
34
+ url = "#{build_url(parent_path: @parent_path, child_path: object_name)}(#{@parent_id})/content"
35
+ Request.call(:patch, @client, url, etag: '', params: {}) do |request|
36
+ request['Content-Type'] = 'application/octet-stream'
37
+ request['If-Match'] = '*'
38
+ request.body = data
39
+ end
40
+ end
41
+
42
+ def update(data)
43
+ url = "#{build_url(parent_path: @parent_path, child_path: object_name)}(#{@parent_id})"
44
+ object = Request.get(@client, url)
45
+ url = "#{build_url(parent_path: @parent_path, child_path: object_name)}(#{@parent_id})/content"
46
+ Request.call(:patch, @client, url, etag: object[:etag], params: {}) do |request|
47
+ request['Content-Type'] = 'application/octet-stream'
48
+ request.body = data
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BusinessCentral
2
4
  module Object
3
5
  class PurchaseInvoice < Base
4
- OBJECT = 'purchaseInvoices'.freeze
6
+ OBJECT = 'purchaseInvoices'
5
7
 
6
8
  OBJECT_VALIDATION = {
7
9
  number: {
@@ -56,22 +58,12 @@ module BusinessCentral
56
58
  }
57
59
  }.freeze
58
60
 
59
- OBJECT_METHODS = [
60
- :get,
61
- :post,
62
- :patch,
63
- :delete
61
+ OBJECT_METHODS = %i[
62
+ get
63
+ post
64
+ patch
65
+ delete
64
66
  ].freeze
65
-
66
- def initialize(client, company_id:)
67
- super(client, company_id: company_id)
68
- @parent_path = [
69
- {
70
- path: 'companies',
71
- id: company_id
72
- }
73
- ]
74
- end
75
67
  end
76
68
  end
77
69
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BusinessCentral
2
4
  module Object
3
5
  class PurchaseInvoiceLine < Base
4
- OBJECT = 'purchaseInvoiceLines'.freeze
6
+ OBJECT = 'purchaseInvoiceLines'
5
7
 
6
8
  OBJECT_VALIDATION = {
7
9
  line_type: {
@@ -16,25 +18,19 @@ module BusinessCentral
16
18
  }
17
19
  }.freeze
18
20
 
19
- OBJECT_METHODS = [
20
- :get,
21
- :post,
22
- :patch,
23
- :delete
21
+ OBJECT_METHODS = %i[
22
+ get
23
+ post
24
+ patch
25
+ delete
24
26
  ].freeze
25
27
 
26
- def initialize(client, company_id:, purchase_invoice_id:)
27
- super(client, company_id: company_id)
28
- @parent_path = [
29
- {
30
- path: 'companies',
31
- id: company_id
32
- },
33
- {
34
- path: 'purchaseInvoices',
35
- id: purchase_invoice_id
36
- }
37
- ]
28
+ def initialize(client, purchase_invoice_id:, **args)
29
+ super(client, args)
30
+ @parent_path << {
31
+ path: 'purchaseInvoices',
32
+ id: purchase_invoice_id
33
+ }
38
34
  end
39
35
  end
40
36
  end
@@ -1,75 +1,86 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BusinessCentral
2
4
  module Object
3
5
  class Request
6
+ class << self
7
+ def get(client, url)
8
+ request(:get, client, url)
9
+ end
4
10
 
5
- def self.get(client, url)
6
- request(:get, client, url)
7
- end
8
-
9
- def self.post(client, url, params)
10
- request(:post, client, url, params: params)
11
- end
12
-
13
- def self.patch(client, url, etag, params)
14
- request(:patch, client, url, etag: etag, params: params)
15
- end
11
+ def post(client, url, params)
12
+ request(:post, client, url, params: params)
13
+ end
16
14
 
17
- def self.delete(client, url, etag)
18
- request(:delete, client, url, etag: etag)
19
- end
15
+ def patch(client, url, etag, params)
16
+ request(:patch, client, url, etag: etag, params: params)
17
+ end
20
18
 
21
- private
19
+ def delete(client, url, etag)
20
+ request(:delete, client, url, etag: etag)
21
+ end
22
22
 
23
- def self.request(method, client, url, etag: '', params: {})
24
- send do
25
- uri = URI(url)
26
- https = Net::HTTP.new(uri.host, uri.port);
27
- https.use_ssl = true
28
- request = Object.const_get("Net::HTTP::#{method.to_s.capitalize}").new(uri)
29
- request['Content-Type'] = 'application/json'
30
- request['Accept'] = 'application/json'
31
- request['If-Match'] = etag if !etag.blank?
32
- request.body = convert(params) if method == :post || method == :patch
33
- if client.access_token
34
- request['Authorization'] = "Bearer #{client.access_token.token}"
35
- else
36
- request.basic_auth(client.username, client.password)
23
+ def convert(request = {})
24
+ result = {}
25
+ request.each do |key, value|
26
+ result[key.to_s.to_camel_case] = value if key.is_a? Symbol
27
+ result[key.to_s] = value if key.is_a? String
37
28
  end
38
- https.request(request)
29
+
30
+ result.to_json
39
31
  end
40
- end
41
32
 
42
- def self.convert(request = {})
43
- result = {}
44
- request.each do |key, value|
45
- result[key.to_s.to_camel_case] = value
33
+ def request(method, client, url, etag: '', params: {})
34
+ send do
35
+ uri = URI(url)
36
+ https = Net::HTTP.new(uri.host, uri.port)
37
+ https.use_ssl = true
38
+ https.set_debug_output($stdout) if client.debug
39
+ request = Object.const_get("Net::HTTP::#{method.to_s.capitalize}").new(uri)
40
+ request['If-Match'] = etag if !etag.blank?
41
+ request['Accept'] = 'application/json'
42
+ if block_given?
43
+ yield(request)
44
+ else
45
+ request['Content-Type'] = 'application/json'
46
+ request.body = convert(params) if %i[post patch].include?(method)
47
+ end
48
+
49
+ if client.access_token
50
+ request['Authorization'] = "Bearer #{client.access_token.token}"
51
+ else
52
+ request.basic_auth(client.username, client.password)
53
+ end
54
+ https.request(request)
55
+ end
46
56
  end
57
+ alias call request
47
58
 
48
- return result.to_json
49
- end
59
+ private
50
60
 
51
- def self.send
52
- begin
61
+ def send
53
62
  request = yield
54
63
  response = Response.new(request.read_body.to_s).results
55
64
 
56
65
  if Response.success?(request.code.to_i)
57
- return response
58
- elsif Response.deleted?(request.code.to_i)
59
- return true
66
+ response
67
+ elsif Response.success_no_content?(request.code.to_i)
68
+ true
60
69
  else
61
70
  if Response.unauthorized?(request.code.to_i)
62
- raise UnauthorizedException.new
71
+ raise UnauthorizedException
72
+ elsif Response.not_found?(request.code.to_i)
73
+ raise NotFoundException
63
74
  else
64
- if response[:error][:code].present?
75
+ if !response.fetch(:error, nil).nil?
65
76
  case response[:error][:code]
66
- when 'Internal_CompanyNotFound'
67
- raise CompanyNotFoundException.new
68
- else
69
- raise ApiException.new("#{request.code} - #{response[:error][:code]} #{response[:error][:message]}")
77
+ when 'Internal_CompanyNotFound'
78
+ raise CompanyNotFoundException
79
+ else
80
+ raise ApiException, "#{request.code} - #{response[:error][:code]} #{response[:error][:message]}"
70
81
  end
71
82
  else
72
- raise ApiException.new("#{request.code} - API call failed")
83
+ raise ApiException, "#{request.code} - API call failed"
73
84
  end
74
85
  end
75
86
  end
@@ -77,4 +88,4 @@ module BusinessCentral
77
88
  end
78
89
  end
79
90
  end
80
- end
91
+ end