Skip to content

Commit

Permalink
Normalize opt name,add example
Browse files Browse the repository at this point in the history
  • Loading branch information
apardods committed Dec 20, 2024
1 parent c288bf7 commit 905792a
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 2 deletions.
2 changes: 2 additions & 0 deletions cmd/gobl.html/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

type convertOpts struct {
*rootOpts
Zugferd bool
}

func convert(o *rootOpts) *convertOpts {
Expand All @@ -24,6 +25,7 @@ func (c *convertOpts) cmd() *cobra.Command {
Short: "Convert a GOBL JSON into an HTML file",
RunE: c.runE,
}
cmd.Flags().BoolVar(&c.Zugferd, "zugferd", false, "Add Zugferd XMP metadata to the PDF")
return cmd
}

Expand Down
179 changes: 179 additions & 0 deletions examples/invoice-de-zugferd.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
{
"$schema": "https://gobl.org/draft-0/envelope",
"head": {
"uuid": "8a51fd30-2a27-11ee-be56-0242ac120002",
"dig": {
"alg": "sha256",
"val": "583130bdfd84c31d23f7bcdf778363ffdbc7eb132faf1180efb1be1fc438e069"
}
},
"doc": {
"$schema": "https://gobl.org/draft-0/bill/invoice",
"$regime": "DE",
"$addons": [
"eu-en16931-v2017"
],
"uuid": "019231f1-9128-71fc-b0e2-820af3036d1b",
"type": "standard",
"series": "SAMPLE",
"code": "001",
"issue_date": "2024-02-13",
"currency": "EUR",
"supplier": {
"name": "Provide One GmbH",
"tax_id": {
"country": "DE",
"code": "111111125"
},
"people": [
{
"name": {
"given": "John",
"surname": "Doe"
}
}
],
"addresses": [
{
"num": "16",
"street": "Dietmar-Hopp-Allee",
"locality": "Walldorf",
"code": "69190",
"country": "DE"
}
],
"emails": [
{
"addr": "[email protected]"
}
],
"telephones": [
{
"num": "+49100200300"
}
]
},
"customer": {
"name": "Sample Consumer",
"tax_id": {
"country": "DE",
"code": "282741168"
},
"addresses": [
{
"num": "25",
"street": "Werner-Heisenberg-Allee",
"locality": "München",
"code": "80939",
"country": "DE"
}
],
"emails": [
{
"addr": "[email protected]"
}
]
},
"lines": [
{
"i": 1,
"quantity": "20",
"item": {
"name": "Development services",
"price": "90.00",
"unit": "h"
},
"sum": "1800.00",
"taxes": [
{
"cat": "VAT",
"rate": "standard",
"percent": "19%"
}
],
"total": "1800.00"
}
],
"ordering": {
"code": "XR-2024-2",
"seller": {
"name": "Salescompany ltd.",
"tax_id": {
"country": "NO",
"code": "123456789MVA"
},
"identities": [
{
"label": "CompanyID",
"code": "123456789"
},
{
"label": "0088",
"code": "1238764941386"
}
],
"people": [
{
"name": {
"given": "Antonio Salesmacher"
}
}
],
"addresses": [
{
"street": "Main street 34",
"street_extra": "Suite 123",
"locality": "Big city",
"region": "RegionA",
"code": "303",
"country": "NO"
}
],
"emails": [
{
"addr": "[email protected]"
}
],
"telephones": [
{
"num": "46211230"
}
]
}
},
"payment": {
"terms": {
"detail": "lorem ipsum"
}
},
"tax": {
"ext": {
"untdid-document-type": "380"
}
},
"totals": {
"sum": "1800.00",
"total": "1800.00",
"taxes": {
"categories": [
{
"code": "VAT",
"rates": [
{
"key": "standard",
"base": "1800.00",
"percent": "19%",
"amount": "342.00"
}
],
"amount": "342.00"
}
],
"sum": "342.00"
},
"tax": "342.00",
"total_with_tax": "2142.00",
"payable": "2142.00"
}
}
}
152 changes: 152 additions & 0 deletions examples/out/invoice-de-zugferd.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<html data-theme="light">
<head>
<title>GOBL HTML Generator</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&amp;display=swap" rel="stylesheet" />
<link rel="stylesheet" href="styles/envelope.css" />
<link rel="stylesheet" href="styles/invoice.css" />
</head>
<body>
<article class="envelope">
<footer class="print">
<span class="page">Page <span class="page-number">1</span> of <span class="pages-number">1</span></span>
<div class="gobl-logo">
<a href="https://gobl.org">
<img
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjQuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkNhcGFfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgdmlld0JveD0iMCAwIDE4MC42IDIxOC44IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAxODAuNiAyMTguODsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxwYXRoIGQ9Ik0xNzIsMTI3LjVWMzIuNmMwLTEuNC0wLjctMi44LTEuOS0zLjZjLTEuMi0wLjgtMi43LTAuOS00LTAuM2wtMzguOCwxNi44di0yN2MwLTEuNC0wLjctMi44LTEuOS0zLjYKCQljLTEuMi0wLjgtMi43LTAuOS00LTAuNEw4Mi42LDMxLjN2LTI3YzAtMS40LTAuNy0yLjgtMS45LTMuNmMtMS4yLTAuOC0yLjctMC45LTQtMC40TDExLDI4LjdjLTEuNiwwLjctMi42LDIuMi0yLjYsMy45djk0LjkKCQljMCwxLjQsMC43LDIuOCwxLjksMy42YzAuNywwLjUsMS41LDAuNywyLjMsMC43YzAuNiwwLDEuMS0wLjEsMS43LTAuM2wzOC44LTE2Ljh2MjdjMCwxLjQsMC43LDIuOCwxLjksMy42CgkJYzAuNywwLjUsMS41LDAuNywyLjMsMC43YzAuNiwwLDEuMS0wLjEsMS43LTAuM2wzOC44LTE2Ljh2MjdjMCwxLjQsMC43LDIuOCwxLjksMy42YzAuNywwLjUsMS41LDAuNywyLjMsMC43CgkJYzAuNiwwLDEuMS0wLjEsMS43LTAuM2w2NS42LTI4LjRDMTcxLDEzMC44LDE3MiwxMjkuMiwxNzIsMTI3LjV6IE0xNjMuNSwxMjQuN2wtNTcuMSwyNC43di0yNC4ybDE4LjMtNy45YzEuNi0wLjcsMi42LTIuMiwyLjYtMy45CgkJVjY0bC04LjUsMy43djQyLjhsLTEyLjQsNS40bC04LjUsMy43bC0zNi4yLDE1LjZWMTExbDE4LjMtNy45YzEuNi0wLjcsMi42LTIuMiwyLjYtMy45VjQ5LjhsLTguNSwzLjd2NDIuOGwtMTIuNCw1LjRsLTguNSwzLjcKCQlMMTcsMTIxVjM1LjRsNTcuMS0yNC43VjM1bC0xOC4zLDcuOWMtMS42LDAuNy0yLjYsMi4yLTIuNiwzLjl2NDkuM2w4LjUtMy43VjQ5LjZsMTIuNC01LjRsOC41LTMuN2wzNi4yLTE1LjZ2MjQuMmwtMTguMyw3LjkKCQljLTEuNiwwLjctMi42LDIuMi0yLjYsMy45djQ5LjNsOC41LTMuN1Y2My44bDEyLjQtNS40bDguNS0zLjdsMzYuMi0xNS42VjEyNC43eiIvPgoJPGc+CgkJPGc+CgkJCTxwYXRoIGQ9Ik00NC4yLDE4Ny40Yy0yLjMtNy4xLTkuNC0xMS40LTIwLjEtMTEuNEM5LjEsMTc2LDAsMTg0LjcsMCwxOTcuNGMwLDEzLDkuMSwyMS41LDIzLDIxLjVjMTYsMCwyMi45LTguNiwyMi45LTIwLjUKCQkJCWMwLTEuMiwwLTIuNS0wLjMtMy44SDIzLjJ2N2gxMi41YzAuMiw1LjYtNS4yLDkuNC0xMS45LDkuNGMtOC42LDAtMTMtNS4zLTEzLTEzLjZjMC04LjMsNC41LTEzLjgsMTIuMy0xMy44CgkJCQljNC42LDAsOC40LDEuOSw5LjksNi4yTDQ0LjIsMTg3LjR6Ii8+CgkJCTxwYXRoIGQ9Ik03NC42LDIxMC45Yy03LjYsMC0xMi40LTUuMy0xMi40LTEzLjVjMC04LjMsNC44LTEzLjUsMTIuNC0xMy41YzcuNiwwLDEyLjQsNS4yLDEyLjQsMTMuNQoJCQkJQzg3LDIwNS43LDgyLjIsMjEwLjksNzQuNiwyMTAuOXogTTc0LjYsMjE4LjhjMTQsMCwyMy4xLTguMywyMy4xLTIxLjRjMC0xMy4xLTkuMS0yMS40LTIzLjEtMjEuNHMtMjMuMSw4LjMtMjMuMSwyMS40CgkJCQlDNTEuNiwyMTAuNSw2MC43LDIxOC44LDc0LjYsMjE4Ljh6Ii8+CgkJCTxwYXRoIGQ9Ik0xMjUsMjEwLjdoLTExLjJ2LTEwLjNoMTEuM2M0LjIsMCw2LjMsMiw2LjMsNS4xQzEzMS40LDIwOC40LDEyOS40LDIxMC43LDEyNSwyMTAuN3ogTTExMy44LDE4NC4yaDEwLjYKCQkJCWM0LjMsMCw1LjksMi4xLDUuOSw0LjZjMCwyLjYtMS40LDQuOS01LjksNC45aC0xMC42VjE4NC4yeiBNMTMzLjQsMTk2LjVjNS0xLjIsNy42LTQuNyw3LjYtOWMwLTUuOS00LjMtMTAuMy0xMy44LTEwLjNoLTIzLjYKCQkJCXY0MC41aDI0LjFjOS45LDAsMTQuNC01LjEsMTQuNC0xMS41QzE0Mi4xLDIwMC45LDEzOS4xLDE5Ny40LDEzMy40LDE5Ni41eiIvPgoJCQk8cG9seWdvbiBwb2ludHM9IjE0OS4yLDE3Ny4yIDE0OS4yLDIxNy43IDE4MC42LDIxNy43IDE4MC42LDIwOS41IDE1OS40LDIwOS41IDE1OS40LDE3Ny4yIAkJCSIvPgoJCTwvZz4KCTwvZz4KPC9nPgo8L3N2Zz4K"
alt="GOBL"
/>
</a>
</div>
</footer>
<article class="invoice">
<header class="regular">
<div class="details">
<section class="title">
<div class="hero"><div class="alias">Provide One GmbH</div></div>
<h1 class="type">Invoice</h1>
<h2 class="code">SAMPLE-001</h2>
</section>
<section class="summary">
<h2 class="title">Summary</h2>
<ul>
<li class="issue-date"><span class="label">Issue Date</span> <span class="value">2024-02-13</span></li>
<li class="currency"><span class="label">Currency</span> <span class="value">Euro (EUR)</span></li>
<li class="ordering-code"><span class="label">Order</span> <span class="value">XR-2024-2</span></li>
</ul>
</section>
</div>
<div class="contacts">
<section class="supplier">
<h2>Supplier</h2>
<div class="org-party">
<div class="name">Provide One GmbH</div>
<div class="person">John Doe</div>
<div class="org-address"><span>Dietmar-Hopp-Allee 16, Walldorf, 69190 (Germany)</span></div>
<div class="telephone">Tel: +49100200300</div>
<div class="emails">Email: [email protected]</div>
<div class="tax-id">TIN: (DE) 111111125</div>
</div>
</section>
<section class="customer">
<h2>Customer</h2>
<div class="org-party">
<div class="name">Sample Consumer</div>
<div class="org-address"><span>Werner-Heisenberg-Allee 25, München, 80939 (Germany)</span></div>
<div class="emails">Email: [email protected]</div>
<div class="tax-id">TIN: (DE) 282741168</div>
</div>
</section>
</div>
</header>
<section class="lines">
<h2>Lines</h2>
<table>
<thead>
<tr>
<th class="ref">#</th>
<th class="description">Description</th>
<th class="quantity">Qty.</th>
<th class="unit">Unit</th>
<th class="price">Price</th>
<th class="tax">VAT</th>
<th class="total">Total</th>
</tr>
</thead>
<tbody>
<tr>
<td class="ref">1</td>
<td class="description"><span>Development services</span></td>
<td class="quantity">20</td>
<td class="unit">h</td>
<td class="price">€90,00</td>
<td class="tax">19%</td>
<td class="total">€1.800,00</td>
</tr>
</tbody>
</table>
</section>
<div class="totals">
<section class="totals">
<h2>Totals</h2>
<table>
<tbody>
<tr class="sum strong">
<th>Sum</th>
<td>€1.800,00</td>
</tr>
<tr class="tax">
<th>Tax</th>
<td>€342,00</td>
</tr>
<tr class="payable strong">
<th>Total to pay</th>
<td>€2.142,00</td>
</tr>
</tbody>
</table>
</section>
<section class="taxes">
<h2>Taxes</h2>
<table>
<thead>
<tr>
<th class="category">Tax</th>
<th class="base">Base</th>
<th class="rate">Rate</th>
<th class="amount">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="1" class="category">VAT</td>
<td class="base">€1.800,00</td>
<td class="rate">19%</td>
<td class="amount">€342,00</td>
</tr>
</tbody>
</table>
</section>
</div>
<section class="payment">
<h2 class="title">Payment</h2>
<ul class="terms"></ul>
</section>
<div class="extensions"></div>
</article>
<footer class="screen">
<div class="gobl-logo">
<a href="https://gobl.org">
<img
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjQuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkNhcGFfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgdmlld0JveD0iMCAwIDE4MC42IDIxOC44IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAxODAuNiAyMTguODsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxwYXRoIGQ9Ik0xNzIsMTI3LjVWMzIuNmMwLTEuNC0wLjctMi44LTEuOS0zLjZjLTEuMi0wLjgtMi43LTAuOS00LTAuM2wtMzguOCwxNi44di0yN2MwLTEuNC0wLjctMi44LTEuOS0zLjYKCQljLTEuMi0wLjgtMi43LTAuOS00LTAuNEw4Mi42LDMxLjN2LTI3YzAtMS40LTAuNy0yLjgtMS45LTMuNmMtMS4yLTAuOC0yLjctMC45LTQtMC40TDExLDI4LjdjLTEuNiwwLjctMi42LDIuMi0yLjYsMy45djk0LjkKCQljMCwxLjQsMC43LDIuOCwxLjksMy42YzAuNywwLjUsMS41LDAuNywyLjMsMC43YzAuNiwwLDEuMS0wLjEsMS43LTAuM2wzOC44LTE2Ljh2MjdjMCwxLjQsMC43LDIuOCwxLjksMy42CgkJYzAuNywwLjUsMS41LDAuNywyLjMsMC43YzAuNiwwLDEuMS0wLjEsMS43LTAuM2wzOC44LTE2Ljh2MjdjMCwxLjQsMC43LDIuOCwxLjksMy42YzAuNywwLjUsMS41LDAuNywyLjMsMC43CgkJYzAuNiwwLDEuMS0wLjEsMS43LTAuM2w2NS42LTI4LjRDMTcxLDEzMC44LDE3MiwxMjkuMiwxNzIsMTI3LjV6IE0xNjMuNSwxMjQuN2wtNTcuMSwyNC43di0yNC4ybDE4LjMtNy45YzEuNi0wLjcsMi42LTIuMiwyLjYtMy45CgkJVjY0bC04LjUsMy43djQyLjhsLTEyLjQsNS40bC04LjUsMy43bC0zNi4yLDE1LjZWMTExbDE4LjMtNy45YzEuNi0wLjcsMi42LTIuMiwyLjYtMy45VjQ5LjhsLTguNSwzLjd2NDIuOGwtMTIuNCw1LjRsLTguNSwzLjcKCQlMMTcsMTIxVjM1LjRsNTcuMS0yNC43VjM1bC0xOC4zLDcuOWMtMS42LDAuNy0yLjYsMi4yLTIuNiwzLjl2NDkuM2w4LjUtMy43VjQ5LjZsMTIuNC01LjRsOC41LTMuN2wzNi4yLTE1LjZ2MjQuMmwtMTguMyw3LjkKCQljLTEuNiwwLjctMi42LDIuMi0yLjYsMy45djQ5LjNsOC41LTMuN1Y2My44bDEyLjQtNS40bDguNS0zLjdsMzYuMi0xNS42VjEyNC43eiIvPgoJPGc+CgkJPGc+CgkJCTxwYXRoIGQ9Ik00NC4yLDE4Ny40Yy0yLjMtNy4xLTkuNC0xMS40LTIwLjEtMTEuNEM5LjEsMTc2LDAsMTg0LjcsMCwxOTcuNGMwLDEzLDkuMSwyMS41LDIzLDIxLjVjMTYsMCwyMi45LTguNiwyMi45LTIwLjUKCQkJCWMwLTEuMiwwLTIuNS0wLjMtMy44SDIzLjJ2N2gxMi41YzAuMiw1LjYtNS4yLDkuNC0xMS45LDkuNGMtOC42LDAtMTMtNS4zLTEzLTEzLjZjMC04LjMsNC41LTEzLjgsMTIuMy0xMy44CgkJCQljNC42LDAsOC40LDEuOSw5LjksNi4yTDQ0LjIsMTg3LjR6Ii8+CgkJCTxwYXRoIGQ9Ik03NC42LDIxMC45Yy03LjYsMC0xMi40LTUuMy0xMi40LTEzLjVjMC04LjMsNC44LTEzLjUsMTIuNC0xMy41YzcuNiwwLDEyLjQsNS4yLDEyLjQsMTMuNQoJCQkJQzg3LDIwNS43LDgyLjIsMjEwLjksNzQuNiwyMTAuOXogTTc0LjYsMjE4LjhjMTQsMCwyMy4xLTguMywyMy4xLTIxLjRjMC0xMy4xLTkuMS0yMS40LTIzLjEtMjEuNHMtMjMuMSw4LjMtMjMuMSwyMS40CgkJCQlDNTEuNiwyMTAuNSw2MC43LDIxOC44LDc0LjYsMjE4Ljh6Ii8+CgkJCTxwYXRoIGQ9Ik0xMjUsMjEwLjdoLTExLjJ2LTEwLjNoMTEuM2M0LjIsMCw2LjMsMiw2LjMsNS4xQzEzMS40LDIwOC40LDEyOS40LDIxMC43LDEyNSwyMTAuN3ogTTExMy44LDE4NC4yaDEwLjYKCQkJCWM0LjMsMCw1LjksMi4xLDUuOSw0LjZjMCwyLjYtMS40LDQuOS01LjksNC45aC0xMC42VjE4NC4yeiBNMTMzLjQsMTk2LjVjNS0xLjIsNy42LTQuNyw3LjYtOWMwLTUuOS00LjMtMTAuMy0xMy44LTEwLjNoLTIzLjYKCQkJCXY0MC41aDI0LjFjOS45LDAsMTQuNC01LjEsMTQuNC0xMS41QzE0Mi4xLDIwMC45LDEzOS4xLDE5Ny40LDEzMy40LDE5Ni41eiIvPgoJCQk8cG9seWdvbiBwb2ludHM9IjE0OS4yLDE3Ny4yIDE0OS4yLDIxNy43IDE4MC42LDIxNy43IDE4MC42LDIwOS41IDE1OS40LDIwOS41IDE1OS40LDE3Ny4yIAkJCSIvPgoJCTwvZz4KCTwvZz4KPC9nPgo8L3N2Zz4K"
alt="GOBL"
/>
</a>
</div>
</footer>
</article>
</body>
</html>
4 changes: 2 additions & 2 deletions pkg/pdf/pdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ func WithAttachment(a *Attachment) Option {
}
}

// WithXMPMetadata adds the XMP metadata to the conversion request.
func WithXMPMetadata() Option {
// WithZugferd adds the Zugferd XMP metadata to the conversion request.
func WithZugferd() Option {
return func(o *options) {
o.xmpMetadata = &XMPMetadata{
Data: loadXMP(),
Expand Down
1 change: 1 addition & 0 deletions pkg/pdf/prince.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func (pc *princeConvertor) HTML(_ context.Context, data []byte, opts ...Option)
if j.PDF == nil {
j.PDF = new(princepdf.PDF)
}
j.PDF.PDFXMP = xmpFilename
j.PDF.Attach = append(j.PDF.Attach, &princepdf.Attachment{
URL: xmpFilename,
Filename: xmpFilename,
Expand Down

0 comments on commit 905792a

Please sign in to comment.