Skip to content

Commit

Permalink
Refining charges, discounts, with keys, removing outlays
Browse files Browse the repository at this point in the history
  • Loading branch information
samlown committed Oct 31, 2024
1 parent 1806e09 commit c25a6c5
Show file tree
Hide file tree
Showing 76 changed files with 4,063 additions and 1,410 deletions.
13 changes: 10 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,28 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- New "tax catalogues" used for defining extensions for specific standards.
- `tax`: New "tax catalogues" used for defining extensions for specific standards.
- `iso`: catalogue created with `iso-schema-id` extensions.
- `untdid`: catalogue created with extensions: `untdid-document-type`, `untdid-payment-means`, and `untdid-tax-category`.
- `untdid`: catalogue created with extensions: `untdid-document-type`, `untdid-payment-means`, `untdid-tax-category`, `untdid-allowance`, and `untdid-charge`.
- `eu-en16931-v2017`: addon for underlying support of the EN16931 semantic specifications.
- `de-xrechnung-v3`: addon with extra normalization for XRechnung specification in Germany.
- `pay`: Added `sepa` payment means key extension in main definition to be used with Credit Transfers and Direct Debit.
- `org`: `Identity` support for extensions.
- `org`: `Identity` and `Inbox` support for extensions.
- `tax`: tags for `export` and `eea` (european economic area) for use with rates.
- `bill`: support for extensions in `Discount`, `Charge`, `LineDiscount`, and `LineCharge`.
- `bill`: specifically defined keys for Discounts and Charges.

### Modified
### Changed

- `tax`: rate keys can now be extended, so `exempt+reverse-charge` will be accepted and may be used by addons to included additional codes.
- `tax`: Addons can now depend on other addons, whose keys will be automatically added during normalization.
- `cbc`: Code now allows `:` separator.

### Removed

- `pay`: UNTDID 4461 mappings from payment means table, now provided by catalogues
- `bill`: `Outlay` has been removed in favour of Charges, we've also not seen any evidence this field has been used.
- `bill`: `ref` field from discounts and charges in favour of `code`.
- `tax`: Regime `ChargeKeys` removed. Keys now provided in `bill` package.
- `it`: Charge keys no longer defined, no migration required, already supported.

## [v0.203.0]

Expand Down
4 changes: 0 additions & 4 deletions addons/co/dian/invoices.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ func validateInvoice(inv *bill.Invoice) error {
validation.Each(validation.By(validateInvoicePreceding(inv.Type))),
validation.Skip,
),
validation.Field(&inv.Outlays,
validation.Empty,
validation.Skip,
),
)
}

Expand Down
65 changes: 65 additions & 0 deletions addons/eu/en16931/bill.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,71 @@ import (
"github.com/invopop/validation"
)

var discountKeyMap = tax.Extensions{
bill.DiscountKeyEarlyCompletion: "41",
bill.DiscountKeyMilitary: "62",
bill.DiscountKeyWorkAccident: "63",
bill.DiscountKeySpecialAgreement: "64",
bill.DiscountKeyProductionError: "65",
bill.DiscountKeyNewOutlet: "66",
bill.DiscountKeySample: "67",
bill.DiscountKeyEndOfRange: "68",
bill.DiscountKeyIncoterm: "70",
bill.DiscountKeyPOSThreshold: "71",
bill.DiscountKeySpecialRebate: "100",
bill.DiscountKeyTemporary: "103",
bill.DiscountKeyStandard: "104",
bill.DiscountKeyYarlyTurnover: "105",
}

// The following map is useful to get started, but for most users it will make
// sense to use the UNTDID codes directly in the extensions.
var chargeKeyMap = tax.Extensions{
bill.ChargeKeyStampDuty: "ST",
bill.ChargeKeyOutlay: "AAE",
bill.ChargeKeyTax: "TX",
bill.ChargeKeyCustoms: "ABW",
bill.ChargeKeyDelivery: "DL",
bill.ChargeKeyPacking: "PC",
bill.ChargeKeyHandling: "HD",
bill.ChargeKeyInsurance: "IN",
bill.ChargeKeyStorage: "ABA",
bill.ChargeKeyAdmin: "AEM",
bill.ChargeKeyCleaning: "CG",
}

func normalizeBillDiscount(m *bill.Discount) {
if val, ok := discountKeyMap[m.Key]; ok {
m.Ext = m.Ext.Merge(tax.Extensions{
untdid.ExtKeyAllowance: val,
})
}
}

