economic-rest 0.3.6 → 0.4.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
  SHA256:
3
- metadata.gz: e4f478be083c1fa788177f69fc0bab5c60c175243d594a75ee6daacafd15027a
4
- data.tar.gz: 5bf39d0170a7339a082ff5c2454fde2f388b8a5260130fcc9cc73647cde74256
3
+ metadata.gz: 7fbacaa257420baadb45e16d45ad531689e6d14d3be3cdf6571ad0a8abc791d7
4
+ data.tar.gz: cd2f866670a486f601f63da4c8a1c5bdf40289db6caae73036f471aca8200818
5
5
  SHA512:
6
- metadata.gz: bcd925be4161f7c7e7b1557569275f8b10c24fea858cfe85399db97cbcf149a22258af71f29a5b086307ddfb1cc4874d52a36c99c883a0d132d13ea9b2b46f2b
7
- data.tar.gz: 914706cf3c7ea9175b682b0dcdb930c18abf502ccd06191d0d3645a88fa02da7d02a1d4c4a0e05195c1fec25b96f0fcce87fbc7f7343a8d78924b5c02f9296dc
6
+ metadata.gz: 0e923292ba32f2adf4832e261cfc38e6f3328cbdec42a19219b11c9133509a1e5e6fb15deb36ae169612dcb769edfde2058db848c42b0dfd0104de8c556252d7
7
+ data.tar.gz: 51e379f96f4907a9dfcdbd070fd3f8d6bb942456db674db9eb1e04faba186853cdf1b1a81d39fbf5bf55db031ebed3bbdbbb63047c137f5ff04fa4092cfb4bdb
data/.gitignore CHANGED
@@ -8,3 +8,6 @@
8
8
 
9
9
  # Ignore coverage
10
10
  /coverage
11
+
12
+ # Ignore environment variables
13
+ .env
@@ -0,0 +1,9 @@
1
+ {
2
+ "ruby.useLanguageServer": true,
3
+ "ruby.lint": {"standard": true},
4
+ "ruby.format": "standard",
5
+ "[ruby]": {
6
+ "editor.formatOnSave": true,
7
+ },
8
+ "editor.formatOnSaveTimeout": 1500,
9
+ }
data/Gemfile.lock CHANGED
@@ -1,23 +1,48 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- economic-rest (0.3.5)
4
+ economic-rest (0.4.0)
5
+ activesupport
6
+ awesome_print
5
7
  rest-client
8
+ savon
6
9
 
7
10
  GEM
8
11
  remote: https://rubygems.org/
9
12
  specs:
13
+ activesupport (6.0.0)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 0.7, < 2)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ zeitwerk (~> 2.1, >= 2.1.8)
10
19
  addressable (2.5.2)
11
20
  public_suffix (>= 2.0.2, < 4.0)
21
+ akami (1.3.1)
22
+ gyoku (>= 0.4.0)
23
+ nokogiri
24
+ ast (2.4.0)
25
+ awesome_print (1.8.0)
26
+ builder (3.2.3)
27
+ concurrent-ruby (1.1.5)
12
28
  crack (0.4.3)
13
29
  safe_yaml (~> 1.0.0)
14
30
  docile (1.3.1)
15
31
  domain_name (0.5.20190701)
16
32
  unf (>= 0.0.5, < 1.0.0)
33
+ dotenv (2.7.4)
34
+ gyoku (1.3.1)
35
+ builder (>= 2.1.2)
17
36
  hashdiff (0.3.8)
18
37
  http-accept (1.7.0)
19
38
  http-cookie (1.0.3)
20
39
  domain_name (~> 0.5)
40
+ httpi (2.4.4)
41
+ rack
42
+ socksify
43
+ i18n (1.6.0)
44
+ concurrent-ruby (~> 1.0)
45
+ jaro_winkler (1.5.3)
21
46
  json (2.1.0)
22
47
  m (1.5.1)
23
48
  method_source (>= 0.6.7)
@@ -26,39 +51,80 @@ GEM
26
51
  mime-types (3.3)
27
52
  mime-types-data (~> 3.2015)
28
53
  mime-types-data (3.2019.0904)
54
+ mini_portile2 (2.4.0)
29
55
  minitest (5.11.3)
30
56
  netrc (0.11.0)
57
+ nokogiri (1.10.4)
58
+ mini_portile2 (~> 2.4.0)
59
+ nori (2.6.0)
60
+ parallel (1.17.0)
61
+ parser (2.6.4.1)
62
+ ast (~> 2.4.0)
31
63
  public_suffix (3.0.3)
64
+ rack (2.0.7)
65
+ rainbow (3.0.0)
32
66
  rake (10.5.0)
33
67
  rest-client (2.1.0)
34
68
  http-accept (>= 1.7.0, < 2.0)
35
69
  http-cookie (>= 1.0.2, < 2.0)
36
70
  mime-types (>= 1.16, < 4.0)
37
71
  netrc (~> 0.8)
72
+ rubocop (0.72.0)
73
+ jaro_winkler (~> 1.5.1)
74
+ parallel (~> 1.10)
75
+ parser (>= 2.6)
76
+ rainbow (>= 2.2.2, < 4.0)
77
+ ruby-progressbar (~> 1.7)
78
+ unicode-display_width (>= 1.4.0, < 1.7)
79
+ rubocop-performance (1.4.1)
80
+ rubocop (>= 0.71.0)
81
+ ruby-progressbar (1.10.1)
38
82
  safe_yaml (1.0.4)
83
+ savon (2.12.0)
84
+ akami (~> 1.2)
85
+ builder (>= 2.1.2)
86
+ gyoku (~> 1.2)
87
+ httpi (~> 2.3)
88
+ nokogiri (>= 1.8.1)
89
+ nori (~> 2.4)
90
+ wasabi (~> 3.4)
39
91
  simplecov (0.16.1)
40
92
  docile (~> 1.1)
41
93
  json (>= 1.8, < 3)
42
94
  simplecov-html (~> 0.10.0)
43
95
  simplecov-html (0.10.2)
96
+ socksify (1.7.1)
97
+ standard (0.1.4)
98
+ rubocop (~> 0.72.0)
99
+ rubocop-performance (~> 1.4.0)
100
+ thread_safe (0.3.6)
101
+ tzinfo (1.2.5)
102
+ thread_safe (~> 0.1)
44
103
  unf (0.1.4)
45
104
  unf_ext
46
105
  unf_ext (0.0.7.6)
106
+ unicode-display_width (1.6.0)
107
+ wasabi (3.5.0)
108
+ httpi (~> 2.0)
109
+ nokogiri (>= 1.4.2)
47
110
  webmock (3.5.1)
48
111
  addressable (>= 2.3.6)
49
112
  crack (>= 0.3.2)
50
113
  hashdiff
114
+ zeitwerk (2.1.10)
51
115
 
52
116
  PLATFORMS
53
117
  ruby
54
118
 
55
119
  DEPENDENCIES
56
120
  bundler (~> 1.17)
121
+ dotenv
57
122
  economic-rest!
58
123
  m
59
124
  minitest (~> 5.0)
60
125
  rake (~> 10.0)
61
126
  simplecov
127
+ standard
62
128
  webmock (~> 3.5)
63
129
 
64
130
  BUNDLED WITH
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Economic::Rest
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/economic/rest`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ [![Build Status](https://semaphoreci.com/api/v1/traels-it/economic-rest/branches/master/badge.svg)](https://semaphoreci.com/traels-it/economic-rest)
4
4
 
5
5
  Ruby wrapper for the e-conomic REST API, that aims at making working with the API bearable.
6
6
  E-conomic is a web-based accounting system. For their marketing speak, see http://www.e-conomic.co.uk/about/. More details about their API at http://www.e-conomic.co.uk/integration/integration-partner/'.
@@ -25,33 +25,40 @@ Or install it yourself as:
25
25
 
26
26
  ## Usage
27
27
 
28
+ ```ruby
28
29
  require 'economic/rest'
29
30
 
30
31
  Economic::Demo.hello
32
+ ```
31
33
 
32
34
  Filter text can be added to the all query to avoid getting everything. e.g. a method for finding an accounting year for a specific date
33
35
 
36
+ ```ruby
34
37
  def get_accounting_year(date)
35
38
  Economic::AccountingYearRepo.all(filter_text: "toDate$gte:#{date}$and:fromDate$lte:#{date}")
36
39
  end
