gobl 0.7.0 → 0.7.2
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/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
|