fortnox-api 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +3 -10
  4. data/CHANGELOG.md +10 -0
  5. data/README.md +7 -4
  6. data/Rakefile +5 -0
  7. data/fortnox-api.gemspec +2 -2
  8. data/lib/fortnox/api/mappers/base/from_json.rb +2 -2
  9. data/lib/fortnox/api/models/document.rb +3 -0
  10. data/lib/fortnox/api/types.rb +6 -1
  11. data/lib/fortnox/api/types/enums.rb +36 -8
  12. data/lib/fortnox/api/version.rb +1 -1
  13. data/spec/fortnox/api/circular_queue_spec.rb +3 -3
  14. data/spec/fortnox/api/repositories/article_spec.rb +1 -1
  15. data/spec/fortnox/api/repositories/customer_spec.rb +1 -1
  16. data/spec/fortnox/api/repositories/invoice_spec.rb +13 -13
  17. data/spec/fortnox/api/repositories/project_spec.rb +1 -1
  18. data/spec/fortnox/api/repositories/terms_of_payment_spec.rb +2 -2
  19. data/spec/fortnox/api/repositories/unit_spec.rb +3 -3
  20. data/spec/fortnox/api/types/enums_spec.rb +1 -0
  21. data/spec/fortnox/api/types/housework_types_spec.rb +151 -34
  22. data/spec/vcr_cassettes/articles/all.yml +25 -9
  23. data/spec/vcr_cassettes/articles/find_by_hash_failure.yml +20 -7
  24. data/spec/vcr_cassettes/articles/find_failure.yml +20 -7
  25. data/spec/vcr_cassettes/articles/find_id_1.yml +21 -8
  26. data/spec/vcr_cassettes/articles/find_new.yml +23 -10
  27. data/spec/vcr_cassettes/articles/multi_param_find_by_hash.yml +20 -7
  28. data/spec/vcr_cassettes/articles/save_new.yml +21 -7
  29. data/spec/vcr_cassettes/articles/save_old.yml +23 -10
  30. data/spec/vcr_cassettes/articles/save_with_specially_named_attribute.yml +21 -7
  31. data/spec/vcr_cassettes/articles/search_by_name.yml +20 -7
  32. data/spec/vcr_cassettes/articles/search_miss.yml +20 -7
  33. data/spec/vcr_cassettes/articles/search_with_special_char.yml +20 -7
  34. data/spec/vcr_cassettes/articles/single_param_find_by_hash.yml +21 -8
  35. data/spec/vcr_cassettes/customers/all.yml +22 -9
  36. data/spec/vcr_cassettes/customers/find_by_hash_failure.yml +20 -7
  37. data/spec/vcr_cassettes/customers/find_failure.yml +20 -7
  38. data/spec/vcr_cassettes/customers/find_id_1.yml +20 -7
  39. data/spec/vcr_cassettes/customers/find_new.yml +22 -9
  40. data/spec/vcr_cassettes/customers/multi_param_find_by_hash.yml +20 -7
  41. data/spec/vcr_cassettes/customers/save_new.yml +20 -6
  42. data/spec/vcr_cassettes/customers/save_new_with_country_code_SE.yml +10 -6
  43. data/spec/vcr_cassettes/customers/save_old.yml +22 -9
  44. data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +20 -6
  45. data/spec/vcr_cassettes/customers/search_by_name.yml +22 -8
  46. data/spec/vcr_cassettes/customers/search_miss.yml +20 -7
  47. data/spec/vcr_cassettes/customers/search_with_special_char.yml +19 -6
  48. data/spec/vcr_cassettes/customers/single_param_find_by_hash.yml +20 -7
  49. data/spec/vcr_cassettes/invoices/all.yml +25 -9
  50. data/spec/vcr_cassettes/invoices/filter_hit.yml +20 -7
  51. data/spec/vcr_cassettes/invoices/filter_invalid.yml +19 -5
  52. data/spec/vcr_cassettes/invoices/find_by_hash_failure.yml +20 -7
  53. data/spec/vcr_cassettes/invoices/find_failure.yml +19 -6
  54. data/spec/vcr_cassettes/invoices/find_id_1.yml +22 -9
  55. data/spec/vcr_cassettes/invoices/find_new.yml +24 -11
  56. data/spec/vcr_cassettes/invoices/multi_param_find_by_hash.yml +20 -7
  57. data/spec/vcr_cassettes/invoices/save_new.yml +22 -8
  58. data/spec/vcr_cassettes/invoices/save_new_with_comments.yml +22 -8
  59. data/spec/vcr_cassettes/invoices/save_new_with_country.yml +12 -8
  60. data/spec/vcr_cassettes/invoices/save_new_with_country_GB.yml +12 -8
  61. data/spec/vcr_cassettes/invoices/save_new_with_country_KR.yml +12 -8
  62. data/spec/vcr_cassettes/invoices/save_new_with_country_Norge.yml +12 -8
  63. data/spec/vcr_cassettes/invoices/save_new_with_country_Norway.yml +12 -8
  64. data/spec/vcr_cassettes/invoices/save_new_with_country_Sverige.yml +12 -8
  65. data/spec/vcr_cassettes/invoices/save_new_with_country_VA.yml +12 -8
  66. data/spec/vcr_cassettes/invoices/save_new_with_country_VI.yml +12 -8
  67. data/spec/vcr_cassettes/invoices/save_new_with_country_empty_string.yml +12 -8
  68. data/spec/vcr_cassettes/invoices/save_new_with_country_nil.yml +12 -8
  69. data/spec/vcr_cassettes/invoices/save_old.yml +24 -11
  70. data/spec/vcr_cassettes/invoices/save_old_with_empty_comments.yml +24 -11
  71. data/spec/vcr_cassettes/invoices/save_old_with_empty_country.yml +14 -11
  72. data/spec/vcr_cassettes/invoices/save_old_with_nil_comments.yml +24 -11
  73. data/spec/vcr_cassettes/invoices/save_old_with_nil_country.yml +14 -11
  74. data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +22 -8
  75. data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +22 -8
  76. data/spec/vcr_cassettes/invoices/search_by_name.yml +20 -7
  77. data/spec/vcr_cassettes/invoices/search_miss.yml +20 -7
  78. data/spec/vcr_cassettes/invoices/search_with_special_char.yml +20 -7
  79. data/spec/vcr_cassettes/invoices/single_param_find_by_hash.yml +19 -6
  80. data/spec/vcr_cassettes/orders/all.yml +21 -8
  81. data/spec/vcr_cassettes/orders/filter_hit.yml +19 -6
  82. data/spec/vcr_cassettes/orders/filter_invalid.yml +19 -5
  83. data/spec/vcr_cassettes/orders/find_by_hash_failure.yml +20 -7
  84. data/spec/vcr_cassettes/orders/find_failure.yml +20 -7
  85. data/spec/vcr_cassettes/orders/find_id_1.yml +21 -8
  86. data/spec/vcr_cassettes/orders/find_new.yml +24 -11
  87. data/spec/vcr_cassettes/orders/housework_invalid_tax_reduction_type.yml +57 -0
  88. data/spec/vcr_cassettes/orders/housework_othercoses_invalid.yml +57 -0
  89. data/spec/vcr_cassettes/orders/housework_type_babysitting.yml +23 -9
  90. data/spec/vcr_cassettes/orders/housework_type_cleaning.yml +23 -9
  91. data/spec/vcr_cassettes/orders/housework_type_construction.yml +23 -9
  92. data/spec/vcr_cassettes/orders/housework_type_cooking.yml +20 -6
  93. data/spec/vcr_cassettes/orders/housework_type_electricity.yml +23 -9
  94. data/spec/vcr_cassettes/orders/housework_type_gardening.yml +23 -9
  95. data/spec/vcr_cassettes/orders/housework_type_glassmetalwork.yml +23 -9
  96. data/spec/vcr_cassettes/orders/housework_type_grounddrainagework.yml +23 -9
  97. data/spec/vcr_cassettes/orders/housework_type_hvac.yml +23 -9
  98. data/spec/vcr_cassettes/orders/housework_type_itservices.yml +60 -0
  99. data/spec/vcr_cassettes/orders/housework_type_majorappliancerepair.yml +60 -0
  100. data/spec/vcr_cassettes/orders/housework_type_masonry.yml +23 -9
  101. data/spec/vcr_cassettes/orders/housework_type_movingservices.yml +60 -0
  102. data/spec/vcr_cassettes/orders/housework_type_othercare.yml +23 -9
  103. data/spec/vcr_cassettes/orders/housework_type_othercosts.yml +23 -9
  104. data/spec/vcr_cassettes/orders/housework_type_paintingwallpapering.yml +23 -9
  105. data/spec/vcr_cassettes/orders/housework_type_snowplowing.yml +23 -9
  106. data/spec/vcr_cassettes/orders/housework_type_textileclothing.yml +23 -9
  107. data/spec/vcr_cassettes/orders/housework_type_tutoring.yml +20 -6
  108. data/spec/vcr_cassettes/orders/housework_without_tax_reduction_type.yml +57 -0
  109. data/spec/vcr_cassettes/orders/multi_param_find_by_hash.yml +20 -7
  110. data/spec/vcr_cassettes/orders/save_new.yml +22 -8
  111. data/spec/vcr_cassettes/orders/save_old.yml +24 -11
  112. data/spec/vcr_cassettes/orders/save_with_nested_model.yml +22 -8
  113. data/spec/vcr_cassettes/orders/search_by_name.yml +20 -7
  114. data/spec/vcr_cassettes/orders/search_miss.yml +20 -7
  115. data/spec/vcr_cassettes/orders/search_with_special_char.yml +19 -6
  116. data/spec/vcr_cassettes/orders/single_param_find_by_hash.yml +20 -7
  117. data/spec/vcr_cassettes/projects/all.yml +40 -25
  118. data/spec/vcr_cassettes/projects/find_by_hash_failure.yml +20 -7
  119. data/spec/vcr_cassettes/projects/find_failure.yml +20 -7
  120. data/spec/vcr_cassettes/projects/find_id_1.yml +20 -7
  121. data/spec/vcr_cassettes/projects/find_new.yml +23 -10
  122. data/spec/vcr_cassettes/projects/multi_param_find_by_hash.yml +22 -9
  123. data/spec/vcr_cassettes/projects/save_new.yml +21 -7
  124. data/spec/vcr_cassettes/projects/save_old.yml +23 -10
  125. data/spec/vcr_cassettes/projects/single_param_find_by_hash.yml +22 -9
  126. data/spec/vcr_cassettes/termsofpayments/all.yml +29 -15
  127. data/spec/vcr_cassettes/termsofpayments/find_failure.yml +20 -7
  128. data/spec/vcr_cassettes/termsofpayments/find_id_1.yml +21 -8
  129. data/spec/vcr_cassettes/termsofpayments/find_new.yml +22 -9
  130. data/spec/vcr_cassettes/termsofpayments/save_new.yml +21 -7
  131. data/spec/vcr_cassettes/termsofpayments/save_old.yml +22 -9
  132. data/spec/vcr_cassettes/units/all.yml +23 -8
  133. data/spec/vcr_cassettes/units/find_failure.yml +19 -6
  134. data/spec/vcr_cassettes/units/find_id_1.yml +20 -7
  135. data/spec/vcr_cassettes/units/find_new.yml +22 -9
  136. data/spec/vcr_cassettes/units/save_new.yml +21 -7
  137. data/spec/vcr_cassettes/units/save_old.yml +22 -9
  138. data/spec/vcr_cassettes/units/save_with_specially_named_attribute.yml +21 -7
  139. metadata +20 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 707b9b050edd8499029c1f2120d11edc923e868847657eb0c108789014a5e3c8
4
- data.tar.gz: 7da764b991529e720f3afbbb01433da52ca4f34800951b05c4f0f1e11f646c6a
3
+ metadata.gz: 02c5fbd6c659d3c6cc4e9ed8dfef6e739ded62fc33107623f4dddc13d33f6672
4
+ data.tar.gz: 14f0815a2fd32e98055d71ef231da2b6fac4b95ecfd9dfcda59b88d1c1445c63
5
5
  SHA512:
6
- metadata.gz: 075e852a210ad2313fcf1c4469cb54a857016d46963e353679f16ea9e5daf09b28857491d9ccdc9b20c2a6843d7bc79093122db5419cf4219f1d830665af27b4
7
- data.tar.gz: 35f8989ec19be2bf69c4f703daf54feb8b7d09e4c6bec95455c3483b23e4f8aa74547f781f2874c39d8903761feb769474bba0795ac2b3a21142a27b4ca706dc
6
+ metadata.gz: 293665ff9e0b860e88c7c6c78fbcfdd0b8a8047444f23cd0560d504442e1a0ac3439c52349413cac63e0c5973d1db74dabcf7ebdd9c10bc3f1b7de922db58cbc
7
+ data.tar.gz: 011b4785ce46af9c4cd57939431f6b09dc6ab44d650023616fe7b0784dcde890727999eb918ac3c3db311afaaff8785d240c54e5c30f198a630b9a1bf41483b7
@@ -1,7 +1,7 @@
1
1
  require: rubocop-rspec
