mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-06 02:36:49 +00:00
191 lines
4.7 KiB
Go
191 lines
4.7 KiB
Go
package pdf
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/charmbracelet/log"
|
|
u "github.com/rjNemo/underscore"
|
|
|
|
"github.com/rjNemo/rentease/config"
|
|
"github.com/rjNemo/rentease/internal/booking"
|
|
)
|
|
|
|
type PdfService struct {
|
|
path string
|
|
invoiceId string
|
|
reportId string
|
|
url string
|
|
apiKey string
|
|
}
|
|
|
|
func NewPdfService(pid, rid, url, key string) (*PdfService, error) {
|
|
if pid == "" || rid == "" || url == "" || key == "" {
|
|
return nil, errors.New("error building Pdf service. Verify your env variables")
|
|
}
|
|
return &PdfService{
|
|
path: "index.html",
|
|
invoiceId: pid,
|
|
reportId: rid,
|
|
url: url,
|
|
apiKey: key,
|
|
}, nil
|
|
}
|
|
|
|
func (ps PdfService) BuildInvoice(b *booking.Booking, hc *config.Host) error {
|
|
data := struct {
|
|
Context map[string]any `json:"context"`
|
|
Path string `json:"path"`
|
|
ProjectId string `json:"projectId"`
|
|
}{
|
|
Context: map[string]any{
|
|
"host": map[string]any{
|
|
"name": hc.Name,
|
|
"address": hc.Address,
|
|
"zip": hc.ZipCode,
|
|
"city": hc.City,
|
|
"phone": hc.PhoneNumber,
|
|
"email": hc.Email,
|
|
},
|
|
"id": b.InvoiceNumber(hc),
|
|
"name": b.Name,
|
|
"phone_number": b.PhoneNumber,
|
|
"customers_number": b.CustomerNumber,
|
|
"platform": b.Platform,
|
|
"from": b.From.Format("02/01/2006"),
|
|
"to": b.To.Format("02/01/2006"),
|
|
"lines": u.Map(b.Items, func(i booking.Item) map[string]any {
|
|
return map[string]any{
|
|
"name": i.Item,
|
|
"quantity": i.Quantity,
|
|
"price": i.Price,
|
|
"total": i.Price * float64(i.Quantity),
|
|
}
|
|
}),
|
|
"total": strconv.FormatFloat(u.Reduce(b.Items, func(i booking.Item, sum float64) float64 {
|
|
return sum + i.Price*float64(i.Quantity)
|
|
}, 0.0), 'f', 2, 64),
|
|
},
|
|
Path: ps.path,
|
|
ProjectId: ps.invoiceId,
|
|
}
|
|
|
|
payload, err := json.Marshal(data)
|
|
if err != nil {
|
|
log.Warnf("Error marshalling JSON: %s", err)
|
|
return err
|
|
}
|
|
|
|
return ps.sendData(payload)
|
|
}
|
|
|
|
func (ps PdfService) BuildReport(r *booking.Report, period string, month, year int) error {
|
|
data := struct {
|
|
Context map[string]any `json:"context"`
|
|
Path string `json:"path"`
|
|
ProjectId string `json:"projectId"`
|
|
}{
|
|
Context: 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 *booking.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),
|
|
}
|
|
}),
|
|
},
|
|
Path: ps.path,
|
|
ProjectId: ps.reportId,
|
|
}
|
|
|
|
payload, err := json.Marshal(data)
|
|
if err != nil {
|
|
log.Warnf("Error marshalling JSON: %s", err)
|
|
return err
|
|
}
|
|
|
|
return ps.sendData(payload)
|
|
}
|
|
|
|
func (ps PdfService) sendData(payload []byte) error {
|
|
req, err := http.NewRequest("POST", ps.url, bytes.NewBuffer(payload))
|
|
if err != nil {
|
|
log.Warnf("Error creating request: %s", err)
|
|
return err
|
|
}
|
|
|
|
req.Header.Set("Authorization", "Bearer "+ps.apiKey)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
client := &http.Client{}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
log.Warnf("Error sending request: %s", err)
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
res := new(struct {
|
|
Url string `json:"url"`
|
|
Error string `json:"error"`
|
|
})
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = json.Unmarshal(body, res)
|
|
if err != nil {
|
|
log.Warnf("error decoding response: %s", err)
|
|
return err
|
|
}
|
|
|
|
if res.Error != "" {
|
|
log.Warnf("error building pdf file %s", err)
|
|
return errors.New(res.Error)
|
|
}
|
|
|
|
resp, err = http.Get(res.Url)
|
|
if err != nil {
|
|
log.Warnf("Error retrieving file")
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
file, err := os.Create("tmp.pdf")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer file.Close()
|
|
|
|
body, err = io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = file.Write(body)
|
|
if err != nil {
|
|
log.Error("Error copying file content")
|
|
return err
|
|
}
|
|
return nil
|
|
}
|