Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #76 from invopop/corrective-data
Browse files Browse the repository at this point in the history
Upgrade to GOBL v0.51, with corrective data param
  • Loading branch information
samlown authored Jul 5, 2023
2 parents 880f422 + 3ebcd02 commit 9b0799d
Show file tree
Hide file tree
Showing 37 changed files with 479 additions and 906 deletions.
74 changes: 57 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Go Business Language - Command Line Interface

Released under the Apache 2.0 [LICENSE](https://github.com/invopop/gobl/blob/main/LICENSE), Copyright 2021,2022 [Invopop Ltd.](https://invopop.com).
Released under the Apache 2.0 [LICENSE](https://github.com/invopop/gobl/blob/main/LICENSE), Copyright 2021-2023 [Invopop Ltd.](https://invopop.com).

## Usage

Expand All @@ -22,29 +22,69 @@ Install with:
mage -v install
```

### `gobl build`
### Build

Build a complete GOBL document from one or more input sources. Example uses:
Build expects a partial GOBL Envelope or Document, in either YAML or JSON as input. It'll automatically run the Calculate and Validate methods and output JSON data as either an envelope or document, according to the input source.

Example uses:

```sh
# Finalize a complete invoice
gobl build invoice.yaml
# Calculate and validate a YAML invoice
gobl build ./samples/invoice-es.yaml

# Output using indented formatting
gobl build -i ./samples/customer.yaml

# Set the supplier from an external file
gobl build invoice.yaml \
--set-file doc.supplier=supplier.yaml
gobl build -i ./samples/invoice-es.yaml \
--set-file customer=./samples/customer.yaml

# Set arbitrary values from the command line. Inputs are parsed as YAML.
gobl build invoice.yaml \
--set doc.foo.bar="a long string" \
--set doc.foo.baz=1234

# Set an explicit string value (to avoid interpetation as a boolean or number)
gobl build invoice.yaml \
--set-string doc.foo.baz=1234 \
--set-string doc.foo.quz=true
gobl build -i ./samples/invoice-es.yaml \
--set meta.bar="a long string" \
--set series="TESTING"

# Set the top-level object:
gobl build invoice.yaml \
--set-file .=envelope.yaml
gobl build -i ./samples/invoice-es.yaml \
--set-file .=./samples/envelope-invoice-es.yaml

# Insert a document into an envelope
gobl build -i --envelop ./samples/invoice-es.yaml
```

### Correct

The GOBL CLI makes it easy to use the library and tax regime specific functionality that create a corrective document that reverts or amends a previous document. This is most useful for invoices and issuing refunds for example.

```sh
# Correct an invoice with a credit note (this will error for ES invoice!)
gobl correct -i ./samples/invoice-es.yaml --credit

# Specify tax regime specific details
gobl correct -i -d '{"credit":true,"corrections":["line"],"correction_method":"complete"}' \
./samples/invoice-es.yaml
```

### Sign

GOBL encourages users to sign data embedded into envelopes using digital signatures. To get started, you'll need to have a JSON Web Key. Use the following commands to generate one:

```sh
# Generate a JSON Web Key and store in ~/.gobl/id_es256.jwk
gobl keygen

# Generate and output a JWK into a new file
gobl keygen ./samples/key.jwk
```

Use the key to sign documents:

```sh
# Add a signature to the envelope using our personal key
gobl sign -i ./samples/envelope-invoice-es.yaml

# Add a signature using a specific key
gobl sign -i --key ./samples/key.jwk ./samples/envelope-invoice-es.yaml
```

It is only possible to sign non-draft envelopes, so the CLI will automatically remove this flag during the signing process. This implies that the document must be completely valid before signing.
33 changes: 7 additions & 26 deletions cmd/gobl/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"encoding/json"
"errors"
"io"
"os"

Expand All @@ -11,11 +10,6 @@ import (
"github.com/invopop/gobl.cli/internal"
)

var (
boolTrue = true
boolFalse = false
)

type buildOpts struct {
*rootOpts
set map[string]string
Expand All @@ -24,8 +18,6 @@ type buildOpts struct {
template string
docType string
envelop bool
draft bool
notDraft bool

// Command options
use string
Expand All @@ -49,14 +41,12 @@ func (b *buildOpts) cmd() *cobra.Command {
}

f := cmd.Flags()
f.StringToStringVar(&b.set, "set", nil, "Set value from the command line")
f.StringToStringVar(&b.setFiles, "set-file", nil, "Set value from the specified YAML or JSON file")
f.StringToStringVar(&b.setStrings, "set-string", nil, "Set STRING value from the command line")
f.StringVarP(&b.template, "template", "T", "", "Template YAML/JSON file into which data is merged")
f.StringVarP(&b.docType, "type", "t", "", "Specify the document type")
f.BoolVarP(&b.envelop, "envelop", "e", false, "format JSON output with indentation")
f.BoolVarP(&b.draft, "draft", "d", false, "Set envelope as draft")
f.BoolVarP(&b.notDraft, "not-draft", "n", false, "Set envelope as non-draft")
f.StringToStringVar(&b.set, "set", nil, "set value from the command line")
f.StringToStringVar(&b.setFiles, "set-file", nil, "set value from the specified YAML or JSON file")
f.StringToStringVar(&b.setStrings, "set-string", nil, "set STRING value from the command line")
f.StringVarP(&b.template, "template", "T", "", "template YAML/JSON file into which data is merged")
f.StringVarP(&b.docType, "type", "t", "", "specify the document type")
f.BoolVarP(&b.envelop, "envelop", "e", false, "insert document into an envelope")

return cmd
}
Expand Down Expand Up @@ -89,7 +79,7 @@ func (b *buildOpts) runE(cmd *cobra.Command, args []string) error {
buildOpts := &internal.BuildOptions{
ParseOptions: &internal.ParseOptions{
Template: template,
Data: input,
Input: input,
SetFile: b.setFiles,
SetYAML: b.set,
SetString: b.setStrings,
Expand All @@ -98,15 +88,6 @@ func (b *buildOpts) runE(cmd *cobra.Command, args []string) error {
},
}

switch {
case b.draft && b.notDraft:
return errors.New("draft and not-draft cannot both be set")
case b.draft:
buildOpts.Draft = &boolTrue
case b.notDraft:
buildOpts.Draft = &boolFalse
}

env, err := internal.Build(ctx, buildOpts)
if err != nil {
return err
Expand Down
30 changes: 0 additions & 30 deletions cmd/gobl/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,36 +167,6 @@ func Test_build(t *testing.T) {
},
},
},
{
name: "set to draft",
args: []string{"testdata/success.json"},
opts: &buildOpts{
draft: true,
},
},
{
name: "set to non-draft",
args: []string{"testdata/success.json"},
opts: &buildOpts{
draft: false,
},
},
{
name: "set to draft on non-envelop",
args: []string{"testdata/envelop.nototals.json"},
opts: &buildOpts{
draft: true,
},
err: "code=422, message=cannot set draft status on non-envelope document",
},
{
name: "set to non-draft on non-envelop",
args: []string{"testdata/envelop.nototals.json"},
opts: &buildOpts{
notDraft: true,
},
err: "code=422, message=cannot set draft status on non-envelope document",
},
{
name: "no document",
in: strings.NewReader(`{
Expand Down
5 changes: 4 additions & 1 deletion cmd/gobl/correct.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

type correctOpts struct {
*rootOpts
data string // JSON Correction Options data
credit bool
debit bool
}
Expand All @@ -30,6 +31,7 @@ func (o *correctOpts) cmd() *cobra.Command {
f := cmd.Flags()
f.BoolVarP(&o.credit, "credit", "", false, "Generate a credit note or negative corrective document.")
f.BoolVarP(&o.debit, "debit", "", false, "Generate a debit note.")
f.StringVarP(&o.data, "data", "d", "", "JSON data for the correction options.")

return cmd
}
Expand All @@ -51,10 +53,11 @@ func (o *correctOpts) runE(cmd *cobra.Command, args []string) error {

cOpts := &internal.CorrectOptions{
ParseOptions: &internal.ParseOptions{
Data: input,
Input: input,
},
Credit: o.credit,
Debit: o.debit,
Data: []byte(o.data),
}

obj, err := internal.Correct(ctx, cOpts)
Expand Down
9 changes: 4 additions & 5 deletions cmd/gobl/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ const (
)

type serveOpts struct {
httpPort int
httpPort int
privateKeyFile string
privateKey *dsig.PrivateKey
privateKey *dsig.PrivateKey
}

func serve() *serveOpts {
Expand Down Expand Up @@ -130,10 +130,9 @@ func prepareBuildOpts(c echo.Context) (*internal.BuildOptions, error) {
}
opts := &internal.BuildOptions{
ParseOptions: &internal.ParseOptions{
Data: bytes.NewReader(req.Data),
Input: bytes.NewReader(req.Data),
DocType: req.DocType,
},
Draft: req.Draft,
}
if len(req.Template) != 0 {
opts.Template = bytes.NewReader(req.Template)
Expand Down Expand Up @@ -185,7 +184,7 @@ func (s *serveOpts) bulk(c echo.Context) error {
enc.SetIndent("", "\t")
}
opts := &internal.BulkOptions{
In: c.Request().Body,
In: c.Request().Body,
DefaultPrivateKey: s.privateKey,
}
for result := range internal.Bulk(ctx, opts) {
Expand Down
2 changes: 1 addition & 1 deletion cmd/gobl/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (opts *signOpts) runE(cmd *cobra.Command, args []string) error {
signOpts := &internal.SignOptions{
ParseOptions: &internal.ParseOptions{
Template: template,
Data: input,
Input: input,
SetFile: opts.setFiles,
SetYAML: opts.set,
SetString: opts.setStrings,
Expand Down
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_force_long
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
template: (string) "",
docType: (string) "",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_force_short
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
template: (string) "",
docType: (string) "",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_in-place_long
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
template: (string) "",
docType: (string) "",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_in-place_short
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
template: (string) "",
docType: (string) "",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_no_args
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
template: (string) "",
docType: (string) "",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_set_files
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
template: (string) "",
docType: (string) "",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_set_string_values
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
template: (string) "",
docType: (string) "",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_set_values
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
template: (string) "",
docType: (string) "",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_template
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
template: (string) (len=8) "foo.yaml",
docType: (string) "",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
2 changes: 0 additions & 2 deletions cmd/gobl/testdata/Test_build_args_type
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
template: (string) "",
docType: (string) (len=12) "bill.Invoice",
envelop: (bool) false,
draft: (bool) false,
notDraft: (bool) false,
use: (string) (len=24) "build [infile] [outfile]",
short: (string) (len=68) "Calculate and validate a document, wrapping it in envelope if needed"
})
Loading

0 comments on commit 9b0799d

Please sign in to comment.