2
2
 
3
3
  AllCops:
4
- TargetRubyVersion: 2.3
4
+ TargetRubyVersion: 2.5
5
5
  DisplayCopNames: true
6
6
 
7
7
  RSpec/FilePath:
@@ -3,16 +3,9 @@ env:
3
3
  - CC_TEST_REPORTER_ID=43ea0acb059b164537ce31bf67e03e1cb552d63df1ad3e9bd95dc3d844697bb4
4
4
  language: ruby
5
5
  rvm:
6
- - 2.4.0
7
- - 2.4.1
8
- - 2.4.2
9
- - 2.4.3
10
- - 2.4.6
11
- - 2.5.0
12
- - 2.5.5
13
- - 2.6.0
14
- - 2.6.3
15
- - 2.7.0-preview1
6
+ - 2.5.8
7
+ - 2.6.6
8
+ - 2.7.1
16
9
  notifications:
17
10
  slack:
18
11
  secure: UEYDtwLaQgAoMRY7ct1y0Uu5HbInMwrLo+TiYRc3rjDrzqDfDyInEr3bpckyPJ79lnzccrFezMdY4jWzRjmsvQzvYMu+DWJ1mAWOa/9Ws4YZ8nHd5KqXxVQ0EqPWuWwMOyOdyy3DK/MjUOobGSc0//Pv5DeaAAEBKLJzN+e1BQM=
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.8.0]
8
+ ### Changed
9
+ - `Fortnox::API::CURRENT_HOUSEWORK_TYPES` is now renamed to `HOUSEWORK_TYPES`
10
+ and is instead a Hash with keys for the different categories of types.
11
+ It also includes legacy types, which means `Fortnox::API::LEGACY_HOUSEWORK_TYPES` is removed.
12
+
13
+ ### Removed
14
+ - Drops support for Ruby < `2.5.0` since they are deprecated
15
+
7
16
  ## [0.7.2]