40
+ ```
37
41
 
38
42
  note: you need to use Lower Camel Case for variable names.
39
- Filter Operators
43
+
44
+ ### Filter Operators
40
45
 
41
46
  The allowed filtering operators are:
42
47
 
43
- Operator Syntax
44
- Equals “$eq:”
45
- Not equals “$ne:”
46
- Greater than “$gt:”
47
- Greater than or equal “$gte:”
48
- Less than “$lt:”
49
- Less than or equal “$lte:”
50
- Substring match “$like:”
51
- And also “$and:”
52
- Or else “$or:”
53
- In “$in:”
54
- Not In “$nin:”
48
+ | Operator | Syntax |
49
+ | -------- | --------- |
50
+ | Equals | `$eq:` |
51
+ | Not equals | `$ne:` |
52
+ | Greater than | `$gt:` |
53
+ | Greater than or equal | `$gte:` |
54
+ | Less than | `$lt:` |
55
+ | Less than or equal | `$lte:` |
56
+ | Substring match | `$like:` |
57
+ | And also | `$and:` |
58
+ | Or else | `$or:` |
59
+ | In | `$in:` |
60
+ | Not In | `$nin:` |
61
+
55
62
  copy pasta from https://restdocs.e-conomic.com/#specifying-operator-affinity
56
63
 
57
64
  ## Development
@@ -29,6 +29,11 @@ The documentation can be found at https://restdocs.e-conomic.com'
29
29
  spec.add_development_dependency "rake", "~> 10.0"
30
30
  spec.add_development_dependency "simplecov"
31
31
  spec.add_development_dependency "webmock", "~> 3.5"
32
+ spec.add_development_dependency "dotenv"
33
+ spec.add_development_dependency "standard"
32
34
 
35
+ spec.add_dependency "savon"
33
36
  spec.add_dependency "rest-client"
37
+ spec.add_dependency "activesupport"
38
+ spec.add_dependency "awesome_print"
34
39
  end
data/lib/economic/base.rb CHANGED
@@ -12,8 +12,8 @@ module Economic
12
12
  (@attributes ||= []).push(name)
13
13
  end
14
14
 
15
- def self.add_relation(name, fields)
16
- (@relations ||= []).push(name: name, fields: fields)
15
+ def self.add_relation(name, fields, multiple)
16
+ (@relations ||= []).push(name: name, fields: fields, multiple: multiple)
17
17
  end
18
18
 
19
19
  def self.field(name, id: false)
@@ -22,13 +22,19 @@ module Economic
22
22
  alias_method snake_case(economic_cased_attibute_name), economic_cased_attibute_name
23
23
  alias_method "#{snake_case(economic_cased_attibute_name)}=", "#{economic_cased_attibute_name}="
24
24
  alias_method "id_key", economic_cased_attibute_name if id
25
+ alias_method "id_key=", "#{economic_cased_attibute_name}=" if id
25
26
  add_attribute economic_cased_attibute_name
26
27
  end
27
28
 
28
- def self.relation(name, fields:)
29
+ def self.relation(name, fields:, multiple: false)
29
30
  economic_cased_attibute_name = name.to_s
30
- add_relation economic_cased_attibute_name, fields
31
- attr_reader economic_cased_attibute_name
31
+ add_relation economic_cased_attibute_name, fields, multiple
32
+ if multiple
33
+ attr_accessor economic_cased_attibute_name
34
+ alias_method "#{snake_case(economic_cased_attibute_name)}=", "#{economic_cased_attibute_name}="
35
+ else
36
+ attr_reader economic_cased_attibute_name
37
+ end
32
38
  alias_method snake_case(economic_cased_attibute_name), economic_cased_attibute_name
33
39
  end
34
40
 
@@ -39,10 +45,18 @@ module Economic
39
45
  end
40
46
 
41
47
  self.class.relations&.each do |relation_hash|
42
- name = relation_hash[:name]
43
- related_model = model_class(name).new(@internal_hash[name])
44
-
45
- instance_variable_set("@#{name}", related_model)
48
+ if relation_hash[:multiple]
49
+ relation_name = relation_hash[:name]
50
+ model_name = relation_hash[:name].singularize
51
+ related_model_array = @internal_hash[relation_name]&.map { |data|
52
+ model_class(model_name).new(data)
53
+ }
54
+ instance_variable_set("@#{relation_name}", related_model_array)
55
+ else
56
+ name = relation_hash[:name]
57
+ related_model = model_class(name).new(@internal_hash[name])
58
+ instance_variable_set("@#{name}", related_model)
59
+ end
46
60
  end
47
61
  end
48
62
 
@@ -56,12 +70,21 @@ module Economic
56
70
  end
57
71
 
58
72
  self.class.relations&.each do |relation_hash|
59
- relation_name = relation_hash[:name]
60
- relation_fields = relation_hash[:fields]
73
+ if relation_hash[:multiple]
74
+ relation_name = relation_hash[:name]
75
+ relation_fields = relation_hash[:fields]
76
+
77
+ arr = public_send(relation_name).map { |relation| relation_data = relation.to_h(only_fields: relation_fields) }
78
+
79
+ return_hash[relation_name] = arr
80
+ else
81
+ relation_name = relation_hash[:name]
82
+ relation_fields = relation_hash[:fields]
61
83
 
62
- relation_data = public_send(relation_name).to_h(only_fields: relation_fields)
84
+ relation_data = public_send(relation_name).to_h(only_fields: relation_fields)
63
85
 
64
- return_hash[relation_name] = relation_data unless relation_data.empty?
86
+ return_hash[relation_name] = relation_data unless relation_data.empty?
87
+ end
65
88
  end
66
89
  return_hash
67
90
  end
@@ -57,6 +57,12 @@ module Economic
57
57
 
58
58
  private
59
59
 
60
+ def destroy(id)
61
+ response = send_request(method: :delete, url: endpoint_url + "/" + id.to_s)
62
+
63
+ JSON.parse(response.body)["message"] == "Deleted #{model.to_s.split("::").last.downcase}."
64
+ end
65
+
60
66
  def model
61
67
  scopes = name.split("::")
62
68
  scopes[1] = scopes[1][0...-1] if scopes.count == 3
@@ -73,6 +79,9 @@ module Economic
73
79
  end
74
80
  end_p = end_p.gsub("Journals", "Journals-Experimental")
75
81
  end_p = end_p.gsub("Selfs", "Self")
82
+ # PaymentTerms is named with a plural s for a single record, but the end point is still just paymentterms.
83
+ # Therefore the endpoint gets substituted
84
+ end_p = end_p.gsub("PaymentTermss", "PaymentTerms")
76
85
  kebab(end_p)
77
86
  end
78
87
 
@@ -0,0 +1,183 @@
1
+ require "active_support/concern"
2
+
3
+ module Economic
4
+ module SoapMethods
5
+ extend ActiveSupport::Concern
6
+
7
+ class_methods do
8
+ def find(id)
9
+ result = Economic::SoapAPI.call(
10
+ soap_method_names[:find][:method],
11
+ message: {soap_method_names[:find][:handle] => {Id: id}}
12
+ )
13
+
14
+ model.build_from_soap_api(result)
15
+ end
16
+
17
+ def all
18
+ result = Economic::SoapAPI.call(
19
+ soap_method_names[:all][:method],
20
+ )
21
+
22
+ ids = result_array(result[soap_method_names[:all][:handle]]).map { |record|
23
+ record[:id].to_i
24
+ }
25
+
26
+ find_all_records(ids)
27
+ end
28
+
29
+ def send(model)
30
+ # There is a current_invoice_create_from_data_array method for bulk creation of invoices as well, but bulk
31
+ # creation is not supported by the e-conomic REST api or any other REST api. To avoid implementing
32
+ # functionality that will be removed once e-conomic finish the REST api, we only use the standard create end
33
+ # point
34
+
35
+ result = Economic::SoapAPI.call(
36
+ soap_method_names[:send][:method], message: {
37
+ soap_method_names[:send][:handle] => {
38
+ Number: model.customer.customerNumber,
39
+ },
40
+ }
41
+ )
42
+
43
+ model.id_key = result[:id]
44
+
45
+ create_lines(model) if model.lines.any?
46
+
47
+ find(result[:id].to_i)
48
+ end
49
+
50
+ def find_lines(invoice_id)
51
+ result = Economic::SoapAPI.call(
52
+ soap_method_names[:find_lines][:method],
53
+ message: {soap_method_names[:find_lines][:handle] => {Id: invoice_id}}
54
+ )
55
+
56
+ return if result.nil?
57
+
58
+ line_ids = result_array(result[soap_method_names[:find_lines][:line_handle]]).map { |line|
59
+ line[:number].to_i
60
+ }
61
+
62
+ find_all_lines(invoice_id, line_ids)
63
+ end
64
+
65
+ def destroy(id)
66
+ # The SoapAPI raises an exception if the record you try to delete is missing
67
+
68
+ result = Economic::SoapAPI.call(
69
+ soap_method_names[:destroy][:method],
70
+ message: {soap_method_names[:destroy][:handle] => {Id: id}}
71
+ )
72
+
73
+ true
74
+ rescue Savon::SOAPFault
75
+ false
76
+ end
77
+
78
+ private
79
+
80
+ # Since the soap api returns hashes, if there is a single record, and arrays, if there are more, this method
81
+ # wraps a response in an array, if it is not already.
82
+ def result_array(result)
83
+ return result if result.is_a? Array
84
+
85
+ [result]
86
+ end
87
+
88
+ def create_lines(model)
89
+ Economic::SoapAPI.call(
90
+ soap_method_names[:create_lines][:method], message: {
91
+ dataArray: build_line_data_array(model),
92
+ }
93
+ )
94
+ end
95
+
96
+ def find_all_lines(invoice_id, line_ids)
97
+ result = Economic::SoapAPI.call(
98
+ soap_method_names[:find_all_lines][:method],
99
+ message: {soap_method_names[:find_all_lines][:handle] => line_ids_array(invoice_id, line_ids, handle: soap_method_names[:find_all_lines][:line_handle])}
100
+ )
101
+
102
+ result_array(result[soap_method_names[:find_all_lines][:data]]).map do |data|
103
+ Economic::Line.build_from_soap_api(data)
104
+ end
105
+ end
106
+
107
+ def find_all_records(invoice_ids)
108
+ result = Economic::SoapAPI.call(
109
+ soap_method_names[:find_all_records][:method],
110
+ message: {
111
+ entityHandles: ids_array(invoice_ids, handle: soap_method_names[:find_all_records][:handle]),
112
+ }
113
+ )
114
+
115
+ result[soap_method_names[:find_all_records][:data]].map do |data|
116
+ model.build_from_soap_api(data)
117
+ end
118
+ end
119
+
120
+ def line_ids_array(order_id, line_ids, handle:)
121
+ arr = [handle => []]
122
+
123
+ line_ids.each do |line_id|
124
+ arr.first[handle].push(
125
+ {
126
+ Id: order_id,
127
+ Number: line_id,
128
+ }
129
+ )
130
+ end
131
+
132
+ arr
133
+ end
134
+
135
+ def ids_array(invoice_ids, handle:)
136
+ arr = [handle => []]
137
+
138
+ invoice_ids.each do |invoice_id|
139
+ arr.first[handle].push(
140
+ {
141
+ Id: invoice_id,
142
+ }
143
+ )
144
+ end
145
+
146
+ arr
147
+ end
148
+
149
+ def build_line_data_array(order)
150
+ arr = [soap_method_names[:create_lines][:line_data_handle] => []]
151
+
152
+ order.lines.each do |line|
153
+ arr.first[soap_method_names[:create_lines][:line_data_handle]].push(
154
+ {
155
+ :Handle => {
156
+ Id: order.id_key,
157
+ Number: line.line_number, # must be sent - does not have to fit with the next linenumber
158
+ },
159
+ :Id => order.id_key,
160
+ :Number => line.line_number, # must be sent - does not have to fit with the next linenumber
161
+ soap_method_names[:create_lines][:model_handle] => {
162
+ Id: order.id_key,
163
+ },
164
+ :Description => line.description,
165
+ :DeliveryDate => line.delivery.delivery_date,
166
+ :UnitHandle => {Number: line.unit.unit_number},
167
+ :ProductHandle => {Number: line.product.product_number},
168
+ :Quantity => line.quantity,
169
+ :UnitNetPrice => line.unit_net_price,
170
+ :DiscountAsPercent => line.discount_percentage,
171
+ :UnitCostPrice => line.unit_cost_price,
172
+ :TotalNetAmount => line.total_net_amount, # TODO: Should this not be sent?
173
+ :TotalMargin => line.margin_in_base_currency,
174
+ :MarginAsPercent => line.margin_percentage,
175
+ }
176
+ )
177
+ end
178
+
179
+ arr
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,56 @@
1
+ module Economic
2
+ class Invoice < Base
3
+ # currency, customer, date, layout, paymentTerms, recipient, recipient.name, recipient.vatZone
4
+ field :currency
5
+ field :date
6
+ field :dueDate
7
+ field :exchangeRate
8
+ field :grossAmount
9
+ field :grossAmountInBaseCurrency
10
+ field :marginInBaseCurrency
11
+ field :marginPercentage
12
+ field :netAmount
13
+ field :roundingAmount
14
+ field :vatAmount
15
+ field :draftInvoiceNumber, id: true # This changes name depending on its type (draft, unpaid etc)
16
+
17
+ relation :customer, fields: [:customerNumber]
18
+ # relation :delivery, fields: []
19
+ # relation :deliveryLocation, fields: []
20
+ relation :layout, fields: [:layoutNumber]
21
+ # relation :notes, fields: []
22
+ relation :paymentTerms, fields: [:paymentTermsNumber]
23
+ # relation :pdf, fields: []
24
+ # relation :project, fields: []
25
+ relation :recipient, fields: [:name]
26
+ relation :references, fields: [:other]
27
+ relation :lines, fields: [:lineNumber], multiple: true
28
+
29
+ def self.build_from_soap_api(data)
30
+ hash = {
31
+ "currency" => data[:currency_handle][:code],
32
+ "date" => data[:date].to_date,
33
+ "dueDate" => data[:due_date].to_date,
34
+ "exchangeRate" => data[:exchange_rate],
35
+ "grossAmount" => data[:gross_amount],
36
+ # where is grossAmountInBaseCurrency?
37
+ "lines" => repo.find_lines(data[:handle][:id]),
38
+ "marginInBaseCurrency" => data[:margin],
39
+ "marginPercentage" => data[:margin_as_percent],
40
+ "netAmount" => data[:net_amount],
41
+ "roundingAmount" => data[:rounding_amount],
42
+ "vatAmount" => data[:vat_amount],
43
+ "draftInvoiceNumber" => data[:handle][:id], # TODO: What about id?
44
+ "customer" => {"customerNumber" => data[:debtor_handle][:id].to_i},
45
+ "layout" => {"layoutNumber" => data[:layout_handle][:id].to_i},
46
+ "paymentTerms" => {"paymentTermsNumber" => data[:term_of_payment_handle][:id].to_i},
47
+ }
48
+
49
+ new(hash)
50
+ end
51
+
52
+ def self.repo
53
+ Economic::Invoices::DraftsRepo
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,6 @@
1
+ module Economic
2
+ module Invoices
3
+ class BookedRepo < Economic::Invoices::Repo
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,42 @@
1
+ module Economic
2
+ module Invoices
3
+ class DraftsRepo < Economic::Invoices::Repo
4
+ include Economic::SoapMethods
5
+
6
+ class << self
7
+ def soap_method_names
8
+ {
9
+ find: {method: :current_invoice_get_data, handle: :entityHandle},
10
+ all: {method: :current_invoice_get_all, handle: :current_invoice_handle},
11
+ send: {method: :current_invoice_create, handle: :debtorHandle},
12
+ find_lines: {
13
+ method: :current_invoice_get_lines,
14
+ handle: :currentInvoiceHandle,
15
+ line_handle: :current_invoice_line_handle,
16
+ },
17
+ create_lines: {
18
+ method: :current_invoice_line_create_from_data_array,
19
+ line_data_handle: :CurrentInvoiceLineData,
20
+ model_handle: :InvoiceHandle,
21
+ },
22
+ find_all_lines: {
23
+ method: :current_invoice_line_get_data_array,
24
+ handle: :entityHandles,
25
+ data: :current_invoice_line_data,
26
+ line_handle: :CurrentInvoiceLineHandle,
27
+ },
28
+ find_all_records: {
29
+ method: :current_invoice_get_data_array,
30
+ handle: :CurrentInvoiceHandle,
31
+ data: :current_invoice_data,
32
+ },
33
+ destroy: {
34
+ method: :current_invoice_delete,
35
+ handle: :currentInvoiceHandle,
36
+ },
37
+ }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,6 @@
1
+ module Economic
2
+ module Invoices
3
+ class NotDueRepo < Economic::Invoices::Repo
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Economic
2
+ module Invoices
3
+ class OverdueRepo < Economic::Invoices::Repo
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Economic
2
+ module Invoices
3
+ class PaidRepo < Economic::Invoices::Repo
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Economic
2
+ module Invoices
3
+ class Repo < Economic::BaseRepo
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Economic
2
+ module Invoices
3
+ class SentRepo < Economic::Invoices::Repo
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Economic
2
+ module Invoices
3
+ class UnpaidRepo < Economic::Invoices::Repo
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,39 @@
1
+ module Economic
2
+ class Line < Base
3
+ field :lineNumber
4
+ field :description
5
+ field :sortKey
6
+ field :quantity
7
+ field :unitNetPrice
8
+ field :discountPercentage
9
+ field :unitCostPrice
10
+ field :marginInBaseCurrency
11
+ field :marginPercentage
12
+ field :totalNetAmount
13
+
14
+ relation :product, fields: [:productNumber]
15
+ relation :unit, fields: [:unitNumber, :name]
16
+ relation :delivery, fields: [:address, :zip, :city, :country, :deliveryDate]
17
+
18
+ def self.build_from_soap_api(data)
19
+ # This is not instantiated with the hash, as lines are never pulled out by themselves, but always as part of
20
+ # a invoice or order
21
+ {
22
+ "lineNumber" => data[:number].to_i,
23
+ "description" => data[:description],
24
+ "quantity" => data[:quantity].to_f,
25
+ "unitNetPrice" => data[:unit_net_price].to_f,
26
+ "discountPercentage" => data[:discount_as_percent].to_f,
27
+ "unitCostPrice" => data[:unit_cost_price].to_f,
28
+ "totalNetAmount" => data[:total_net_amount].to_f,
29
+ "marginPercentage" => data[:margin_as_percent].to_f,
30
+ "marginInBaseCurrency" => data[:total_margin].to_f,
31
+ "product" => {"productNumber" => data[:product_handle][:number]},
32
+ # Unmapped values in soap
33
+ # delivery_date
34
+ # :accrual_start_date => nil,
35
+ # :accrual_end_date => nil
36
+ }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,4 @@
1
+ module Economic
2
+ class PaymentTermsRepo < Economic::BaseRepo
3
+ end
4
+ end
data/lib/economic/rest.rb CHANGED
@@ -1,8 +1,14 @@
1
1
  require "economic/rest/version"
2
+ require "dotenv/load"
2
3
  require "rest-client"
4
+ require "savon"
5
+ require "awesome_print"
6
+ require "active_support/inflector"
3
7
 
4
8
  require "economic/base_repo"
5
9
  require "economic/base"
10
+ require "economic/soap_api"
11
+ require "economic/concerns/soap_methods"
6
12
 
7
13
  require "economic/currency"
8
14
  require "economic/vat_zone"
@@ -19,6 +25,7 @@ require "economic/layout"
19
25
  require "economic/layout_repo"
20
26
  require "economic/notes"
21
27
  require "economic/payment_terms"
28
+ require "economic/payment_terms_repo"
22
29
  require "economic/pdf"
23
30
  require "economic/project"
24
31
  require "economic/recipient"
@@ -38,6 +45,16 @@ require "economic/orders/drafts_repo"
38
45
  require "economic/orders/sent_repo"
39
46
  require "economic/product_group_repo"
40
47
 
48
+ require "economic/invoices/repo"
49
+ require "economic/invoice"
50
+ require "economic/invoices/drafts_repo"
51
+ require "economic/invoices/booked_repo"
52
+ require "economic/invoices/not_due_repo"
53
+ require "economic/invoices/overdue_repo"
54
+ require "economic/invoices/paid_repo"
55
+ require "economic/invoices/sent_repo"
56
+ require "economic/invoices/unpaid_repo"
57
+
41
58
  require "economic/journal_repo"
42
59
  require "economic/journal"
43
60
  require "economic/journal_voucher_repo"
@@ -49,10 +66,12 @@ require "economic/accounting_year_repo"
49
66
  require "economic/unit"
50
67
  require "economic/unit_repo"
51
68
 
52
- require 'economic/user'
69
+ require "economic/user"
70
+
53
71
  require "economic/company"
54
72
  require "economic/self"
55
73
  require "economic/self_repo"
74
+ require "economic/line"
56
75
 
57
76
  module Economic
58
77
  class Demo
@@ -1,5 +1,5 @@
1
1
  module Economic
2
2
  module Rest
3
- VERSION = "0.3.6".freeze
3
+ VERSION = "0.4.0".freeze
4
4
  end
5
5
  end
@@ -0,0 +1,24 @@
1
+ module Economic
2
+ class SoapAPI
3
+ URL = "https://api.e-conomic.com/secure/api1/EconomicWebService.asmx?WSDL".freeze
4
+
5
+ class << self
6
+ def call(method, message: {})
7
+ response = client.call(method, message: message, cookies: auth_cookies)
8
+
9
+ response.body["#{method}_response".to_sym]["#{method}_result".to_sym]
10
+ end
11
+
12
+ def auth_cookies
13
+ @auth_cookies ||= client.call(:connect_with_token, message: {token: Economic::Session.agreement_grant_token, appToken: Economic::Session.app_secret_token}).http.cookies
14
+ end
15
+
16
+ def client
17
+ @client ||= Savon.client {
18
+ wsdl(URL)
19
+ convert_request_keys_to :none # or one of [:lower_camelcase, :upcase, :none]
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: economic-rest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Klogborg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-26 00:00:00.000000000 Z
11
+ date: 2019-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,6 +94,48 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '3.5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: dotenv
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: standard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: savon
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
97
139
  - !ruby/object:Gem::Dependency
98
140
  name: rest-client
99
141
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +150,34 @@ dependencies:
108
150
  - - ">="
109
151
  - !ruby/object:Gem::Version
110
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: activesupport
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: awesome_print
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
111
181
  description:
112
182
  email:
113
183
  - klogborg@traels.it
@@ -116,6 +186,7 @@ extensions: []
116
186
  extra_rdoc_files: []
117
187
  files:
118
188
  - ".gitignore"
189
+ - ".vscode/settings.json"
119
190
  - CODE_OF_CONDUCT.md
120
191
  - Gemfile
121
192
  - Gemfile.lock
@@ -130,6 +201,7 @@ files:
130
201
  - lib/economic/base.rb
131
202
  - lib/economic/base_repo.rb
132
203
  - lib/economic/company.rb
204
+ - lib/economic/concerns/soap_methods.rb
133
205
  - lib/economic/currency.rb
134
206
  - lib/economic/customer.rb
135
207
  - lib/economic/customer_group.rb
@@ -137,11 +209,21 @@ files:
137
209
  - lib/economic/customer_repo.rb
138
210
  - lib/economic/delivery.rb
139
211
  - lib/economic/inventory.rb
212
+ - lib/economic/invoice.rb
213
+ - lib/economic/invoices/booked_repo.rb
214
+ - lib/economic/invoices/drafts_repo.rb
215
+ - lib/economic/invoices/not_due_repo.rb
216
+ - lib/economic/invoices/overdue_repo.rb
217
+ - lib/economic/invoices/paid_repo.rb
218
+ - lib/economic/invoices/repo.rb
219
+ - lib/economic/invoices/sent_repo.rb
220
+ - lib/economic/invoices/unpaid_repo.rb
140
221
  - lib/economic/journal.rb
141
222
  - lib/economic/journal_repo.rb
142
223
  - lib/economic/journal_voucher_repo.rb
143
224
  - lib/economic/layout.rb
144
225
  - lib/economic/layout_repo.rb
226
+ - lib/economic/line.rb
145
227
  - lib/economic/notes.rb
146
228
  - lib/economic/order.rb
147
229
  - lib/economic/orders/archived_repo.rb
@@ -149,6 +231,7 @@ files:
149
231
  - lib/economic/orders/repo.rb
150
232
  - lib/economic/orders/sent_repo.rb
151
233
  - lib/economic/payment_terms.rb
234
+ - lib/economic/payment_terms_repo.rb
152
235
  - lib/economic/pdf.rb
153
236
  - lib/economic/pricing.rb
154
237
  - lib/economic/pricing_repo.rb
@@ -164,6 +247,7 @@ files:
164
247
  - lib/economic/self.rb
165
248
  - lib/economic/self_repo.rb
166
249
  - lib/economic/session.rb
250
+ - lib/economic/soap_api.rb
167
251
  - lib/economic/unit.rb
168
252
  - lib/economic/unit_repo.rb
169
253
  - lib/economic/user.rb