fortnox-api 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +3 -2
- data/.env.test +3 -0
- data/.rubocop.yml +32 -23
- data/.travis.yml +3 -2
- data/Guardfile +2 -2
- data/LICENSE.txt +165 -22
- data/README.md +56 -37
- data/fortnox-api.gemspec +9 -6
- data/lib/fortnox/api.rb +18 -2
- data/lib/fortnox/api/base.rb +5 -3
- data/lib/fortnox/api/environment_validation.rb +51 -6
- data/lib/fortnox/api/mappers.rb +49 -0
- data/lib/fortnox/api/mappers/base.rb +47 -0
- data/lib/fortnox/api/mappers/base/from_json.rb +78 -0
- data/lib/fortnox/api/mappers/base/to_json.rb +65 -0
- data/lib/fortnox/api/mappers/customer.rb +27 -0
- data/lib/fortnox/api/mappers/default_delivery_types.rb +13 -0
- data/lib/fortnox/api/mappers/default_templates.rb +15 -0
- data/lib/fortnox/api/mappers/edi_information.rb +22 -0
- data/lib/fortnox/api/mappers/email_information.rb +18 -0
- data/lib/fortnox/api/mappers/invoice.rb +27 -0
- data/lib/fortnox/api/mappers/invoice_row.rb +20 -0
- data/lib/fortnox/api/mappers/order.rb +23 -0
- data/lib/fortnox/api/mappers/order_row.rb +16 -0
- data/lib/fortnox/api/models.rb +2 -0
- data/lib/fortnox/api/models/base.rb +56 -13
- data/lib/fortnox/api/models/customer.rb +112 -101
- data/lib/fortnox/api/models/document_base.rb +189 -0
- data/lib/fortnox/api/models/invoice.rb +29 -195
- data/lib/fortnox/api/models/label.rb +17 -0
- data/lib/fortnox/api/models/order.rb +27 -0
- data/lib/fortnox/api/repositories.rb +2 -0
- data/lib/fortnox/api/repositories/base.rb +4 -5
- data/lib/fortnox/api/repositories/base/loaders.rb +22 -14
- data/lib/fortnox/api/repositories/base/savers.rb +30 -16
- data/lib/fortnox/api/repositories/customer.rb +3 -25
- data/lib/fortnox/api/repositories/invoice.rb +3 -22
- data/lib/fortnox/api/repositories/order.rb +16 -0
- data/lib/fortnox/api/request_handling.rb +3 -3
- data/lib/fortnox/api/types.rb +44 -0
- data/lib/fortnox/api/types/default_delivery_types.rb +20 -0
- data/lib/fortnox/api/types/default_templates.rb +23 -0
- data/lib/fortnox/api/types/defaulted.rb +11 -0
- data/lib/fortnox/api/types/document_row.rb +65 -0
- data/lib/fortnox/api/types/edi_information.rb +29 -0
- data/lib/fortnox/api/types/email_information.rb +26 -0
- data/lib/fortnox/api/types/enums.rb +75 -0
- data/lib/fortnox/api/types/invoice_row.rb +19 -0
- data/lib/fortnox/api/types/model.rb +40 -0
- data/lib/fortnox/api/types/nullable.rb +21 -0
- data/lib/fortnox/api/types/order_row.rb +16 -0
- data/lib/fortnox/api/types/required.rb +13 -0
- data/lib/fortnox/api/types/sized.rb +25 -0
- data/lib/fortnox/api/version.rb +1 -1
- data/spec/fortnox/api/base_spec.rb +85 -14
- data/spec/fortnox/api/mappers/base/from_json_spec.rb +70 -0
- data/spec/fortnox/api/mappers/base/to_json_spec.rb +76 -0
- data/spec/fortnox/api/mappers/base_spec.rb +156 -0
- data/spec/fortnox/api/mappers/contexts/json_conversion.rb +56 -0
- data/spec/fortnox/api/mappers/customer_spec.rb +25 -0
- data/spec/fortnox/api/mappers/default_delivery_types_spec.rb +12 -0
- data/spec/fortnox/api/mappers/edi_information_spec.rb +21 -0
- data/spec/fortnox/api/mappers/email_information_spec.rb +17 -0
- data/spec/fortnox/api/mappers/examples/mapper.rb +26 -0
- data/spec/fortnox/api/mappers/invoice_row_spec.rb +19 -0
- data/spec/fortnox/api/mappers/invoice_spec.rb +24 -0
- data/spec/fortnox/api/mappers/order_row_spec.rb +14 -0
- data/spec/fortnox/api/mappers/order_spec.rb +20 -0
- data/spec/fortnox/api/models/base_spec.rb +44 -22
- data/spec/fortnox/api/models/customer_spec.rb +9 -0
- data/spec/fortnox/api/models/examples/document_base.rb +13 -0
- data/spec/fortnox/api/models/examples/model.rb +13 -0
- data/spec/fortnox/api/models/invoice_spec.rb +7 -31
- data/spec/fortnox/api/models/order_spec.rb +13 -0
- data/spec/fortnox/api/repositories/customer_spec.rb +20 -76
- data/spec/fortnox/api/repositories/examples/all.rb +17 -0
- data/spec/fortnox/api/repositories/examples/find.rb +25 -0
- data/spec/fortnox/api/repositories/examples/only.rb +42 -0
- data/spec/fortnox/api/repositories/examples/save.rb +69 -0
- data/spec/fortnox/api/repositories/examples/save_with_nested_model.rb +32 -0
- data/spec/fortnox/api/repositories/examples/save_with_specially_named_attribute.rb +27 -0
- data/spec/fortnox/api/repositories/examples/search.rb +31 -0
- data/spec/fortnox/api/repositories/invoice_spec.rb +36 -5
- data/spec/fortnox/api/repositories/order_spec.rb +35 -0
- data/spec/fortnox/api/types/account_number_spec.rb +28 -0
- data/spec/fortnox/api/types/default_delivery_types_spec.rb +10 -0
- data/spec/fortnox/api/types/edi_information_spec.rb +13 -0
- data/spec/fortnox/api/types/email_information_spec.rb +13 -0
- data/spec/fortnox/api/types/email_spec.rb +29 -0
- data/spec/fortnox/api/types/enums_spec.rb +13 -0
- data/spec/fortnox/api/types/examples/document_row.rb +15 -0
- data/spec/fortnox/api/types/examples/enum.rb +48 -0
- data/spec/fortnox/api/types/examples/types.rb +9 -0
- data/spec/fortnox/api/types/house_work_types_spec.rb +60 -0
- data/spec/fortnox/api/types/invoice_row_spec.rb +9 -0
- data/spec/fortnox/api/types/model_spec.rb +56 -0
- data/spec/fortnox/api/types/nullable_spec.rb +57 -0
- data/spec/fortnox/api/types/order_row_spec.rb +13 -0
- data/spec/fortnox/api/types/required_spec.rb +42 -0
- data/spec/fortnox/api/types/sized_spec.rb +74 -0
- data/spec/fortnox/api_spec.rb +16 -15
- data/spec/spec_helper.rb +19 -9
- data/spec/support/helpers/dummy_class_helper.rb +19 -0
- data/spec/support/helpers/environment_helper.rb +7 -0
- data/spec/support/helpers/repository_helper.rb +8 -0
- data/spec/support/helpers/when_performing_helper.rb +5 -0
- data/spec/support/matchers.rb +1 -1
- data/spec/support/matchers/type.rb +17 -0
- data/spec/support/matchers/type/attribute_matcher.rb +39 -0
- data/spec/support/matchers/type/enum_matcher.rb +21 -0
- data/spec/support/matchers/type/have_account_number_matcher.rb +21 -0
- data/spec/support/matchers/type/have_country_code_matcher.rb +13 -0
- data/spec/support/matchers/type/have_currency_matcher.rb +7 -0
- data/spec/support/matchers/type/have_customer_type_matcher.rb +13 -0
- data/spec/support/matchers/type/have_default_delivery_type_matcher.rb +7 -0
- data/spec/support/matchers/type/have_discount_type_matcher.rb +7 -0
- data/spec/support/matchers/type/have_email_matcher.rb +22 -0
- data/spec/support/matchers/type/have_house_work_type_matcher.rb +7 -0
- data/spec/support/matchers/type/have_nullable_date_matcher.rb +58 -0
- data/spec/support/matchers/type/have_nullable_matcher.rb +52 -0
- data/spec/support/matchers/type/have_nullable_string_matcher.rb +49 -0
- data/spec/support/matchers/type/have_sized_float_matcher.rb +8 -0
- data/spec/support/matchers/type/have_sized_integer_matcher.rb +8 -0
- data/spec/support/matchers/type/have_sized_string_matcher.rb +35 -0
- data/spec/support/matchers/type/have_vat_type_matcher.rb +7 -0
- data/spec/support/matchers/type/numeric_matcher.rb +50 -0
- data/spec/support/matchers/type/require_attribute_matcher.rb +69 -0
- data/spec/support/matchers/type/type_matcher.rb +38 -0
- data/spec/vcr_cassettes/customers/all.yml +119 -9
- data/spec/vcr_cassettes/customers/find_id_1.yml +8 -9
- data/spec/vcr_cassettes/customers/find_new.yml +46 -0
- data/spec/vcr_cassettes/customers/save_new.yml +9 -11
- data/spec/vcr_cassettes/customers/save_old.yml +9 -12
- data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +45 -0
- data/spec/vcr_cassettes/customers/search_by_name.yml +66 -0
- data/spec/vcr_cassettes/customers/search_miss.yml +45 -0
- data/spec/vcr_cassettes/invoices/all.yml +104 -0
- data/spec/vcr_cassettes/invoices/filter_hit.yml +46 -0
- data/spec/vcr_cassettes/invoices/filter_invalid.yml +42 -0
- data/spec/vcr_cassettes/invoices/find_id_1.yml +47 -0
- data/spec/vcr_cassettes/invoices/find_new.yml +49 -0
- data/spec/vcr_cassettes/invoices/save_new.yml +48 -0
- data/spec/vcr_cassettes/invoices/save_old.yml +49 -0
- data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +47 -0
- data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +47 -0
- data/spec/vcr_cassettes/invoices/search_by_name.yml +48 -0
- data/spec/vcr_cassettes/invoices/search_miss.yml +45 -0
- data/spec/vcr_cassettes/orders/all.yml +144 -0
- data/spec/vcr_cassettes/orders/filter_hit.yml +48 -0
- data/spec/vcr_cassettes/orders/filter_invalid.yml +42 -0
- data/spec/vcr_cassettes/orders/find_id_1.yml +48 -0
- data/spec/vcr_cassettes/orders/find_new.yml +49 -0
- data/spec/vcr_cassettes/orders/house_work_type_babysitting.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_cleaning.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_construction.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_cooking.yml +43 -0
- data/spec/vcr_cassettes/orders/house_work_type_electricity.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_gardening.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_glassmetalwork.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_grounddrainagework.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_hvac.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_masonry.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_othercare.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_othercosts.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_paintingwallpapering.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_snowplowing.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_textileclothing.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_tutoring.yml +43 -0
- data/spec/vcr_cassettes/orders/save_new.yml +48 -0
- data/spec/vcr_cassettes/orders/save_old.yml +49 -0
- data/spec/vcr_cassettes/orders/save_with_nested_model.yml +47 -0
- data/spec/vcr_cassettes/orders/search_by_name.yml +47 -0
- data/spec/vcr_cassettes/orders/search_miss.yml +45 -0
- metadata +301 -71
- data/lib/fortnox/api/models/attributes/country_code.rb +0 -17
- data/lib/fortnox/api/models/attributes/currency.rb +0 -17
- data/lib/fortnox/api/models/edi_information.rb +0 -28
- data/lib/fortnox/api/models/email_information.rb +0 -25
- data/lib/fortnox/api/models/row.rb +0 -82
- data/lib/fortnox/api/repositories/base/json_convertion.rb +0 -68
- data/lib/fortnox/api/repositories/base/options.rb +0 -33
- data/lib/fortnox/api/validators.rb +0 -1
- data/lib/fortnox/api/validators/attributes/country_code.rb +0 -42
- data/lib/fortnox/api/validators/attributes/currency.rb +0 -38
- data/lib/fortnox/api/validators/base.rb +0 -70
- data/lib/fortnox/api/validators/constant.rb +0 -21
- data/lib/fortnox/api/validators/customer.rb +0 -29
- data/lib/fortnox/api/validators/edi_information.rb +0 -11
- data/lib/fortnox/api/validators/email_information.rb +0 -19
- data/lib/fortnox/api/validators/invoice.rb +0 -33
- data/lib/fortnox/api/validators/row.rb +0 -22
- data/spec/fortnox/api/models/attributes/country_code_spec.rb +0 -23
- data/spec/fortnox/api/models/attributes/currency_spec.rb +0 -23
- data/spec/fortnox/api/models/attributes/dummy_model_context.rb +0 -9
- data/spec/fortnox/api/models/row_spec.rb +0 -13
- data/spec/fortnox/api/repositories/context.rb +0 -10
- data/spec/fortnox/api/repositories/examples.rb +0 -16
- data/spec/fortnox/api/validators/attributes/country_code_spec.rb +0 -9
- data/spec/fortnox/api/validators/attributes/currency_spec.rb +0 -9
- data/spec/fortnox/api/validators/attributes/examples_for_validate.rb +0 -29
- data/spec/fortnox/api/validators/base_spec.rb +0 -61
- data/spec/fortnox/api/validators/constant_spec.rb +0 -12
- data/spec/fortnox/api/validators/context.rb +0 -102
- data/spec/fortnox/api/validators/customer_spec.rb +0 -31
- data/spec/fortnox/api/validators/edi_information_spec.rb +0 -18
- data/spec/fortnox/api/validators/email_information_spec.rb +0 -26
- data/spec/fortnox/api/validators/invoice_spec.rb +0 -36
- data/spec/fortnox/api/validators/row_spec.rb +0 -27
- data/spec/fortnox/api/validators/validator_examples.rb +0 -20
- data/spec/support/matchers/models.rb +0 -27
- data/spec/support/matchers/validators.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e14de06afe9e870c90a72663071002f8acb19e5
|
4
|
+
data.tar.gz: 4dc0b9ee89a977e576736102451ef54efa1fcdbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64e08b1aa313475699bb3e6f9ce31f19bab00ab9104df525dc71dd05bf3c6b6503a9a0405931cb4e92b5d3eba1b1f4143e4b334d207d9f4451a0ad5d78bbae08
|
7
|
+
data.tar.gz: 171f54a4cca2ec7567e357c7141df4b689e0ccf4622e42ebdac04411a6109b90cd200a4052e056ffa7c03c6699084cce94678514afa2ce223bea34a6c18ced23
|
data/.codeclimate.yml
CHANGED
data/.env.test
ADDED
data/.rubocop.yml
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
|
1
3
|
AllCops:
|
2
|
-
|
3
|
-
|
4
|
+
TargetRubyVersion: 2.2
|
5
|
+
DisplayCopNames: true
|
4
6
|
|
5
7
|
#################### Lint ################################
|
6
8
|
|
@@ -316,12 +318,6 @@ Performance/StringReplacement:
|
|
316
318
|
|
317
319
|
################## Style #################################
|
318
320
|
|
319
|
-
Style/SpaceBeforeFirstArg:
|
320
|
-
Description: >-
|
321
|
-
Put a space between a method name and the first argument
|
322
|
-
in a method call without parentheses.
|
323
|
-
Enabled: true
|
324
|
-
|
325
321
|
Style/AccessModifierIndentation:
|
326
322
|
Description: Check indentation of private/protected visibility modifiers.
|
327
323
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-public-private-protected'
|
@@ -485,11 +481,6 @@ Style/DefWithParentheses:
|
|
485
481
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens'
|
486
482
|
Enabled: false
|
487
483
|
|
488
|
-
Style/DeprecatedHashMethods:
|
489
|
-
Description: 'Checks for use of deprecated Hash methods.'
|
490
|
-
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-key'
|
491
|
-
Enabled: false
|
492
|
-
|
493
484
|
Style/Documentation:
|
494
485
|
Description: 'Document classes and non-namespace modules.'
|
495
486
|
Enabled: false
|
@@ -811,6 +802,11 @@ Style/PredicateName:
|
|
811
802
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark'
|
812
803
|
Enabled: false
|
813
804
|
|
805
|
+
Style/PreferredHashMethods:
|
806
|
+
Description: 'Checks for use of deprecated Hash methods.'
|
807
|
+
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-key'
|
808
|
+
Enabled: false
|
809
|
+
|
814
810
|
Style/Proc:
|
815
811
|
Description: 'Use proc instead of Proc.new.'
|
816
812
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc'
|
@@ -892,10 +888,6 @@ Style/SpaceAfterComma:
|
|
892
888
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators'
|
893
889
|
Enabled: false
|
894
890
|
|
895
|
-
Style/SpaceAfterControlKeyword:
|
896
|
-
Description: 'Use spaces after if/elsif/unless/while/until/case/when.'
|
897
|
-
Enabled: false
|
898
|
-
|
899
891
|
Style/SpaceAfterMethodName:
|
900
892
|
Description: >-
|
901
893
|
Do not put a space between a method name and the opening
|
@@ -934,6 +926,12 @@ Style/SpaceBeforeSemicolon:
|
|
934
926
|
Description: 'No spaces before semicolons.'
|
935
927
|
Enabled: false
|
936
928
|
|
929
|
+
Style/SpaceBeforeFirstArg:
|
930
|
+
Description: >-
|
931
|
+
Put a space between a method name and the first argument
|
932
|
+
in a method call without parentheses.
|
933
|
+
Enabled: true
|
934
|
+
|
937
935
|
Style/SpaceInsideBlockBraces:
|
938
936
|
Description: >-
|
939
937
|
Checks that block braces have or don't have surrounding space.
|
@@ -964,7 +962,7 @@ Style/SpaceAroundOperators:
|
|
964
962
|
AllowForAlignment: true
|
965
963
|
Enabled: true
|
966
964
|
|
967
|
-
Style/
|
965
|
+
Style/SpaceAroundKeyword:
|
968
966
|
Description: 'Put a space before the modifier keyword.'
|
969
967
|
Enabled: false
|
970
968
|
|
@@ -980,17 +978,21 @@ Style/SpaceInsideHashLiteralBraces:
|
|
980
978
|
EnforcedStyleForEmptyBraces: no_space
|
981
979
|
Enabled: true
|
982
980
|
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
# Enabled: true
|
981
|
+
Style/SpaceInsideParens:
|
982
|
+
Description: 'Require spaces after ( or before ).'
|
983
|
+
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces'
|
984
|
+
Enabled: false
|
988
985
|
|
989
986
|
Style/SpaceInsideRangeLiteral:
|
990
987
|
Description: 'No spaces inside range literals.'
|
991
988
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-space-inside-range-literals'
|
992
989
|
Enabled: false
|
993
990
|
|
991
|
+
Style/SpaceInsideStringInterpolation:
|
992
|
+
Description: 'This cop checks for whitespace within string interpolations.'
|
993
|
+
EnforcedStyle: space
|
994
|
+
Enabled: true
|
995
|
+
|
994
996
|
Style/SpecialGlobalVars:
|
995
997
|
Description: 'Avoid Perl-style global variables.'
|
996
998
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms'
|
@@ -1105,3 +1107,10 @@ Style/WordArray:
|
|
1105
1107
|
Description: 'Use %w or %W for arrays of words.'
|
1106
1108
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-w'
|
1107
1109
|
Enabled: false
|
1110
|
+
|
1111
|
+
#################### RSpec ################################
|
1112
|
+
RSpec/FilePath:
|
1113
|
+
Enabled: false
|
1114
|
+
|
1115
|
+
RSpec/NestedGroups:
|
1116
|
+
MaxNesting: 4
|
data/.travis.yml
CHANGED
data/Guardfile
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
guard :rspec, cmd: 'bundle exec rspec --color', all_after_pass: true do
|
2
2
|
watch(%r{^spec/.+_spec\.rb$})
|
3
|
-
watch(%r{^lib/(.+)\.rb$}){ |m| "spec/#{m[1]}_spec.rb" }
|
3
|
+
watch(%r{^lib/(.+)\.rb$}){ |m| "spec/#{ m[1] }_spec.rb" }
|
4
4
|
watch('spec/spec_helper.rb'){ "spec" }
|
5
|
-
end
|
5
|
+
end
|
data/LICENSE.txt
CHANGED
@@ -1,22 +1,165 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
the
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
1
|
+
GNU LESSER GENERAL PUBLIC LICENSE
|
2
|
+
Version 3, 29 June 2007
|
3
|
+
|
4
|
+
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
5
|
+
Everyone is permitted to copy and distribute verbatim copies
|
6
|
+
of this license document, but changing it is not allowed.
|
7
|
+
|
8
|
+
|
9
|
+
This version of the GNU Lesser General Public License incorporates
|
10
|
+
the terms and conditions of version 3 of the GNU General Public
|
11
|
+
License, supplemented by the additional permissions listed below.
|
12
|
+
|
13
|
+
0. Additional Definitions.
|
14
|
+
|
15
|
+
As used herein, "this License" refers to version 3 of the GNU Lesser
|
16
|
+
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
17
|
+
General Public License.
|
18
|
+
|
19
|
+
"The Library" refers to a covered work governed by this License,
|
20
|
+
other than an Application or a Combined Work as defined below.
|
21
|
+
|
22
|
+
An "Application" is any work that makes use of an interface provided
|
23
|
+
by the Library, but which is not otherwise based on the Library.
|
24
|
+
Defining a subclass of a class defined by the Library is deemed a mode
|
25
|
+
of using an interface provided by the Library.
|
26
|
+
|
27
|
+
A "Combined Work" is a work produced by combining or linking an
|
28
|
+
Application with the Library. The particular version of the Library
|
29
|
+
with which the Combined Work was made is also called the "Linked
|
30
|
+
Version".
|
31
|
+
|
32
|
+
The "Minimal Corresponding Source" for a Combined Work means the
|
33
|
+
Corresponding Source for the Combined Work, excluding any source code
|
34
|
+
for portions of the Combined Work that, considered in isolation, are
|
35
|
+
based on the Application, and not on the Linked Version.
|
36
|
+
|
37
|
+
The "Corresponding Application Code" for a Combined Work means the
|
38
|
+
object code and/or source code for the Application, including any data
|
39
|
+
and utility programs needed for reproducing the Combined Work from the
|
40
|
+
Application, but excluding the System Libraries of the Combined Work.
|
41
|
+
|
42
|
+
1. Exception to Section 3 of the GNU GPL.
|
43
|
+
|
44
|
+
You may convey a covered work under sections 3 and 4 of this License
|
45
|
+
without being bound by section 3 of the GNU GPL.
|
46
|
+
|
47
|
+
2. Conveying Modified Versions.
|
48
|
+
|
49
|
+
If you modify a copy of the Library, and, in your modifications, a
|
50
|
+
facility refers to a function or data to be supplied by an Application
|
51
|
+
that uses the facility (other than as an argument passed when the
|
52
|
+
facility is invoked), then you may convey a copy of the modified
|
53
|
+
version:
|
54
|
+
|
55
|
+
a) under this License, provided that you make a good faith effort to
|
56
|
+
ensure that, in the event an Application does not supply the
|
57
|
+
function or data, the facility still operates, and performs
|
58
|
+
whatever part of its purpose remains meaningful, or
|
59
|
+
|
60
|
+
b) under the GNU GPL, with none of the additional permissions of
|
61
|
+
this License applicable to that copy.
|
62
|
+
|
63
|
+
3. Object Code Incorporating Material from Library Header Files.
|
64
|
+
|
65
|
+
The object code form of an Application may incorporate material from
|
66
|
+
a header file that is part of the Library. You may convey such object
|
67
|
+
code under terms of your choice, provided that, if the incorporated
|
68
|
+
material is not limited to numerical parameters, data structure
|
69
|
+
layouts and accessors, or small macros, inline functions and templates
|
70
|
+
(ten or fewer lines in length), you do both of the following:
|
71
|
+
|
72
|
+
a) Give prominent notice with each copy of the object code that the
|
73
|
+
Library is used in it and that the Library and its use are
|
74
|
+
covered by this License.
|
75
|
+
|
76
|
+
b) Accompany the object code with a copy of the GNU GPL and this license
|
77
|
+
document.
|
78
|
+
|
79
|
+
4. Combined Works.
|
80
|
+
|
81
|
+
You may convey a Combined Work under terms of your choice that,
|
82
|
+
taken together, effectively do not restrict modification of the
|
83
|
+
portions of the Library contained in the Combined Work and reverse
|
84
|
+
engineering for debugging such modifications, if you also do each of
|
85
|
+
the following:
|
86
|
+
|
87
|
+
a) Give prominent notice with each copy of the Combined Work that
|
88
|
+
the Library is used in it and that the Library and its use are
|
89
|
+
covered by this License.
|
90
|
+
|
91
|
+
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
92
|
+
document.
|
93
|
+
|
94
|
+
c) For a Combined Work that displays copyright notices during
|
95
|
+
execution, include the copyright notice for the Library among
|
96
|
+
these notices, as well as a reference directing the user to the
|
97
|
+
copies of the GNU GPL and this license document.
|
98
|
+
|
99
|
+
d) Do one of the following:
|
100
|
+
|
101
|
+
0) Convey the Minimal Corresponding Source under the terms of this
|
102
|
+
License, and the Corresponding Application Code in a form
|
103
|
+
suitable for, and under terms that permit, the user to
|
104
|
+
recombine or relink the Application with a modified version of
|
105
|
+
the Linked Version to produce a modified Combined Work, in the
|
106
|
+
manner specified by section 6 of the GNU GPL for conveying
|
107
|
+
Corresponding Source.
|
108
|
+
|
109
|
+
1) Use a suitable shared library mechanism for linking with the
|
110
|
+
Library. A suitable mechanism is one that (a) uses at run time
|
111
|
+
a copy of the Library already present on the user's computer
|
112
|
+
system, and (b) will operate properly with a modified version
|
113
|
+
of the Library that is interface-compatible with the Linked
|
114
|
+
Version.
|
115
|
+
|
116
|
+
e) Provide Installation Information, but only if you would otherwise
|
117
|
+
be required to provide such information under section 6 of the
|
118
|
+
GNU GPL, and only to the extent that such information is
|
119
|
+
necessary to install and execute a modified version of the
|
120
|
+
Combined Work produced by recombining or relinking the
|
121
|
+
Application with a modified version of the Linked Version. (If
|
122
|
+
you use option 4d0, the Installation Information must accompany
|
123
|
+
the Minimal Corresponding Source and Corresponding Application
|
124
|
+
Code. If you use option 4d1, you must provide the Installation
|
125
|
+
Information in the manner specified by section 6 of the GNU GPL
|
126
|
+
for conveying Corresponding Source.)
|
127
|
+
|
128
|
+
5. Combined Libraries.
|
129
|
+
|
130
|
+
You may place library facilities that are a work based on the
|
131
|
+
Library side by side in a single library together with other library
|
132
|
+
facilities that are not Applications and are not covered by this
|
133
|
+
License, and convey such a combined library under terms of your
|
134
|
+
choice, if you do both of the following:
|
135
|
+
|
136
|
+
a) Accompany the combined library with a copy of the same work based
|
137
|
+
on the Library, uncombined with any other library facilities,
|
138
|
+
conveyed under the terms of this License.
|
139
|
+
|
140
|
+
b) Give prominent notice with the combined library that part of it
|
141
|
+
is a work based on the Library, and explaining where to find the
|
142
|
+
accompanying uncombined form of the same work.
|
143
|
+
|
144
|
+
6. Revised Versions of the GNU Lesser General Public License.
|
145
|
+
|
146
|
+
The Free Software Foundation may publish revised and/or new versions
|
147
|
+
of the GNU Lesser General Public License from time to time. Such new
|
148
|
+
versions will be similar in spirit to the present version, but may
|
149
|
+
differ in detail to address new problems or concerns.
|
150
|
+
|
151
|
+
Each version is given a distinguishing version number. If the
|
152
|
+
Library as you received it specifies that a certain numbered version
|
153
|
+
of the GNU Lesser General Public License "or any later version"
|
154
|
+
applies to it, you have the option of following the terms and
|
155
|
+
conditions either of that published version or of any later version
|
156
|
+
published by the Free Software Foundation. If the Library as you
|
157
|
+
received it does not specify a version number of the GNU Lesser
|
158
|
+
General Public License, you may choose any version of the GNU Lesser
|
159
|
+
General Public License ever published by the Free Software Foundation.
|
160
|
+
|
161
|
+
If the Library as you received it specifies that a proxy can decide
|
162
|
+
whether future versions of the GNU Lesser General Public License shall
|
163
|
+
apply, that proxy's public statement of acceptance of any version is
|
164
|
+
permanent authorization for you to choose that version for the
|
165
|
+
Library.
|
data/README.md
CHANGED
@@ -1,29 +1,33 @@
|
|
1
1
|
# Fortnox API
|
2
|
-
> Wrapper gem for Fortnox AB's version 3 REST(ish) API. If you need to integrate an existing or new Ruby or Rails app against Fortnox this gem will save you a lot of time, you are welcome. Feel free to repay the community with some nice PRs of your own :simple_smile:
|
2
|
+
> Wrapper gem for Fortnox AB's version 3 REST(ish) API. If you need to integrate an existing or new Ruby or Rails app against Fortnox this gem will save you a lot of time, you are welcome. Feel free to repay the community with some nice PRs of your own :simple_smile:
|
3
3
|
|
4
|
-
# Status
|
5
|
-
[![Gem
|
6
|
-
[![Build
|
7
|
-
[![
|
8
|
-
[![Test Coverage](https://codeclimate.com/github/my-codeworks/fortnox-api/badges/coverage.svg)](https://codeclimate.com/github/my-codeworks/fortnox-api/coverage)
|
9
|
-
[![Dependency Status](https://gemnasium.com/my-codeworks/fortnox-api.svg)](https://gemnasium.com/my-codeworks/fortnox-api)
|
4
|
+
# Status for master
|
5
|
+
[![Gem version](https://img.shields.io/gem/v/fortnox-api.svg?style=flat-square)](https://rubygems.org/gems/fortnox-api)
|
6
|
+
[![Build status](https://img.shields.io/travis/my-codeworks/fortnox-api/master.svg?style=flat-square)](https://travis-ci.org/my-codeworks/fortnox-api)
|
7
|
+
[![Dependency status](https://img.shields.io/gemnasium/my-codeworks/fortnox-api.svg?style=flat-square)](https://gemnasium.com/my-codeworks/fortnox-api)
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
* Advanced features around the corner. Things like filtering entities or sorting, pagination of results etc.
|
16
|
-
* A few models implemented. Right now it's Customer and Invoice that are the furthest along. Order and Offer will be done quickly once Invoice is completed and adding more models in general is quick and easy, see the developer guid further down.
|
17
|
-
* Massive refactorings of the code occurs weakly :) This is not at all stable for production yet.
|
9
|
+
# Status for development
|
10
|
+
[![Build status](https://img.shields.io/travis/my-codeworks/fortnox-api/development.svg?style=flat-square)](https://travis-ci.org/my-codeworks/fortnox-api)
|
11
|
+
[![Code Climate](https://img.shields.io/codeclimate/github/my-codeworks/fortnox-api.svg?style=flat-square)](https://codeclimate.com/github/my-codeworks/fortnox-api)
|
12
|
+
[![Test coverage](https://img.shields.io/codeclimate/coverage/github/my-codeworks/fortnox-api.svg?style=flat-square)](https://codeclimate.com/github/my-codeworks/fortnox-api/coverage)
|
18
13
|
|
19
|
-
The
|
14
|
+
The rough status of this project is as follows (as of November 2016):
|
15
|
+
* In active development (just check out the commit log)
|
16
|
+
* Two developers. At least twice as good as one.
|
17
|
+
* Basic structure complete. Things like getting customers and invoices, updating and saving etc.
|
18
|
+
* Some advanced features implemented, for instance support for multiple Access Tokens and filtering entities.
|
19
|
+
* Advanced features around the corner. Things like sorting entities, pagination of results etc.
|
20
|
+
* A few models implemented. Right now we have nearly full support for `Customer`, `Invoice` and `Order`. Adding more models in general is quick and easy, see the developer guide further down.
|
21
|
+
* Massive refactorings no longer occurs weakly :) We are running this gem in production for live test.
|
22
|
+
|
23
|
+
The goal is to have a production ready version that covers at least the `Invoice`, `Order`, `Customer` and `Project` models by January.
|
20
24
|
|
21
25
|
# Architecture overview
|
22
|
-
The gem is structured with
|
26
|
+
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.
|
23
27
|
|
24
|
-
If you come from a Rails background and have not been exposed to other ways of structuring the solution to the CRUD problem this might seem strange to you since ActiveRecord merges these
|
28
|
+
If you come from a Rails background and have not been exposed to other ways of structuring the solution to the CRUD problem this might seem strange to you since ActiveRecord merges these roles into the `ActiveRecord::Base` class.
|
25
29
|
|
26
|
-
To keep it simple: The active record pattern (as implemented by Rails) is easier to work with if you only have one data source, the database, in your application. The data mapper pattern is easier to work with if you have several data sources, such
|
30
|
+
To keep it simple: The active record pattern (as implemented by Rails) is easier to work with if you only have one data source, the database, in your application. The data mapper pattern is easier to work with if you have several data sources, such as different databases, external APIs and flat files on disk etc, in your application. It's also easier to compose the data mapper components into active record like classes than to separate active records parts to get a data mapper style structure.
|
27
31
|
|
28
32
|
If you are interested in a more detailed description of the difference between the two architectures you can read this post that explains it well using simple examples: [What’s the difference between Active Record and Data Mapper?](http://culttt.com/2014/06/18/whats-difference-active-record-data-mapper/)
|
29
33
|
|
@@ -31,9 +35,7 @@ If you are interested in a more detailed description of the difference between t
|
|
31
35
|
The model role classes serve as dumb data objects. They do have some logic to coheres values etc, but they do not contain validation logic nor any business logic at all.
|
32
36
|
|
33
37
|
### Attribute
|
34
|
-
Several of the models share attributes. One example is account, as in a
|
35
|
-
|
36
|
-
You can find several of these under the `/models/attributes` directory where the implementation of the definition and cohesion lives. For the validation part see Validator below.
|
38
|
+
Several of the models share attributes. One example is account, as in a `Bookkeeping` account number. These attributes have the same definition, cohesion and validation logic so it makes sense to extract them from the models and put them in separate classes. For more information, see Types below.
|
37
39
|
|
38
40
|
### Immutability
|
39
41
|
The model instances are immutable. That means:
|
@@ -52,30 +54,31 @@ customer = customer.name = 'New Name' # => "New Name"
|
|
52
54
|
But if you are familiar with chaining assignments in Ruby you will see that this does not work. The result of any assignment, `LHS = RHS`, operation in Ruby is `RHS`. Even if you implement your own `=` method and explicitly return something else. This is a feature of the language and not something we can get around. So instead you have to do:
|
53
55
|
```ruby
|
54
56
|
customer.name # => "Old Name"
|
55
|
-
|
56
|
-
|
57
|
+
updated_customer = customer.update( name: 'New Name' ) # => <Fortnox::API::Model::Customer:0x007fdf22949298 ... >
|
58
|
+
updated_customer.name == "New Name" # => true
|
57
59
|
```
|
58
60
|
And note that:
|
59
61
|
```ruby
|
60
62
|
customer.name # => "Old Name"
|
61
|
-
customer.update( name: 'New Name' ) # => <Fortnox::API::Customer:0x007fdf21100b00 ... >
|
63
|
+
customer.update( name: 'New Name' ) # => <Fortnox::API::Model::Customer:0x007fdf21100b00 ... >
|
62
64
|
customer.name == "New Name" # => false
|
63
65
|
```
|
64
66
|
This is how all the models work, they are all immutable.
|
65
|
-
## Validator
|
66
|
-
The validators enforce the constraints on values, lengths and, in some cases, content of the model attributes. You should run the validator on the model before trying to persist it using the repository. You can send any model instance off to the repository and you will get errors back from Fortnox's API server, but using the validator you get a nice list of errors that you can present to the end user instead of pinging the API once for every error and rescuing the exception we throw when we get a 4xx/5xx response from the server.
|
67
67
|
|
68
|
-
|
69
|
-
|
68
|
+
## Type
|
69
|
+
The types automatically enforce the constraints on values, lengths and, in some cases, content of the model attributes. Types forces your models to be correct before sending data to the API, which saves you a lot of API calls and rescuing the exception we throw when we get a 4xx/5xx response from the server (you can still get errors from the server; our implementation is not perfect. Also, Fortnox sometimes requires a specific combination of attributes).
|
70
70
|
|
71
71
|
## Repositories
|
72
|
-
Used to load, update, create and delete model instances.
|
72
|
+
Used to load, update, create and delete model instances. These are what is actually wrapping the HTTP REST API requests against Fortnox's server.
|
73
|
+
|
74
|
+
## Mappers
|
75
|
+
These are responsible for the mapping between our plain old Ruby object models and Fortnox JSON requests. The repositories use the mappers to map models to JSON requests and JSON to model instances when working with the Fortnox API, you will not need to use them directly.
|
73
76
|
|
74
77
|
# Requirements
|
75
78
|
|
76
|
-
This gem is build for Ruby 2.
|
77
|
-
and
|
78
|
-
versions.
|
79
|
+
This gem is build for Ruby 2.2 or higher, it's tested agains Ruby 2.2.5, 2.3.0 and 2.3.1. Since it uses the keywords argument feature and since Ruby 2.1
|
80
|
+
is [officially outdated and unsupported](https://www.ruby-lang.org/en/news/2016/03/30/ruby-2-1-9-released/)
|
81
|
+
it won't work on older versions.
|
79
82
|
|
80
83
|
If you want or need Ruby 1.9 compatibility please submit a pull request.
|
81
84
|
Instructions can be found below :)
|
@@ -105,7 +108,7 @@ $ gem install fortnox-api
|
|
105
108
|
## Getting an AccessToken
|
106
109
|
To make calls to the API server you need a `ClientSecret` and an `AccessToken`. When you sign up for an API-account with Fortnox you should get a client secret and an authorization code. To get the access token, that is reusable, you need to do a one time exchange with the API-server and exchange your authorization code for an access token. This can be done in several ways but we provide a method for it in the gem that you can use.
|
107
110
|
|
108
|
-
>
|
111
|
+
> :warning: **Do not do this more than once!** If you try to do the auth code/access token exchange more than once, regardless of method, it will lock your API-account! So if you get the token using curl or whatever do not use this method as well. If your account is not working and you think it might be due to this you will have to contact Fortnox support and have them reset the authorization code for you. If you want to use several access tokens, you need to use a new authorization code for each one of them!
|
109
112
|
|
110
113
|
```ruby
|
111
114
|
# Load the special class from the gem. You need to install the gem first ofc.
|
@@ -117,6 +120,8 @@ Fortnox::API::AccessToken.new(
|
|
117
120
|
authorization_code: 'ea3862b1-189c-464b-8e25-1b9702365fa1', # Replace with your auth code
|
118
121
|
)
|
119
122
|
```
|
123
|
+
> :info: **This will be made into an executable part of the gem for version 1.0
|
124
|
+
|
120
125
|
This will output a new token like `3f08d038-f380-4893-94a0a0-8f6e60e67a` that is your access token, **save it!** Set it in the environment by following the instructions in the next step.
|
121
126
|
|
122
127
|
## Environment variables
|
@@ -126,11 +131,20 @@ You can choose to use the [`dotenv` gem](https://github.com/bkeepers/dotenv) tha
|
|
126
131
|
|
127
132
|
The environment variables we use are:
|
128
133
|
```bash
|
134
|
+
FORTNOX_API_BASE_URL
|
129
135
|
FORTNOX_API_CLIENT_SECRET
|
130
136
|
FORTNOX_API_ACCESS_TOKEN
|
131
137
|
```
|
132
138
|
Their values should match their name.
|
133
139
|
|
140
|
+
The gem only supports the latest API version, version 3, so base URL should be set to `FORTNOX_API_BASE_URL=https://api.fortnox.se/3/` . Note that Fortnox requires `https`!
|
141
|
+
|
142
|
+
> :info: ** FORTNOX_API_BASE_URL is deprecated and will be gone in version 1.0, it will be static in the gem instead.
|
143
|
+
|
144
|
+
### Multiple AccessTokens
|
145
|
+
|
146
|
+
Fortnox uses quite low [API rate limits](https://developer.fortnox.se/blog/important-implementation-of-rate-limits/). The limit is for each access token, and according to Fortnox you can use as many tokens as you like to get around this problem. This gem supports multiple access tokens automatically. Just separate them with a comma: `FORTNOX_API_ACCESS_TOKEN=a78d35hc-j5b1-ga1b-a1h6-h72n74fj5327,s2b45f67-dh5d-3g5s-2dj5-dku6gn26sh62` and the gem will automatically rotate between these tokens. In theory you can declare as many as you like. Remember that you will need one authorization code for each token! See Getting an AccessToken above.
|
147
|
+
|
134
148
|
# Usage
|
135
149
|
## Repositories
|
136
150
|
Repositories are used to load,save and remove entities from the remote server. The calls are subject to network latency and are blocking. Do make sure to rescue appropriate network errors in your code.
|
@@ -143,15 +157,19 @@ repo = Fortnox::API::Repository::Customer.new
|
|
143
157
|
repo.all #=> <Fortnox::API::Collection:0x007fdf2104575638 @entities: [<Fortnox::API::Customer::Simple:0x007fdf21033ee8>, <Fortnox::API::Customer::Simple:0x007fdf22994310>, ... ]
|
144
158
|
|
145
159
|
# Get entity by id
|
146
|
-
repo.find( 5 ) #=> <Fortnox::API::Customer:0x007fdf21100b00>
|
160
|
+
repo.find( 5 ) #=> <Fortnox::API::Model::Customer:0x007fdf21100b00>
|
147
161
|
|
148
162
|
# Get entities by attribute
|
149
163
|
repo.find_by( customer_number: 5 ) #=> <Fortnox::API::Collection:0x007fdf22994310 @entities: [<Fortnox::API::Customer::Simple:0x007fdf22949298>]
|
150
164
|
```
|
151
165
|
If you are eagle eyed you might have spotted the different classes for the entities returned in a collection vs the one we get from find. The `Simple` version of a class is used in thouse cases where the API-server doesn't return a full set of attributes for an entity. For customers the simple version has 10 attributes while the full have over 40.
|
152
166
|
|
167
|
+
> :info: ** Collections not implemented yet.
|
168
|
+
|
153
169
|
You should try to get by using the simple versions for as long as possible. Both the `Collection` and `Simple` classes have a `.full` method that will give you full versions of the entities. Bare in mind though that a collection of 20 simple models that you run `.full` on will call out to the server 20 times, in sequence.
|
154
170
|
|
171
|
+
> :info: ** We have opened a dialog with Fortnox about this API practice to allow for full models in the list request, on demand, and/or the ability for the client to specify the fields of interest when making the request, as per usual in REST APIs with partial load.
|
172
|
+
|
155
173
|
## Entities
|
156
174
|
All the repository methods return instances or collections of instances of some resource
|
157
175
|
class such as customer, invoice, item, voucher and so on.
|
@@ -160,15 +178,16 @@ Instances are immutable and any update returns a new instance with the
|
|
160
178
|
appropriate attributes changed (see the Immutable section under Architecture above for more details). To change the properties of a model works like this:
|
161
179
|
|
162
180
|
```ruby
|
163
|
-
customer #=> <Fortnox::API::Customer:0x007fdf228db310>
|
181
|
+
customer #=> <Fortnox::API::Model::Customer:0x007fdf228db310>
|
164
182
|
customer.name #=> "Nelly Bloom"
|
165
|
-
customer.update( name: "Ned Stark" ) #=> <Fortnox::API::Customer:0x0193a456ff0307>
|
183
|
+
customer.update( name: "Ned Stark" ) #=> <Fortnox::API::Model::Customer:0x0193a456ff0307>
|
166
184
|
customer.name #=> "Nelly Bloom"
|
167
185
|
|
168
|
-
updated_customer = customer.update( name: "Ned Stark" ) #=> <Fortnox::API::Customer:0x0193a456fe3791>
|
186
|
+
updated_customer = customer.update( name: "Ned Stark" ) #=> <Fortnox::API::Model::Customer:0x0193a456fe3791>
|
169
187
|
updated_customer.name #=> "Ned Stark"
|
170
188
|
```
|
171
189
|
|
172
190
|
The update method takes an implicit hash of attributes to update, so you can update as many as you like in one go.
|
191
|
+
|
173
192
|
# Contributing
|
174
193
|
See the [CONTRIBUTE](CONTRIBUTE.md) readme.
|