QNE 0.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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +13 -0
  4. data/CHANGELOG.md +5 -0
  5. data/CODE_OF_CONDUCT.md +84 -0
  6. data/Gemfile +13 -0
  7. data/Gemfile.lock +95 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +411 -0
  10. data/Rakefile +12 -0
  11. data/lib/QNE/agent/all.rb +22 -0
  12. data/lib/QNE/customer/all.rb +22 -0
  13. data/lib/QNE/customer/create.rb +21 -0
  14. data/lib/QNE/customer/find.rb +18 -0
  15. data/lib/QNE/customer/find_by.rb +20 -0
  16. data/lib/QNE/customer/show.rb +18 -0
  17. data/lib/QNE/customer/update.rb +21 -0
  18. data/lib/QNE/customer_category/all.rb +22 -0
  19. data/lib/QNE/sales_invoice/all.rb +22 -0
  20. data/lib/QNE/sales_invoice/create.rb +21 -0
  21. data/lib/QNE/sales_invoice/download.rb +26 -0
  22. data/lib/QNE/sales_invoice/find_by.rb +20 -0
  23. data/lib/QNE/sales_invoice/show.rb +18 -0
  24. data/lib/QNE/sales_invoice/update.rb +21 -0
  25. data/lib/QNE/sales_order/all.rb +22 -0
  26. data/lib/QNE/sales_order/create.rb +21 -0
  27. data/lib/QNE/sales_order/show.rb +18 -0
  28. data/lib/QNE/stock/all.rb +22 -0
  29. data/lib/QNE/stock/find.rb +18 -0
  30. data/lib/QNE/stock/uoms.rb +18 -0
  31. data/lib/QNE/stock_location/all.rb +17 -0
  32. data/lib/QNE/tax_code/all.rb +22 -0
  33. data/lib/QNE/tax_code/input_tax_codes.rb +22 -0
  34. data/lib/QNE/tax_code/output_tax_codes.rb +22 -0
  35. data/lib/QNE/term/all.rb +22 -0
  36. data/lib/QNE/term/show.rb +18 -0
  37. data/lib/QNE/uom/all.rb +22 -0
  38. data/lib/QNE/user/login.rb +21 -0
  39. data/lib/QNE/version.rb +5 -0
  40. data/lib/QNE.rb +13 -0
  41. data/lib/agents.rb +17 -0
  42. data/lib/base.rb +23 -0
  43. data/lib/connection.rb +139 -0
  44. data/lib/customer_categories.rb +17 -0
  45. data/lib/customers.rb +71 -0
  46. data/lib/default_tax_code.rb +15 -0
  47. data/lib/query_builder.rb +65 -0
  48. data/lib/sales_invoices.rb +64 -0
  49. data/lib/sales_orders.rb +35 -0
  50. data/lib/stock_locations.rb +15 -0
  51. data/lib/stocks.rb +45 -0
  52. data/lib/system_version.rb +13 -0
  53. data/lib/tax_codes.rb +35 -0
  54. data/lib/terms.rb +26 -0
  55. data/lib/uoms.rb +17 -0
  56. data/lib/users.rb +19 -0
  57. data/sig/QNE.rbs +4 -0
  58. metadata +151 -0
