mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-06 02:36:49 +00:00
update report template (#43)
This commit is contained in:
parent
b0198f7f9a
commit
44cf04bac7
8 changed files with 210 additions and 92 deletions
|
|
@ -1,68 +1,118 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="fr">
|
||||||
|
|
||||||
<head>
|
<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>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1>Bilan réservations</h1>
|
<div class="header">
|
||||||
<h2>{{month}} {{ year }}</h2>
|
Rapport Mensuel - {{ .Month }} {{ .Year }}
|
||||||
<div class="overflow-auto">
|
</div>
|
||||||
<table class="items-table">
|
|
||||||
<thead>
|
<div class="report-summary">
|
||||||
<tr>
|
<div class="summary-item">Revenu total : {{ .Total }} €</div>
|
||||||
<th scope="col">#</th>
|
<div class="summary-item">dont paiements par Carte Bancaire : {{ .CardTotal }} €</div>
|
||||||
<th scope="col">Nom</th>
|
<div class="summary-item">Frais Booking.com : {{ .BookingFees }} €</div>
|
||||||
<th scope="col">Du</th>
|
<div class="summary-item">Frais NemoImmo : {{ .Fee }} €</div>
|
||||||
<th scope="col">Au</th>
|
<div class="summary-item">Bénéfice : {{ .Profit }} €</div>
|
||||||
<th scope="col">Revenue (€)</th>
|
</div>
|
||||||
<th scope="col">Platforme</th>
|
|
||||||
<th scope="col">Commission (€)</th>
|
<table class="bookings-table">
|
||||||
<th scope="col">NemoImmo (€)</th>
|
<thead>
|
||||||
<th scope="col">Profit (€)</th>
|
<tr>
|
||||||
</tr>
|
<th>N° Facture</th>
|
||||||
</thead>
|
<th>Nom Client</th>
|
||||||
<tbody>
|
<th>Du</th>
|
||||||
{% for row in lines %}
|
<th>Au</th>
|
||||||
<tr>
|
<th>Revenu (€)</th>
|
||||||
<th scope="row"> {{ row.Id }} </th>
|
<th>Plateforme</th>
|
||||||
<td>{{ row.CustomerName }}</td>
|
<th>Frais Plateforme (€)</th>
|
||||||
<td>{{ row.From }}</td>
|
<th>Frais NemoImmo (€)</th>
|
||||||
<td>{{ row.To }}</td>
|
<th>Bénéfice (€)</th>
|
||||||
<td>{{ row.Total }}</td>
|
</tr>
|
||||||
<td>{{ row.Platform }}</td>
|
</thead>
|
||||||
<td>{{ row.PlatformFees }}</td>
|
<tbody>
|
||||||
<td>{{ row.Fee }}</td>
|
{{ range .Lines }}
|
||||||
<td>{{ row.Profit }}</td>
|
<tr>
|
||||||
</tr>
|
<td>{{ .InvoiceNumber }}</td>
|
||||||
{% endfor %}
|
<td>{{ .CustomerName }}</td>
|
||||||
</tbody>
|
<td>{{ .From }}</td>
|
||||||
<tfoot>
|
<td>{{ .To }}</td>
|
||||||
<tr>
|
<td>{{ .Total }}</td>
|
||||||
<td scope="row">Totaux</td>
|
<td>{{ .Platform }}</td>
|
||||||
<td></td>
|
<td>{{ .PlatformFees }}</td>
|
||||||
<td></td>
|
<td>{{ .Fee }}</td>
|
||||||
<td></td>
|
<td>{{ .Profit }}</td>
|
||||||
<td>{{ total }}</td>
|
</tr>
|
||||||
<td></td>
|
{{ end }}
|
||||||
<td>{{ platformFees }}</td>
|
</tbody>
|
||||||
<td>{{ fee }}</td>
|
<tfoot>
|
||||||
<td>{{ profit }}</td>
|
<tr class="total-row">
|
||||||
</tr>
|
<td colspan="4">Totaux</td>
|
||||||
<tr>
|
<td>{{ .Total }}</td>
|
||||||
<td scope="row"></td>
|
<td></td>
|
||||||
<td></td>
|
<td>{{ .PlatformFees }}</td>
|
||||||
<td></td>
|
<td>{{ .Fee }}</td>
|
||||||
<td>dont CB :</td>
|
<td>{{ .Profit }}</td>
|
||||||
<td>{{ cardTotal }}</td>
|
</tr>
|
||||||
<td>Frais Booking :</td>
|
</tfoot>
|
||||||
<td>{{ bookingFees }}</td>
|
</table>
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,4 @@ func (p Platform) ToFrench() string {
|
||||||
|
|
||||||
type Translatable interface {
|
type Translatable interface {
|
||||||
ToFrench() string
|
ToFrench() string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package constant
|
package constant
|
||||||
|
|
||||||
var Months = []string{
|
type Month string
|
||||||
|
|
||||||
|
var Months = []Month{
|
||||||
"January",
|
"January",
|
||||||
"February",
|
"February",
|
||||||
"March",
|
"March",
|
||||||
|
|
@ -14,3 +16,20 @@ var Months = []string{
|
||||||
"November",
|
"November",
|
||||||
"December",
|
"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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
|
@ -36,6 +37,23 @@ func (pc *HtmlPdfClient) BuildInvoice(data booking.Invoice) (string, error) {
|
||||||
return outputPath, nil
|
return outputPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pc *HtmlPdfClient) BuildReport(context map[string]any, period string, month int, year int) error {
|
func (pc *HtmlPdfClient) BuildReport(report booking.ReportData, period string, month int, year int) (string, error) {
|
||||||
panic("unimplemented")
|
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)
|
report := bs.Report(period, month, year)
|
||||||
err = bs.BuildReport(report, period, month, year)
|
filePath,err := bs.BuildReport(report, period, month, year)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
yearStr = time.Now().Format("2006")
|
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"
|
"time"
|
||||||
|
|
||||||
u "github.com/rjNemo/underscore"
|
u "github.com/rjNemo/underscore"
|
||||||
|
|
||||||
|
"github.com/rjNemo/rentease/internal/config"
|
||||||
|
"github.com/rjNemo/rentease/internal/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var hc = config.NewHost()
|
||||||
|
|
||||||
type Report struct {
|
type Report struct {
|
||||||
Lines []*Line
|
Lines []*Line
|
||||||
Total float64
|
Total float64
|
||||||
|
|
@ -18,27 +23,51 @@ type Report struct {
|
||||||
BookingFees float64
|
BookingFees float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Report) Serialize(month, year int) map[string]any {
|
type ReportData struct {
|
||||||
return map[string]any{
|
Month string
|
||||||
"month": month,
|
Year int
|
||||||
"year": year,
|
Total string
|
||||||
"total": strconv.FormatFloat(r.Total, 'f', 2, 64),
|
PlatformFees string
|
||||||
"platform_fees": strconv.FormatFloat(r.PlatformFees, 'f', 2, 64),
|
Fee string
|
||||||
"fee": strconv.FormatFloat(r.Fee, 'f', 2, 64),
|
Profit string
|
||||||
"profit": strconv.FormatFloat(r.Profit, 'f', 2, 64),
|
CardTotal string
|
||||||
"card_total": strconv.FormatFloat(r.CardTotal, 'f', 2, 64),
|
BookingFees string
|
||||||
"booking_fees": strconv.FormatFloat(r.BookingFees, 'f', 2, 64),
|
Lines []ReportLine
|
||||||
"lines": u.Map(r.Lines, func(l *Line) map[string]any {
|
}
|
||||||
return map[string]any{
|
|
||||||
"id": l.Id,
|
type ReportLine struct {
|
||||||
"name": l.CustomerName,
|
InvoiceNumber string
|
||||||
"from": l.From.Format("02/01/2006"),
|
CustomerName string
|
||||||
"to": l.To.Format("02/01/2006"),
|
From string
|
||||||
"total": strconv.FormatFloat(l.Total, 'f', 2, 64),
|
To string
|
||||||
"platform": l.Platform,
|
Total string
|
||||||
"platform_fees": strconv.FormatFloat(l.PlatformFees, 'f', 2, 64),
|
Platform string
|
||||||
"fee": strconv.FormatFloat(l.Fee(), 'f', 2, 64),
|
PlatformFees string
|
||||||
"profit": strconv.FormatFloat(l.Profit(), 'f', 2, 64),
|
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 {
|
func (bs Service) BuildReport(report *Report, period string, month, year int) (string, error) {
|
||||||
return bs.pdf.BuildReport(report.Serialize(month, year), period, month, year)
|
return bs.pdf.BuildReport(report.Data(month, year), period, month, year)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ type Store interface {
|
||||||
|
|
||||||
type PdfClient interface {
|
type PdfClient interface {
|
||||||
BuildInvoice(invoice Invoice) (string, error)
|
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 {
|
type CalendarClient interface {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue