pdf building script

This commit is contained in:
Ruidy 2025-01-20 17:26:19 +01:00
parent 7c3208c3b5
commit b8d5907f36
No known key found for this signature in database
GPG key ID: E00F51288CB857CC
4 changed files with 213 additions and 503 deletions

3
.gitignore vendored
View file

@ -28,4 +28,5 @@ tmp.pdf
*.env
*templ.txt
token.json
.aider*
.aider*
output.html

View file

@ -1,288 +1,288 @@
<!doctype html>
<html lang="en">
<head>
<html lang="fr">
<head>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f9f9f9;
color: #333;
}
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f9f9f9;
color: #333;
}
.header {
background-color: #007b8f;
color: #fff;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.header {
background-color: #007b8f;
color: #fff;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
height: 60px;
}
.logo {
height: 60px;
}
.payee {
text-align: right;
}
.payee {
text-align: right;
}
hr {
border: none;
border-top: 2px solid #ddd;
margin: 20px 0;
}
hr {
border: none;
border-top: 2px solid #ddd;
margin: 20px 0;
}
.info-table {
width: 48%;
margin-bottom: 20px;
}
.info-table {
width: 48%;
margin-bottom: 20px;
}
.info-table td {
padding: 5px 10px;
}
.info-table td {
padding: 5px 10px;
}
.billing-details {
display: flex;
justify-content: space-between;
}
.billing-details {
display: flex;
justify-content: space-between;
}
.items-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.items-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.items-table th,
.items-table td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
.items-table th,
.items-table td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
.items-table th {
background-color: #007b8f;
color: #fff;
}
.items-table th {
background-color: #007b8f;
color: #fff;
}
.items-table .align-right {
text-align: right;
}
.items-table .align-right {
text-align: right;
}
.bg-gray {
background-color: #f4f4f4;
}
.bg-gray {
background-color: #f4f4f4;
}
.payment-summary {
margin-top: 20px;
}
.payment-summary {
margin-top: 20px;
}
.summary-table {
width: 100%;
}
.summary-table {
width: 100%;
}
.summary-table td {
padding: 10px;
}
.summary-table td {
padding: 10px;
}
.payment-history h3 {
color: #007b8f;
}
.payment-history h3 {
color: #007b8f;
}
.history-table {
width: 100%;
border-collapse: collapse;
}
.history-table {
width: 100%;
border-collapse: collapse;
}
.history-table th,
.history-table td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
.history-table th,
.history-table td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
.history-table th {
background-color: #007b8f;
color: #fff;
}
.history-table th {
background-color: #007b8f;
color: #fff;
}
.card {
background-color: #eef7f9;
padding: 15px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.card {
background-color: #eef7f9;
padding: 15px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.order-total {
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 20px;
}
.order-total {
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 20px;
}
.total {
text-align: right;
}
.total {
text-align: right;
}
.amount-due {
font-size: 18px;
font-weight: bold;
}
.amount-due {
font-size: 18px;
font-weight: bold;
}
.amount-due-total {
font-size: 24px;
font-weight: bold;
color: #007b8f;
}
.amount-due-total {
font-size: 24px;
font-weight: bold;
color: #007b8f;
}
.space-between {
display: flex;
justify-content: space-between;
}
.space-between {
display: flex;
justify-content: space-between;
}
.text-break {
word-wrap: break-word;
}
.text-break {
word-wrap: break-word;
}
</style>
</head>
</head>
<body>
<div class="header space-between">
<img class="logo" src="assets/img/logo.png" />
<div class="payee">
<b>{{ .Host.Name }}</b><br />
{{ .Host.Address }}<br />
{{ .Host.ZipCode }} {{ .Host.City }}<br />
<b>Tel:</b> {{ .Host.Phone }}<br />
<b>Mail:</b> {{ .Host.Email }}<br />
</div>
<body>
<div class="header space-between">
<img class="logo" src="assets/img/logo.png"/>
<div class="payee">
<b>{{ .Host.Name }}</b><br/>
{{ .Host.Address }}<br/>
{{ .Host.ZipCode }} {{ .Host.City }}<br/>
<b>Tel :</b> {{ .Host.Phone }}<br/>
<b>Mail :</b> {{ .Host.Email }}<br/>
</div>
<hr />
<div class="billing-details space-between">
<table class="info-table">
</div>
<hr/>
<div class="billing-details space-between">
<table class="info-table">
<tbody>
<tr>
<tr>
<td><strong>{{ .Name }}</strong></td>
</tr>
<tr>
<td><strong>Tel:</strong></td>
</tr>
<tr>
<td><strong>Tel :</strong></td>
<td>{{ .PhoneNumber }}</td>
</tr>
<tr>
<td><strong>Voyageurs:</strong></td>
</tr>
<tr>
<td><strong>Client :</strong></td>
<td>{{ .CustomersNumber }}</td>
</tr>
<tr>
<td><strong>Plateforme:</strong></td>
</tr>
<tr>
<td><strong>Plateforme :</strong></td>
<td>{{ .Platform }}</td>
</tr>
</tr>
</tbody>
</table>
<table class="info-table">
</table>
<table class="info-table">
<tbody>
<tr>
<td><strong>Nº de facture:</strong></td>
<tr>
<td><strong>Nº de facture :</strong></td>
<td>{{ .ID }}</td>
</tr>
<tr>
<td><strong>Du:</strong></td>
</tr>
<tr>
<td><strong>Du :</strong></td>
<td>{{ .From }}</td>
</tr>
<tr>
<td><strong>Au:</strong></td>
</tr>
<tr>
<td><strong>Au :</strong></td>
<td>{{ .To }}</td>
</tr>
<tr>
<td><strong>Montant Total:</strong></td>
</tr>
<tr>
<td><strong>Montant Total :</strong></td>
<td>{{ .Total }}</td>
</tr>
</tr>
</tbody>
</table>
</div>
<hr />
<div class="order-details">
<table class="items-table">
</table>
</div>
<hr/>
<div class="order-details">
<table class="items-table">
<thead>
<tr>
<tr>
<th>Objet</th>
<th>Quantité</th>
<th>Prix (€)</th>
<th class="align-right">Total (€)</th>
</tr>
</tr>
</thead>
<tbody class="bg-gray rounded">
{{ range .Lines }}
<tr class="item-row">
{{ range .Lines }}
<tr class="item-row">
<td class="text-break product_name">{{ .Name }}</td>
<td>{{ .Quantity }}</td>
<td>{{ .Price }}</td>
<td class="align-right">{{ .Total }}</td>
</tr>
{{ end }}
</tr>
{{ end }}
</tbody>
</table>
</div>
</table>
</div>
<div class="payment-history">
<h3>Historique des Paiements</h3>
<table class="history-table">
<div class="payment-history">
<h3>Historique des Paiements</h3>
<table class="history-table">
<thead>
<tr>
<tr>
<th>Date</th>
<th>Mode de Paiement</th>
<th>Montant (€)</th>
</tr>
</tr>
</thead>
<tbody>
{{ range .Payments }}
<tr>
{{ range .Payments }}
<tr>
<td>{{ .Date }}</td>
<td>{{ .Method }}</td>
<td>{{ .Amount }}</td>
</tr>
{{ end }}
</tr>
{{ end }}
</tbody>
</table>
</div>
</table>
</div>
<div class="payment-summary space-between">
<table class="summary-table">
<div class="payment-summary space-between">
<table class="summary-table">
<tbody>
<tr>
<td><strong>Montant Total:</strong></td>
<tr>
<td><strong>Montant Total :</strong></td>
<td>{{ .Total }}</td>
</tr>
<tr>
<td><strong>Montant Payé:</strong></td>
</tr>
<tr>
<td><strong>Montant Payé :</strong></td>
<td>{{ .AmountPaid }}</td>
</tr>
<tr>
<td><strong>Solde Restant:</strong></td>
</tr>
<tr>
<td><strong>Solde Restant :</strong></td>
<td>{{ .BalanceDue }}</td>
</tr>
</tr>
</tbody>
</table>
</div>
<hr />
<div class="order-summary space-between">
<div class="card">
<b>Notes</b> <br />
TVA non applicable, art. 293 B du CGI <br />
</table>
</div>
<hr/>
<div class="order-summary space-between">
<div class="card">
<b>Notes</b> <br/>
TVA non applicable, art. 293 B du CGI <br/>
Dispensé dimmatriculation au registre du commerce et des sociétés (RCS)
et au répertoire des métiers. <br />
et au répertoire des métiers. <br/>
Conditions de paiement : paiement à réception de facture. Aucun escompte
consenti pour règlement anticipé ou désistement. Tout incident de
paiement est passible d'intérêts de retard. Le montant des pénalités
résulte de l'application aux sommes restant dues d'un taux d'intérêt
légal en vigueur au moment de l'incident. <br />
</div>
légal en vigueur au moment de l'incident. <br/>
</div>
<div class="order-total space-between">
<div></div>
<div class="total">
</div>
<div class="order-total space-between">
<div></div>
<div class="total">
<div class="amount-due">Total</div>
<div class="amount-due-total">{{ .Total }}</div>
</div>
</div>
</body>
</div>
</body>
</html>

View file

@ -7,6 +7,8 @@ import (
"os"
)
const invoiceTemplate = "assets/html/invoice.html"
func main() {
// Define the invoice data structure
type Invoice struct {
@ -42,7 +44,7 @@ func main() {
}
// Read the template file
tmpl, err := template.ParseFiles("assets/html/invoice.html")
tmpl, err := template.ParseFiles(invoiceTemplate)
if err != nil {
log.Fatalf("Error parsing template: %v", err)
}
@ -64,8 +66,8 @@ func main() {
Phone: "+590 690 44 15 30",
Email: "location.villafleurie@gmail.com",
},
Name: "VillaFleurie",
PhoneNumber: "+590 690 44 15 30",
Name: "Michel Le Corre",
//PhoneNumber: "+590 690 44 15 30",
CustomersNumber: 2,
Platform: "Privée",
ID: "VFNI0332",
@ -107,7 +109,6 @@ func main() {
// Create a buffer to store the rendered HTML
var buf bytes.Buffer
// Execute the template with the invoice data
if err := tmpl.Execute(&buf, invoice); err != nil {
log.Fatalf("Error executing template: %v", err)

View file

@ -1,292 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f9f9f9;
color: #333;
}
.header {
background-color: #007b8f;
color: #fff;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
height: 60px;
}
.payee {
text-align: right;
}
hr {
border: none;
border-top: 2px solid #ddd;
margin: 20px 0;
}
.info-table {
width: 48%;
margin-bottom: 20px;
}
.info-table td {
padding: 5px 10px;
}
.billing-details {
display: flex;
justify-content: space-between;
}
.items-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.items-table th,
.items-table td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
.items-table th {
background-color: #007b8f;
color: #fff;
}
.items-table .align-right {
text-align: right;
}
.bg-gray {
background-color: #f4f4f4;
}
.payment-summary {
margin-top: 20px;
}
.summary-table {
width: 100%;
}
.summary-table td {
padding: 10px;
}
.payment-history h3 {
color: #007b8f;
}
.history-table {
width: 100%;
border-collapse: collapse;
}
.history-table th,
.history-table td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
.history-table th {
background-color: #007b8f;
color: #fff;
}
.card {
background-color: #eef7f9;
padding: 15px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.order-total {
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 20px;
}
.total {
text-align: right;
}
.amount-due {
font-size: 18px;
font-weight: bold;
}
.amount-due-total {
font-size: 24px;
font-weight: bold;
color: #007b8f;
}
.space-between {
display: flex;
justify-content: space-between;
}
.text-break {
word-wrap: break-word;
}
</style>
</head>
<body>
<div class="header space-between">
<img class="logo" src="assets/img/logo.png" />
<div class="payee">
<b>VillaFleurie</b><br />
4 rue Gerty Archimede<br />
97190 Le Gosier<br />
<b>Tel:</b> &#43;590 690 44 15 30<br />
<b>Mail:</b> location.villafleurie@gmail.com<br />
</div>
</div>
<hr />
<div class="billing-details space-between">
<table class="info-table">
<tbody>
<tr>
<td><strong>VillaFleurie</strong></td>
</tr>
<tr>
<td><strong>Tel:</strong></td>
<td>&#43;590 690 44 15 30</td>
</tr>
<tr>
<td><strong>Voyageurs:</strong></td>
<td>2</td>
</tr>
<tr>
<td><strong>Plateforme:</strong></td>
<td>Privée</td>
</tr>
</tbody>
</table>
<table class="info-table">
<tbody>
<tr>
<td><strong>Nº de facture:</strong></td>
<td>VFNI0332</td>
</tr>
<tr>
<td><strong>Du:</strong></td>
<td>15 Janvier 2025</td>
</tr>
<tr>
<td><strong>Au:</strong></td>
<td>15 Mars 2025</td>
</tr>
<tr>
<td><strong>Montant Total:</strong></td>
<td>2065.00</td>
</tr>
</tbody>
</table>
</div>
<hr />
<div class="order-details">
<table class="items-table">
<thead>
<tr>
<th>Objet</th>
<th>Quantité</th>
<th>Prix</th>
<th class="align-right">Total</th>
</tr>
</thead>
<tbody class="bg-gray rounded">
<tr class="item-row">
<td class="text-break product_name">T2</td>
<td>59</td>
<td>35.00</td>
<td class="align-right">2065.00</td>
</tr>
</tbody>
</table>
</div>
<div class="payment-summary space-between">
<table class="summary-table">
<tbody>
<tr>
<td><strong>Montant Total:</strong></td>
<td>2065.00</td>
</tr>
<tr>
<td><strong>Montant Payé:</strong></td>
<td>1565.00</td>
</tr>
<tr>
<td><strong>Solde Restant:</strong></td>
<td>500.00</td>
</tr>
</tbody>
</table>
</div>
<div class="payment-history">
<h3>Historique des Paiements</h3>
<table class="history-table">
<thead>
<tr>
<th>Date</th>
<th>Mode de Paiement</th>
<th>Montant</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>Espèces</td>
<td>500.00</td>
</tr>
<tr>
<td></td>
<td>Cheque</td>
<td>1565.00</td>
</tr>
</tbody>
</table>
</div>
<hr />
<div class="order-summary space-between">
<div class="card">
<b>Notes</b> <br />
TVA non applicable, art. 293 B du CGI <br />
Dispensé dimmatriculation au registre du commerce et des sociétés (RCS)
et au répertoire des métiers. <br />
Conditions de paiement : paiement à réception de facture. Aucun escompte
consenti pour règlement anticipé ou désistement. Tout incident de
paiement est passible d'intérêts de retard. Le montant des pénalités
résulte de l'application aux sommes restant dues d'un taux d'intérêt
légal en vigueur au moment de l'incident. <br />
</div>
</div>
<div class="order-total space-between">
<div></div>
<div class="total">
<div class="amount-due">Total</div>
<div class="amount-due-total">2065.00</div>
</div>
</div>
</body>
</html>