fortnox-api 0.7.2 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +1 -0
- data/.rubocop.yml +1 -1
- data/.tool-versions +1 -0
- data/.travis.yml +5 -10
- data/CHANGELOG.md +45 -1
- data/README.md +7 -4
- data/Rakefile +5 -0
- data/fortnox-api.gemspec +22 -17
- data/lib/fortnox/api/mappers/article.rb +1 -1
- data/lib/fortnox/api/mappers/base/from_json.rb +3 -3
- data/lib/fortnox/api/mappers/base/to_json.rb +2 -2
- data/lib/fortnox/api/mappers/base.rb +3 -3
- data/lib/fortnox/api/mappers/customer.rb +1 -1
- data/lib/fortnox/api/mappers/default_delivery_types.rb +1 -1
- data/lib/fortnox/api/mappers/default_templates.rb +1 -1
- data/lib/fortnox/api/mappers/edi_information.rb +1 -1
- data/lib/fortnox/api/mappers/email_information.rb +1 -1
- data/lib/fortnox/api/mappers/invoice.rb +4 -4
- data/lib/fortnox/api/mappers/invoice_row.rb +1 -1
- data/lib/fortnox/api/mappers/order.rb +4 -4
- data/lib/fortnox/api/mappers/order_row.rb +1 -1
- data/lib/fortnox/api/mappers/project.rb +1 -1
- data/lib/fortnox/api/mappers/terms_of_payment.rb +1 -1
- data/lib/fortnox/api/mappers/unit.rb +1 -1
- data/lib/fortnox/api/mappers/value/country_string.rb +1 -1
- data/lib/fortnox/api/mappers.rb +18 -18
- data/lib/fortnox/api/models/article.rb +2 -2
- data/lib/fortnox/api/models/base.rb +14 -14
- data/lib/fortnox/api/models/customer.rb +2 -2
- data/lib/fortnox/api/models/document.rb +5 -2
- data/lib/fortnox/api/models/invoice.rb +2 -2
- data/lib/fortnox/api/models/label.rb +1 -1
- data/lib/fortnox/api/models/order.rb +2 -2
- data/lib/fortnox/api/models/project.rb +2 -2
- data/lib/fortnox/api/models/terms_of_payment.rb +2 -2
- data/lib/fortnox/api/models/unit.rb +2 -2
- data/lib/fortnox/api/models.rb +7 -7
- data/lib/fortnox/api/repositories/article.rb +3 -3
- data/lib/fortnox/api/repositories/base.rb +4 -3
- data/lib/fortnox/api/repositories/customer.rb +3 -3
- data/lib/fortnox/api/repositories/invoice.rb +3 -3
- data/lib/fortnox/api/repositories/order.rb +3 -3
- data/lib/fortnox/api/repositories/project.rb +3 -3
- data/lib/fortnox/api/repositories/terms_of_payment.rb +3 -3
- data/lib/fortnox/api/repositories/unit.rb +3 -3
- data/lib/fortnox/api/repositories.rb +7 -7
- data/lib/fortnox/api/types/default_delivery_types.rb +0 -2
- data/lib/fortnox/api/types/default_templates.rb +0 -2
- data/lib/fortnox/api/types/edi_information.rb +0 -2
- data/lib/fortnox/api/types/email_information.rb +0 -2
- data/lib/fortnox/api/types/enums.rb +36 -8
- data/lib/fortnox/api/types/invoice_row.rb +1 -1
- data/lib/fortnox/api/types/model.rb +4 -6
- data/lib/fortnox/api/types/nullable.rb +13 -9
- data/lib/fortnox/api/types/order_row.rb +1 -1
- data/lib/fortnox/api/types/required.rb +3 -3
- data/lib/fortnox/api/types/sized.rb +2 -2
- data/lib/fortnox/api/types.rb +23 -23
- data/lib/fortnox/api/version.rb +1 -1
- data/lib/fortnox/api.rb +18 -16
- data/spec/fortnox/api/circular_queue_spec.rb +3 -3
- data/spec/fortnox/api/mappers/base/canonical_name_sym_spec.rb +9 -7
- data/spec/fortnox/api/mappers/default_delivery_types_spec.rb +1 -1
- data/spec/fortnox/api/mappers/examples/mapper.rb +1 -1
- data/spec/fortnox/api/models/base_spec.rb +8 -8
- data/spec/fortnox/api/repositories/article_spec.rb +2 -2
- data/spec/fortnox/api/repositories/base_spec.rb +4 -12
- data/spec/fortnox/api/repositories/customer_spec.rb +1 -1
- data/spec/fortnox/api/repositories/invoice_spec.rb +13 -19
- data/spec/fortnox/api/repositories/project_spec.rb +1 -1
- data/spec/fortnox/api/repositories/terms_of_payment_spec.rb +2 -2
- data/spec/fortnox/api/repositories/unit_spec.rb +3 -3
- data/spec/fortnox/api/types/enums_spec.rb +1 -0
- data/spec/fortnox/api/types/housework_types_spec.rb +122 -34
- data/spec/fortnox/api/types/model_spec.rb +11 -17
- data/spec/fortnox/api/types/nullable_spec.rb +30 -10
- data/spec/fortnox/api/types/required_spec.rb +1 -4
- data/spec/support/matchers/type/enum_matcher.rb +1 -1
- data/spec/support/matchers/type/have_account_number_matcher.rb +1 -1
- data/spec/support/matchers/type/have_email_matcher.rb +1 -1
- data/spec/support/matchers/type/have_nullable_date_matcher.rb +5 -5
- data/spec/support/matchers/type/have_nullable_string_matcher.rb +3 -3
- data/spec/vcr_cassettes/articles/all.yml +43 -17
- data/spec/vcr_cassettes/articles/find_by_hash_failure.yml +34 -15
- data/spec/vcr_cassettes/articles/find_failure.yml +34 -15
- data/spec/vcr_cassettes/articles/find_id_1.yml +35 -16
- data/spec/vcr_cassettes/articles/find_new.yml +37 -18
- data/spec/vcr_cassettes/articles/multi_param_find_by_hash.yml +34 -15
- data/spec/vcr_cassettes/articles/save_new.yml +35 -15
- data/spec/vcr_cassettes/articles/save_old.yml +37 -18
- data/spec/vcr_cassettes/articles/save_with_specially_named_attribute.yml +35 -15
- data/spec/vcr_cassettes/articles/search_by_name.yml +34 -15
- data/spec/vcr_cassettes/articles/search_miss.yml +34 -15
- data/spec/vcr_cassettes/articles/search_with_special_char.yml +34 -15
- data/spec/vcr_cassettes/articles/single_param_find_by_hash.yml +38 -18
- data/spec/vcr_cassettes/customers/all.yml +36 -17
- data/spec/vcr_cassettes/customers/find_by_hash_failure.yml +34 -15
- data/spec/vcr_cassettes/customers/find_failure.yml +34 -15
- data/spec/vcr_cassettes/customers/find_id_1.yml +34 -15
- data/spec/vcr_cassettes/customers/find_new.yml +36 -17
- data/spec/vcr_cassettes/customers/multi_param_find_by_hash.yml +34 -15
- data/spec/vcr_cassettes/customers/save_new.yml +34 -14
- data/spec/vcr_cassettes/customers/save_new_with_country_code_SE.yml +30 -20
- data/spec/vcr_cassettes/customers/save_old.yml +36 -17
- data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +34 -14
- data/spec/vcr_cassettes/customers/search_by_name.yml +38 -16
- data/spec/vcr_cassettes/customers/search_miss.yml +34 -15
- data/spec/vcr_cassettes/customers/search_with_special_char.yml +34 -15
- data/spec/vcr_cassettes/customers/single_param_find_by_hash.yml +34 -15
- data/spec/vcr_cassettes/invoices/all.yml +39 -17
- data/spec/vcr_cassettes/invoices/filter_hit.yml +34 -15
- data/spec/vcr_cassettes/invoices/filter_invalid.yml +33 -13
- data/spec/vcr_cassettes/invoices/find_by_hash_failure.yml +34 -15
- data/spec/vcr_cassettes/invoices/find_failure.yml +34 -15
- data/spec/vcr_cassettes/invoices/find_id_1.yml +36 -17
- data/spec/vcr_cassettes/invoices/find_new.yml +39 -20
- data/spec/vcr_cassettes/invoices/multi_param_find_by_hash.yml +34 -15
- data/spec/vcr_cassettes/invoices/save_new.yml +37 -17
- data/spec/vcr_cassettes/invoices/save_new_with_comments.yml +37 -17
- data/spec/vcr_cassettes/invoices/save_new_with_country.yml +32 -22
- data/spec/vcr_cassettes/invoices/save_new_with_country_GB.yml +33 -23
- data/spec/vcr_cassettes/invoices/save_new_with_country_Norge.yml +32 -22
- data/spec/vcr_cassettes/invoices/save_new_with_country_Norway.yml +32 -22
- data/spec/vcr_cassettes/invoices/save_new_with_country_Sverige.yml +32 -22
- data/spec/vcr_cassettes/invoices/save_new_with_country_VA.yml +33 -23
- data/spec/vcr_cassettes/invoices/save_new_with_country_VI.yml +33 -23
- data/spec/vcr_cassettes/invoices/save_new_with_country_empty_string.yml +32 -22
- data/spec/vcr_cassettes/invoices/save_new_with_country_nil.yml +32 -22
- data/spec/vcr_cassettes/invoices/save_old.yml +39 -20
- data/spec/vcr_cassettes/invoices/save_old_with_empty_comments.yml +39 -20
- data/spec/vcr_cassettes/invoices/save_old_with_empty_country.yml +34 -25
- data/spec/vcr_cassettes/invoices/save_old_with_nil_comments.yml +39 -20
- data/spec/vcr_cassettes/invoices/save_old_with_nil_country.yml +34 -25
- data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +36 -16
- data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +36 -16
- data/spec/vcr_cassettes/invoices/search_by_name.yml +34 -15
- data/spec/vcr_cassettes/invoices/search_miss.yml +34 -15
- data/spec/vcr_cassettes/invoices/search_with_special_char.yml +34 -15
- data/spec/vcr_cassettes/invoices/single_param_find_by_hash.yml +34 -15
- data/spec/vcr_cassettes/orders/all.yml +35 -16
- data/spec/vcr_cassettes/orders/filter_hit.yml +34 -15
- data/spec/vcr_cassettes/orders/filter_invalid.yml +33 -13
- data/spec/vcr_cassettes/orders/find_by_hash_failure.yml +34 -15
- data/spec/vcr_cassettes/orders/find_failure.yml +34 -15
- data/spec/vcr_cassettes/orders/find_id_1.yml +35 -16
- data/spec/vcr_cassettes/orders/find_new.yml +38 -19
- data/spec/vcr_cassettes/orders/housework_invalid_tax_reduction_type.yml +63 -0
- data/spec/vcr_cassettes/orders/housework_othercoses_invalid.yml +63 -0
- data/spec/vcr_cassettes/orders/housework_type_babysitting.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_cleaning.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_construction.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_cooking.yml +34 -14
- data/spec/vcr_cassettes/orders/housework_type_electricity.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_gardening.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_glassmetalwork.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_grounddrainagework.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_hvac.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_itservices.yml +66 -0
- data/spec/vcr_cassettes/orders/housework_type_majorappliancerepair.yml +66 -0
- data/spec/vcr_cassettes/orders/housework_type_masonry.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_movingservices.yml +66 -0
- data/spec/vcr_cassettes/orders/housework_type_othercare.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_othercosts.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_paintingwallpapering.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_snowplowing.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_textileclothing.yml +37 -17
- data/spec/vcr_cassettes/orders/housework_type_tutoring.yml +34 -14
- data/spec/vcr_cassettes/orders/multi_param_find_by_hash.yml +34 -15
- data/spec/vcr_cassettes/orders/save_new.yml +36 -16
- data/spec/vcr_cassettes/orders/save_old.yml +38 -19
- data/spec/vcr_cassettes/orders/save_with_nested_model.yml +36 -16
- data/spec/vcr_cassettes/orders/search_by_name.yml +34 -15
- data/spec/vcr_cassettes/orders/search_miss.yml +34 -15
- data/spec/vcr_cassettes/orders/search_with_special_char.yml +34 -15
- data/spec/vcr_cassettes/orders/single_param_find_by_hash.yml +34 -15
- data/spec/vcr_cassettes/projects/all.yml +58 -33
- data/spec/vcr_cassettes/projects/find_by_hash_failure.yml +34 -15
- data/spec/vcr_cassettes/projects/find_failure.yml +34 -15
- data/spec/vcr_cassettes/projects/find_id_1.yml +34 -15
- data/spec/vcr_cassettes/projects/find_new.yml +37 -18
- data/spec/vcr_cassettes/projects/multi_param_find_by_hash.yml +36 -17
- data/spec/vcr_cassettes/projects/save_new.yml +35 -15
- data/spec/vcr_cassettes/projects/save_old.yml +37 -18
- data/spec/vcr_cassettes/projects/single_param_find_by_hash.yml +36 -17
- data/spec/vcr_cassettes/termsofpayments/all.yml +46 -25
- data/spec/vcr_cassettes/termsofpayments/find_failure.yml +34 -15
- data/spec/vcr_cassettes/termsofpayments/find_id_1.yml +35 -16
- data/spec/vcr_cassettes/termsofpayments/find_new.yml +36 -17
- data/spec/vcr_cassettes/termsofpayments/save_new.yml +35 -15
- data/spec/vcr_cassettes/termsofpayments/save_old.yml +36 -17
- data/spec/vcr_cassettes/units/all.yml +45 -22
- data/spec/vcr_cassettes/units/find_failure.yml +34 -15
- data/spec/vcr_cassettes/units/find_id_1.yml +35 -16
- data/spec/vcr_cassettes/units/find_new.yml +36 -17
- data/spec/vcr_cassettes/units/save_new.yml +35 -15
- data/spec/vcr_cassettes/units/save_old.yml +36 -17
- data/spec/vcr_cassettes/units/save_with_specially_named_attribute.yml +35 -15
- metadata +115 -43
- data/spec/support/helpers/dummy_class_helper.rb +0 -38
- data/spec/vcr_cassettes/invoices/save_new_with_country_KR.yml +0 -57
data/lib/fortnox/api/models.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
require_relative 'models/article'
|
4
|
+
require_relative 'models/customer'
|
5
|
+
require_relative 'models/invoice'
|
6
|
+
require_relative 'models/order'
|
7
|
+
require_relative 'models/project'
|
8
|
+
require_relative 'models/unit'
|
9
|
+
require_relative 'models/terms_of_payment'
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative 'base'
|
4
|
+
require_relative '../models/article'
|
5
|
+
require_relative '../mappers/article'
|
6
6
|
|
7
7
|
module Fortnox
|
8
8
|
module API
|
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'httparty'
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
|
5
|
+
require_relative 'base/loaders'
|
6
|
+
require_relative 'base/savers'
|
7
|
+
require_relative '../request_handling'
|
7
8
|
|
8
9
|
module Fortnox
|
9
10
|
module API
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative 'base'
|
4
|
+
require_relative '../models/customer'
|
5
|
+
require_relative '../mappers/customer'
|
6
6
|
|
7
7
|
module Fortnox
|
8
8
|
module API
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative 'base'
|
4
|
+
require_relative '../models/invoice'
|
5
|
+
require_relative '../mappers/invoice'
|
6
6
|
|
7
7
|
module Fortnox
|
8
8
|
module API
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative 'base'
|
4
|
+
require_relative '../models/order'
|
5
|
+
require_relative '../mappers/order'
|
6
6
|
|
7
7
|
module Fortnox
|
8
8
|
module API
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative 'base'
|
4
|
+
require_relative '../models/project'
|
5
|
+
require_relative '../mappers/project'
|
6
6
|
|
7
7
|
module Fortnox
|
8
8
|
module API
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative 'base'
|
4
|
+
require_relative '../models/terms_of_payment'
|
5
|
+
require_relative '../mappers/terms_of_payment'
|
6
6
|
|
7
7
|
module Fortnox
|
8
8
|
module API
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative 'base'
|
4
|
+
require_relative '../models/unit'
|
5
|
+
require_relative '../mappers/unit'
|
6
6
|
|
7
7
|
module Fortnox
|
8
8
|
module API
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
require_relative 'repositories/article'
|
4
|
+
require_relative 'repositories/customer'
|
5
|
+
require_relative 'repositories/invoice'
|
6
|
+
require_relative 'repositories/order'
|
7
|
+
require_relative 'repositories/project'
|
8
|
+
require_relative 'repositories/unit'
|
9
|
+
require_relative 'repositories/terms_of_payment'
|
@@ -17,6 +17,13 @@ module Fortnox
|
|
17
17
|
value.to_s.upcase unless value.nil?
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
def self.lower_case
|
22
|
+
lambda do |value|
|
23
|
+
return nil if value == ''
|
24
|
+
value.to_s.downcase unless value.nil?
|
25
|
+
end
|
26
|
+
end
|
20
27
|
end
|
21
28
|
|
22
29
|
ArticleTypes = Types::Strict::String.enum(
|
@@ -25,15 +32,31 @@ module Fortnox
|
|
25
32
|
DiscountTypes = Types::Strict::String.enum(
|
26
33
|
'AMOUNT', 'PERCENT'
|
27
34
|
)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
+
HOUSEWORK_TYPES = {
|
36
|
+
rot: %w[
|
37
|
+
CONSTRUCTION ELECTRICITY GLASSMETALWORK GROUNDDRAINAGEWORK
|
38
|
+
MASONRY PAINTINGWALLPAPERING HVAC OTHERCOSTS
|
39
|
+
],
|
40
|
+
rut: %w[
|
41
|
+
MAJORAPPLIANCEREPAIR MOVINGSERVICES ITSERVICES CLEANING
|
42
|
+
TEXTILECLOTHING SNOWPLOWING GARDENING BABYSITTING OTHERCARE
|
43
|
+
OTHERCOSTS
|
44
|
+
],
|
45
|
+
legacy_rut: %w[COOKING TUTORING]
|
46
|
+
}.freeze
|
47
|
+
|
48
|
+
# TODO: RUT to be added:
|
49
|
+
# HOMEMAINTENANCE FURNISHING TRANSPORTATIONSERVICES
|
50
|
+
# WASHINGANDCAREOFCLOTHING
|
51
|
+
#
|
52
|
+
# TODO: GREEN to be added:
|
53
|
+
# SOLARCELLS STORAGESELFPRODUCEDELECTRICTY
|
54
|
+
# CHARGINGSTATIONELECTRICVEHICLE OTHERCOSTS
|
55
|
+
|
35
56
|
HouseworkTypes = Types::Strict::String.enum(
|
36
|
-
*(
|
57
|
+
*(HOUSEWORK_TYPES[:rot] +
|
58
|
+
HOUSEWORK_TYPES[:rut] +
|
59
|
+
HOUSEWORK_TYPES[:legacy_rut]).uniq
|
37
60
|
)
|
38
61
|
Currencies = Types::Strict::String.enum(
|
39
62
|
'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN',
|
@@ -67,6 +90,11 @@ module Fortnox
|
|
67
90
|
ProjectStatusTypes = Types::Strict::String.enum(
|
68
91
|
'NOTSTARTED', 'ONGOING', 'COMPLETED'
|
69
92
|
)
|
93
|
+
# NOTE: Yes, these needs to be in lower case...
|
94
|
+
# I know, this is stupid... Fortnox: why?!
|
95
|
+
TaxReductionTypes = Types::Strict::String.enum(
|
96
|
+
'rot', 'rut', 'green', 'none'
|
97
|
+
)
|
70
98
|
end
|
71
99
|
end
|
72
100
|
end
|
@@ -4,7 +4,7 @@ module Fortnox
|
|
4
4
|
module API
|
5
5
|
module Types
|
6
6
|
class Model < Dry::Struct
|
7
|
-
|
7
|
+
transform_types(&:omittable)
|
8
8
|
|
9
9
|
def initialize(input_attributes)
|
10
10
|
if (missing_key = first_missing_required_key(input_attributes))
|
@@ -15,23 +15,21 @@ module Fortnox
|
|
15
15
|
super
|
16
16
|
end
|
17
17
|
|
18
|
-
def self.is?(*_args) end
|
19
|
-
|
20
18
|
private
|
21
19
|
|
22
20
|
def missing_keys(attributes)
|
23
21
|
non_nil_attributes = attributes.reject { |_, value| value.nil? }
|
24
22
|
|
25
23
|
attribute_keys = non_nil_attributes.keys
|
26
|
-
schema_keys =
|
24
|
+
schema_keys = self.class.schema.keys.map(&:name)
|
27
25
|
|
28
26
|
schema_keys - attribute_keys
|
29
27
|
end
|
30
28
|
|
31
29
|
def first_missing_required_key(attributes)
|
32
30
|
missing_keys(attributes).find do |name|
|
33
|
-
attribute = self.class.schema
|
34
|
-
attribute.respond_to?(:options) && attribute.options[:required]
|
31
|
+
attribute = self.class.schema.keys.find { |key| key.name == name }
|
32
|
+
attribute.type.respond_to?(:options) && attribute.type.options[:required]
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|
@@ -6,15 +6,19 @@ module Fortnox
|
|
6
6
|
module API
|
7
7
|
module Types
|
8
8
|
module Nullable
|
9
|
-
String = Types::Strict::String.optional.constructor { |value| value
|
10
|
-
Float = Types::Strict::Float.optional.constructor { |value| value
|
11
|
-
Integer = Types::Strict::
|
12
|
-
Boolean = Types::Bool.optional.constructor { |value| THE_TRUTH.fetch(value
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
String = Types::Strict::String.optional.constructor { |value| value&.to_s }
|
10
|
+
Float = Types::Strict::Float.optional.constructor { |value| value&.to_f }
|
11
|
+
Integer = Types::Strict::Integer.optional.constructor { |value| value&.to_i }
|
12
|
+
Boolean = Types::Bool.optional.constructor { |value| THE_TRUTH.fetch(value, false) }
|
13
|
+
Date = Types::Date.optional.constructor do |value|
|
14
|
+
next if value.nil? || value == ''
|
15
|
+
|
16
|
+
begin
|
17
|
+
::Date.parse(value.to_s)
|
18
|
+
rescue ::Date::Error
|
19
|
+
raise Fortnox::API::AttributeError, 'invalid date'
|
20
|
+
end
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
@@ -4,9 +4,9 @@ module Fortnox
|
|
4
4
|
module API
|
5
5
|
module Types
|
6
6
|
module Required
|
7
|
-
String = Types::Strict::String.constructor { |value| value
|
8
|
-
Integer = Types::Strict::
|
9
|
-
Float = Types::Strict::Float.constructor { |value| value
|
7
|
+
String = Types::Strict::String.constructor { |value| value&.to_s }.is(:required)
|
8
|
+
Integer = Types::Strict::Integer.constructor { |value| value&.to_i }.is(:required)
|
9
|
+
Float = Types::Strict::Float.constructor { |value| value&.to_f }.is(:required)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -14,8 +14,8 @@ module Fortnox
|
|
14
14
|
|
15
15
|
module Integer
|
16
16
|
def self.[](low, high)
|
17
|
-
Types::Strict::
|
18
|
-
value
|
17
|
+
Types::Strict::Integer.constrained(gteq: low, lteq: high).optional.constructor do |value|
|
18
|
+
value&.to_i
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
data/lib/fortnox/api/types.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'dry-struct'
|
4
4
|
require 'dry-types'
|
5
5
|
require 'countries'
|
6
|
-
|
6
|
+
require_relative 'types/shim/country_string'
|
7
7
|
|
8
8
|
module Dry
|
9
9
|
module Types
|
@@ -12,11 +12,7 @@ module Dry
|
|
12
12
|
new_options = option_names.each_with_object({}) do |name, hash|
|
13
13
|
hash[name] = true
|
14
14
|
end
|
15
|
-
with(new_options)
|
16
|
-
end
|
17
|
-
|
18
|
-
def is?(option_name)
|
19
|
-
@options[option_name]
|
15
|
+
with(**new_options)
|
20
16
|
end
|
21
17
|
end
|
22
18
|
end
|
@@ -25,20 +21,19 @@ end
|
|
25
21
|
module Fortnox
|
26
22
|
module API
|
27
23
|
module Types
|
28
|
-
include Dry
|
24
|
+
include Dry.Types(default: :nominal)
|
29
25
|
ISO3166.configure { |config| config.locales = %i[en sv] }
|
30
26
|
|
31
27
|
THE_TRUTH = { true => true, 'true' => true, false => false, 'false' => false }.freeze
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
require 'fortnox/api/types/enums'
|
29
|
+
require_relative 'types/required'
|
30
|
+
require_relative 'types/defaulted'
|
31
|
+
require_relative 'types/nullable'
|
38
32
|
|
39
|
-
|
33
|
+
require_relative 'types/enums'
|
34
|
+
require_relative 'types/sized'
|
40
35
|
|
41
|
-
AccountNumber = Strict::
|
36
|
+
AccountNumber = Strict::Integer
|
42
37
|
.constrained(gteq: 0, lteq: 9999)
|
43
38
|
.optional
|
44
39
|
.constructor do |value|
|
@@ -57,10 +52,10 @@ module Fortnox
|
|
57
52
|
next value if value.nil? || value == ''
|
58
53
|
|
59
54
|
# Fortnox only supports Swedish translation of Sweden
|
60
|
-
next CountryString.new('SE') if value
|
55
|
+
next CountryString.new('SE') if value.match?(/^s(e$|we|ve)/i)
|
61
56
|
|
62
57
|
country = ::ISO3166::Country[value] ||
|
63
|
-
::ISO3166::Country.
|
58
|
+
::ISO3166::Country.find_country_by_any_name(value) ||
|
64
59
|
::ISO3166::Country.find_country_by_translated_names(value)
|
65
60
|
|
66
61
|
raise Dry::Types::ConstraintError.new('value violates constraints', value) if country.nil?
|
@@ -119,13 +114,18 @@ module Fortnox
|
|
119
114
|
.optional
|
120
115
|
.constructor(EnumConstructors.default)
|
121
116
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
117
|
+
TaxReductionType = Strict::String
|
118
|
+
.constrained(included_in: TaxReductionTypes.values)
|
119
|
+
.optional
|
120
|
+
.constructor(EnumConstructors.lower_case)
|
121
|
+
|
122
|
+
require_relative 'types/model'
|
123
|
+
require_relative 'types/default_delivery_types'
|
124
|
+
require_relative 'types/default_templates'
|
125
|
+
require_relative 'types/email_information'
|
126
|
+
require_relative 'types/edi_information'
|
127
|
+
require_relative 'types/invoice_row'
|
128
|
+
require_relative 'types/order_row'
|
129
129
|
end
|
130
130
|
end
|
131
131
|
end
|
data/lib/fortnox/api/version.rb
CHANGED
data/lib/fortnox/api.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'set'
|
4
|
-
require 'dry-
|
5
|
-
require '
|
6
|
-
require 'fortnox/api/version'
|
4
|
+
require 'dry-configurable'
|
5
|
+
require 'dry-container'
|
7
6
|
require 'logger'
|
8
7
|
|
8
|
+
require_relative 'api/circular_queue'
|
9
|
+
require_relative 'api/version'
|
10
|
+
|
9
11
|
module Fortnox
|
10
12
|
module API
|
11
13
|
extend Dry::Configurable
|
@@ -18,29 +20,29 @@ module Fortnox
|
|
18
20
|
access_tokens: nil,
|
19
21
|
debugging: false,
|
20
22
|
logger: lambda {
|
21
|
-
logger = Logger.new(
|
23
|
+
logger = Logger.new($stdout)
|
22
24
|
logger.level = Logger::WARN
|
23
25
|
return logger
|
24
26
|
}.call
|
25
27
|
}.freeze
|
26
28
|
|
27
|
-
setting :base_url, DEFAULT_CONFIGURATION[:base_url]
|
28
|
-
setting :client_secret, DEFAULT_CONFIGURATION[:client_secret]
|
29
|
-
setting :token_store, DEFAULT_CONFIGURATION[:token_store]
|
30
|
-
setting :access_token, DEFAULT_CONFIGURATION[:access_token] do |value|
|
29
|
+
setting :base_url, default: DEFAULT_CONFIGURATION[:base_url]
|
30
|
+
setting :client_secret, default: DEFAULT_CONFIGURATION[:client_secret]
|
31
|
+
setting :token_store, default: DEFAULT_CONFIGURATION[:token_store]
|
32
|
+
setting :access_token, default: DEFAULT_CONFIGURATION[:access_token], constructor: (proc do |value|
|
31
33
|
next if value.nil? # nil is a valid unassigned value
|
32
34
|
invalid_access_token_format!(value) unless value.is_a?(String)
|
33
35
|
config.token_store = { default: value }
|
34
36
|
value
|
35
|
-
end
|
36
|
-
setting :access_tokens, DEFAULT_CONFIGURATION[:access_tokens] do |value|
|
37
|
+
end)
|
38
|
+
setting :access_tokens, default: DEFAULT_CONFIGURATION[:access_tokens], constructor: (proc do |value|
|
37
39
|
next if value.nil? # nil is a valid unassigned value
|
38
40
|
invalid_access_tokens_format!(value) unless value.is_a?(Hash) || value.is_a?(Array)
|
39
41
|
config.token_store = value.is_a?(Hash) ? value : { default: value }
|
40
42
|
value
|
41
|
-
end
|
42
|
-
setting :debugging, DEFAULT_CONFIGURATION[:debugging], reader: true
|
43
|
-
setting :logger, DEFAULT_CONFIGURATION[:logger], reader: true
|
43
|
+
end)
|
44
|
+
setting :debugging, default: DEFAULT_CONFIGURATION[:debugging], reader: true
|
45
|
+
setting :logger, default: DEFAULT_CONFIGURATION[:logger], reader: true
|
44
46
|
|
45
47
|
class Exception < StandardError
|
46
48
|
end
|
@@ -75,6 +77,6 @@ module Fortnox
|
|
75
77
|
end
|
76
78
|
end
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
80
|
+
require_relative 'api/models'
|
81
|
+
require_relative 'api/repositories'
|
82
|
+
require_relative 'api/mappers'
|
@@ -6,11 +6,11 @@ require 'fortnox/api/circular_queue'
|
|
6
6
|
describe Fortnox::API::CircularQueue do
|
7
7
|
describe 'start index' do
|
8
8
|
context 'when running several times' do
|
9
|
+
subject { Set.new(samples).size }
|
10
|
+
|
9
11
|
let(:test_array) { (0..99).to_a }
|
10
12
|
let(:samples) { Array.new(100) { described_class.new(*test_array).next } }
|
11
13
|
|
12
|
-
subject { Set.new(samples).size }
|
13
|
-
|
14
14
|
# NOTE: This test is not perfect. We are testing that a random generator
|
15
15
|
# with 100 items to choose from does not choose the same item 100 times in a row.
|
16
16
|
# Yes, the possibility is low, but I thought I should just mention it :)
|
@@ -22,7 +22,7 @@ describe Fortnox::API::CircularQueue do
|
|
22
22
|
|
23
23
|
describe '#next' do
|
24
24
|
context 'when several items in queue' do
|
25
|
-
let(:queue) { described_class.new(1,2,3) }
|
25
|
+
let(:queue) { described_class.new(1, 2, 3) }
|
26
26
|
let(:first_round) { Array.new(3) { queue.next } }
|
27
27
|
let(:second_round) { Array.new(3) { queue.next } }
|
28
28
|
|
@@ -6,10 +6,12 @@ require 'fortnox/api/mappers/base/canonical_name_sym'
|
|
6
6
|
describe Fortnox::API::Mapper::CanonicalNameSym do
|
7
7
|
describe '.canonical_name_sym' do
|
8
8
|
context 'with simple class' do
|
9
|
-
|
10
|
-
|
9
|
+
before do
|
10
|
+
test_class = Class.new do
|
11
11
|
extend Fortnox::API::Mapper::CanonicalNameSym
|
12
12
|
end
|
13
|
+
|
14
|
+
stub_const('TestClass', test_class)
|
13
15
|
end
|
14
16
|
|
15
17
|
subject { TestClass.canonical_name_sym }
|
@@ -18,12 +20,12 @@ describe Fortnox::API::Mapper::CanonicalNameSym do
|
|
18
20
|
end
|
19
21
|
|
20
22
|
context 'when class included in module' do
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
extend Fortnox::API::Mapper::CanonicalNameSym
|
25
|
-
end
|
23
|
+
before do
|
24
|
+
test_class = Class.new do
|
25
|
+
extend Fortnox::API::Mapper::CanonicalNameSym
|
26
26
|
end
|
27
|
+
|
28
|
+
stub_const('Something::Test', test_class)
|
27
29
|
end
|
28
30
|
|
29
31
|
subject { Something::Test.canonical_name_sym }
|
@@ -8,7 +8,7 @@ require 'fortnox/api/mappers/examples/mapper'
|
|
8
8
|
describe Fortnox::API::Mapper::DefaultDeliveryTypes do
|
9
9
|
key_map = {}
|
10
10
|
|
11
|
-
it_behaves_like 'mapper', key_map do
|
11
|
+
it_behaves_like 'mapper', key_map, nil, nil do
|
12
12
|
let(:mapper) { described_class.new }
|
13
13
|
end
|
14
14
|
end
|
@@ -12,7 +12,7 @@ shared_examples_for 'mapper' do |key_map, json_entity_wrapper = nil, json_collec
|
|
12
12
|
describe 'key_map' do
|
13
13
|
subject { described_class::KEY_MAP }
|
14
14
|
|
15
|
-
it {
|
15
|
+
it { expect(subject).to eq(key_map) }
|
16
16
|
end
|
17
17
|
|
18
18
|
unless json_entity_wrapper.nil?
|
@@ -5,8 +5,8 @@ require 'fortnox/api/models/base'
|
|
5
5
|
require 'fortnox/api/types'
|
6
6
|
|
7
7
|
describe Fortnox::API::Model::Base do
|
8
|
-
|
9
|
-
|
8
|
+
let(:entity_class) do
|
9
|
+
Class.new(Fortnox::API::Model::Base) do
|
10
10
|
attribute :private, Fortnox::API::Types::String.is(:read_only)
|
11
11
|
attribute :string, Fortnox::API::Types::Required::String
|
12
12
|
attribute :number, Fortnox::API::Types::Nullable::Integer
|
@@ -16,15 +16,15 @@ describe Fortnox::API::Model::Base do
|
|
16
16
|
|
17
17
|
describe '.new' do
|
18
18
|
context 'with basic attribute' do
|
19
|
-
subject {
|
19
|
+
subject { entity_class.new(string: 'Test') }
|
20
20
|
|
21
|
-
it { is_expected.to be_a
|
21
|
+
it { is_expected.to be_a entity_class }
|
22
22
|
it { is_expected.to be_new }
|
23
23
|
it { is_expected.not_to be_saved }
|
24
24
|
end
|
25
25
|
|
26
26
|
context 'without required attribute' do
|
27
|
-
subject { -> {
|
27
|
+
subject { -> { entity_class.new({}) } }
|
28
28
|
|
29
29
|
it { is_expected.to raise_error Fortnox::API::Exception }
|
30
30
|
it { is_expected.to raise_error Fortnox::API::MissingAttributeError }
|
@@ -32,7 +32,7 @@ describe Fortnox::API::Model::Base do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
context 'with invalid attribute value' do
|
35
|
-
subject { -> {
|
35
|
+
subject { -> { entity_class.new(string: 'Test', account: 13_337) } }
|
36
36
|
|
37
37
|
it { is_expected.to raise_error Fortnox::API::Exception }
|
38
38
|
it { is_expected.to raise_error Fortnox::API::AttributeError }
|
@@ -41,7 +41,7 @@ describe Fortnox::API::Model::Base do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
describe '.update' do
|
44
|
-
let(:original) {
|
44
|
+
let(:original) { entity_class.new(string: 'Test') }
|
45
45
|
|
46
46
|
context 'with new, simple value' do
|
47
47
|
subject { updated_model }
|
@@ -85,7 +85,7 @@ describe Fortnox::API::Model::Base do
|
|
85
85
|
|
86
86
|
context 'when updating' do
|
87
87
|
let(:updated_entity) do
|
88
|
-
saved_entity =
|
88
|
+
saved_entity = entity_class.new(string: 'Saved', new: false, unsaved: false)
|
89
89
|
saved_entity.update(string: 'Updated')
|
90
90
|
end
|
91
91
|
|