func normalizeBillLineDiscount(m *bill.LineDiscount) {
if val, ok := discountKeyMap[m.Key]; ok {
m.Ext = m.Ext.Merge(tax.Extensions{
untdid.ExtKeyAllowance: val,
})
}
}

func normalizeBillCharge(m *bill.Charge) {
if val, ok := chargeKeyMap[m.Key]; ok {
m.Ext = m.Ext.Merge(tax.Extensions{
untdid.ExtKeyCharge: val,
})
}
}

func normalizeBillLineCharge(m *bill.LineCharge) {
if val, ok := chargeKeyMap[m.Key]; ok {
m.Ext = m.Ext.Merge(tax.Extensions{
untdid.ExtKeyCharge: val,
})
}
}

func validateBillInvoice(inv *bill.Invoice) error {
return validation.ValidateStruct(inv,
validation.Field(&inv.Tax,
Expand Down
84 changes: 84 additions & 0 deletions addons/eu/en16931/bill_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,87 @@ func testInvoiceStandard(t *testing.T) *bill.Invoice {
}
return inv
}

func TestNormalizeBillLineDiscount(t *testing.T) {
ad := tax.AddonForKey(en16931.V2017)
t.Run("with key", func(t *testing.T) {
l := &bill.LineDiscount{
Key: "sample",
Reason: "Product sample",
Amount: num.MakeAmount(100, 2),
}
ad.Normalizer(l)
assert.Equal(t, "67", l.Ext[untdid.ExtKeyAllowance].String())
})
t.Run("without key", func(t *testing.T) {
l := &bill.LineDiscount{
Reason: "Product sample",
Amount: num.MakeAmount(100, 2),
}
ad.Normalizer(l)
assert.Nil(t, l.Ext)
})
}

func TestNormalizeBillDiscount(t *testing.T) {
ad := tax.AddonForKey(en16931.V2017)
t.Run("with key", func(t *testing.T) {
l := &bill.Discount{
Key: "sample",
Reason: "Product sample",
Amount: num.MakeAmount(100, 2),
}
ad.Normalizer(l)
assert.Equal(t, "67", l.Ext[untdid.ExtKeyAllowance].String())
})
t.Run("without key", func(t *testing.T) {
l := &bill.Discount{
Reason: "Product sample",
Amount: num.MakeAmount(100, 2),
}
ad.Normalizer(l)
assert.Nil(t, l.Ext)
})
}

func TestNormalizeBillLineCharge(t *testing.T) {
ad := tax.AddonForKey(en16931.V2017)
t.Run("with key", func(t *testing.T) {
l := &bill.LineCharge{
Key: "outlay",
Reason: "Notary costs",
Amount: num.MakeAmount(1000, 2),
}
ad.Normalizer(l)
assert.Equal(t, "AAE", l.Ext[untdid.ExtKeyCharge].String())
})
t.Run("without key", func(t *testing.T) {
l := &bill.LineCharge{
Reason: "Additional costs",
Amount: num.MakeAmount(3000, 2),
}
ad.Normalizer(l)
assert.Nil(t, l.Ext)
})
}

func TestNormalizeBillCharge(t *testing.T) {
ad := tax.AddonForKey(en16931.V2017)
t.Run("with key", func(t *testing.T) {
l := &bill.Charge{
Key: "outlay",
Reason: "Notary costs",
Amount: num.MakeAmount(1000, 2),
}
ad.Normalizer(l)
assert.Equal(t, "AAE", l.Ext[untdid.ExtKeyCharge].String())
})
t.Run("without key", func(t *testing.T) {
l := &bill.Charge{
Reason: "Additional costs",
Amount: num.MakeAmount(3000, 2),
}
ad.Normalizer(l)
assert.Nil(t, l.Ext)
})
}
8 changes: 8 additions & 0 deletions addons/eu/en16931/en16931.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ func normalize(doc any) {
normalizePayInstructions(obj)
case *tax.Combo:
normalizeTaxCombo(obj)
case *bill.Discount:
normalizeBillDiscount(obj)
case *bill.LineDiscount:
normalizeBillLineDiscount(obj)
case *bill.Charge:
normalizeBillCharge(obj)
case *bill.LineCharge:
normalizeBillLineCharge(obj)
}
}

Expand Down
Loading

0 comments on commit c25a6c5

Please sign in to comment.