gobl 0.7.0 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +257 -0
- data/lib/gobl/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0eeb23e35c8e6a71e80538d5ea0416b0d3ce5cdfd1ab30a42bc96291450d1cb
|
4
|
+
data.tar.gz: 6bf0d67871769486fd924c363c637e34dca14791e24df72e71c776b9ceca893d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63d7f2fd50b76786c888101c0caeb3d978c875629253f3c300f6e9ab7d44489b7285906182a0430b54515ac108921f5a527b407df15118d0a45636626ec42d24
|
7
|
+
data.tar.gz: d4878ff574e3c33c8014d560ff657b0d2f7d86b48eba12791e0627b95cec63405fadc1073db39741f4589bcc226d1cdb4684477eb8a01b9da4b7d13047f7d1ed
|
data/README.md
ADDED
@@ -0,0 +1,257 @@
|
|
1
|
+
# GOBL Ruby
|
2
|
+
|
3
|
+
<img src="https://github.com/invopop/gobl/blob/main/gobl_logo_black_rgb.svg?raw=true" width="181" height="219" alt="GOBL Logo">
|
4
|
+
|
5
|
+
Go Business Language – Ruby.
|
6
|
+
|
7
|
+
Released under the Apache 2.0 [LICENSE](https://github.com/invopop/gobl/blob/main/LICENSE), Copyright 2021,2022 [Invopop Ltd.](https://invopop.com). Trademark pending.
|
8
|
+
|
9
|
+
## Introduction
|
10
|
+
|
11
|
+
Ruby library for reading, producing, manipulating and operating over [GOBL][3] documents and structures.
|
12
|
+
|
13
|
+
### Features
|
14
|
+
|
15
|
+
* Dedicated Ruby classes for each GOBL structure with typed attributes
|
16
|
+
* [Object instantiation from nested hashes and arrays of attributes](#instantiating-structures)
|
17
|
+
* [Object serialization/deserialization to/from JSON GOBL data](#serializing-to-and-deserializing-from-json)
|
18
|
+
* [Idiomatic value objects with enumerations support](#handling-value-objects-and-enumerations)
|
19
|
+
* Access to operations in the [GOBL CLI][4] service: [build, validate and sign](#running-operations)
|
20
|
+
* [Full API reference documentation][1]
|
21
|
+
|
22
|
+
### Documentation
|
23
|
+
|
24
|
+
* [User guide](#user-guide)
|
25
|
+
* [API reference][6]
|
26
|
+
* [GOBL documentation][2]
|
27
|
+
|
28
|
+
## User guide
|
29
|
+
|
30
|
+
### Installation
|
31
|
+
|
32
|
+
Add this line to your application's Gemfile:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
gem 'gobl'
|
36
|
+
```
|
37
|
+
|
38
|
+
And then execute:
|
39
|
+
|
40
|
+
```shell
|
41
|
+
bundle install
|
42
|
+
```
|
43
|
+
|
44
|
+
### Instantiating structures
|
45
|
+
|
46
|
+
You can instantiate any struct in the library using a hash of nested attributes. For example:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
invoice = GOBL::Bill::Invoice.new(
|
50
|
+
code: 'SAMPLE-001',
|
51
|
+
currency: :eur,
|
52
|
+
issue_date: Date.new(2021, 1, 1),
|
53
|
+
supplier: { tax_id: { country: :es, code: '55105445K' }, name: 'Provide One S.L.' },
|
54
|
+
customer: { tax_id: { country: :es, code: '65870696F' }, name: 'Sample Consumer' },
|
55
|
+
lines: [{
|
56
|
+
quantity: 20,
|
57
|
+
item: { name: 'Development services', price: 90.0 },
|
58
|
+
taxes: [ { cat: 'VAT', rate: :standard } ]
|
59
|
+
}]
|
60
|
+
)
|
61
|
+
invoice #=> #<GOBL::Bill::Invoice uuid=nil code="SAMPLE-001" ...>
|
62
|
+
invoice.code # => "SAMPLE-001"
|
63
|
+
invoice.currency # => #<GOBL::Currency::Code _value="EUR">
|
64
|
+
invoice.date # => #<GOBL::Cal::Date _value="2021-01-01">
|
65
|
+
invoice.lines.first.item.price #=> #<GOBL::Num::Amount:... @value=900, @exp=1>
|
66
|
+
```
|
67
|
+
|
68
|
+
Note how the constructor took care of creating every nested object in the attributes hash and also coercing strings, symbols and dates into GOBL objects.
|
69
|
+
|
70
|
+
The constructor requires any attribute marked as mandatory and not calculated in the GOBL schema to be present in the input data. Otherwise, it will raise an error. For example:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
message = GOBL::Note::Message.new #=> Dry::Struct::Error ([GOBL::Note::Message.new] :content is missing in Hash input)
|
74
|
+
```
|
75
|
+
|
76
|
+
_See also: [`GOBL::Bill::Invoice#new`](https://rubydoc.info/github/invopop/gobl.ruby/GOBL/Bill/Invoice#new-class_method)_
|
77
|
+
|
78
|
+
### Serializing to and deserializing from JSON
|
79
|
+
|
80
|
+
GOBL is a JSON format. So, you'll probably need to read or produce valid GOBL JSON at some point. Every struct class in the library provides a `.from_json!` and a `#to_json` method for those very purposes:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
json = '{"$schema":"https://gobl.org/draft-0/note/message", "content":"Hello World!"}'
|
84
|
+
document = GOBL::Document.from_json!(json) #=> #<GOBL::Document _value={"$schema"=>"https://gobl.org/draft-0/note/message", "content"=>"Hello World!"}>
|
85
|
+
message = document.extract #=> #<GOBL::Note::Message title=nil content="Hello World!" meta=nil>
|
86
|
+
message.content #=> "Hello World!"
|
87
|
+
```
|
88
|
+
|
89
|
+
Note that, in the previous example, we parsed the JSON fragment as a document. A [document](https://docs.gobl.org/core/documents) is one of the fundamental entities of GOBL, and it represents a business document in an abstract way. To get the specific document type instantiated –a message, in the example above–, we needed to call the [`#extract`](https://rubydoc.info/github/invopop/gobl.ruby/GOBL%2FExtensions%2FDocumentHelper:extract) method of the document object.
|
90
|
+
|
91
|
+
The previous instantiation method is useful if you don't know the document type in advance. If you do, you could also instantiate the object in this more direct way:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
json = '{"$schema":"https://gobl.org/draft-0/note/message", "content":"Hello World!"}'
|
95
|
+
message = GOBL::Note::Message.from_json!(json) #=> #<GOBL::Note::Message title=nil content="Hello World!" meta=nil>
|
96
|
+
message.content #=> "Hello World!"
|
97
|
+
```
|
98
|
+
|
99
|
+
Conversely, you can generate JSON GOBL from any instantiated object:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
message = GOBL::Note::Message.new(content: 'Hello World!')
|
103
|
+
message.to_json #=> "{\"content\":\"Hello World!\"}"
|
104
|
+
```
|
105
|
+
|
106
|
+
Note that, in the previous example, the generated JSON doesn't include a `$schema` attribute. This is because the GOBL schema doesn't require that attribute in a standalone message structure. If you want to use that structure as a document, you will need a `$schema` to be present. You can get that from your Ruby code by simply [_embedding_](https://rubydoc.info/github/invopop/gobl.ruby/GOBL%2FExtensions%2FDocumentHelper%2FClassMethods:embed) the struct in a document:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
message = GOBL::Note::Message.new(content: 'Hello World!')
|
110
|
+
document = GOBL::Document.embed(message)
|
111
|
+
document.to_json #=> "{\"content\":\"Hello World!\",\"$schema\":\"https://gobl.org/draft-0/note/message\"}"
|
112
|
+
```
|
113
|
+
|
114
|
+
_See also [`GOBL::Struct.from_json!`](https://rubydoc.info/github/invopop/gobl.ruby/GOBL%2FStruct%2Efrom_json!), [`GOBL::Struct#to_json`](https://rubydoc.info/github/invopop/gobl.ruby/GOBL%2FStruct:to_json), [`GOBL::Document#embed`](https://rubydoc.info/github/invopop/gobl.ruby/GOBL%2FExtensions%2FDocumentHelper%2FClassMethods:embed), [`GOBL::Document.extract`](https://rubydoc.info/github/invopop/gobl.ruby/GOBL%2FExtensions%2FDocumentHelper:extract)_
|
115
|
+
|
116
|
+
### Handling value objects and enumerations
|
117
|
+
|
118
|
+
You can instantiate value objects in the library from a Symbol, a String or something that can be coerced into one via `#to_s`:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
code = GOBL::Org::Code.new('A123') #=> #<GOBL::Org::Code _value="A123">
|
122
|
+
date = GOBL::Cal::Date.new(Date.today) #=> #<GOBL::Cal::Date _value="2022-09-23">
|
123
|
+
type = GOBL::Bill::InvoiceType.new(:credit_note) #=> #<GOBL::Bill::InvoiceType _value="credit-note">
|
124
|
+
```
|
125
|
+
|
126
|
+
Similarly, you can compare value objects to symbols, strings or any object coercible into one:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
GOBL::Org::Code.new('A123') == 'A123' #=> true
|
130
|
+
GOBL::Org::Code.new('2022-01-01') == Date.new(2022,1,1) #=> true
|
131
|
+
GOBL::Bill::InvoiceType.new('credit-note') == :credit_note #=> true
|
132
|
+
```
|
133
|
+
|
134
|
+
The GOBL schema uses composition with certain value objects to delimit the range of allowed values. For those enumerated types, the library provides additional convenience methods:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
# `.all` class method
|
138
|
+
GOBL::Bill::InvoiceType.all #=> Returns an array with all the objects in the enumeration
|
139
|
+
|
140
|
+
# Inquirers
|
141
|
+
type = GOBL::Bill::InvoiceType.new('credit-note')
|
142
|
+
type.proforma? #=> false
|
143
|
+
type.credit_note? #=> true
|
144
|
+
|
145
|
+
# Descriptions
|
146
|
+
type = GOBL::Org::Unit.new('kg')
|
147
|
+
type.description #=> "Metric kilograms"
|
148
|
+
```
|
149
|
+
|
150
|
+
_See also [`GOBL::Org::Code`](https://rubydoc.info/github/invopop/gobl.ruby/GOBL/Org/Code), [`GOBL::Bill::InvoiceType`](https://rubydoc.info/github/invopop/gobl.ruby/GOBL/Bill/InvoiceType)_
|
151
|
+
|
152
|
+
### Running operations
|
153
|
+
|
154
|
+
The library also provides an interface to run operations over GOBL structs in the GOBL CLI service. To run those operations, you'll need the [CLI installed][4] and the service running:
|
155
|
+
|
156
|
+
```shell
|
157
|
+
$ gobl serve -p 3033
|
158
|
+
```
|
159
|
+
|
160
|
+
Then, in your app, you need to configure the host and the port where the service is listening:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
GOBL.config.service_host = '127.0.0.1'
|
164
|
+
GOBL.config.service_port = 3033
|
165
|
+
```
|
166
|
+
|
167
|
+
And then you run your operations! For instance, you can build an invoice document, which will validate and calculate it:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
invoice = GOBL::Bill::Invoice.new(
|
171
|
+
code: 'SAMPLE-001',
|
172
|
+
currency: :eur,
|
173
|
+
issue_date: Date.new(2021, 1, 1),
|
174
|
+
supplier: { tax_id: { country: :es, code: '55105445K' }, name: 'Provide One S.L.' },
|
175
|
+
customer: { tax_id: { country: :es, code: '65870696F' }, name: 'Sample Consumer' },
|
176
|
+
lines: [{
|
177
|
+
quantity: 20,
|
178
|
+
item: { name: 'Development services', price: 90.0 },
|
179
|
+
taxes: [ { cat: 'VAT', rate: :standard } ]
|
180
|
+
}]
|
181
|
+
)
|
182
|
+
document = GOBL::Document.embed(invoice)
|
183
|
+
calculated_document = GOBL.build(document)
|
184
|
+
calculated_invoice = calculated_document.extract
|
185
|
+
calculated_invoice.totals.total_with_tax #=> "2178.00"
|
186
|
+
```
|
187
|
+
|
188
|
+
Note how the `#build` operation expects and returns either document or envelope structs. That's why we needed to embed our invoice in a document and extract the calculated invoice from the returned document. See the [operations API reference][5] for more details about this and the rest of the available operations.
|
189
|
+
|
190
|
+
_See also [`GOBL::Operations`][5]_
|
191
|
+
|
192
|
+
## Developer guide
|
193
|
+
|
194
|
+
### Project Structure
|
195
|
+
|
196
|
+
#### `lib`
|
197
|
+
|
198
|
+
Contains the `gobl` library components to be imported into other projects.
|
199
|
+
|
200
|
+
All the auto-generated files from the JSON schema are also defined here. You must not modify files containing an auto-generate header should not be modified. Under the hood, the gem uses `Zeitwerk` to load.
|
201
|
+
|
202
|
+
#### `tasks`
|
203
|
+
|
204
|
+
The tasks directory contains code able to parse (`tasks/parser`) GOBL JSON Schema and generate (`tasks/generators`) the Ruby versions of the GOBL structures.
|
205
|
+
|
206
|
+
### Development tasks
|
207
|
+
|
208
|
+
The project provides a `mage.go` file with a set of [Mage](https://magefile.org) tasks to be used by developers of the library. All these tasks run within a Docker container.
|
209
|
+
|
210
|
+
You can avoid mage and the docker container if you prefer so. Take a look at the `mage.go` file to learn the commands it invokes under the hood and run them yourself.
|
211
|
+
|
212
|
+
#### Installation
|
213
|
+
|
214
|
+
The command `mage setup` fetches and installs all the required dependencies to use the gem.
|
215
|
+
|
216
|
+
#### Code generation
|
217
|
+
|
218
|
+
Ensure all the GOBL JSON Schema files are available by manually copying the base GOBL project's `build/schemas` path to the `data/schemas` path in this repository. Schemas are _.gitignored_, and you must copy them every time you want to update the generated code:
|
219
|
+
|
220
|
+
```bash
|
221
|
+
rm -rf ./data/schemas
|
222
|
+
cp -r ../gobl/build/schemas ./data
|
223
|
+
```
|
224
|
+
|
225
|
+
You can also update the regimes’ data with:
|
226
|
+
|
227
|
+
```bash
|
228
|
+
rm -rf ./data/regimes
|
229
|
+
cp -r ../gobl/build/regimes ./data
|
230
|
+
```
|
231
|
+
|
232
|
+
Now you can delete any previously generated code with
|
233
|
+
|
234
|
+
```bash
|
235
|
+
find lib -name "*.rb" -exec grep -l "Generated with GOBL" {} \; | xargs rm
|
236
|
+
```
|
237
|
+
|
238
|
+
The command `mage -v generate` generates the Ruby files from the JSON Schema. If the schema is updated, it will update the Ruby files.
|
239
|
+
|
240
|
+
#### Tests
|
241
|
+
|
242
|
+
Use the `mage spec` command to run the entire test suite.
|
243
|
+
|
244
|
+
#### Console
|
245
|
+
|
246
|
+
The command `mage console` spins up an IRB session with the library required.
|
247
|
+
|
248
|
+
#### YARD documentation
|
249
|
+
|
250
|
+
The library is fully documented using YARD. You can spin up a YARD server with the command `mage yardserver`.
|
251
|
+
|
252
|
+
[1]: https://rubydoc.info/github/invopop/gobl.ruby
|
253
|
+
[2]: https://docs.gobl.org/
|
254
|
+
[3]: https://gobl.org/
|
255
|
+
[4]: https://github.com/invopop/gobl.cli
|
256
|
+
[5]: https://rubydoc.info/github/invopop/gobl.ruby/GOBL/Operations
|
257
|
+
[6]: https://rubydoc.info/github/invopop/gobl.ruby/index
|
data/lib/gobl/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gobl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Lilue
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-01-
|
13
|
+
date: 2023-01-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -60,6 +60,7 @@ executables: []
|
|
60
60
|
extensions: []
|
61
61
|
extra_rdoc_files: []
|
62
62
|
files:
|
63
|
+
- README.md
|
63
64
|
- data/regimes/co.json
|
64
65
|
- data/regimes/es.json
|
65
66
|
- data/regimes/fr.json
|