data/lib/connection.rb ADDED
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'agents'
4
+ require_relative 'customers'
5
+ require_relative 'customer_categories'
6
+ require_relative 'default_tax_code'
7
+ require_relative 'sales_invoices'
8
+ require_relative 'sales_orders'
9
+ require_relative 'stocks'
10
+ require_relative 'stock_locations'
11
+ require_relative 'system_version'
12
+ require_relative 'terms'
13
+ require_relative 'uoms'
14
+ require_relative 'tax_codes'
15
+ require_relative 'users'
16
+
17
+ module QNE
18
+ class Connection
19
+ BASE_URI = 'https://dev-api.qne.cloud'.freeze
20
+
21
+ # You can provide your own block before executing retry function
22
+ def initialize(options = {}, &retry_block)
23
+ @db_code = options.fetch(:db_code, nil) || ENV['QNE_DB_CODE']
24
+ @api_token = options.fetch(:api_token, nil)
25
+ @retry_block = retry_block
26
+ end
27
+
28
+ def system_version
29
+ @system_version ||= QNE::SystemVersion.new(connection).call
30
+ end
31
+
32
+ def agents
33
+ @agents ||= QNE::Agents.new(connection)
34
+ end
35
+
36
+ def customers
37
+ @customers ||= QNE::Customers.new(connection)
38
+ end
39
+
40
+ def customer_categories
41
+ @customer_categories ||= QNE::CustomerCategories.new(connection)
42
+ end
43
+
44
+ def default_tax_code
45
+ @default_tax_code ||= QNE::DefaultTaxCode.new(connection).call
46
+ end
47
+
48
+ def sales_invoices
49
+ @sales_invoices ||= QNE::SalesInvoices.new(connection)
50
+ end
51
+
52
+ def sales_orders
53
+ @sales_orders ||= QNE::SalesOrders.new(connection)
54
+ end
55
+
56
+ def stocks
57
+ @stocks ||= QNE::Stocks.new(connection)
58
+ end
59
+
60
+ def terms
61
+ @terms ||= QNE::Terms.new(connection)
62
+ end
63
+
64
+ def stock_locations
65
+ @stock_locations ||= QNE::StockLocations.new(connection)
66
+ end
67
+
68
+ def uoms
69
+ @uoms ||= QNE::UOMs.new(connection)
70
+ end
71
+
72
+ def tax_codes
73
+ @tax_codes ||= QNE::TaxCodes.new(connection)
74
+ end
75
+
76
+ def users
77
+ @users ||= QNE::Users.new(Faraday.new(url: BASE_URI))
78
+ end
79
+
80
+ def connected?
81
+ QNE::SystemVersion.new(connection).call
82
+ rescue Faraday::TimeoutError
83
+ false
84
+ end
85
+
86
+ def authenticated?
87
+ qne = QNE::SystemVersion.new(connection)
88
+ qne.call
89
+ qne.success?
90
+ end
91
+
92
+ def connection
93
+ @connection ||= Faraday.new(faraday_params) do |conn|
94
+ conn.request :retry, retry_options
95
+ conn.adapter Faraday.default_adapter
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ def faraday_params
102
+ @faraday_params ||= {
103
+ url: BASE_URI,
104
+ headers: auth_method,
105
+ request: request_options
106
+ }
107
+ end
108
+
109
+ def retry_options
110
+ @retry_options ||= {
111
+ retry_statuses: [401, 409, 500],
112
+ max: ENV.fetch('MAX_REQUEST_RETRY', '3').to_i, # total request will be made is 4
113
+ interval: ENV.fetch('INTERVAL_RETRY_NUMBER', '10').to_i, # interval each retry request
114
+ backoff_factor: 0,
115
+ exceptions: [Faraday::ResourceNotFound, Faraday::UnauthorizedError, Faraday::TimeoutError, Faraday::ConnectionFailed],
116
+ retry_block: @retry_block
117
+ }
118
+ end
119
+
120
+ def auth_method
121
+ @api_token ? bearer_auth : dbcode_auth
122
+ end
123
+
124
+ def dbcode_auth
125
+ { 'DbCode' => @db_code }
126
+ end
127
+
128
+ def bearer_auth
129
+ { 'Authorization' => "Bearer #{@api_token}" }
130
+ end
131
+
132
+ def request_options
133
+ {
134
+ read_timeout: ENV.fetch('FARADAY_READ_TIMEOUT', '60').to_i,
135
+ timeout: ENV.fetch('FARADAY_TIMEOUT', '60').to_i
136
+ }
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/customer_category/all'
4
+
5
+ module QNE
6
+ class CustomerCategories < Base
7
+ include ::QNE::QueryBuilder
8
+
9
+ def all(params = {})
10
+ @response = QNE::CustomerCategory::All.new(
11
+ conn, params: uri_query(params)
12
+ ).call
13
+
14
+ parse_to_json(@response.body)
15
+ end
16
+ end
17
+ end
data/lib/customers.rb ADDED
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/customer/all'
4
+ require_relative 'QNE/customer/create'
5
+ require_relative 'QNE/customer/find_by'
6
+ require_relative 'QNE/customer/show'
7
+ require_relative 'QNE/customer/update'
8
+ require_relative 'QNE/customer/find'
9
+
10
+ module QNE
11
+ class Customers < Base
12
+ attr_accessor :id, :customer
13
+
14
+ include ::QNE::QueryBuilder
15
+
16
+ def find(id)
17
+ @id = id
18
+ finder = QNE::Customer::Find.new(conn, id: id).call
19
+
20
+ return unless finder.success?
21
+
22
+ define_singleton_method 'show' do
23
+ parse_to_json(finder.body)
24
+ end
25
+
26
+ self
27
+ end
28
+
29
+ def all(params = {})
30
+ @response = QNE::Customer::All.new(
31
+ conn, params: uri_query(params)
32
+ ).call
33
+
34
+ parse_to_json(@response.body)
35
+ end
36
+
37
+ def find_by(params)
38
+ @response = QNE::Customer::FindBy.new(
39
+ conn, params: eq_query(params)
40
+ ).call
41
+
42
+ body = parse_to_json(@response.body)
43
+
44
+ @response.success? ? body.first : body
45
+ end
46
+
47
+ def create(request_body)
48
+ @response = QNE::Customer::Create.new(
49
+ conn, request_body: request_body
50
+ ).call
51
+
52
+ parse_to_json(@response.body)
53
+ end
54
+
55
+ def show(id)
56
+ @response = QNE::Customer::Show.new(
57
+ conn, id: id
58
+ ).call
59
+
60
+ parse_to_json(@response.body)
61
+ end
62
+
63
+ def update(request_body)
64
+ @response = QNE::Customer::Update.new(
65
+ conn, request_body: request_body
66
+ ).call
67
+
68
+ parse_to_json(@response.body)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QNE
4
+ class DefaultTaxCode < Base
5
+ include ::QNE::QueryBuilder
6
+
7
+ PATH = '/api/DefaultTaxCodes/OutputTaxCode'.freeze
8
+
9
+ def call
10
+ @response = conn.get(PATH)
11
+
12
+ parse_to_json(@response.body)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QNE
4
+ module QueryBuilder
5
+ OPERATORS = {
6
+ eq: {
7
+ string: "COLUMN OPERATOR 'VALUE'",
8
+ default: "COLUMN OPERATOR VALUE",
9
+ },
10
+ in: {
11
+ default: "COLUMN OPERATOR (VALUE)"
12
+ }
13
+ }.freeze
14
+
15
+ def eq_query(queries)
16
+ filters = queries.map { |column, value| "#{column} eq '#{value}'" }
17
+ filters.join(' and ')
18
+ end
19
+
20
+ def multi_query(queries)
21
+ filters = queries.map do |column, operators|
22
+ operators.map do |operator, value|
23
+ parse_query_by_operator(column, operator, value)
24
+ end
25
+ end
26
+
27
+ filters.join(' and ')
28
+ end
29
+
30
+ def uri_query(queries)
31
+ return filterables if queries.empty?
32
+
33
+ filters = queries.map do |filter, value|
34
+ { "$#{filter}" => value }
35
+ end
36
+
37
+ filterables.merge(filters.reduce(&:merge))
38
+ end
39
+
40
+ def where(params)
41
+ filterables['$filter'] = multi_query(params)
42
+
43
+ self
44
+ end
45
+
46
+ private
47
+
48
+ def parse_query_by_operator(col, operator, val)
49
+ string = OPERATORS[operator.to_sym]
50
+ datatype = val.class.name.downcase.to_sym
51
+
52
+ return "#{col} #{operator} #{val}" unless string
53
+
54
+ query = String.new(string[datatype] || string[:default])
55
+
56
+ query.gsub!(/COLUMN/, col.to_s)
57
+ query.gsub!(/OPERATOR/, operator.to_s)
58
+ query.gsub!(/VALUE/, val)
59
+ end
60
+
61
+ def filterables
62
+ @filterables ||= {}
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/sales_invoice/find_by'
4
+ require_relative 'QNE/sales_invoice/all'
5
+ require_relative 'QNE/sales_invoice/show'
6
+ require_relative 'QNE/sales_invoice/create'
7
+ require_relative 'QNE/sales_invoice/update'
8
+ require_relative 'QNE/sales_invoice/download'
9
+
10
+ module QNE
11
+ class SalesInvoices < Base
12
+ include ::QNE::QueryBuilder
13
+
14
+ def find_by(params)
15
+ @response = QNE::SalesInvoice::FindBy.new(
16
+ conn, params: eq_query(params)
17
+ ).call
18
+
19
+ body = parse_to_json(@response.body)
20
+
21
+ @response.success? ? body.first : body
22
+ end
23
+
24
+ def all(params = {})
25
+ @response = QNE::SalesInvoice::All.new(
26
+ conn, params: uri_query(params)
27
+ ).call
28
+
29
+ parse_to_json(@response.body)
30
+ end
31
+
32
+ def show(id)
33
+ @response = QNE::SalesInvoice::Show.new(
34
+ conn, id: id
35
+ ).call
36
+
37
+ parse_to_json(@response.body)
38
+ end
39
+
40
+ def create(request_body)
41
+ @response = QNE::SalesInvoice::Create.new(
42
+ conn, request_body: request_body
43
+ ).call
44
+
45
+ parse_to_json(@response.body)
46
+ end
47
+
48
+ def update(request_body)
49
+ @response = QNE::SalesInvoice::Update.new(
50
+ conn, request_body: request_body
51
+ ).call
52
+
53
+ parse_to_json(@response.body)
54
+ end
55
+
56
+ def download(id, type = :sales_invoice)
57
+ @response = QNE::SalesInvoice::Download.new(
58
+ conn, id: id, type: type
59
+ ).call
60
+
61
+ parse_to_json(@response.body)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/sales_order/all'
4
+ require_relative 'QNE/sales_order/show'
5
+ require_relative 'QNE/sales_order/create'
6
+
7
+ module QNE
8
+ class SalesOrders < Base
9
+ include ::QNE::QueryBuilder
10
+
11
+ def all(params = {})
12
+ @response = QNE::SalesOrder::All.new(
13
+ conn, params: uri_query(params)
14
+ ).call
15
+
16
+ parse_to_json(@response.body)
17
+ end
18
+
19
+ def show(id)
20
+ @response = QNE::SalesOrder::Show.new(
21
+ conn, id: id
22
+ ).call
23
+
24
+ parse_to_json(@response.body)
25
+ end
26
+
27
+ def create(request_body)
28
+ @response = QNE::SalesOrder::Create.new(
29
+ conn, request_body: request_body
30
+ ).call
31
+
32
+ parse_to_json(@response.body)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/stock_location/all'
4
+
5
+ module QNE
6
+ class StockLocations < Base
7
+ include ::QNE::QueryBuilder
8
+
9
+ def all
10
+ @response = QNE::StockLocation::All.new(conn).call
11
+
12
+ parse_to_json(@response.body)
13
+ end
14
+ end
15
+ end
data/lib/stocks.rb ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/stock/all'
4
+ require_relative 'QNE/stock/uoms'
5
+ require_relative 'QNE/stock/find'
6
+
7
+ module QNE
8
+ class Stocks < Base
9
+ include ::QNE::QueryBuilder
10
+
11
+ attr_reader :id
12
+
13
+ def find(id)
14
+ finder = QNE::Stocks::Find.new(conn, id: id).call
15
+
16
+ return unless finder.success?
17
+
18
+ define_singleton_method 'uoms' do
19
+ find_uoms_by_id(id)
20
+ end
21
+
22
+ define_singleton_method 'show' do
23
+ @response = parse_to_json(finder.body)
24
+ end
25
+
26
+ self
27
+ end
28
+
29
+ def all(params = {})
30
+ @response = QNE::Stock::All.new(
31
+ conn, params: uri_query(params)
32
+ ).call
33
+
34
+ parse_to_json(@response.body)
35
+ end
36
+
37
+ def find_uoms_by_id(id)
38
+ @response = QNE::Stock::UOMs.new(
39
+ conn, id: id
40
+ ).call
41
+
42
+ parse_to_json(@response.body)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QNE
4
+ class SystemVersion < Base
5
+ PATH = '/api/System/Version'.freeze
6
+
7
+ def call
8
+ @response = conn.get(PATH)
9
+
10
+ parse_to_json(@response.body)
11
+ end
12
+ end
13
+ end
data/lib/tax_codes.rb ADDED
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/tax_code/all'
4
+ require_relative 'QNE/tax_code/output_tax_codes'
5
+ require_relative 'QNE/tax_code/input_tax_codes'
6
+
7
+ module QNE
8
+ class TaxCodes < Base
9
+ include ::QNE::QueryBuilder
10
+
11
+ def all(params = {})
12
+ @response = QNE::TaxCode::All.new(
13
+ conn, params: uri_query(params)
14
+ ).call
15
+
16
+ parse_to_json(@response.body)
17
+ end
18
+
19
+ def output_tax_codes(params = {})
20
+ @response = QNE::TaxCode::OutputTaxCodes.new(
21
+ conn, params: uri_query(params)
22
+ ).call
23
+
24
+ parse_to_json(@response.body)
25
+ end
26
+
27
+ def input_tax_codes(params = {})
28
+ @response = QNE::TaxCode::InputTaxCodes.new(
29
+ conn, params: uri_query(params)
30
+ ).call
31
+
32
+ parse_to_json(@response.body)
33
+ end
34
+ end
35
+ end
data/lib/terms.rb ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/term/all'
4
+ require_relative 'QNE/term/show'
5
+
6
+ module QNE
7
+ class Terms < Base
8
+ include ::QNE::QueryBuilder
9
+
10
+ def all(params = {})
11
+ @response = QNE::Term::All.new(
12
+ conn, params: uri_query(params)
13
+ ).call
14
+
15
+ parse_to_json(@response.body)
16
+ end
17
+
18
+ def show(id)
19
+ @response = QNE::Term::Show.new(
20
+ conn, id: id
21
+ ).call
22
+
23
+ parse_to_json(@response.body)
24
+ end
25
+ end
26
+ end
data/lib/uoms.rb ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/uom/all'
4
+
5
+ module QNE
6
+ class UOMs < Base
7
+ include ::QNE::QueryBuilder
8
+
9
+ def all(params = {})
10
+ @response = QNE::UOM::All.new(
11
+ conn, params: uri_query(params)
12
+ ).call
13
+
14
+ parse_to_json(@response.body)
15
+ end
16
+ end
17
+ end
data/lib/users.rb ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'QNE/user/login'
4
+
5
+ module QNE
6
+ class Users < Base
7
+ def login(username:, password:, db_code:)
8
+ @response = QNE::User::Login.new(
9
+ @conn, params: {
10
+ dbCode: db_code,
11
+ userName: username,
12
+ password: password
13
+ }
14
+ ).call
15
+
16
+ parse_to_json(@response.body)
17
+ end
18
+ end
19
+ end
data/sig/QNE.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module QNE
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end