gobl 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +257 -0
  3. data/lib/gobl/version.rb +1 -1
  4. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78b100eaffbd2c950338c44d3e84840281f1ff155e35beb993d6873f3e893a28
4
- data.tar.gz: b865e5e7cd8cc1c27fc7a043e6e290f739710e895f7d040b53ff8250492e9cf8
3
+ metadata.gz: 6c8c990624452c1ab148203b5defc61b51aa3e7a4386b19ad28b1220335d94f1
4
+ data.tar.gz: b1e4c114a06c6481b10e0c864af010e26e69224938584e8151f22e682a8c59f8
5
5
  SHA512:
6
- metadata.gz: 85298a4930680c0a044eb8c92e03e0d5d6888e727e82849cf1dab56083f19e9475f2476b6178f9b7d24277bec95853c91a74ecbd34206005a61e78a4a99b7cfe
7
- data.tar.gz: d2ce9cfa5f5d539fbd79ea5d6e2df724046c045d28b627b8827d383ce1510e74a11d1aef5fe1ba0776420fb94c986cc7a278f26a17384c6a40776f6094d2a528
6
+ metadata.gz: fadee2c91a1392c55892a779da1270febb35413cd42c97a3a99ef10e45873e8f366f867ebed5aedbfd1f616404eac1f8027626a9366e26ecb192bf8c5d644c01
7
+ data.tar.gz: efe5f63e54694022ccd0dc0b875a24cbb4d17ce2bcd6731906b464fdfd316d61afba04197a1ab5c930784fc7184d5c2670cb0bd852578146410f9aba9cdbe65f
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GOBL
4
- VERSION = '0.7.0'
4
+ VERSION = '0.7.1'
5
5
  end
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.0
4
+ version: 0.7.1
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-23 00:00:00.000000000 Z
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