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 }