8
17
  ### Fixed
9
18
  - Invalid validation for Customer's account number attribute
@@ -32,6 +41,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
32
41
  ### Fixed
33
42
  - Model attribute `url` is no longer null
34
43
 
44
+ [0.8.0]: https://github.com/accodeing/fortnox-api/compare/v0.7.2...v0.8.0
35
45
  [0.7.2]: https://github.com/accodeing/fortnox-api/compare/v0.7.1...v0.7.2
36
46
  [0.7.1]: https://github.com/accodeing/fortnox-api/compare/v0.7.0...v0.7.1
37
47
  [0.7.0]: https://github.com/accodeing/fortnox-api/compare/v0.6.3...v0.7.0
data/README.md CHANGED
@@ -10,14 +10,13 @@
10
10
  [![Maintainability](https://api.codeclimate.com/v1/badges/89d30a43fedf210d470b/maintainability)](https://codeclimate.com/github/accodeing/fortnox-api/maintainability)
11
11
  [![Test Coverage](https://api.codeclimate.com/v1/badges/89d30a43fedf210d470b/test_coverage)](https://codeclimate.com/github/accodeing/fortnox-api/test_coverage)
12
12
 
13
- The rough status of this project is as follows (as of October 2018):
13
+ The rough status of this project is as follows (as of December 2020):
14
14
  * Development is not as active as it used to be, but the project is not forgotten. We have an app running this gem in production and it works like a charm for what we do.
15
- * We are planning on generalize REST API's in general with our [rest_easy gem](https://github.com/accodeing/rest_easy).
15
+ * We hope to be able to continue with our work with [rest_easy gem](https://github.com/accodeing/rest_easy), which generalize REST API's in general.
16
16
  * Basic structure complete. Things like getting customers and invoices, updating and saving etc.
17
17
  * Some advanced features implemented, for instance support for multiple Access Tokens and filtering entities.
18
18
  * We have ideas for more advanced features, like sorting entities, pagination of results but nothing in the pipeline right now.
19
19
  * A few models implemented. Right now we pretty good support for `Customer`, `Invoice`, `Order`, `Article`, `Label` and `Project`. Adding more models in general is quick and easy (that's the whole point with this gem), see the developer guide further down.
20
- * Massive refactorings no longer occurs weekly :)
21
20
 
22
21
  # Architecture overview
23
22
  The gem is structured with distinct models for the tasks of data, JSON mapping and saving state. These are called: model, type, mapper and repository.
@@ -81,7 +80,7 @@ These are responsible for the mapping between our plain old Ruby object models a
81
80
 
82
81
  # Requirements
83
82
 
84
- This gem is build for Ruby 2.4 or higher (see Travis configuration file for what versions we are testing against).
83
+ This gem is built for Ruby 2.5 or higher (see Travis configuration file for what versions we are testing against).
85
84
 
86
85
  ## Installation
87
86
 
@@ -191,5 +190,9 @@ updated_customer.name #=> "Ned Stark"
191
190
 
192
191
  The update method takes an implicit hash of attributes to update, so you can update as many as you like in one go.
193
192
 
193
+ # Development
194
+ ## Testing
195
+ This gem has integration tests to verify the code against the real API. It uses [vcr](https://github.com/vcr/vcr) to record API endpoint responses. These responses are stored locally and are called vcr cassettes. If no cassettes are available, vcr will record new ones for you. Once in a while, it's good to throw away all cassettes and rerecord them. Fortnox updates their endpoints and we need to keep our code up to date with the reality. There's a handy rake task for removing all cassettes, see `rake -T`. Note that when rerecording all cassettes, do it one repository at a time, otherwise you'll definitely get `429 Too Many Requests` from Fortnox. Run them manually with something like `bundle exec rspec spec/fortnox/api/repositories/article_spec.rb`. Also, you will need to update some test data in specs, see notes in specs.
196
+
194
197
  # Contributing
195
198
  See the [CONTRIBUTE](CONTRIBUTE.md) readme.
data/Rakefile CHANGED
@@ -5,3 +5,8 @@ require 'rspec/core/rake_task'
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
 
7
7
  task default: :spec
8
+
9
+ desc 'Remove all VCR cassettes so we can rerecord them'
10
+ task :throw_vcr_cassettes do
11
+ FileUtils.rm_rf(Dir.glob('spec/vcr_cassettes/**'))
12
+ end
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
23
23
  spec.test_files = spec.files.grep(%r{^(spec)/})
24
24
  spec.require_paths = ['lib']
25
25
 
26
- spec.required_ruby_version = '>= 2.4'
26
+ spec.required_ruby_version = '>= 2.5'
27
27
  spec.add_dependency 'countries', '~> 3.0'
28
28
  spec.add_dependency 'dry-struct', '~> 0.1'
29
29
  spec.add_dependency 'dry-types', '~> 0.8', '< 0.13.0'
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
33
33
  spec.add_development_dependency 'guard', '~> 2.12'
34
34
  spec.add_development_dependency 'guard-rspec', '~> 4.5'
35
35
  spec.add_development_dependency 'pry', '~> 0'
36
- spec.add_development_dependency 'rake', '~> 10.4'
36
+ spec.add_development_dependency 'rake', '>= 12.3.3'
37
37
  spec.add_development_dependency 'rspec', '~> 3.2'
38
38
  spec.add_development_dependency 'rspec-collection_matchers', '~> 0'
39
39
  spec.add_development_dependency 'rubocop', '~> 0.52.0'
@@ -72,8 +72,8 @@ module Fortnox
72
72
 
73
73
  def default_key_from_json_transform(key)
74
74
  key = key.to_s
75
- key = camelcase_to_underscore(key) unless key =~ /\A[A-Z]+\z/
76
- key = strip_at_symbol(key) if key =~ /\A@.*\z/
75
+ key = camelcase_to_underscore(key) unless key.match?(/\A[A-Z]+\z/)
76
+ key = strip_at_symbol(key) if key.match?(/\A@.*\z/)
77
77
  key.downcase.to_sym
78
78
  end
79
79
 
@@ -154,6 +154,9 @@ module Fortnox
154
154
  # TaxReduction The amount of tax reduction.
155
155
  attribute :tax_reduction, Types::Nullable::Integer.is(:read_only)
156
156
 
157
+ # TaxReductionType Tax Reduction Type
158
+ attribute :tax_reduction_type, Types::TaxReductionType
159
+
157
160
  # TermsOfDelivery Code of the terms of delivery.
158
161
  attribute :terms_of_delivery, Types::Nullable::String
159
162
 
@@ -57,7 +57,7 @@ module Fortnox
57
57
  next value if value.nil? || value == ''
58
58
 
59
59
  # Fortnox only supports Swedish translation of Sweden
60
- next CountryString.new('SE') if value =~ /^s(e$|we|ve)/i
60
+ next CountryString.new('SE') if value.match?(/^s(e$|we|ve)/i)
61
61
 
62
62
  country = ::ISO3166::Country[value] ||
63
63
  ::ISO3166::Country.find_country_by_name(value) ||
@@ -119,6 +119,11 @@ module Fortnox
119
119
  .optional
120
120
  .constructor(EnumConstructors.default)
121
121
 
122
+ TaxReductionType = Strict::String
123
+ .constrained(included_in: TaxReductionTypes.values)
124
+ .optional
125
+ .constructor(EnumConstructors.lower_case)
126
+
122
127
  require 'fortnox/api/types/model'
123
128
  require 'fortnox/api/types/default_delivery_types'
124
129
  require 'fortnox/api/types/default_templates'
@@ -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
- CURRENT_HOUSEWORK_TYPES = %w[
29
- CONSTRUCTION ELECTRICITY GLASSMETALWORK GROUNDDRAINAGEWORK
30
- MASONRY PAINTINGWALLPAPERING HVAC MAJORAPPLIANCEREPAIR
31
- MOVINGSERVICES ITSERVICES CLEANING TEXTILECLOTHING
32
- SNOWPLOWING GARDENING BABYSITTING OTHERCARE OTHERCOSTS
33
- ].freeze
34
- LEGACY_HOUSEWORK_TYPES = %w[COOKING TUTORING].freeze
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
- *(CURRENT_HOUSEWORK_TYPES + LEGACY_HOUSEWORK_TYPES)
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Fortnox
4
4
  module API
5
- VERSION = '0.7.2'
5
+ VERSION = '0.8.0'
6
6
  end
7
7
  end
@@ -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
 
@@ -27,7 +27,7 @@ describe Fortnox::API::Repository::Article, order: :defined, integration: true d
27
27
  '5901234123457'
28
28
 
29
29
  # When recording new VCR cassettes, expected matches must be increased
30
- include_examples '.all', 26
30
+ include_examples '.all', 29
31
31
 
32
32
  # When recording new VCR cassettes, expected matches must be increased
33
33
  include_examples '.find', '1' do
@@ -39,7 +39,7 @@ describe Fortnox::API::Repository::Customer, order: :defined, integration: true
39
39
  end
40
40
 
41
41
  # When recording new VCR casettes, expected matches must be increased
42
- include_examples '.search', :name, 'Test', 30
42
+ include_examples '.search', :name, 'Test', 31
43
43
 
44
44
  describe 'country reference' do
45
45
  describe 'with valid country code \'SE\'' do
@@ -37,7 +37,7 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
37
37
 
38
38
  # It is not possible to delete Invoces. Therefore, expected nr of Orders
39
39
  # when running .all will continue to increase (until 100, which is max by default).
40
- include_examples '.all', 97
40
+ include_examples '.all', 100
41
41
 
42
42
  include_examples '.find', 1 do
43
43
  let(:find_by_hash_failure) { { yourreference: 'Not found' } }
@@ -129,27 +129,27 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
129
129
 
130
130
  before { persisted_invoice }
131
131
 
132
- context 'by setting value to nil' do
132
+ context 'when setting value to nil' do
133
+ subject { updated_persisted_invoice.comments }
134
+
133
135
  let(:updated_persisted_invoice) do
134
136
  VCR.use_cassette("#{vcr_dir}/save_old_with_nil_comments") do
135
137
  repository.save(persisted_invoice.update(comments: nil))
136
138
  end
137
139
  end
138
140
 
139
- subject { updated_persisted_invoice.comments }
140
-
141
141
  pending { is_expected.to eq(nil) }
142
142
  end
143
143
 
144
- context 'by setting value to empty string' do
144
+ context 'when setting value to empty string' do
145
+ subject { updated_persisted_invoice.comments }
146
+
145
147
  let(:updated_persisted_invoice) do
146
148
  VCR.use_cassette("#{vcr_dir}/save_old_with_empty_comments") do
147
149
  repository.save(persisted_invoice.update(comments: ''))
148
150
  end
149
151
  end
150
152
 
151
- subject { updated_persisted_invoice.comments }
152
-
153
153
  it 'does not reset the value' do
154
154
  is_expected.to eq('A comment to be reset')
155
155
  end
@@ -169,7 +169,9 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
169
169
 
170
170
  before { persisted_invoice }
171
171
 
172
- context 'by setting value to nil' do
172
+ context 'when setting value to nil' do
173
+ subject { updated_persisted_invoice.country }
174
+
173
175
  let(:updated_persisted_invoice) do
174
176
  # TODO: This VCR cassette needs to be re-recorded again
175
177
  # when the we fix #172.
@@ -178,20 +180,18 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
178
180
  end
179
181
  end
180
182
 
181
- subject { updated_persisted_invoice.country }
182
-
183
183
  pending { is_expected.to eq(nil) }
184
184
  end
185
185
 
186
- context 'by setting value to empty string' do
186
+ context 'when setting value to empty string' do
187
+ subject { updated_persisted_invoice.country }
188
+
187
189
  let(:updated_persisted_invoice) do
188
190
  VCR.use_cassette("#{vcr_dir}/save_old_with_empty_country") do
189
191
  repository.save(persisted_invoice.update(country: ''))
190
192
  end
191
193
  end
192
194
 
193
- subject { updated_persisted_invoice.country }
194
-
195
195
  it 'does not reset the country' do
196
196
  is_expected.to eq('SE')
197
197
  end
@@ -22,7 +22,7 @@ describe Fortnox::API::Repository::Project, order: :defined, integration: true d
22
22
  # It is not yet possible to delete Projects. Therefore, expected nr of
23
23
  # Projects when running .all will continue to increase
24
24
  # (until 100, which is max by default).
25
- include_examples '.all', 31
25
+ include_examples '.all', 33
26
26
 
27
27
  include_examples '.find', '1' do
28
28
  let(:find_by_hash_failure) { { offset: 10_000 } }
@@ -18,12 +18,12 @@ describe Fortnox::API::Repository::TermsOfPayment, order: :defined, integration:
18
18
  before { set_api_test_configuration }
19
19
 
20
20
  # When recording new VCR cassettes, code must be changed to a new unique one
21
- required_hash = { code: '18DAYS' }
21
+ required_hash = { code: '19DAYS' }
22
22
 
23
23
  include_examples '.save', :description, additional_attrs: required_hash
24
24
 
25
25
  # When recording new VCR cassettes, expected matches needs to be increased
26
- include_examples '.all', 12
26
+ include_examples '.all', 13
27
27
 
28
28
  include_examples '.find', '15DAYS', find_by_hash: false do
29
29
  let(:find_by_hash_failure) { { code: '15days' } }
@@ -19,16 +19,16 @@ describe Fortnox::API::Repository::Unit, order: :defined, integration: true do
19
19
  # When recording new VCR cassettes, code needs to be changed to a unique value
20
20
  include_examples '.save',
21
21
  :description,
22
- additional_attrs: { code: 'blarg4' }
22
+ additional_attrs: { code: 'blarg5' }
23
23
 
24
24
  # When recording new VCR cassettes, code needs to be changed to a unique value
25
25
  include_examples '.save with specially named attribute',
26
26
  { description: 'Happy clouds' },
27
27
  :code,
28
- 'woooh4'
28
+ 'woooh5'
29
29
 
30
30
  # When recording new VCR cassettes, expected number must be updated
31
- include_examples '.all', 12
31
+ include_examples '.all', 14
32
32
 
33
33
  include_examples '.find', 'blarg', find_by_hash: false do
34
34
  let(:find_by_hash_failure) { { code: 'notfound' } }
@@ -13,4 +13,5 @@ describe Fortnox::API::Types do
13
13
  it_behaves_like 'enum', 'VATType', 'VATTypes'
14
14
  it_behaves_like 'enum', 'DefaultDeliveryType', 'DefaultDeliveryTypeValues'
15
15
  it_behaves_like 'enum', 'ProjectStatusType', 'ProjectStatusTypes'
16
+ it_behaves_like 'enum', 'TaxReductionType', 'TaxReductionTypes'
16
17
  end
@@ -14,29 +14,32 @@ describe 'HouseworkTypes', integration: true do
14
14
  before { set_api_test_configuration }
15
15
 
16
16
  let(:repository) { Fortnox::API::Repository::Order.new }
17
- let(:valid_model) do
18
- Fortnox::API::Model::Order.new(customer_number: '1', order_rows: [order_row])
19
- end
20
- let(:order_row) do
21
- Fortnox::API::Types::OrderRow.new(ordered_quantity: 1,
22
- article_number: '0000',
23
- housework_type: housework_type)
24
- end
25
17
 
26
- shared_examples_for 'housework type' do |type, legacy: false|
18
+ shared_examples_for 'housework type' do |type, tax_reduction_type, legacy: false, housework: true|
27
19
  subject do
28
- lambda do
29
- VCR.use_cassette("orders/housework_type_#{type.downcase}") do
30
- repository.save(valid_model)
31
- end
32
- end
20
+ cassette = "orders/housework_type_#{type.downcase}"
21
+ -> { VCR.use_cassette(cassette) { repository.save(document) } }
33
22
  end
34
23
 
35
- let(:error_message) { 'Skattereduktion för den valda typen av husarbete har upphört.' }
36
- let(:housework_type) { Fortnox::API::Types::HouseworkTypes[type] }
24
+ let(:document) do
25
+ Fortnox::API::Model::Order.new(
26
+ customer_number: '1',
27
+ tax_reduction_type: tax_reduction_type,
28
+ order_rows: [
29
+ Fortnox::API::Types::OrderRow.new(
30
+ ordered_quantity: 1,
31
+ article_number: '0000',
32
+ housework_type: Fortnox::API::Types::HouseworkTypes[type],
33
+ housework: housework
34
+ )
35
+ ]
36
+ )
37
+ end
37
38
 
38
39
  context "when creating an OrderRow with housework_type set to #{type}" do
39
40
  if legacy
41
+ let(:error_message) { 'Skattereduktion för den valda typen av husarbete har upphört.' }
42
+
40
43
  it 'raises an error' do
41
44
  is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
42
45
  end
@@ -46,23 +49,137 @@ describe 'HouseworkTypes', integration: true do
46
49
  end
47
50
  end
48
51
 
49
- it_behaves_like 'housework type', 'CONSTRUCTION'
50
- it_behaves_like 'housework type', 'ELECTRICITY'
51
- it_behaves_like 'housework type', 'GLASSMETALWORK'
52
- it_behaves_like 'housework type', 'GROUNDDRAINAGEWORK'
53
- it_behaves_like 'housework type', 'MASONRY'
54
- it_behaves_like 'housework type', 'PAINTINGWALLPAPERING'
55
- it_behaves_like 'housework type', 'HVAC'
56
- it_behaves_like 'housework type', 'CLEANING'
57
- it_behaves_like 'housework type', 'TEXTILECLOTHING'
58
- it_behaves_like 'housework type', 'CLEANING'
59
- it_behaves_like 'housework type', 'SNOWPLOWING'
60
- it_behaves_like 'housework type', 'GARDENING'
61
- it_behaves_like 'housework type', 'BABYSITTING'
62
- it_behaves_like 'housework type', 'OTHERCARE'
63
- it_behaves_like 'housework type', 'OTHERCOSTS'
64
-
65
- it_behaves_like 'housework type', 'COOKING', legacy: true
66
- it_behaves_like 'housework type', 'TUTORING', legacy: true
52
+ TYPE_ROT = Fortnox::API::Types::TaxReductionTypes['rot']
53
+ TYPE_RUT = Fortnox::API::Types::TaxReductionTypes['rut']
54
+
55
+ it_behaves_like 'housework type', 'CONSTRUCTION', TYPE_ROT
56
+ it_behaves_like 'housework type', 'ELECTRICITY', TYPE_ROT
57
+ it_behaves_like 'housework type', 'GLASSMETALWORK', TYPE_ROT
58
+ it_behaves_like 'housework type', 'GROUNDDRAINAGEWORK', TYPE_ROT
59
+ it_behaves_like 'housework type', 'MASONRY', TYPE_ROT
60
+ it_behaves_like 'housework type', 'PAINTINGWALLPAPERING', TYPE_ROT
61
+ it_behaves_like 'housework type', 'HVAC', TYPE_ROT
62
+ it_behaves_like 'housework type', 'OTHERCOSTS', TYPE_ROT, housework: false
63
+
64
+ it_behaves_like 'housework type', 'MAJORAPPLIANCEREPAIR', TYPE_RUT
65
+ it_behaves_like 'housework type', 'MOVINGSERVICES', TYPE_RUT
66
+ it_behaves_like 'housework type', 'ITSERVICES', TYPE_RUT
67
+ it_behaves_like 'housework type', 'CLEANING', TYPE_RUT
68
+ it_behaves_like 'housework type', 'TEXTILECLOTHING', TYPE_RUT
69
+ it_behaves_like 'housework type', 'SNOWPLOWING', TYPE_RUT
70
+ it_behaves_like 'housework type', 'GARDENING', TYPE_RUT
71
+ it_behaves_like 'housework type', 'BABYSITTING', TYPE_RUT
72
+ it_behaves_like 'housework type', 'OTHERCARE', TYPE_RUT
73
+ it_behaves_like 'housework type', 'OTHERCOSTS', TYPE_RUT, housework: false
74
+
75
+ # rubocop:disable RSpec/RepeatedDescription
76
+ pending 'to be added' do
77
+ raise Exception, 'Will be supported 2021-01-01'
78
+ # it_behaves_like 'housework type', 'HOMEMAINTENANCE', TYPE_RUT
79
+ # it_behaves_like 'housework type', 'FURNISHING', TYPE_RUT
80
+ # it_behaves_like 'housework type', 'TRANSPORTATIONSERVICES', TYPE_RUT
81
+ # it_behaves_like 'housework type', 'WASHINGANDCAREOFCLOTHING', TYPE_RUT
82
+ end
83
+
84
+ pending 'to be added' do
85
+ raise Exception, 'Will be supported 2021-01-01'
86
+ # it_behaves_like 'housework type', 'SOLARCELLS', TYPE_GREEN
87
+ # it_behaves_like 'housework type', 'STORAGESELFPRODUCEDELECTRICTY', TYPE_GREEN
88
+ # it_behaves_like 'housework type', 'CHARGINGSTATIONELECTRICVEHICLE', TYPE_GREEN
89
+ # it_behaves_like 'housework type', 'OTHERCOSTS', TYPE_GREEN
90
+ end
91
+ # rubocop:enable RSpec/RepeatedDescription
92
+
93
+ it_behaves_like 'housework type', 'COOKING', TYPE_RUT, legacy: true
94
+ it_behaves_like 'housework type', 'TUTORING', TYPE_RUT, legacy: true
95
+
96
+ describe 'without tax reduction type' do
97
+ subject do
98
+ cassette = 'orders/housework_without_tax_reduction_type'
99
+ -> { VCR.use_cassette(cassette) { repository.save(document) } }
100
+ end
101
+
102
+ let(:document) do
103
+ Fortnox::API::Model::Order.new(
104
+ customer_number: '1',
105
+ order_rows: [
106
+ Fortnox::API::Types::OrderRow.new(
107
+ ordered_quantity: 1,
108
+ article_number: '0000',
109
+ housework_type: Fortnox::API::Types::HouseworkTypes['CONSTRUCTION'],
110
+ housework: true
111
+ )
112
+ ]
113
+ )
114
+ end
115
+
116
+ let(:error_message) do
117
+ 'Dokument utan angiven skattereduktionstyp får inte innehålla artikelrader med husarbetestyp.'
118
+ end
119
+
120
+ it 'raises an error' do
121
+ is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
122
+ end
123
+ end
124
+
125
+ describe 'with OTHERCOSTS' do
126
+ subject do
127
+ cassette = 'orders/housework_othercoses_invalid'
128
+ -> { VCR.use_cassette(cassette) { repository.save(document) } }
129
+ end
130
+
131
+ let(:document) do
132
+ Fortnox::API::Model::Order.new(
133
+ customer_number: '1',
134
+ tax_reduction_type: TYPE_ROT,
135
+ order_rows: [
136
+ Fortnox::API::Types::OrderRow.new(
137
+ ordered_quantity: 1,
138
+ article_number: '0000',
139
+ housework_type: Fortnox::API::Types::HouseworkTypes['OTHERCOSTS'],
140
+ housework: true
141
+ )
142
+ ]
143
+ )
144
+ end
145
+
146
+ let(:error_message) { 'Kan inte sätta typen övrig kostnad på en rad markerad som husarbete.' }
147
+
148
+ it "can't have housework set to true" do
149
+ is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
150
+ end
151
+ end
152
+
153
+ describe 'with wrong tax reduction type' do
154
+ subject do
155
+ cassette = 'orders/housework_invalid_tax_reduction_type'
156
+ -> { VCR.use_cassette(cassette) { repository.save(document) } }
157
+ end
158
+
159
+ let(:type) { 'CONSTRUCTION' }
160
+ let(:document) do
161
+ Fortnox::API::Model::Order.new(
162
+ customer_number: '1',
163
+ tax_reduction_type: TYPE_RUT,
164
+ order_rows: [
165
+ Fortnox::API::Types::OrderRow.new(
166
+ ordered_quantity: 1,
167
+ article_number: '0000',
168
+ housework_type: Fortnox::API::Types::HouseworkTypes[type],
169
+ housework: true
170
+ )
171
+ ]
172
+ )
173
+ end
174
+
175
+ let(:error_message) do
176
+ "Dokument med skattereduktionstypen '#{TYPE_RUT}' " \
177
+ "får inte innehålla rader med husarbetestypen '#{type}'."
178
+ end
179
+
180
+ it 'raises an error' do
181
+ is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
182
+ end
183
+ end
67
184
  end
68
185
  # rubocop:enable RSpec/DescribeClass