fortnox-api 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
@@ -0,0 +1,29 @@
|
|
1
|
+
require "fortnox/api/types"
|
2
|
+
|
3
|
+
module Fortnox
|
4
|
+
module API
|
5
|
+
module Types
|
6
|
+
class EDIInformation < Types::Model
|
7
|
+
STUB = {}.freeze
|
8
|
+
|
9
|
+
#EDIGlobalLocationNumber Invoice address GLN for EDI
|
10
|
+
attribute :edi_global_location_number, Types::Nullable::String
|
11
|
+
|
12
|
+
#EDIGlobalLocationNumberDelivery Delivery address GLN for EDI
|
13
|
+
attribute :edi_global_location_number_delivery, Types::Nullable::String
|
14
|
+
|
15
|
+
#EDIInvoiceExtra1 Extra EDI Information
|
16
|
+
attribute :edi_invoice_extra1, Types::Nullable::String
|
17
|
+
|
18
|
+
#EDIInvoiceExtra2 Extra EDI Information
|
19
|
+
attribute :edi_invoice_extra2, Types::Nullable::String
|
20
|
+
|
21
|
+
#EDIOurElectronicReference Our electronic reference for EDI
|
22
|
+
attribute :edi_our_electronic_reference, Types::Nullable::String
|
23
|
+
|
24
|
+
#EDIYourElectronicReference Your electronic reference for EDI
|
25
|
+
attribute :edi_your_electronic_reference, Types::Nullable::String
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "fortnox/api/types"
|
2
|
+
|
3
|
+
module Fortnox
|
4
|
+
module API
|
5
|
+
module Types
|
6
|
+
class EmailInformation < Types::Model
|
7
|
+
STUB = {}.freeze
|
8
|
+
|
9
|
+
#EmailAddressTo Customer e-mail address. Must be a valid e-mail address. 1024 characters
|
10
|
+
attribute :email_address_to, Types::Email
|
11
|
+
|
12
|
+
#EmailAddressCC Customer e-mail address – Carbon copy. Must be a valid e-mail address. 1024 characters
|
13
|
+
attribute :email_address_cc, Types::Email
|
14
|
+
|
15
|
+
#EmailAddressBCC Customer e-mail address – Blind carbon copy. Must be a valid e-mail address. 1024 characters
|
16
|
+
attribute :email_address_bcc, Types::Email
|
17
|
+
|
18
|
+
#EmailSubject Subject of the e-mail, 100 characters.
|
19
|
+
attribute :email_subject, Types::Sized::String[ 100 ]
|
20
|
+
|
21
|
+
#EmailBody Body of the e-mail, 20000 characters.
|
22
|
+
attribute :email_body, Types::Sized::String[ 20000 ]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Fortnox
|
2
|
+
module API
|
3
|
+
module Types
|
4
|
+
|
5
|
+
module EnumConstructors
|
6
|
+
def self.sized( size )
|
7
|
+
-> (value){ return nil if value == ''; value.to_s.upcase[0...size] unless value.nil? }
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.default
|
11
|
+
-> (value){ return nil if value == ''; value.to_s.upcase unless value.nil? }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
DiscountTypes = Types::Strict::String.enum(
|
16
|
+
'AMOUNT','PERCENT'
|
17
|
+
)
|
18
|
+
CURRENT_HOUSE_WORK_TYPES = [
|
19
|
+
'CONSTRUCTION','ELECTRICITY','GLASSMETALWORK','GROUNDDRAINAGEWORK',
|
20
|
+
'MASONRY','PAINTINGWALLPAPERING','HVAC','CLEANING','TEXTILECLOTHING',
|
21
|
+
'SNOWPLOWING','GARDENING','BABYSITTING','OTHERCARE', 'OTHERCOSTS'
|
22
|
+
].freeze
|
23
|
+
LEGACY_HOUSE_WORK_TYPES = [ 'COOKING', 'TUTORING' ].freeze
|
24
|
+
HouseWorkTypes = Types::Strict::String.enum(
|
25
|
+
*(CURRENT_HOUSE_WORK_TYPES + LEGACY_HOUSE_WORK_TYPES)
|
26
|
+
)
|
27
|
+
CountryCodes = Types::Strict::String.enum(
|
28
|
+
'AF','AX','AL','DZ','AS','AD','AO','AI','AQ','AG','AR','AM','AW','AU',
|
29
|
+
'AT','AZ','BS','BH','BD','BB','BY','BE','BZ','BJ','BM','BT','BO','BQ',
|
30
|
+
'BA','BW','BV','BR','IO','BN','BG','BF','BI','CV','KH','CM','CA','KY',
|
31
|
+
'CF','TD','CL','CN','CX','CC','CO','KM','CG','CD','CK','CR','CI','HR',
|
32
|
+
'CU','CW','CY','CZ','DK','DJ','DM','DO','EC','EG','SV','GQ','ER','EE',
|
33
|
+
'ET','FK','FO','FJ','FI','FR','GF','PF','TF','GA','GM','GE','DE','GH',
|
34
|
+
'GI','GR','GL','GD','GP','GU','GT','GG','GN','GW','GY','HT','HM','VA',
|
35
|
+
'HN','HK','HU','IS','IN','ID','IR','IQ','IE','IM','IL','IT','JM','JP',
|
36
|
+
'JE','JO','KZ','KE','KI','KP','KR','KW','KG','LA','LV','LB','LS','LR',
|
37
|
+
'LY','LI','LT','LU','MO','MK','MG','MW','MY','MV','ML','MT','MH','MQ',
|
38
|
+
'MR','MU','YT','MX','FM','MD','MC','MN','ME','MS','MA','MZ','MM','NA',
|
39
|
+
'NR','NP','NL','NC','NZ','NI','NE','NG','NU','NF','MP','NO','OM','PK',
|
40
|
+
'PW','PS','PA','PG','PY','PE','PH','PN','PL','PT','PR','QA','RE','RO',
|
41
|
+
'RU','RW','BL','SH','KN','LC','MF','PM','VC','WS','SM','ST','SA','SN',
|
42
|
+
'RS','SC','SL','SG','SX','SK','SI','SB','SO','ZA','GS','SS','ES','LK',
|
43
|
+
'SD','SR','SJ','SZ','SE','CH','SY','TW','TJ','TZ','TH','TL','TG','TK',
|
44
|
+
'TO','TT','TN','TR','TM','TC','TV','UG','UA','AE','GB','US','UM','UY',
|
45
|
+
'UZ','VU','VE','VN','VG','VI','WF','EH','YE','ZM','ZW'
|
46
|
+
)
|
47
|
+
Currencies = Types::Strict::String.enum(
|
48
|
+
'AED','AFN','ALL','AMD','ANG','AOA','ARS','AUD','AWG','AZN','BAM','BBD',
|
49
|
+
'BDT','BGN','BHD','BIF','BMD','BND','BOB','BOV','BRL','BSD','BTN','BWP',
|
50
|
+
'BYR','BZD','CAD','CDF','CHE','CHF','CHW','CLF','CLP','CNY','COP','COU',
|
51
|
+
'CRC','CUP','CVE','CZK','DJF','DKK','DOP','DZD','EGP','ERN','ETB','EUR',
|
52
|
+
'FJD','FKP','GBP','GEL','GHS','GIP','GMD','GNF','GTQ','GYD','HKD','HNL',
|
53
|
+
'HRK','HTG','HUF','IDR','ILS','INR','IQD','IRR','ISK','JMD','JOD','JPY',
|
54
|
+
'KES','KGS','KHR','KUR','KMF','KPW','KRW','KWD','KYD','KZT','LAK','LBP',
|
55
|
+
'LKR','LRD','LSL','LYD','MAD','MDL','MGA','MKD','MMK','MNT','MOP','MRO',
|
56
|
+
'MUR','MVR','MWK','MXN','MXV','MYR','MZN','NAD','NGN','NIO','NOK','NPR',
|
57
|
+
'NZD','OMR','PAB','PEN','PGK','PHP','PKR','PLN','PYG','QAR','RON','RSD',
|
58
|
+
'RUB','RWF','SAR','SBD','SCR','SDG','SEK','SGD','SHP','SLL','SOS','SRD',
|
59
|
+
'SSP','STD','SYP','SZL','THB','TJS','TMM','TND','TOP','TRY','TTD','TWD',
|
60
|
+
'TZS','UAH','UGX','USD','USN','USS','UYU','UZS','VEF','VND','VUV','WST',
|
61
|
+
'XAF','XAG','XAU','XBA','XBB','XBC','XBD','XCD','XDR','XFU','XOF','XPD',
|
62
|
+
'XPF','XPT','XTS','XXX','YER','ZAR','ZMK','ZWD'
|
63
|
+
)
|
64
|
+
CustomerTypes = Types::Strict::String.enum(
|
65
|
+
'PRIVATE', 'COMPANY'
|
66
|
+
)
|
67
|
+
VATTypes = Types::Strict::String.enum(
|
68
|
+
'SEVAT', 'SEREVERSEDVAT', 'EUREVERSEDVAT', 'EUVAT', 'EXPORT'
|
69
|
+
)
|
70
|
+
DefaultDeliveryTypeValues = Types::Strict::String.enum(
|
71
|
+
'PRINT', 'EMAIL', 'PRINTSERVICE'
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "fortnox/api/types/document_row"
|
2
|
+
|
3
|
+
module Fortnox
|
4
|
+
module API
|
5
|
+
module Types
|
6
|
+
class InvoiceRow < Fortnox::API::Types::Model
|
7
|
+
STUB = {}.freeze
|
8
|
+
|
9
|
+
DocumentRow.ify self
|
10
|
+
|
11
|
+
#PriceExcludingVAT Price per unit excluding VAT.
|
12
|
+
attribute :price_excluding_vat, Types::Nullable::Float.with( private: true )
|
13
|
+
|
14
|
+
#TotalExcludingVAT Total amount for the row excluding VAT.
|
15
|
+
attribute :total_excluding_vat, Types::Nullable::Float.with( private: true )
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Fortnox
|
2
|
+
module API
|
3
|
+
module Types
|
4
|
+
class Model < Dry::Struct
|
5
|
+
constructor_type(:schema)
|
6
|
+
|
7
|
+
def initialize( input_attributes )
|
8
|
+
if (missing_key = first_missing_required_key( input_attributes ))
|
9
|
+
raise Fortnox::API::MissingAttributeError.new( "Missing attribute #{ missing_key.inspect } in attributes: #{ input_attributes }" )
|
10
|
+
end
|
11
|
+
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def missing_keys( attributes )
|
18
|
+
non_nil_attributes = attributes.select{ |_,value| !value.nil? }
|
19
|
+
|
20
|
+
attribute_keys = non_nil_attributes.keys
|
21
|
+
schema_keys = self.class.schema.keys
|
22
|
+
|
23
|
+
schema_keys - attribute_keys
|
24
|
+
end
|
25
|
+
|
26
|
+
def first_missing_required_key( attributes )
|
27
|
+
all_missing_keys = missing_keys( attributes )
|
28
|
+
missing_required = all_missing_keys.select do |name|
|
29
|
+
attribute = self.class.schema[ name ]
|
30
|
+
next unless attribute.respond_to? :options
|
31
|
+
attribute.options[:required]
|
32
|
+
end
|
33
|
+
|
34
|
+
missing_required.first
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Fortnox
|
4
|
+
module API
|
5
|
+
module Types
|
6
|
+
|
7
|
+
module Nullable
|
8
|
+
String = Types::Strict::String.optional.constructor{ |value| value.to_s unless value.nil? }
|
9
|
+
Float = Types::Strict::Float.optional.constructor{ |value| value.to_f unless value.nil? }
|
10
|
+
Integer = Types::Strict::Int.optional.constructor{ |value| value.to_i unless value.nil? }
|
11
|
+
Boolean = Types::Bool.optional.constructor{ |value| THE_TRUTH.fetch( value ){ false } }
|
12
|
+
# TODO: Improve parsing!
|
13
|
+
# In case date parsing fails, ArgumentError is thrown. Currently, it is rescued in Repository::Loaders.find.
|
14
|
+
# That method assumes that the exception is due to invalid argument to the find method, which is not the case
|
15
|
+
# if it is raised from here!
|
16
|
+
Date = Types::Date.optional.constructor{ |value| ::Date.parse( value.to_s ) unless value.nil? || value == '' }
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "fortnox/api/types/document_row"
|
2
|
+
|
3
|
+
module Fortnox
|
4
|
+
module API
|
5
|
+
module Types
|
6
|
+
class OrderRow < Fortnox::API::Types::Model
|
7
|
+
STUB = { ordered_quantity: 0 }.freeze
|
8
|
+
|
9
|
+
DocumentRow.ify self
|
10
|
+
|
11
|
+
#OrderedQuantity Ordered quantity
|
12
|
+
attribute :ordered_quantity, Types::Required::Float
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Fortnox
|
2
|
+
module API
|
3
|
+
module Types
|
4
|
+
|
5
|
+
module Required
|
6
|
+
String = Types::Strict::String.constructor{ |value| value.to_s unless value.nil? }.with( required: true )
|
7
|
+
Integer = Types::Strict::Int.constructor{ |value| value.to_i unless value.nil? }.with( required: true )
|
8
|
+
Float = Types::Strict::Float.constructor{ |value| value.to_f unless value.nil? }.with( required: true )
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Fortnox
|
2
|
+
module API
|
3
|
+
module Types
|
4
|
+
module Sized
|
5
|
+
module String
|
6
|
+
def self.[]( size )
|
7
|
+
Types::Strict::String.constrained( max_size: size ).optional.constructor{ |value| value.to_s unless value.nil? }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module Integer
|
12
|
+
def self.[]( low, high )
|
13
|
+
Types::Strict::Int.constrained( gteq: low, lteq: high ).optional.constructor{ |value| value.to_i unless value.nil? }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Float
|
18
|
+
def self.[]( low, high )
|
19
|
+
Types::Strict::Float.constrained( gteq: low, lteq: high ).optional.constructor{ |value| value.to_f unless value.nil? }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/fortnox/api/version.rb
CHANGED
@@ -2,20 +2,28 @@ require 'spec_helper'
|
|
2
2
|
require 'fortnox/api'
|
3
3
|
|
4
4
|
describe Fortnox::API::Base do
|
5
|
+
include Helpers::Environment
|
5
6
|
|
6
7
|
describe 'creation' do
|
8
|
+
before do
|
9
|
+
stub_environment('FORTNOX_API_BASE_URL' => nil,
|
10
|
+
'FORTNOX_API_CLIENT_SECRET' => nil,
|
11
|
+
'FORTNOX_API_ACCESS_TOKEN' => nil)
|
12
|
+
end
|
7
13
|
|
8
|
-
subject{ ->{
|
14
|
+
subject{ ->{ described_class.new() } }
|
9
15
|
|
10
16
|
context 'without FORTNOX_API_BASE_URL' do
|
11
|
-
before
|
17
|
+
before do
|
18
|
+
stub_environment('FORTNOX_API_BASE_URL' => nil)
|
19
|
+
end
|
12
20
|
|
13
21
|
it{ is_expected.to raise_error( ArgumentError, /base url/ ) }
|
14
22
|
end
|
15
23
|
|
16
24
|
context 'without FORTNOX_API_CLIENT_SECRET' do
|
17
25
|
before do
|
18
|
-
|
26
|
+
stub_environment('FORTNOX_API_BASE_URL' => 'xxx')
|
19
27
|
end
|
20
28
|
|
21
29
|
it{ is_expected.to raise_error( ArgumentError, /client secret/ ) }
|
@@ -23,8 +31,8 @@ describe Fortnox::API::Base do
|
|
23
31
|
|
24
32
|
context 'without FORTNOX_API_ACCESS_TOKEN' do
|
25
33
|
before do
|
26
|
-
|
27
|
-
|
34
|
+
stub_environment('FORTNOX_API_BASE_URL' => 'xxx',
|
35
|
+
'FORTNOX_API_CLIENT_SECRET' => 'xxx')
|
28
36
|
end
|
29
37
|
|
30
38
|
it{ is_expected.to raise_error( ArgumentError, /access token/ ) }
|
@@ -34,9 +42,11 @@ describe Fortnox::API::Base do
|
|
34
42
|
|
35
43
|
context 'making a request including the proper headers' do
|
36
44
|
before do
|
37
|
-
|
38
|
-
|
39
|
-
|
45
|
+
stub_environment(
|
46
|
+
'FORTNOX_API_BASE_URL' => 'http://api.fortnox.se/3',
|
47
|
+
'FORTNOX_API_CLIENT_SECRET' => 'P5K5vE3Kun',
|
48
|
+
'FORTNOX_API_ACCESS_TOKEN' => '3f08d038-f380-4893-94a0-a08f6e60e67a'
|
49
|
+
)
|
40
50
|
|
41
51
|
stub_request(
|
42
52
|
:get,
|
@@ -53,17 +63,78 @@ describe Fortnox::API::Base do
|
|
53
63
|
)
|
54
64
|
end
|
55
65
|
|
56
|
-
subject{
|
66
|
+
subject{ described_class.new.get( '/test', { body: '' }) }
|
57
67
|
|
58
68
|
it{ is_expected.to be_nil }
|
59
69
|
end
|
60
70
|
|
71
|
+
describe 'making requests with multiple access tokens' do
|
72
|
+
|
73
|
+
before do
|
74
|
+
stub_environment(
|
75
|
+
'FORTNOX_API_BASE_URL' => 'http://api.fortnox.se/3',
|
76
|
+
'FORTNOX_API_CLIENT_SECRET' => 'P5K5vE3Kun',
|
77
|
+
'FORTNOX_API_ACCESS_TOKEN' => '3f08d038-f380-4893-94a0-a08f6e60e67a,aaee8217-0bbd-2e16-441f-668931d582cd'
|
78
|
+
)
|
79
|
+
|
80
|
+
stub_request(
|
81
|
+
:get,
|
82
|
+
'http://api.fortnox.se/3/test',
|
83
|
+
).with(
|
84
|
+
headers: {
|
85
|
+
'Access-Token' => '3f08d038-f380-4893-94a0-a08f6e60e67a',
|
86
|
+
'Client-Secret' => 'P5K5vE3Kun',
|
87
|
+
'Content-Type' => 'application/json',
|
88
|
+
'Accept' => 'application/json',
|
89
|
+
}
|
90
|
+
).to_return(
|
91
|
+
status: 200,
|
92
|
+
body: '1'
|
93
|
+
)
|
94
|
+
|
95
|
+
stub_request(
|
96
|
+
:get,
|
97
|
+
'http://api.fortnox.se/3/test',
|
98
|
+
).with(
|
99
|
+
headers: {
|
100
|
+
'Access-Token' => 'aaee8217-0bbd-2e16-441f-668931d582cd',
|
101
|
+
'Client-Secret' => 'P5K5vE3Kun',
|
102
|
+
'Content-Type' => 'application/json',
|
103
|
+
'Accept' => 'application/json',
|
104
|
+
}
|
105
|
+
).to_return(
|
106
|
+
status: 200,
|
107
|
+
body: '2'
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with subsequent requests on same object' do
|
112
|
+
let!(:response1){ api.get( '/test', body: '' ) }
|
113
|
+
let!(:response2){ api.get( '/test', body: '' ) }
|
114
|
+
let!(:response3){ api.get( '/test', body: '' ) }
|
115
|
+
|
116
|
+
let(:api){ described_class.new }
|
117
|
+
|
118
|
+
# rubocop:disable RSpec/MultipleExpectations
|
119
|
+
# All these checks must be run in same it-statement because
|
120
|
+
# of the random starting index.
|
121
|
+
it 'works' do
|
122
|
+
expect(response1).not_to eq( response2 )
|
123
|
+
expect(response1).to eq( response3 )
|
124
|
+
expect(response3).not_to eq( response2 )
|
125
|
+
end
|
126
|
+
# rubocop:enable RSpec/MultipleExpectations
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
61
130
|
context 'raising error from remote server' do
|
62
131
|
|
63
132
|
before do
|
64
|
-
|
65
|
-
|
66
|
-
|
133
|
+
stub_environment(
|
134
|
+
'FORTNOX_API_BASE_URL' => 'http://api.fortnox.se/3',
|
135
|
+
'FORTNOX_API_CLIENT_SECRET' => 'P5K5vE3Kun',
|
136
|
+
'FORTNOX_API_ACCESS_TOKEN' => '3f08d038-f380-4893-94a0-a08f6e60e67a'
|
137
|
+
)
|
67
138
|
|
68
139
|
stub_request(
|
69
140
|
:post,
|
@@ -75,14 +146,14 @@ describe Fortnox::API::Base do
|
|
75
146
|
)
|
76
147
|
end
|
77
148
|
|
78
|
-
subject{ ->{
|
149
|
+
subject{ ->{ described_class.new.post( '/test', { body: '' }) } }
|
79
150
|
|
80
151
|
it{ is_expected.to raise_error( Fortnox::API::RemoteServerError ) }
|
81
152
|
it{ is_expected.to raise_error( 'Räkenskapsår finns inte upplagt. För att kunna skapa en faktura krävs det att det finns ett räkenskapsår' ) }
|
82
153
|
|
83
154
|
context 'with debugging enabled' do
|
84
155
|
|
85
|
-
around
|
156
|
+
around do |example|
|
86
157
|
Fortnox::API.debugging = true
|
87
158
|
example.run
|
88
159
|
Fortnox::API.debugging = false
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fortnox/api/mappers/base/from_json'
|
3
|
+
require 'fortnox/api/mappers/contexts/json_conversion'
|
4
|
+
|
5
|
+
describe Fortnox::API::Mapper::FromJSON do
|
6
|
+
include_context 'JSON conversion'
|
7
|
+
|
8
|
+
before do
|
9
|
+
module Test
|
10
|
+
class BaseMapper
|
11
|
+
include Fortnox::API::Mapper::FromJSON
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
register_mapper( :categories, Test::CategoryMapper )
|
16
|
+
register_mapper( :designer, Test::ProductDesignerMapper )
|
17
|
+
end
|
18
|
+
|
19
|
+
let( :mapper ){ Test::ProductMapper.new }
|
20
|
+
|
21
|
+
describe 'wrapped_json_hash_to_entity_hash' do
|
22
|
+
let( :entity_hash ){ mapper.wrapped_json_hash_to_entity_hash( wrapped_json_hash ) }
|
23
|
+
let( :wrapped_json_hash ) do
|
24
|
+
{
|
25
|
+
'Product' => {
|
26
|
+
'@url': 'someurl@example.com',
|
27
|
+
'Name': 'Ford Mustang',
|
28
|
+
'VAT': 30000,
|
29
|
+
'Categories': [{ 'Name' => 'Cars', 'ID' => '1' }, { 'Name' => 'Fast cars', 'ID' => '2' }],
|
30
|
+
'Designer': { 'Name' => 'John Najjar', 'ID' => '23' }
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
specify 'converts keys without mapping correctly' do
|
36
|
+
expect( entity_hash[:name] ).to eq 'Ford Mustang'
|
37
|
+
end
|
38
|
+
|
39
|
+
specify 'converts keys with mapping correctly' do
|
40
|
+
expect( entity_hash[:vat] ).to eq 30000
|
41
|
+
end
|
42
|
+
|
43
|
+
specify 'converts keys starting with "@" correctly'
|
44
|
+
# do
|
45
|
+
# expect( entity_hash[:url] ).to eq 'someurl@example.com'
|
46
|
+
# end
|
47
|
+
|
48
|
+
context 'with nested models' do
|
49
|
+
let( :expected_nested_model_hash ) do
|
50
|
+
[{ name: 'Cars', id: '1' }, { name: 'Fast cars', id: '2' }]
|
51
|
+
end
|
52
|
+
|
53
|
+
specify 'are converted correctly' do
|
54
|
+
expect( entity_hash[:categories] ).to eq( expected_nested_model_hash )
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'with nested model' do
|
59
|
+
let( :expected_nested_model_hash ){ { name: 'John Najjar', id: '23' } }
|
60
|
+
|
61
|
+
specify 'is converted correctly' do
|
62
|
+
expect( entity_hash[:designer] ).to eq( expected_nested_model_hash )
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'wrapped_json_collection_to_entities_hash' do
|
68
|
+
it 'is tested'
|
69
|
+
end
|
70
|
+
end
|