Skip to content

Commit

Permalink
Merge pull request #336 from invopop/scenario-ext-notes
Browse files Browse the repository at this point in the history
Advanced scenarios supported with additional notes for exempt reasons
  • Loading branch information
samlown authored Jul 29, 2024
2 parents 659ce2f + d3afe15 commit c4e850d
Show file tree
Hide file tree
Showing 14 changed files with 720 additions and 136 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

## [Unreleased]

## [v0.112.0] - 2024-07-26

### Added

- `tax`: Scenarios now handle extension key and value for filtering.
- PT: exemption text handling moved to scenarios.

## [v0.111.1] - 2024-07-25

### Added
Expand Down
37 changes: 32 additions & 5 deletions bill/invoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ func (inv *Invoice) Calculate() error {
}
}

if err := inv.prepareTagsAndScenarios(); err != nil {
if err := inv.prepareTags(); err != nil {
return err
}

Expand All @@ -321,7 +321,15 @@ func (inv *Invoice) Calculate() error {
return err
}

return inv.calculateWithRegime(r)
if err := inv.calculateWithRegime(r); err != nil {
return err
}

if err := inv.prepareScenarios(); err != nil {
return err
}

return nil
}

// RemoveIncludedTaxes is a special function that will go through all prices which may include
Expand Down Expand Up @@ -404,14 +412,25 @@ func (inv *Invoice) scenarioSummary(r *tax.Regime) *tax.ScenarioSummary {
if ss == nil {
return nil
}
exts := make([]tax.Extensions, 0)
tags := []cbc.Key{}

if inv.Tax != nil {
tags = inv.Tax.Tags
if len(inv.Tax.Ext) > 0 {
exts = append(exts, inv.Tax.Ext)
}
}
return ss.SummaryFor(inv.Type, tags)
for _, cat := range inv.Totals.Taxes.Categories {
for _, rate := range cat.Rates {
exts = append(exts, rate.Ext)
}
}

return ss.SummaryFor(inv.Type, tags, exts)
}

func (inv *Invoice) prepareTagsAndScenarios() error {
func (inv *Invoice) prepareTags() error {
r := inv.TaxRegime()
if r == nil {
return nil
Expand All @@ -426,6 +445,14 @@ func (inv *Invoice) prepareTagsAndScenarios() error {
return fmt.Errorf("invalid document tag: %v", k)
}
}
return nil
}

func (inv *Invoice) prepareScenarios() error {
r := inv.TaxRegime()
if r == nil {
return nil
}

// Use the scenario summary to add any notes to the invoice
ss := inv.scenarioSummary(r)
Expand All @@ -436,7 +463,7 @@ func (inv *Invoice) prepareTagsAndScenarios() error {
// make sure we don't already have the same note in the invoice
var en *cbc.Note
for _, n2 := range inv.Notes {
if n.Src == n2.Src {
if n.Src == n2.Src && n.Code == n2.Code {
en = n
break
}
Expand Down
13 changes: 13 additions & 0 deletions cbc/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ func (m Meta) Validate() error {
return err
}

// Equals checks if the meta data is the same.
func (m Meta) Equals(m2 Meta) bool {
if len(m) != len(m2) {
return false
}
for k, v := range m {
if m2[k] != v {
return false
}
}
return true
}

// JSONSchemaExtend ensures the meta keys are valid.
func (Meta) JSONSchemaExtend(schema *jsonschema.Schema) {
prop := schema.AdditionalProperties
Expand Down
21 changes: 21 additions & 0 deletions cbc/meta_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,24 @@ func TestMeta(t *testing.T) {
assert.Error(t, err)
assert.Contains(t, err.Error(), "Meta: (bad_key: must be in a valid format.)")
}

func TestMetaEquals(t *testing.T) {
m1 := cbc.Meta{
cbc.Key("test"): "bar",
}
m2 := cbc.Meta{
cbc.Key("test"): "bar",
}
assert.True(t, m1.Equals(m2))

m2 = cbc.Meta{
cbc.Key("test"): "foo",
}
assert.False(t, m1.Equals(m2))

m2 = cbc.Meta{
cbc.Key("test"): "bar",
cbc.Key("foo"): "bar",
}
assert.False(t, m1.Equals(m2))
}
16 changes: 16 additions & 0 deletions cbc/notes.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,22 @@ func (n *Note) WithSrc(src Key) *Note {
return &nw
}

// WithCode provides a new copy of the note with the code set.
func (n *Note) WithCode(code string) *Note {
nw := *n // copy
nw.Code = code
return &nw
}

// Equals returns true if the provided note is the same as the current one.
func (n *Note) Equals(n2 *Note) bool {
return n.Key == n2.Key &&
n.Code == n2.Code &&
n.Src == n2.Src &&
n.Text == n2.Text &&
n.Meta.Equals(n2.Meta)
}

// JSONSchemaExtend adds the list of definitions for the notes.
func (Note) JSONSchemaExtend(schema *jsonschema.Schema) {
ks, _ := schema.Properties.Get("key")
Expand Down
Loading

0 comments on commit c4e850d

Please sign in to comment.