fortnox-api 1.0.0.rc7 → 1.0.0.rc10
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/CHANGELOG.md +44 -1
- data/README.md +11 -1
- data/bin/fortnox-setup +9 -3
- data/fortnox.gemspec +1 -1
- data/lib/fortnox/resources/customer.rb +23 -0
- data/lib/fortnox/structs/default_delivery_types.rb +4 -4
- data/lib/fortnox/types.rb +8 -0
- data/lib/fortnox/version.rb +1 -1
- data/lib/fortnox.rb +8 -0
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d90c382b3359e0c55cda22e41eee63112f77c721bdabfd490d903cd1d0dbc34f
|
|
4
|
+
data.tar.gz: 9198f60533f070aa7ccbb12e0e4950aaf0d69476541ad6b13b2d23c1cec86781
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d1847fe3c20ce526ee13328f78d2114e5abb82ac3b5de5e4e08da49989f66a91dc6bbec9eaffed96f52b1af6588689a93834ebe6e095484a780f306ebb213013
|
|
7
|
+
data.tar.gz: c01f1d2cbf228d825dcfd1092efe7e53ad20fd653a5dc856e03084cce174ccfb1220317afd37b52c93aae30fc6b34ad2c6f3a20e1c8f06444229983b1a094d65
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,46 @@ and this project adheres to
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [1.0.0.rc10] - 2026-05-27
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Upgraded `rest-easy` dependency to `~> 1.3.1`.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- `Types::AccountNumber` no longer raises `Fortnox::ConstraintError` when
|
|
20
|
+
Fortnox returns `""` for an unset attribute using that type. Observed in production on
|
|
21
|
+
`Customer#sales_account`. Blank strings now coerce to `nil`.
|
|
22
|
+
This bug was introduced in 1.0.0.rc1 and did not exist in 0.x.
|
|
23
|
+
|
|
24
|
+
## [1.0.0.rc9] - 2026-05-20
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- `Fortnox::ALLOWED_CHARACTERS_REGEXP` constant, exposing the character
|
|
29
|
+
set Fortnox accepts in text fields. Sourced from the official Fortnox
|
|
30
|
+
docs. Useful for pre-validating strings before sending them to the API.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- `Customer#default_delivery_types.invoice` now accepts `'ELECTRONICINVOICE'`
|
|
35
|
+
when returned by Fortnox. The value is read-only — attempting to set it from
|
|
36
|
+
consumer code raises `Fortnox::ConstraintError` at save time,
|
|
37
|
+
rather than letting Fortnox reject the request.
|
|
38
|
+
Unchanged values round-trip through `save` as before.
|
|
39
|
+
|
|
40
|
+
## [1.0.0.rc8] - 2026-05-19
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- `fortnox-setup` now prints the authorization URL and asks before
|
|
45
|
+
opening a browser when a non-localhost redirect URI is used, defaulting
|
|
46
|
+
to not opening it. Previously it always opened the URL locally, so the
|
|
47
|
+
browser immediately followed the redirect and the URL was lost — making
|
|
48
|
+
it impossible to hand off to whoever should log in (e.g. a customer).
|
|
49
|
+
The local-server flow is unchanged.
|
|
50
|
+
|
|
11
51
|
## [1.0.0.rc7] - 2026-05-19
|
|
12
52
|
|
|
13
53
|
### Changed
|
|
@@ -217,7 +257,10 @@ for the full list of breaking changes.
|
|
|
217
257
|
For changes prior to the 1.0 rewrite, see the
|
|
218
258
|
[0.x changelog](https://github.com/accodeing/fortnox-api/blob/v0.9.2/CHANGELOG.md).
|
|
219
259
|
|
|
220
|
-
[Unreleased]: https://github.com/accodeing/fortnox-api/compare/v1.0.0.
|
|
260
|
+
[Unreleased]: https://github.com/accodeing/fortnox-api/compare/v1.0.0.rc10...HEAD
|
|
261
|
+
[1.0.0.rc10]: https://github.com/accodeing/fortnox-api/compare/v1.0.0.rc9...v1.0.0.rc10
|
|
262
|
+
[1.0.0.rc9]: https://github.com/accodeing/fortnox-api/compare/v1.0.0.rc8...v1.0.0.rc9
|
|
263
|
+
[1.0.0.rc8]: https://github.com/accodeing/fortnox-api/compare/v1.0.0.rc7...v1.0.0.rc8
|
|
221
264
|
[1.0.0.rc7]: https://github.com/accodeing/fortnox-api/compare/v1.0.0.rc6...v1.0.0.rc7
|
|
222
265
|
[1.0.0.rc6]: https://github.com/accodeing/fortnox-api/compare/v1.0.0.rc5...v1.0.0.rc6
|
|
223
266
|
[1.0.0.rc5]: https://github.com/accodeing/fortnox-api/compare/v1.0.0.rc4...v1.0.0.rc5
|
data/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Adding more resources is quick and easy — see the
|
|
|
18
18
|
## Status
|
|
19
19
|
|
|
20
20
|
Version 1.0 is a complete rewrite, currently in release candidate
|
|
21
|
-
(`1.0.0.
|
|
21
|
+
(`1.0.0.rc8`). It is built on
|
|
22
22
|
[rest-easy](https://github.com/accodeing/rest-easy), replacing the old
|
|
23
23
|
HTTParty + Data Mapper architecture with a single resource class per entity.
|
|
24
24
|
Authorization uses the Fortnox client credentials flow.
|
|
@@ -64,6 +64,16 @@ sending it to the API, which saves you API calls and time debugging. You can
|
|
|
64
64
|
still get errors from the server; our implementation is not perfect. Also,
|
|
65
65
|
Fortnox sometimes requires a specific combination of attributes.
|
|
66
66
|
|
|
67
|
+
#### Allowed characters
|
|
68
|
+
|
|
69
|
+
`Fortnox::ALLOWED_CHARACTERS_REGEXP` exposes the character set Fortnox
|
|
70
|
+
accepts in text fields, sourced from the [official Fortnox docs][formats].
|
|
71
|
+
The gem itself does not apply this regex to attribute values — it is
|
|
72
|
+
provided so consumers can pre-validate or sanitize strings before
|
|
73
|
+
sending them to the API.
|
|
74
|
+
|
|
75
|
+
[formats]: https://www.fortnox.se/developer/guides-and-good-to-know/formats-and-encoding
|
|
76
|
+
|
|
67
77
|
#### Exceptions
|
|
68
78
|
|
|
69
79
|
The gem raises the following exceptions:
|
data/bin/fortnox-setup
CHANGED
|
@@ -154,15 +154,21 @@ auth_params = URI.encode_www_form(
|
|
|
154
154
|
authorize_url = "#{OAUTH_ENDPOINT}/auth?#{auth_params}"
|
|
155
155
|
|
|
156
156
|
puts
|
|
157
|
-
puts 'Opening browser for Fortnox authorization...'
|
|
158
|
-
|
|
159
|
-
open_browser(authorize_url)
|
|
160
157
|
|
|
161
158
|
if use_local_server
|
|
159
|
+
puts 'Opening browser for Fortnox authorization...'
|
|
160
|
+
open_browser(authorize_url)
|
|
162
161
|
puts
|
|
163
162
|
puts 'Waiting for Fortnox to redirect back...'
|
|
164
163
|
authorization_code = get_auth_code_from_server(LOCAL_PORT, nonce)
|
|
165
164
|
else
|
|
165
|
+
puts 'Authorization URL. Open it to log in, or send it to whoever should'
|
|
166
|
+
puts 'log in to the Fortnox account being connected:'
|
|
167
|
+
puts
|
|
168
|
+
puts " #{authorize_url}"
|
|
169
|
+
puts
|
|
170
|
+
open_here = prompt('Open it in your browser now?', default: 'n')
|
|
171
|
+
open_browser(authorize_url) if open_here.downcase.start_with?('y')
|
|
166
172
|
authorization_code = auth_code_manually
|
|
167
173
|
end
|
|
168
174
|
|
data/fortnox.gemspec
CHANGED
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
spec.add_dependency 'base64'
|
|
25
25
|
spec.add_dependency 'countries', '~> 7.1'
|
|
26
26
|
spec.add_dependency 'dry-struct', '~> 1.5'
|
|
27
|
-
spec.add_dependency 'rest-easy', '~> 1.3.
|
|
27
|
+
spec.add_dependency 'rest-easy', '~> 1.3.1'
|
|
28
28
|
|
|
29
29
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
30
30
|
end
|
|
@@ -11,6 +11,10 @@ module Fortnox
|
|
|
11
11
|
scope 'customer'
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
+
before_serialise do |_attrs|
|
|
15
|
+
validate_electronic_invoice_delivery_type!(default_delivery_types&.invoice)
|
|
16
|
+
end
|
|
17
|
+
|
|
14
18
|
# Direct URL to the record.
|
|
15
19
|
attr :url <=> '@url', Coercible::String.optional, :read_only
|
|
16
20
|
|
|
@@ -205,5 +209,24 @@ module Fortnox
|
|
|
205
209
|
|
|
206
210
|
# WWW Website URL
|
|
207
211
|
attr :www <=> 'WWW', Sized::String[128]
|
|
212
|
+
|
|
213
|
+
private
|
|
214
|
+
|
|
215
|
+
# ELECTRONICINVOICE is only possible to set in the Fortnox UI.
|
|
216
|
+
# Raise if a consumer tries to set it from this gem.
|
|
217
|
+
def validate_electronic_invoice_delivery_type!(type)
|
|
218
|
+
return unless type == DefaultInvoiceDeliveryTypeValues['ELECTRONICINVOICE']
|
|
219
|
+
|
|
220
|
+
set_by_consumer = meta.new? || __changes__.key?(:default_delivery_types)
|
|
221
|
+
|
|
222
|
+
return unless set_by_consumer
|
|
223
|
+
|
|
224
|
+
raise Fortnox::ConstraintError.new(
|
|
225
|
+
:default_delivery_types,
|
|
226
|
+
'ELECTRONICINVOICE',
|
|
227
|
+
"Customer#default_delivery_types.invoice cannot be changed to 'ELECTRONICINVOICE' " \
|
|
228
|
+
'via the API, you can only do that change from within Fortnox.'
|
|
229
|
+
)
|
|
230
|
+
end
|
|
208
231
|
end
|
|
209
232
|
end
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
module Fortnox
|
|
4
4
|
module Structs
|
|
5
5
|
class DefaultDeliveryTypes < Fortnox::Struct
|
|
6
|
-
# Default delivery type for invoices.
|
|
7
|
-
attribute? :invoice, Types::
|
|
6
|
+
# Default delivery type for invoices.
|
|
7
|
+
attribute? :invoice, Types::DefaultInvoiceDeliveryTypeValues
|
|
8
8
|
|
|
9
|
-
# Default delivery type for orders.
|
|
9
|
+
# Default delivery type for orders.
|
|
10
10
|
attribute? :order, Types::DefaultDeliveryTypeValues
|
|
11
11
|
|
|
12
|
-
# Default delivery type for offers.
|
|
12
|
+
# Default delivery type for offers.
|
|
13
13
|
attribute? :offer, Types::DefaultDeliveryTypeValues
|
|
14
14
|
end
|
|
15
15
|
end
|
data/lib/fortnox/types.rb
CHANGED
|
@@ -66,6 +66,10 @@ module Fortnox
|
|
|
66
66
|
'PRINT', 'EMAIL', 'PRINTSERVICE'
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
+
DefaultInvoiceDeliveryTypeValues = Types::Strict::String.enum(
|
|
70
|
+
'PRINT', 'EMAIL', 'PRINTSERVICE', 'ELECTRONICINVOICE'
|
|
71
|
+
)
|
|
72
|
+
|
|
69
73
|
AccountingMethods = Types::Strict::String.enum(
|
|
70
74
|
'', 'ACCRUAL', 'CASH'
|
|
71
75
|
)
|
|
@@ -90,9 +94,13 @@ module Fortnox
|
|
|
90
94
|
'', 'none', 'rot', 'rut', 'green'
|
|
91
95
|
)
|
|
92
96
|
|
|
97
|
+
# Fortnox sometimes returns "" for unset attributes using AccountNumber as type.
|
|
98
|
+
# Without this constructor, "" falls through to Coercible::Integer and
|
|
99
|
+
# `Integer("")` raises, surfacing as Fortnox::ConstraintError.
|
|
93
100
|
AccountNumber = Coercible::Integer
|
|
94
101
|
.constrained(gteq: 0, lteq: 9999)
|
|
95
102
|
.optional
|
|
103
|
+
.constructor { |v| v == '' ? nil : v }
|
|
96
104
|
|
|
97
105
|
Email = Strict::String
|
|
98
106
|
.constrained(max_size: 1024, format: /\A\z|\A[[[:alnum:]]+-_.]+@[[[:alnum:]]+-_.]+\.[a-z]+\z/i)
|
data/lib/fortnox/version.rb
CHANGED
data/lib/fortnox.rb
CHANGED
|
@@ -93,6 +93,14 @@ module Fortnox
|
|
|
93
93
|
|
|
94
94
|
OAUTH_TOKEN_URL = 'https://apps.fortnox.se/oauth-v1/token'
|
|
95
95
|
|
|
96
|
+
# Character set allowed in Fortnox text fields, per the official Fortnox docs.
|
|
97
|
+
# Useful for pre-validating strings before sending them to the API.
|
|
98
|
+
# See: https://www.fortnox.se/developer/guides-and-good-to-know/formats-and-encoding
|
|
99
|
+
# (The docs spell Unicode codepoints as \x{NNNN}; Ruby's regex parser uses
|
|
100
|
+
# \u{NNNN} for the same thing, so the three codepoints below are translated.)
|
|
101
|
+
ALLOWED_CHARACTERS_REGEXP =
|
|
102
|
+
%r{\A[\p{L}’\\\u{0308}\u{030a}a-zåäöéáœæøüA-ZÅÄÖÉÁÜŒÆØ0-9 –:.`´,;\^¤#%§£$€¢¥©™°&/()=+\-*_!?²³®½@\u{00a0}\n\r]*\z}
|
|
103
|
+
|
|
96
104
|
class << self
|
|
97
105
|
def access_token=(token)
|
|
98
106
|
Thread.current[Auth::ThreadLocal::THREAD_LOCAL_KEY] = token
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fortnox-api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.0.
|
|
4
|
+
version: 1.0.0.rc10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jonas Schubert Erlandsson
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2026-05-
|
|
14
|
+
date: 2026-05-27 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: base64
|
|
@@ -61,14 +61,14 @@ dependencies:
|
|
|
61
61
|
requirements:
|
|
62
62
|
- - "~>"
|
|
63
63
|
- !ruby/object:Gem::Version
|
|
64
|
-
version: 1.3.
|
|
64
|
+
version: 1.3.1
|
|
65
65
|
type: :runtime
|
|
66
66
|
prerelease: false
|
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
|
68
68
|
requirements:
|
|
69
69
|
- - "~>"
|
|
70
70
|
- !ruby/object:Gem::Version
|
|
71
|
-
version: 1.3.
|
|
71
|
+
version: 1.3.1
|
|
72
72
|
description: Fortnox F3 REST API library, based on rest-easy.
|
|
73
73
|
email:
|
|
74
74
|
- info@accodeing.com
|