rentease/internal/pdf/service.go
2024-03-03 12:15:45 +01:00

190 lines
4.5 KiB
Go

package pdf
import (
"bytes"
"encoding/json"
"errors"
"io"
"net/http"
"os"
"strconv"
"github.com/labstack/gommon/log"
"github.com/rjNemo/rentease/config"
"github.com/rjNemo/rentease/internal/booking"
u "github.com/rjNemo/underscore"
)
type PdfService struct {
invoicePath string
projectId string
url string
apiKey string
}
func NewPdfService() (*PdfService, error) {
pid := os.Getenv("HTMLDOCS_PROJECT_ID")
url := os.Getenv("HTMLDOCS_URL")
key := os.Getenv("HTMLDOCS_KEY")
if pid == "" || url == "" || key == "" {
return nil, errors.New("error building Pdf service. Verify your env variables")
}
return &PdfService{
invoicePath: "index.html",
projectId: pid,
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.invoicePath,
ProjectId: ps.projectId,
}
payload, err := json.Marshal(data)
if err != nil {
log.Warnf("Error marshalling JSON:", err)
return err
}
return ps.sendData(payload)
}
func (ps PdfService) BuildReport(r *booking.Report) error {
// data := struct {
// Context map[string]any `w`
// Path string `json:"path"`
// ProjectId string `json:"projectId"`
// }{
// Context: map[string]any{
// "id": r.InvoiceNumber(hc),
// "name": r.Name,
// "phone_number": r.PhoneNumber,
// "customers_number": r.CustomerNumber,
// "platform": r.Platform,
// "from": r.From.Format("02/01/2006"),
// "to": r.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.invoicePath,
// ProjectId: ps.projectId,
// }
// payload, err := json.Marshal(data)
// if err != nil {
// log.Warnf("Error marshalling JSON:", err)
// return err
// }
//
// return ps.sendData(payload)
return nil
}
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:", 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:", 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
}