mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-06 02:36:49 +00:00
update report template
This commit is contained in:
parent
b0198f7f9a
commit
40edb8c6f0
8 changed files with 210 additions and 92 deletions
|
|
@ -1,68 +1,118 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="fr">
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="main.css">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f9f9f9;
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: #007b8f;
|
||||
color: white;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.report-summary {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
background-color: #eef7f9;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.bookings-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.bookings-table th, .bookings-table td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.bookings-table th {
|
||||
background-color: #007b8f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.total-row {
|
||||
font-weight: bold;
|
||||
background-color: #eef7f9;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Bilan réservations</h1>
|
||||
<h2>{{month}} {{ year }}</h2>
|
||||
<div class="overflow-auto">
|
||||
<table class="items-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Nom</th>
|
||||
<th scope="col">Du</th>
|
||||
<th scope="col">Au</th>
|
||||
<th scope="col">Revenue (€)</th>
|
||||
<th scope="col">Platforme</th>
|
||||
<th scope="col">Commission (€)</th>
|
||||
<th scope="col">NemoImmo (€)</th>
|
||||
<th scope="col">Profit (€)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in lines %}
|
||||
<tr>
|
||||
<th scope="row"> {{ row.Id }} </th>
|
||||
<td>{{ row.CustomerName }}</td>
|
||||
<td>{{ row.From }}</td>
|
||||
<td>{{ row.To }}</td>
|
||||
<td>{{ row.Total }}</td>
|
||||
<td>{{ row.Platform }}</td>
|
||||
<td>{{ row.PlatformFees }}</td>
|
||||
<td>{{ row.Fee }}</td>
|
||||
<td>{{ row.Profit }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td scope="row">Totaux</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>{{ total }}</td>
|
||||
<td></td>
|
||||
<td>{{ platformFees }}</td>
|
||||
<td>{{ fee }}</td>
|
||||
<td>{{ profit }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td scope="row"></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>dont CB :</td>
|
||||
<td>{{ cardTotal }}</td>
|
||||
<td>Frais Booking :</td>
|
||||
<td>{{ bookingFees }}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<body>
|
||||
<div class="header">
|
||||
Rapport Mensuel - {{ .Month }} {{ .Year }}
|
||||
</div>
|
||||
|
||||
<div class="report-summary">
|
||||
<div class="summary-item">Revenu total : {{ .Total }} €</div>
|
||||
<div class="summary-item">dont paiements par Carte Bancaire : {{ .CardTotal }} €</div>
|
||||
<div class="summary-item">Frais Booking.com : {{ .BookingFees }} €</div>
|
||||
<div class="summary-item">Frais NemoImmo : {{ .Fee }} €</div>
|
||||
<div class="summary-item">Bénéfice : {{ .Profit }} €</div>
|
||||
</div>
|
||||
|
||||
<table class="bookings-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>N° Facture</th>
|
||||
<th>Nom Client</th>
|
||||
<th>Du</th>
|
||||
<th>Au</th>
|
||||
<th>Revenu (€)</th>
|
||||
<th>Plateforme</th>
|
||||
<th>Frais Plateforme (€)</th>
|
||||
<th>Frais NemoImmo (€)</th>
|
||||
<th>Bénéfice (€)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range .Lines }}
|
||||
<tr>
|
||||
<td>{{ .InvoiceNumber }}</td>
|
||||
<td>{{ .CustomerName }}</td>
|
||||
<td>{{ .From }}</td>
|
||||
<td>{{ .To }}</td>
|
||||
<td>{{ .Total }}</td>
|
||||
<td>{{ .Platform }}</td>
|
||||
<td>{{ .PlatformFees }}</td>
|
||||
<td>{{ .Fee }}</td>
|
||||
<td>{{ .Profit }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="total-row">
|
||||
<td colspan="4">Totaux</td>
|
||||
<td>{{ .Total }}</td>
|
||||
<td></td>
|
||||
<td>{{ .PlatformFees }}</td>
|
||||
<td>{{ .Fee }}</td>
|
||||
<td>{{ .Profit }}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -13,4 +13,4 @@ func (p Platform) ToFrench() string {
|
|||
|
||||
type Translatable interface {
|
||||
ToFrench() string
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package constant
|
||||
|
||||
var Months = []string{
|
||||
type Month string
|
||||
|
||||
var Months = []Month{
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
|
|
@ -14,3 +16,20 @@ var Months = []string{
|
|||
"November",
|
||||
"December",
|
||||
}
|
||||
|
||||
func (m Month) ToFrench() string {
|
||||
return map[Month]string{
|
||||
"January": "Janvier",
|
||||
"February": "Février",
|
||||
"March": "Mars",
|
||||
"April": "Avril",
|
||||
"May": "Mai",
|
||||
"June": "Juin",
|
||||
"July": "Juillet",
|
||||
"August": "Août",
|
||||
"September": "Septembre",
|
||||
"October": "Octobre",
|
||||
"November": "Novembre",
|
||||
"December": "Décembre",
|
||||
}[m]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package pdf
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
|
|
@ -36,6 +37,23 @@ func (pc *HtmlPdfClient) BuildInvoice(data booking.Invoice) (string, error) {
|
|||
return outputPath, nil
|
||||
}
|
||||
|
||||
func (pc *HtmlPdfClient) BuildReport(context map[string]any, period string, month int, year int) error {
|
||||
panic("unimplemented")
|
||||
func (pc *HtmlPdfClient) BuildReport(report booking.ReportData, period string, month int, year int) (string, error) {
|
||||
tmpl, err := template.ParseFS(assets.Static, "assets/html/report.html")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error parsing template: %v", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tmpl.Execute(&buf, report); err != nil {
|
||||
log.Printf("err: %+v\n", err)
|
||||
return "", fmt.Errorf("error executing template: %v", err)
|
||||
}
|
||||
|
||||
outputPath := fmt.Sprintf("report-%s-%d-%d.html", period, month, year)
|
||||
if err := os.WriteFile(outputPath, buf.Bytes(), 0644); err != nil {
|
||||
log.Printf("err: %+v\n", err)
|
||||
return "", fmt.Errorf("error writing HTML file: %v", err)
|
||||
}
|
||||
|
||||
return outputPath, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,11 +62,11 @@ func handlePdfCreateReport(bs *booking.Service) echo.HandlerFunc {
|
|||
}
|
||||
|
||||
report := bs.Report(period, month, year)
|
||||
err = bs.BuildReport(report, period, month, year)
|
||||
filePath,err := bs.BuildReport(report, period, month, year)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Attachment("tmp.pdf", fmt.Sprintf("VF-%02d-report.pdf", month))
|
||||
return c.File(filePath)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ func handleReportsPage() echo.HandlerFunc {
|
|||
if err != nil {
|
||||
yearStr = time.Now().Format("2006")
|
||||
}
|
||||
return renderTempl(c, http.StatusOK, view.Reports(constant.Months, month, yearStr))
|
||||
return renderTempl(c, http.StatusOK, view.Reports(u.Map(constant.Months, func(m constant.Month) string {
|
||||
return string(m)
|
||||
}), month, yearStr))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,13 @@ import (
|
|||
"time"
|
||||
|
||||
u "github.com/rjNemo/underscore"
|
||||
|
||||
"github.com/rjNemo/rentease/internal/config"
|
||||
"github.com/rjNemo/rentease/internal/constant"
|
||||
)
|
||||
|
||||
var hc = config.NewHost()
|
||||
|
||||
type Report struct {
|
||||
Lines []*Line
|
||||
Total float64
|
||||
|
|
@ -18,27 +23,51 @@ type Report struct {
|
|||
BookingFees float64
|
||||
}
|
||||
|
||||
func (r Report) Serialize(month, year int) map[string]any {
|
||||
return map[string]any{
|
||||
"month": month,
|
||||
"year": year,
|
||||
"total": strconv.FormatFloat(r.Total, 'f', 2, 64),
|
||||
"platform_fees": strconv.FormatFloat(r.PlatformFees, 'f', 2, 64),
|
||||
"fee": strconv.FormatFloat(r.Fee, 'f', 2, 64),
|
||||
"profit": strconv.FormatFloat(r.Profit, 'f', 2, 64),
|
||||
"card_total": strconv.FormatFloat(r.CardTotal, 'f', 2, 64),
|
||||
"booking_fees": strconv.FormatFloat(r.BookingFees, 'f', 2, 64),
|
||||
"lines": u.Map(r.Lines, func(l *Line) map[string]any {
|
||||
return map[string]any{
|
||||
"id": l.Id,
|
||||
"name": l.CustomerName,
|
||||
"from": l.From.Format("02/01/2006"),
|
||||
"to": l.To.Format("02/01/2006"),
|
||||
"total": strconv.FormatFloat(l.Total, 'f', 2, 64),
|
||||
"platform": l.Platform,
|
||||
"platform_fees": strconv.FormatFloat(l.PlatformFees, 'f', 2, 64),
|
||||
"fee": strconv.FormatFloat(l.Fee(), 'f', 2, 64),
|
||||
"profit": strconv.FormatFloat(l.Profit(), 'f', 2, 64),
|
||||
type ReportData struct {
|
||||
Month string
|
||||
Year int
|
||||
Total string
|
||||
PlatformFees string
|
||||
Fee string
|
||||
Profit string
|
||||
CardTotal string
|
||||
BookingFees string
|
||||
Lines []ReportLine
|
||||
}
|
||||
|
||||
type ReportLine struct {
|
||||
InvoiceNumber string
|
||||
CustomerName string
|
||||
From string
|
||||
To string
|
||||
Total string
|
||||
Platform string
|
||||
PlatformFees string
|
||||
Fee string
|
||||
Profit string
|
||||
}
|
||||
|
||||
func (r Report) Data(month, year int) ReportData {
|
||||
return ReportData{
|
||||
Month: constant.Months[month-1].ToFrench(),
|
||||
Year: year,
|
||||
Total: strconv.FormatFloat(r.Total, 'f', 2, 64),
|
||||
PlatformFees: strconv.FormatFloat(r.PlatformFees, 'f', 2, 64),
|
||||
Fee: strconv.FormatFloat(r.Fee, 'f', 2, 64),
|
||||
Profit: strconv.FormatFloat(r.Profit, 'f', 2, 64),
|
||||
CardTotal: strconv.FormatFloat(r.CardTotal, 'f', 2, 64),
|
||||
BookingFees: strconv.FormatFloat(r.BookingFees, 'f', 2, 64),
|
||||
Lines: u.Map(r.Lines, func(l *Line) ReportLine {
|
||||
return ReportLine{
|
||||
InvoiceNumber: l.InvoiceNumber(hc),
|
||||
CustomerName: l.CustomerName,
|
||||
From: l.From.Format("02/01/2006"),
|
||||
To: l.To.Format("02/01/2006"),
|
||||
Total: strconv.FormatFloat(l.Total, 'f', 2, 64),
|
||||
Platform: l.Platform,
|
||||
PlatformFees: strconv.FormatFloat(l.PlatformFees, 'f', 2, 64),
|
||||
Fee: strconv.FormatFloat(l.Fee(), 'f', 2, 64),
|
||||
Profit: strconv.FormatFloat(l.Profit(), 'f', 2, 64),
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
|
@ -82,6 +111,6 @@ func (bs Service) Report(period string, month, year int) *Report {
|
|||
}
|
||||
}
|
||||
|
||||
func (bs Service) BuildReport(report *Report, period string, month, year int) error {
|
||||
return bs.pdf.BuildReport(report.Serialize(month, year), period, month, year)
|
||||
func (bs Service) BuildReport(report *Report, period string, month, year int) (string, error) {
|
||||
return bs.pdf.BuildReport(report.Data(month, year), period, month, year)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ type Store interface {
|
|||
|
||||
type PdfClient interface {
|
||||
BuildInvoice(invoice Invoice) (string, error)
|
||||
BuildReport(context map[string]any, period string, month, year int) error
|
||||
BuildReport(report ReportData, period string, month, year int) (string, error)
|
||||
}
|
||||
|
||||
type CalendarClient interface {
|
||||
|
|
|
|||
Loading…
Reference in a new issue