Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions allowance_charge_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import (
"github.com/invopop/gobl/tax"
)

const (
percentageCalculationFactor = 10000
percentageCalculationScale = 2
)

func goblAddChargesAndDiscounts(stlm *Settlement, out *bill.Invoice) error {
var charges []*bill.Charge
var discounts []*bill.Discount
Expand Down Expand Up @@ -74,6 +79,14 @@ func goblNewCharge(ac *AllowanceCharge) (*bill.Charge, error) {
return nil, err
}
c.Percent = &p
} else if c.Base != nil && !c.Amount.IsZero() {
// Calculate percent from amount and base
if !c.Base.IsZero() {
// Calculate percentage: (amount / base) * 100
ratio := c.Amount.Multiply(num.MakeAmount(percentageCalculationFactor, percentageCalculationScale)).Divide(*c.Base)
percent := num.PercentageFromAmount(ratio)
c.Percent = &percent
}
}
if ac.Tax != nil {
if ac.Tax.TypeCode != "" {
Expand Down Expand Up @@ -127,6 +140,14 @@ func goblNewDiscount(ac *AllowanceCharge) (*bill.Discount, error) {
return nil, err
}
d.Percent = &p
} else if d.Base != nil && !d.Amount.IsZero() {
// Calculate percent from amount and base
if !d.Base.IsZero() {
// Calculate percentage: (amount / base) * 100
ratio := d.Amount.Multiply(num.MakeAmount(percentageCalculationFactor, percentageCalculationScale)).Divide(*d.Base)
percent := num.PercentageFromAmount(ratio)
d.Percent = &percent
}
}
if ac.Tax != nil {
if ac.Tax.TypeCode != "" {
Expand Down Expand Up @@ -176,6 +197,15 @@ func goblNewLineCharge(ac *AllowanceCharge) (*bill.LineCharge, error) {
return nil, err
}
c.Percent = &p
} else if ac.Base != "" && ac.Amount != "" {
// Calculate percent from amount and base
base, err := num.AmountFromString(ac.Base)
if err == nil && !base.IsZero() {
// Calculate percentage: (amount / base) * 100
ratio := c.Amount.Multiply(num.MakeAmount(percentageCalculationFactor, percentageCalculationScale)).Divide(base)
percent := num.PercentageFromAmount(ratio)
c.Percent = &percent
}
}
return c, nil
}
Expand Down Expand Up @@ -205,6 +235,15 @@ func goblNewLineDiscount(ac *AllowanceCharge) (*bill.LineDiscount, error) {
return nil, err
}
d.Percent = &p
} else if ac.Base != "" && ac.Amount != "" {
// Calculate percent from amount and base
base, err := num.AmountFromString(ac.Base)
if err == nil && !base.IsZero() {
// Calculate percentage: (amount / base) * 100
ratio := d.Amount.Multiply(num.MakeAmount(percentageCalculationFactor, percentageCalculationScale)).Divide(base)
percent := num.PercentageFromAmount(ratio)
d.Percent = &percent
}
}
return d, nil
}
1 change: 1 addition & 0 deletions examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func TestParseInvoice(t *testing.T) {
inv.UUID = staticUUID
}
require.NoError(t, env.Calculate())
assert.NoError(t, env.Validate())

writeEnvelope(dataPath(pathParse, pathOut, outName), env)

Expand Down
6 changes: 0 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/gobl v0.216.3 h1:i8PVVSPOePGSYWApPQ7xMGObAvKK7AGzxWhF4fEgjOA=
github.com/invopop/gobl v0.216.3/go.mod h1:RDgv26Zs8PyVq7gHU17fqyX0tWifCEdPQzoz3dNtEv0=
github.com/invopop/gobl v0.217.2-0.20250611151101-6468d2ad9104 h1:07az1n6GlFxQLK/+V5xoqKo92u0aHkuwHLsQji0DGio=
github.com/invopop/gobl v0.217.2-0.20250611151101-6468d2ad9104/go.mod h1:RDgv26Zs8PyVq7gHU17fqyX0tWifCEdPQzoz3dNtEv0=
github.com/invopop/gobl v0.217.2-0.20250611161148-355e6c17e45f h1:t09jgqn5flRQW/wMjI4qYPIGpgvg5zU1EG3bLmN/iHM=
github.com/invopop/gobl v0.217.2-0.20250611161148-355e6c17e45f/go.mod h1:RDgv26Zs8PyVq7gHU17fqyX0tWifCEdPQzoz3dNtEv0=
github.com/invopop/gobl v0.218.0 h1:2IFMx0Y/XeNgM9XfyGbdB7RX7RCQrCFuyAzWJP1TtxA=
github.com/invopop/gobl v0.218.0/go.mod h1:RDgv26Zs8PyVq7gHU17fqyX0tWifCEdPQzoz3dNtEv0=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
Expand Down
4 changes: 2 additions & 2 deletions lines_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ func goblAddLines(in *Transaction, out *bill.Invoice) error {
l.Item.Unit = goblUnitFromUNECE(u)
}

