diff --git a/components/org/address.templ b/components/org/address.templ index 9860413..a408f99 100644 --- a/components/org/address.templ +++ b/components/org/address.templ @@ -19,7 +19,7 @@ templ AddressWithLabel(addr *org.Address) {
if addr.Label != "" { - @t.T("organizing.address.label", i18n.M{"label": addr.Label}) + @t.T("org.address.label", i18n.M{"label": addr.Label})   } @@ -31,7 +31,7 @@ templ addressLines(addr *org.Address) { { strings.Join(buildAddressLines(addr), ", ") } if addr.Country != "" { - @t.T("organizing.address.country", i18n.M{"country": i18n.T(ctx, "country_names."+addr.Country.String())}) + @t.T("org.address.country", i18n.M{"country": i18n.T(ctx, "country_names."+addr.Country.String())}) } } diff --git a/components/org/address_templ.go b/components/org/address_templ.go index 6f1483f..ec9c9d0 100644 --- a/components/org/address_templ.go +++ b/components/org/address_templ.go @@ -73,7 +73,7 @@ func AddressWithLabel(addr *org.Address) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = t.T("organizing.address.label", i18n.M{"label": addr.Label}).Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = t.T("org.address.label", i18n.M{"label": addr.Label}).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -128,7 +128,7 @@ func addressLines(addr *org.Address) templ.Component { return templ_7745c5c3_Err } if addr.Country != "" { - templ_7745c5c3_Err = t.T("organizing.address.country", i18n.M{"country": i18n.T(ctx, "country_names."+addr.Country.String())}).Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = t.T("org.address.country", i18n.M{"country": i18n.T(ctx, "country_names."+addr.Country.String())}).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/components/org/party.templ b/components/org/party.templ index 78b96dc..f11c6c0 100644 --- a/components/org/party.templ +++ b/components/org/party.templ @@ -2,6 +2,7 @@ package org import ( "cmp" + "fmt" "slices" "strings" @@ -16,7 +17,7 @@ import ( templ Party(party *org.Party) {
- @t.Scope("organizing.party") { + @t.Scope("org.party") {
{ party.Name }
if party.Alias != "" {
{ party.Alias }
@@ -120,6 +121,12 @@ func identityLabel(ctx context.Context, ident *org.Identity) string { if ident.Type != "" { return ident.Type.String() } + if ident.Key != "" { + label := i18n.T(ctx, fmt.Sprintf(".identity_labels.%s", ident.Key)) + if !strings.HasPrefix(label, "!") { + return label + } + } return i18n.T(ctx, ".identity_code") } diff --git a/components/org/party_templ.go b/components/org/party_templ.go index 56fc864..e838b60 100644 --- a/components/org/party_templ.go +++ b/components/org/party_templ.go @@ -12,6 +12,7 @@ import "bytes" import ( "cmp" + "fmt" "slices" "strings" @@ -54,7 +55,7 @@ func Party(party *org.Party) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(party.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/org/party.templ`, Line: 20, Col: 33} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/org/party.templ`, Line: 21, Col: 33} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -72,7 +73,7 @@ func Party(party *org.Party) templ.Component { var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(party.Alias) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/org/party.templ`, Line: 22, Col: 36} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/org/party.templ`, Line: 23, Col: 36} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { @@ -152,7 +153,7 @@ func Party(party *org.Party) templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = t.Scope("organizing.party").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = t.Scope("org.party").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -369,7 +370,7 @@ func partyExtensions(party *org.Party) templ.Component { var templ_7745c5c3_Var11 string templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(txt) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/org/party.templ`, Line: 95, Col: 9} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/org/party.templ`, Line: 96, Col: 9} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { @@ -410,6 +411,12 @@ func identityLabel(ctx context.Context, ident *org.Identity) string { if ident.Type != "" { return ident.Type.String() } + if ident.Key != "" { + label := i18n.T(ctx, fmt.Sprintf(".identity_labels.%s", ident.Key)) + if !strings.HasPrefix(label, "!") { + return label + } + } return i18n.T(ctx, ".identity_code") } diff --git a/examples/it-hotel-b2c.json b/examples/it-hotel-b2c.json new file mode 100644 index 0000000..a815c86 --- /dev/null +++ b/examples/it-hotel-b2c.json @@ -0,0 +1,145 @@ +{ + "$schema": "https://gobl.org/draft-0/envelope", + "head": { + "uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", + "dig": { + "alg": "sha256", + "val": "277eb3247d67ce9de6feef8bec4d710e1a1f10feae546ab9da138e62dd6b1cc1" + }, + "draft": true + }, + "doc": { + "$schema": "https://gobl.org/draft-0/bill/invoice", + "uuid": "3aea7b56-59d8-4beb-90bd-f8f280d852a0", + "type": "standard", + "series": "SAMPLE", + "code": "002", + "issue_date": "2023-05-21", + "currency": "EUR", + "tax": { + "prices_include": "VAT" + }, + "supplier": { + "name": "Hotel California", + "tax_id": { + "country": "IT", + "code": "12345678903" + }, + "addresses": [ + { + "num": "102", + "street": "Via California", + "locality": "Palermo", + "region": "PA", + "code": "33213", + "country": "IT" + } + ], + "registration": { + "capital": "50000.00", + "currency": "EUR", + "office": "RM", + "entry": "123456" + } + }, + "customer": { + "name": "Mela S.r.l.", + "tax_id": { + "country": "IT" + }, + "identities": [ + { + "key": "it-fiscal-code", + "code": "RSSGNN60R30H501U" + } + ], + "inboxes": [ + { + "key": "it-sdi-code", + "code": "M5UXCR5" + } + ], + "addresses": [ + { + "num": "23", + "street": "Via dei Mille", + "locality": "Firenze", + "region": "FI", + "code": "00100", + "country": "IT" + } + ] + }, + "lines": [ + { + "i": 1, + "quantity": "1", + "item": { + "name": "Tassa di Soggiorno", + "price": "1.00" + }, + "sum": "1.00", + "taxes": [ + { + "cat": "VAT", + "rate": "exempt", + "ext": { + "it-sdi-nature": "N4" + } + } + ], + "total": "1.00" + }, + { + "i": 2, + "quantity": "1", + "item": { + "name": "Camera Matrimoniale", + "price": "125.00" + }, + "sum": "125.00", + "taxes": [ + { + "cat": "VAT", + "rate": "intermediate", + "percent": "10.0%" + } + ], + "total": "125.00" + } + ], + "totals": { + "sum": "126.00", + "tax_included": "11.36", + "total": "114.64", + "taxes": { + "categories": [ + { + "code": "VAT", + "rates": [ + { + "key": "exempt", + "ext": { + "it-sdi-nature": "N4" + }, + "base": "1.00", + "amount": "0.00" + }, + { + "key": "intermediate", + "base": "113.64", + "percent": "10.0%", + "amount": "11.36" + } + ], + "amount": "11.36" + } + ], + "sum": "11.36" + }, + "tax": "11.36", + "total_with_tax": "126.00", + "payable": "126.00" + } + } +} \ No newline at end of file diff --git a/examples/out/it-hotel-b2c.html b/examples/out/it-hotel-b2c.html new file mode 100644 index 0000000..b00273d --- /dev/null +++ b/examples/out/it-hotel-b2c.html @@ -0,0 +1,310 @@ + + + + GOBL HTML Generator + + + + + + + + + + +
+
+ + Page + + 1 + + of + + 1 + + + +
+
+
+
+
+
+
+ Hotel California +
+
+

+ Invoice +

+

+ SAMPLE-002 +

+
+
+

+ Summary +

+
    +
  • + + Issue Date + + + 2023-05-21 + +
  • +
  • + + Currency + + + Euro (EUR) + +
  • +
+
+
+
+
+

+ Supplier +

+
+
+ Hotel California +
+
+ + Via California 102, Palermo, PA, 33213 (Italy) + +
+
+ Tax Code: (IT) 12345678903 +
+
+
+
+

+ Customer +

+
+
+ Mela S.r.l. +
+
+ + Via dei Mille 23, Firenze, FI, 00100 (Italy) + +
+
+ Codice Fiscale: RSSGNN60R30H501U +
+
+
+
+
+
+

+ Lines +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ # + + Description + + Qty. + + Price + + VAT + + Total +
+ 1 + + + Tassa di Soggiorno + + + 1 + + €1,00 + + — + + €1,00 +
+ 2 + + + Camera Matrimoniale + + + 1 + + €125,00 + + 10,0% + + €125,00 +
+
+
+
+

+ Totals +

+ + + + + + + + + + + + + + + + + + + +
+ Sum + + €126,00 +
+ Included VAT + + €11,36 +
+ Total + + €114,64 +
+ Total to pay + + €126,00 +
+
+
+

+ Taxes +

+ + + + + + + + + + + + + + + + + + + + + + +
+ Tax + + Base + + Rate + + Amount +
+ VAT + + €1,00 + + (N4) + + €0,00 +
+ €113,64 + + 10,0% + + €11,36 +
+
+
+
+

+ Notes +

+
+ + Registration: + + + Social Capital €50.000,00 + + + RM + + + Entry 123456 + +
+
+
+
+ +
+ + \ No newline at end of file diff --git a/go.mod b/go.mod index 7d4b96f..2ef83ec 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/a-h/templ v0.2.731 github.com/go-resty/resty/v2 v2.12.0 github.com/invopop/ctxi18n v0.6.0 - github.com/invopop/gobl v0.80.0 + github.com/invopop/gobl v0.81.0 github.com/invopop/princepdf v0.0.0-20240408123340-585be3cab91a github.com/labstack/echo/v4 v4.11.4 github.com/piglig/go-qr v0.2.4 diff --git a/go.sum b/go.sum index 7c00770..6deda4f 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/invopop/ctxi18n v0.6.0 h1:Qm3ZL/kK4EKvmLI3U2ETN2rWrtSTaxXrcA6ZUY9aVGE= github.com/invopop/ctxi18n v0.6.0/go.mod h1:1Osw+JGYA+anHt0Z4reF36r5FtGHYjGQ+m1X7keIhPc= -github.com/invopop/gobl v0.80.0 h1:Gm7hZP6WW+LhrAWw1p9bOHrO6VHx7THDo6HXZXx24eI= -github.com/invopop/gobl v0.80.0/go.mod h1:3ixShxX1jlOKo5Rw22HVQh3jXnK9AZa7Twcw7L92qn0= +github.com/invopop/gobl v0.81.0 h1:bFzXkiNCdjXZcTrggsM8bzeddPDwAk/sUxinK7jaSlQ= +github.com/invopop/gobl v0.81.0/go.mod h1:3ixShxX1jlOKo5Rw22HVQh3jXnK9AZa7Twcw7L92qn0= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/invopop/princepdf v0.0.0-20240408123340-585be3cab91a h1:xt18LlIfizLkFgLi+vK/m2SWOsAbQwVwQgbkzxKY0eU= diff --git a/locales/de/app.yml b/locales/de/app.yml index a894e72..43750bf 100644 --- a/locales/de/app.yml +++ b/locales/de/app.yml @@ -118,7 +118,7 @@ de: cude: "CUDE: %{cude}" preceding_cufe: "CUFE Vorherige Rechnung: %{cufe}" - organizing: + org: party: tax_id: "%{label}: (%{country}) %{code}" tel: "Tel: %{num}" diff --git a/locales/el/app.yml b/locales/el/app.yml index c529269..d9cce80 100644 --- a/locales/el/app.yml +++ b/locales/el/app.yml @@ -123,7 +123,7 @@ el: cude: "CUDE: %{cude}" preceding_cufe: "CUFE Προηγούμενου τιμολογίου: %{cufe}" - organizing: + org: party: tax_id: "%{label}: (%{country}) %{code}" tel: "Τηλ: %{num}" diff --git a/locales/en/app.yml b/locales/en/app.yml index 824519b..6535d66 100644 --- a/locales/en/app.yml +++ b/locales/en/app.yml @@ -123,7 +123,7 @@ en: cude: "CUDE: %{cude}" preceding_cufe: "CUFE Previous invoice: %{cufe}" - organizing: + org: party: tax_id: "%{label}: (%{country}) %{code}" tel: "Tel: %{num}" @@ -134,11 +134,13 @@ en: email_label: "%{addr} (%{label})" website: "Web: %{url}" website_label: "%{label}: %{url}" - identity: "%{label}: %{code}" - identity_code: "Identity code" po_box: "P.O. Box %{po_box}" labels: default: "Tax Code" + identity: "%{label}: %{code}" + identity_code: "Identity code" + identity_labels: + it-fiscal-code: "Codice Fiscale" ext: "%{label}: %{value}" ext_map: co-dian-municipality: "Municipality" diff --git a/locales/es/app.yml b/locales/es/app.yml index a351865..90dc5bc 100644 --- a/locales/es/app.yml +++ b/locales/es/app.yml @@ -120,7 +120,7 @@ es: cude: "CUDE: %{cude}" preceding_cufe: "CUFE Factura anterior: %{cufe}" - organizing: + org: party: tax_id: "%{label}: (%{country}) %{code}" tel: "Tel: %{num}" diff --git a/locales/fr/app.yml b/locales/fr/app.yml index 0ee8369..8c68796 100644 --- a/locales/fr/app.yml +++ b/locales/fr/app.yml @@ -107,7 +107,7 @@ fr: cufe: "CUFE: %{cufe}" cude: "CUDE: %{cude}" preceding_cufe: "CUFE Facture précédente: %{cufe}" - organizing: + org: party: tax_id: "%{label}: (%{country}) %{code}" tel: "Tél: %{num}" diff --git a/locales/it/app.yml b/locales/it/app.yml index 57545b7..09b7d43 100644 --- a/locales/it/app.yml +++ b/locales/it/app.yml @@ -107,7 +107,7 @@ it: cufe: "CUFE: %{cufe}" cude: "CUDE: %{cude}" preceding_cufe: "CUFE Fattura precedente: %{cufe}" - organizing: + org: party: tax_id: "%{label}: (%{country}) %{code}" tel: "Tel: %{num}" diff --git a/locales/pl/app.yml b/locales/pl/app.yml index dcc6059..b0e22a4 100644 --- a/locales/pl/app.yml +++ b/locales/pl/app.yml @@ -118,7 +118,7 @@ pl: cude: "CUDE: %{cude}" preceding_cufe: "Poprzedni CUFE faktury: %{cufe}" - organizing: + org: party: tax_id: "%{label}: (%{country}) %{code}" tel: "Tel: %{num}" diff --git a/locales/pt/app.yml b/locales/pt/app.yml index 24f4e20..b8765c0 100644 --- a/locales/pt/app.yml +++ b/locales/pt/app.yml @@ -113,7 +113,7 @@ pt: page: "Página %{id}" entry: "Entrada %{id}" - organizing: + org: party: tax_id: "%{label}: (%{country}) %{code}" tel: "Tel: %{num}"