if it.Product.SellerAssignedID != nil {
if it.Product.SellerAssignedID != nil && *it.Product.SellerAssignedID != "" {
l.Item.Ref = cbc.Code(*it.Product.SellerAssignedID)
}

if it.Product.BuyerAssignedID != nil {
if it.Product.BuyerAssignedID != nil && *it.Product.BuyerAssignedID != "" {
if l.Item.Identities == nil {
l.Item.Identities = make([]*org.Identity, 0)
}
Expand Down
19 changes: 19 additions & 0 deletions party_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,25 @@ func goblNewParty(party *Party) *org.Party {
}
}

// Handle LegalOrganization ID
if party.LegalOrganization != nil && party.LegalOrganization.ID != nil && party.LegalOrganization.ID.Value != "" {
if p.Identities == nil {
p.Identities = make([]*org.Identity, 0)
}
identity := &org.Identity{
Code: cbc.Code(party.LegalOrganization.ID.Value),
}
if party.PostalTradeAddress != nil {
identity.Country = l10n.ISOCountryCode(party.PostalTradeAddress.CountryID)
}
if party.LegalOrganization.ID.SchemeID != "" {
identity.Ext = tax.Extensions{
iso.ExtKeySchemeID: cbc.Code(party.LegalOrganization.ID.SchemeID),
}
}
p.Identities = append(p.Identities, identity)
}

// Global ID is not yet mapped to the ISO 6523 ICD, its identifier is used as the label
if party.GlobalID != nil {
if p.Identities == nil {
Expand Down
10 changes: 6 additions & 4 deletions party_parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestParseCtoGParty(t *testing.T) {

assert.Equal(t, "Sample Seller", seller.Name)
assert.Equal(t, l10n.TaxCountryCode("DE"), seller.TaxID.Country)
assert.Equal(t, cbc.Code("049120826"), seller.TaxID.Code)
assert.Equal(t, cbc.Code("282741168"), seller.TaxID.Code)

assert.Equal(t, "Sample Buyer", buyer.Name)
assert.Equal(t, "Sample Street 2", buyer.Addresses[0].Street)
Expand Down Expand Up @@ -88,9 +88,11 @@ func TestParseCtoGParty(t *testing.T) {
assert.Equal(t, "The Buyercompany", customer.Name)
assert.Equal(t, cbc.Code("987654321MVA"), customer.TaxID.Code)
assert.Equal(t, l10n.TaxCountryCode("NO"), customer.TaxID.Country)
require.Len(t, customer.Identities, 1)
assert.Equal(t, "3456789012098", customer.Identities[0].Code.String())
assert.Equal(t, "0088", customer.Identities[0].Ext[iso.ExtKeySchemeID].String())
require.Len(t, customer.Identities, 2)
assert.Equal(t, "987654321", customer.Identities[0].Code.String())
assert.Equal(t, l10n.ISOCountryCode("NO"), customer.Identities[0].Country)
assert.Equal(t, "3456789012098", customer.Identities[1].Code.String())
assert.Equal(t, "0088", customer.Identities[1].Ext[iso.ExtKeySchemeID].String())
})

t.Run("CII-IN_SE-R-003.xml", func(t *testing.T) {
Expand Down
21 changes: 19 additions & 2 deletions settlement_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ import (
"github.com/invopop/gobl/tax"
)

const (
advancePaymentDescription = "Advance Payment"
fullPercentageAmount = 100
fullPercentageScale = 0
)

var paymentMeansMap = map[string]cbc.Key{
"10": pay.MeansKeyCash,
"20": pay.MeansKeyCheque,
Expand Down Expand Up @@ -63,6 +69,7 @@ func goblNewPaymentDetails(stlm *Settlement) (*bill.PaymentDetails, error) {
}
a.Date = &advancePaymentReceivedDateTime
}
a.Description = advancePaymentDescription
pymt.Advances = append(pymt.Advances, a)
}
} else if stlm.Summary.TotalPrepaidAmount != "" {
Expand All @@ -72,7 +79,8 @@ func goblNewPaymentDetails(stlm *Settlement) (*bill.PaymentDetails, error) {
return nil, err
}
a := &pay.Advance{
Amount: amt,
Description: advancePaymentDescription,
Amount: amt,
}
pymt.Advances = append(pymt.Advances, a)
}
Expand Down Expand Up @@ -114,14 +122,23 @@ func goblNewTerms(settlement *Settlement) (*pay.Terms, error) {
return nil, err
}
dd.Amount = amt
if dd.Amount != num.AmountZero {
dates = append(dates, dd)
}
} else if term.Percent != "" {
p, err := num.PercentageFromString(term.Percent)
if err != nil {
return nil, err
}
dd.Percent = &p
if dd.Percent != nil && *dd.Percent != num.PercentageZero {
dates = append(dates, dd)
}
} else {
p := num.PercentageFromAmount(num.MakeAmount(fullPercentageAmount, fullPercentageScale))
dd.Percent = &p
dates = append(dates, dd)
}
dates = append(dates, dd)
}
}

Expand Down
Loading
Loading