diff --git a/.gitignore b/.gitignore index 770d796..9455f0a 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ tmp.pdf *.env *templ.txt token.json -.aider* \ No newline at end of file +.aider* +output.html \ No newline at end of file diff --git a/assets/html/invoice.html b/assets/html/invoice.html index 8c1eead..744913c 100644 --- a/assets/html/invoice.html +++ b/assets/html/invoice.html @@ -1,115 +1,288 @@ - - + + + + + + + +
+ +
+ {{ .Host.Name }}
+ {{ .Host.Address }}
+ {{ .Host.ZipCode }} {{ .Host.City }}
+ Tel : {{ .Host.Phone }}
+ Mail : {{ .Host.Email }}
-
-
- + +
+
+
- - - - - - - - - - - - - - - + + + + + + + + + + + + + + + -
- {{name}}
- Tel : {{phone_number}}
- Voyageurs : {{ customers_number }}
- Plateforme : {{platform}}
{{ .Name }}
Tel :{{ .PhoneNumber }}
Client :{{ .CustomersNumber }}
Plateforme :{{ .Platform }}
- +
+ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + -
- Nº de facture : {{id}}
- Du : {{ from }}
- Au : {{ to }}
- Montant : {{ total }}
Nº de facture :{{ .ID }}
Du :{{ .From }}
Au :{{ .To }}
Montant Total :{{ .Total }}
-
-
-
- +
+
+
+
+ - + - - - + + + - {% for row in lines %} - - - - - - - {% endfor %} + {{ range .Lines }} + + + + + + + {{ end }} -
Objet QuantitéPrixTotal
Prix (€)Total (€)
- {{ row.name }} - {{ row.quantity }}{{row.price }}{{ row.total }}
{{ .Name }}{{ .Quantity }}{{ .Price }}{{ .Total }}
-
-
-
+ +
+ +
+

Historique des Paiements

+ + + + + + + + + + {{ range .Payments }} + + + + + + {{ end }} + +
DateMode de PaiementMontant (€)
{{ .Date }}{{ .Method }}{{ .Amount }}
+
+ +
+ + + + + + + + + + + + + + + +
Montant Total :{{ .Total }}
Montant Payé :{{ .AmountPaid }}
Solde Restant :{{ .BalanceDue }}
+
+
+
+
Notes
TVA non applicable, art. 293 B du CGI
- Dispensé d’immatriculation au registre du commerce et des sociétés (RCS) et au répertoire des métiers.
- Conditions de paiement : paiement à réception de facture. Aucun escompte consenti pour règlement anticipé ou désistement. Tout incident de paiement est passible d'intérêts de retard. Le montant des pénalités résulte de l'application aux sommes restant dues d'un taux d'intérêt légal en vigueur au moment de l'incident.
-
+ Dispensé d’immatriculation au registre du commerce et des sociétés (RCS) + et au répertoire des métiers.
+ Conditions de paiement : paiement à réception de facture. Aucun escompte + consenti pour règlement anticipé ou désistement. Tout incident de + paiement est passible d'intérêts de retard. Le montant des pénalités + résulte de l'application aux sommes restant dues d'un taux d'intérêt + légal en vigueur au moment de l'incident.
-
-
-
-
- Total -
-
- {{ total }} -
-
+
+
+
+
+
Total
+
{{ .Total }}
- +
+ diff --git a/cmd/pdf/main.go b/cmd/pdf/main.go new file mode 100644 index 0000000..75e5a61 --- /dev/null +++ b/cmd/pdf/main.go @@ -0,0 +1,124 @@ +package main + +import ( + "bytes" + "html/template" + "log" + "os" +) + +const invoiceTemplate = "assets/html/invoice.html" + +func main() { + // Define the invoice data structure + type Invoice struct { + Host struct { + Name string + Address string + ZipCode string + City string + Phone string + Email string + } + Name string + PhoneNumber string + CustomersNumber int + Platform string + ID string + From string + To string + Total string + AmountPaid string + BalanceDue string + Lines []struct { + Name string + Quantity int + Price string + Total string + } + Payments []struct { + Date string + Method string + Amount string + } + } + + // Read the template file + tmpl, err := template.ParseFiles(invoiceTemplate) + if err != nil { + log.Fatalf("Error parsing template: %v", err) + } + + // Create sample invoice data + invoice := Invoice{ + Host: struct { + Name string + Address string + ZipCode string + City string + Phone string + Email string + }{ + Name: "VillaFleurie", + Address: "4 rue Gerty Archimede", + ZipCode: "97190", + City: "Le Gosier", + Phone: "+590 690 44 15 30", + Email: "location.villafleurie@gmail.com", + }, + Name: "Michel Le Corre", + //PhoneNumber: "+590 690 44 15 30", + CustomersNumber: 2, + Platform: "Privée", + ID: "VFNI0332", + From: "15 Janvier 2025", + To: "15 Mars 2025", + Total: "2065.00 €", + AmountPaid: "1565.00 €", + BalanceDue: "500.00 €", + Lines: []struct { + Name string + Quantity int + Price string + Total string + }{ + { + Name: "T2", + Quantity: 59, + Price: "35.00", + Total: "2065.00", + }, + }, + Payments: []struct { + Date string + Method string + Amount string + }{ + { + "–", + "Espèces", + "500.00", + }, + { + "–", + "Chèque", + "1065.00", + }, + }, + } + + // Create a buffer to store the rendered HTML + var buf bytes.Buffer + // Execute the template with the invoice data + if err := tmpl.Execute(&buf, invoice); err != nil { + log.Fatalf("Error executing template: %v", err) + } + + // Write the rendered HTML to a file + outputPath := "output.html" + if err := os.WriteFile(outputPath, buf.Bytes(), 0644); err != nil { + log.Fatalf("Error writing HTML file: %v", err) + } + + log.Printf("HTML file created successfully: %s", outputPath) +} diff --git a/internal/constant/routes.go b/internal/constant/routes.go index 1e04076..4165fe2 100644 --- a/internal/constant/routes.go +++ b/internal/constant/routes.go @@ -5,4 +5,5 @@ const ( RouteBooking = "/bookings" RouteReports = "/reports" RouteItem = "/items" + RoutePayment = "/payments" ) diff --git a/internal/driver/calendar/service.go b/internal/driver/calendar/service.go index ea35f26..9a24c0f 100644 --- a/internal/driver/calendar/service.go +++ b/internal/driver/calendar/service.go @@ -16,10 +16,6 @@ import ( "google.golang.org/api/option" ) -type Client interface { - Create(calendarId, name, description string, from, to time.Time) error -} - type GoogleClient struct { calIds map[string]struct{} *calendar.Service diff --git a/internal/driver/pdf/service.go b/internal/driver/pdf/service.go index bf7163e..b24a230 100644 --- a/internal/driver/pdf/service.go +++ b/internal/driver/pdf/service.go @@ -11,11 +11,6 @@ import ( "github.com/labstack/gommon/log" ) -type Client interface { - BuildInvoice(context map[string]any) error - BuildReport(context map[string]any, period string, month, year int) error -} - type PdfClient struct { path string invoiceId string diff --git a/internal/repository/booking/pg_store.go b/internal/repository/booking/pg_store.go index bec8417..6e57c98 100644 --- a/internal/repository/booking/pg_store.go +++ b/internal/repository/booking/pg_store.go @@ -82,7 +82,7 @@ func (ps *PgStore) CardTotal(from, to time.Time) (float64, error) { func (ps *PgStore) Get(id int) *booking.Booking { var b booking.Booking - ps.db.Preload("Items").First(&b, id) + ps.db.Preload("Items").Preload("Payments").First(&b, id) return &b } @@ -136,3 +136,29 @@ func (ps *PgStore) UpdateItem(id int, item string, paymentMethod string, payment Error return i, err } + +func (ps *PgStore) CreatePayment(p *booking.Payment) (*booking.Payment, error) { + if err := ps.db.Create(p).Error; err != nil { + return nil, fmt.Errorf("failed to create payment: %w", err) + } + return p, nil +} + +func (ps *PgStore) GetPayment(id int) (*booking.Payment, error) { + p := &booking.Payment{} + err := ps.db.First(p, id).Error + return p, err +} + +func (ps *PgStore) UpdatePayment(id int, amount float64, paymentMethod string) (*booking.Payment, error) { + p := new(booking.Payment) + err := ps.db.Model(p). + Clauses(clause.Returning{}). + Where("id = ?", id). + Updates(map[string]any{ + "amount": amount, + "payment_method": paymentMethod, + }). + Error + return p, err +} diff --git a/internal/server/handle_bookings.go b/internal/server/handle_bookings.go index 541bf11..e62da8f 100644 --- a/internal/server/handle_bookings.go +++ b/internal/server/handle_bookings.go @@ -52,6 +52,21 @@ func handleBookingListPage(bs *booking.Service, hc *config.Host) echo.HandlerFun } } +func handleBookingList(bs *booking.Service) echo.HandlerFunc { + return func(c echo.Context) error { + search := c.FormValue("search") + + var bookings []*booking.Line + if search != "" { + bookings = bs.Search(search) + } else { + bookings = bs.All() + } + + return c.JSON(http.StatusOK, bookings) + } +} + func handleBookingCreatePage(hc *config.Host) echo.HandlerFunc { return func(c echo.Context) error { return renderTempl(c, http.StatusOK, view.NewBooking(hc.Platforms)) @@ -122,18 +137,27 @@ func handleBookingPage(bs *booking.Service, hc *config.Host) echo.HandlerFunc { Url: templ.EscapeString(fmt.Sprintf("%s/%d", constant.RouteBooking, b.Id)), PdfUrl: templ.SafeURL(fmt.Sprintf("%s/pdf/%d", constant.RouteBooking, b.Id)), CancelUrl: fmt.Sprintf("%s/%d/cancel", constant.RouteBooking, b.Id), - Items: u.Map(b.Items, func(i booking.Item) view.ItemViewModel { - return view.ItemViewModel{ - Id: strconv.Itoa(i.Id), - Item: i.Item, - Quantity: strconv.Itoa(i.Quantity), - Price: strconv.FormatFloat(i.Price, 'f', 2, 64), - SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), - PaymentMethod: i.PaymentMethod, - PaymentStatus: i.PaymentStatus, - ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), - } - }), + PaymentUrl: fmt.Sprintf("%s/%d", constant.RoutePayment, b.Id), + Items: view.ItemListViewModel{ + Items: u.Map(b.Items, func(i booking.Item) view.ItemViewModel { + return view.ItemViewModel{ + Id: strconv.Itoa(i.Id), + Item: i.Item, + Quantity: strconv.Itoa(i.Quantity), + Price: strconv.FormatFloat(i.Price, 'f', 2, 64), + SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), + PaymentStatus: i.PaymentStatus, + ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), + } + }), + Payments: u.Map(b.Payments, func(p booking.Payment) view.PaymentViewModel { + return view.PaymentViewModel{ + Amount: strconv.FormatFloat(p.Amount, 'f', 2, 64), + PaymentMethod: p.PaymentMethod, + PaymentUrl: fmt.Sprintf("%s/%d", constant.RoutePayment, p.ID), + } + }), + }, 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), @@ -219,7 +243,6 @@ func handleLineItemForm(bs *booking.Service) echo.HandlerFunc { Item: i.Item, Quantity: strconv.Itoa(i.Quantity), Price: strconv.FormatFloat(i.Price, 'f', 2, 64), - PaymentMethod: i.PaymentMethod, PaymentStatus: i.PaymentStatus, SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), @@ -275,7 +298,6 @@ func handleCreateItem(bs *booking.Service, hc *config.Host) echo.HandlerFunc { Item: i.Item, Quantity: strconv.Itoa(i.Quantity), Price: strconv.FormatFloat(i.Price, 'f', 2, 64), - PaymentMethod: i.PaymentMethod, PaymentStatus: i.PaymentStatus, SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), @@ -300,7 +322,6 @@ func handleItemPay(bs *booking.Service) echo.HandlerFunc { Item: i.Item, Quantity: strconv.Itoa(i.Quantity), Price: strconv.FormatFloat(i.Price, 'f', 2, 64), - PaymentMethod: i.PaymentMethod, PaymentStatus: i.PaymentStatus, SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), @@ -332,7 +353,6 @@ func handleItemUpdate(bs *booking.Service) echo.HandlerFunc { Item: i.Item, Quantity: strconv.Itoa(i.Quantity), Price: strconv.FormatFloat(i.Price, 'f', 2, 64), - PaymentMethod: i.PaymentMethod, PaymentStatus: i.PaymentStatus, SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), @@ -340,6 +360,29 @@ func handleItemUpdate(bs *booking.Service) echo.HandlerFunc { } } +func handlePaymentUpdate(bs *booking.Service) echo.HandlerFunc { + type updatePayment struct { + Id int `param:"id"` + Amount float64 `form:"amount"` + PaymentMethod string `form:"paymentMethod"` + } + return func(c echo.Context) error { + up := new(updatePayment) + + if err := c.Bind(up); err != nil { + return fmt.Errorf("could not parse update payment request body: %w", err) + } + + p := bs.UpdatePayment(up.Id, up.Amount, up.PaymentMethod) + + return renderTempl(c, http.StatusOK, view.PaymentLine(&view.PaymentViewModel{ + Amount: strconv.FormatFloat(p.Amount, 'f', 2, 64), + PaymentMethod: p.PaymentMethod, + PaymentUrl: fmt.Sprintf("%s/%d", constant.RoutePayment, p.ID), + })) + } +} + func handleBookingCancel(bs *booking.Service) echo.HandlerFunc { return func(c echo.Context) error { idStr := c.Param("id") diff --git a/internal/server/handle_payments.go b/internal/server/handle_payments.go new file mode 100644 index 0000000..e234ab8 --- /dev/null +++ b/internal/server/handle_payments.go @@ -0,0 +1,80 @@ +package server + +import ( + "fmt" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + u "github.com/rjNemo/underscore" + + "github.com/rjNemo/rentease/internal/constant" + "github.com/rjNemo/rentease/internal/service/booking" + "github.com/rjNemo/rentease/internal/view" +) + +func handleCreatePayment(bs *booking.Service) echo.HandlerFunc { + type CreatePaymentInput struct { + Amount float64 `form:"amount"` + PaymentMethod string `form:"paymentMethod"` + } + + return func(c echo.Context) error { + idStr := c.Param("id") + id, err := strconv.Atoi(idStr) + if err != nil { + return err + } + + np := new(CreatePaymentInput) + c.Bind(np) + + b := bs.One(id) + + _, err = bs.CreatePayment(b.Id, np.Amount, np.PaymentMethod) + if err != nil { + return err + } + + nb := bs.One(id) + + return renderTempl(c, http.StatusOK, view.ItemList(view.ItemListViewModel{ + Items: u.Map(nb.Items, func(i booking.Item) view.ItemViewModel { + return view.ItemViewModel{ + Id: strconv.Itoa(i.Id), + Item: i.Item, + Quantity: strconv.Itoa(i.Quantity), + Price: strconv.FormatFloat(i.Price, 'f', 2, 64), + SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), + PaymentStatus: i.PaymentStatus, + ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), + } + }), + Payments: u.Map(nb.Payments, func(p booking.Payment) view.PaymentViewModel { + return view.PaymentViewModel{ + Amount: strconv.FormatFloat(p.Amount, 'f', 2, 64), + PaymentMethod: p.PaymentMethod, + PaymentUrl: fmt.Sprintf("%s/%d", constant.RoutePayment, p.ID), + } + }), + })) + } +} + +func handlePaymentForm(bs *booking.Service) echo.HandlerFunc { + return func(c echo.Context) error { + idStr := c.Param("id") + id, err := strconv.Atoi(idStr) + if err != nil { + return err + } + + p := bs.OnePayment(id) + form := view.PaymentForm(&view.PaymentViewModel{ + Amount: strconv.FormatFloat(p.Amount, 'f', 2, 64), + PaymentMethod: p.PaymentMethod, + PaymentUrl: fmt.Sprintf("%s/%d", constant.RoutePayment, p.ID), + }) + return renderTempl(c, http.StatusOK, form) + } +} diff --git a/internal/server/routes.go b/internal/server/routes.go index b55f5a2..9dc56aa 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -18,9 +18,11 @@ func (s Server) MountHandlers() { }, })) api.POST("/sync", handleSync(s.bs)) + api.GET("/bookings", handleBookingList(s.bs)) private := s.Router.Group("") private.Use(MakeAuthMiddleware(s.as)) + private.GET("/bookings", handleBookingListPage(s.bs, s.hc)) private.GET("/bookings/new", handleBookingCreatePage(s.hc)) private.POST("/bookings/new", handleBookingCreate(s.bs)) @@ -29,10 +31,16 @@ func (s Server) MountHandlers() { private.PATCH("/bookings/:id/cancel", handleBookingCancel(s.bs)) private.POST("/bookings/:id/items", handleCreateItem(s.bs, s.hc)) private.GET("/bookings/pdf/:id", handlePdfCreateInvoice(s.bs, s.hc)) + private.POST("/items/:id", handleItemPay(s.bs)) private.PUT("/items/:id", handleItemUpdate(s.bs)) private.GET("/items/:id", handleLineItemForm(s.bs)) + private.GET("/reports", handleReportsPage()) private.GET("/reports/do", handleReportCompute(s.bs, s.hc)) private.GET("/reports/pdf", handlePdfCreateReport(s.bs)) + + private.POST("/payments/:id", handleCreatePayment(s.bs)) + private.PUT("/payments/:id", handlePaymentUpdate(s.bs)) + private.GET("/payments/:id", handlePaymentForm(s.bs)) } diff --git a/internal/service/booking/mocks_test.go b/internal/service/booking/mocks_test.go index 279eacb..dc16ac8 100644 --- a/internal/service/booking/mocks_test.go +++ b/internal/service/booking/mocks_test.go @@ -71,6 +71,26 @@ func (m *MockStore) UpdateItem(id int, item string, paymentMethod string, paymen return args.Get(0).(*Item), args.Error(1) } +func (m *MockStore) CreatePayment(p *Payment) (*Payment, error) { + args := m.Called(p) + return args.Get(0).(*Payment), args.Error(1) +} + +func (m *MockStore) GetPayment(id int) (*Payment, error) { + args := m.Called(id) + return args.Get(0).(*Payment), args.Error(1) +} + +func (m *MockStore) UpdatePayment(id int, amount float64, paymentMethod string) (*Payment, error) { + args := m.Called(id, amount, paymentMethod) + return args.Get(0).(*Payment), args.Error(1) +} + +// MockParserClient is a mock implementation of the parser.Client interface +type MockParserClient struct { + mock.Mock +} + // MockCalendarClient is a mock implementation of the calendar.Client interface type MockCalendarClient struct { mock.Mock diff --git a/internal/service/booking/models.go b/internal/service/booking/models.go index 77743ca..88a68c4 100644 --- a/internal/service/booking/models.go +++ b/internal/service/booking/models.go @@ -21,6 +21,7 @@ type Booking struct { Platform string ExternalId *string `gorm:"uniqueIndex:booking_external_id"` Items []Item + Payments []Payment `gorm:"foreignKey:BookingID"` Id int CustomerNumber int `gorm:"column:customers"` PlatformFees float64 `gorm:"type:decimal(10,2)"` @@ -29,7 +30,8 @@ type Booking struct { // NewBooking creates a new booking with the given parameters func NewBooking(from, to time.Time, name, phoneNumber, email, platform string, - customerNumber int, platformFees float64, externalId *string) *Booking { + customerNumber int, platformFees float64, externalId *string, +) *Booking { return &Booking{ From: from, To: to, diff --git a/internal/service/booking/payment.go b/internal/service/booking/payment.go new file mode 100644 index 0000000..4c945f8 --- /dev/null +++ b/internal/service/booking/payment.go @@ -0,0 +1,23 @@ +package booking + +import ( + "log" + + "gorm.io/gorm" +) + +type Payment struct { + gorm.Model + BookingID uint `gorm:"not null;index"` + Booking Booking `gorm:"foreignKey:BookingID;constraint:OnDelete:CASCADE"` + Amount float64 + PaymentMethod string +} + +func (bs Service) OnePayment(id int) *Payment { + p, err := bs.store.GetPayment(id) + if err != nil { + log.Println(err) + } + return p +} diff --git a/internal/service/booking/service.go b/internal/service/booking/service.go index de41534..0b39776 100644 --- a/internal/service/booking/service.go +++ b/internal/service/booking/service.go @@ -5,8 +5,6 @@ import ( "time" "github.com/rjNemo/rentease/internal/config" - "github.com/rjNemo/rentease/internal/driver/calendar" - "github.com/rjNemo/rentease/internal/driver/pdf" ) type Store interface { @@ -24,6 +22,20 @@ type Store interface { PayItem(id int) (*Item, error) GetItem(id int) (*Item, error) UpdateItem(id int, item string, paymentMethod string, paymentStatus string, qty int, price float64) (*Item, error) + + // Payment methods + CreatePayment(p *Payment) (*Payment, error) + GetPayment(id int) (*Payment, error) + UpdatePayment(id int, amount float64, paymentMethod string) (*Payment, error) +} + +type PdfClient interface { + BuildInvoice(context map[string]any) error + BuildReport(context map[string]any, period string, month, year int) error +} + +type CalendarClient interface { + Create(calendarId, name, description string, from, to time.Time) error } type parserClient interface { @@ -33,11 +45,11 @@ type parserClient interface { type Service struct { store Store parser parserClient - calendar calendar.Client - pdf pdf.Client + calendar CalendarClient + pdf PdfClient } -func NewService(store Store, parser parserClient, calendar calendar.Client, pdf pdf.Client) (*Service, error) { +func NewService(store Store, parser parserClient, calendar CalendarClient, pdf PdfClient) (*Service, error) { return &Service{ store: store, parser: parser, @@ -91,3 +103,24 @@ func (bs Service) Cancel(id int) { func (bs Service) BuildInvoice(b *Booking, hc *config.Host) error { return bs.pdf.BuildInvoice(b.Serialize(hc)) } + +func (bs Service) CreatePayment(bid int, amount float64, paymentMethod string) (*Payment, error) { + p, err := bs.store.CreatePayment(&Payment{ + BookingID: uint(bid), + Amount: amount, + PaymentMethod: paymentMethod, + }) + if err != nil { + return nil, err + } + + return p, nil +} + +func (bs Service) UpdatePayment(id int, amount float64, paymentMethod string) *Payment { + p, err := bs.store.UpdatePayment(id, amount, paymentMethod) + if err != nil { + log.Println(err) + } + return p +} diff --git a/internal/service/booking/sync_test.go b/internal/service/booking/sync_test.go deleted file mode 100644 index 8d549a5..0000000 --- a/internal/service/booking/sync_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package booking_test - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/rjNemo/rentease/internal/service/booking" -) - -const content = " Date d'arrivée jeu. 3 avr. 2025 Date de départ dim. 6 avr. 2025 Durée de séjour : 3 nuits Nombre de personnes : \n 2\n Nombre d'hébergements \n 1\n Montant total € 186 Nom du client : \n Olga Korovina\n \n ru\n \n okorov.905387@guest.booking.com\n Contactez vos clients ! Indiquez-leur l'heure à laquelle vous souhaitez les accueillir ou l'endroit où ils récupéreront leurs clés. Un simple appel suffit : Afficher le numéro de téléphone Vous pouvez également leur envoyer un e-mail ou un message. Langue préférée \n russe\n Canal : Booking.com Code IATA/TIDS : \n PC029090\n Numéro de réservation : \n 4453602306\n Montant soumis à commission : € 177 Reçu jeu. 2 janv. 2025 Commission : € 31,86 Bloc-notes (usage interne) Ajoutez une note ici \n\n Maison 1 Chambre T2 - VillaFleurie au bourg du Gosier)\n € 186 jeu. 3 avr. 2025 dim. 6 avr. 2025 Nom du client \n Olga Korovina\n Occupation maximum 2 adultes, 2 enfants (3 personnes max.) Photo de l'hébergement Date Tarif Tarif par nuit \n 03 - 04 avril\n \n Standard Rate\n € 59\n 04 - 05 avril\n \n Standard Rate\n € 59\n 05 - 06 avril\n \n Standard Rate\n € 59Sous-total € 177\n Taxe de séjour\n € 1.50 par personne et par nuit € 9Tarif total de l'hébergement € 186 Le tarif comprend 8.9 % de TVA Conversation avec le client \n Aucun message\n \n Les conversations avec vos clients apparaîtront ici.\n Booking.com reçoit tous les messages écrits ici et les traite selon sa Charte de confidentialité et informations sur les cookies Conditions " - -func TestParseFromApi(t *testing.T) { - externalId := "4453602306" - tests := []struct { - name string - rawContent string - expected *booking.Booking - }{ - { - name: "parse booking from raw content", - rawContent: content, - expected: &booking.Booking{ - From: time.Date(2025, time.April, 3, 0, 0, 0, 0, time.UTC), - To: time.Date(2025, time.April, 6, 0, 0, 0, 0, time.UTC), - Name: "Olga Korovina", - Email: "okorov.905387@guest.booking.com", - Platform: "Booking", - CustomerNumber: 2, - PlatformFees: 31.86, - ExternalId: &externalId, - Canceled: false, - Items: []booking.Item{ - { - BookingId: 0, - Item: "T2", - Quantity: 3, - Price: 59.0, - PaymentMethod: "Card", - }, - }, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - bs, _ := booking.NewService(&booking.MockStore{}, nil, nil, nil) - - actual, err := bs.ParseFromApi(tt.rawContent) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - assert.Equal(t, tt.expected, actual, "expected %v, got %v", tt.expected, actual) - }) - } -} diff --git a/internal/view/booking_by_id.templ b/internal/view/booking_by_id.templ index 225a55a..ea8148d 100644 --- a/internal/view/booking_by_id.templ +++ b/internal/view/booking_by_id.templ @@ -31,7 +31,7 @@ templ BookingById(booking *BookingViewModel) { @BookingForm(*booking)
-

Line Items

+

Line Items

@@ -40,19 +40,14 @@ templ BookingById(booking *BookingViewModel) { - - - for _, item := range booking.Items { - @LineItem(&item) - } - + @ItemList(booking.Items) - + @@ -129,5 +124,41 @@ templ BookingById(booking *BookingViewModel) { + @PaymentModal(booking.PaymentUrl) } } + +templ PaymentModal(paymentUrl string) { + + + +} diff --git a/internal/view/booking_by_id_templ.go b/internal/view/booking_by_id_templ.go index c1b91b1..4ed193a 100644 --- a/internal/view/booking_by_id_templ.go +++ b/internal/view/booking_by_id_templ.go @@ -117,24 +117,22 @@ func BookingById(booking *BookingViewModel) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "

Line Items

Quantity Price (€) Payment MethodPayment Status Sub-total (€)
Total:Total: { booking.Total }
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "

Line Items

ItemQuantityPrice (€)Payment MethodPayment StatusSub-total (€)
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - for _, item := range booking.Items { - templ_7745c5c3_Err = LineItem(&item).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } + templ_7745c5c3_Err = ItemList(booking.Items).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " + for _, item := range itemList.Items { + @LineItem(&item) + } + + + + + + + + + + + + + if len(itemList.Payments) >0 { + for _,payment := range itemList.Payments { + + + + + + + + + } + } + +} diff --git a/internal/view/item_list_templ.go b/internal/view/item_list_templ.go new file mode 100644 index 0000000..d9841f1 --- /dev/null +++ b/internal/view/item_list_templ.go @@ -0,0 +1,101 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.3.819 +package view + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +func ItemList(itemList ItemListViewModel) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, item := range itemList.Items { + templ_7745c5c3_Err = LineItem(&item).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if len(itemList.Payments) > 0 { + for _, payment := range itemList.Payments { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/internal/view/item_list_viewmodel.go b/internal/view/item_list_viewmodel.go new file mode 100644 index 0000000..41cd716 --- /dev/null +++ b/internal/view/item_list_viewmodel.go @@ -0,0 +1,6 @@ +package view + +type ItemListViewModel struct { + Items []ItemViewModel + Payments []PaymentViewModel +} diff --git a/internal/view/item_viewmodel.go b/internal/view/item_viewmodel.go index aadea8a..63c9824 100644 --- a/internal/view/item_viewmodel.go +++ b/internal/view/item_viewmodel.go @@ -6,7 +6,6 @@ type ItemViewModel struct { Quantity string Price string SubTotal string - PaymentMethod string PaymentStatus string ItemUrl string } diff --git a/internal/view/line_item.templ b/internal/view/line_item.templ index 0501f14..aaff1d1 100644 --- a/internal/view/line_item.templ +++ b/internal/view/line_item.templ @@ -5,14 +5,10 @@ templ LineItem(item *ItemViewModel) { - - + } @@ -23,7 +19,7 @@ templ LineItemForm(item *ItemViewModel) { - + ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" hx-target=\"closest tr\" hx-swap=\"outerHTML\">Edit") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -167,103 +118,90 @@ func LineItemForm(item *ItemViewModel) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var10 := templ.GetChildren(ctx) - if templ_7745c5c3_Var10 == nil { - templ_7745c5c3_Var10 = templ.NopComponent + templ_7745c5c3_Var7 := templ.GetChildren(ctx) + if templ_7745c5c3_Var7 == nil { + templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/view/payment.templ b/internal/view/payment.templ new file mode 100644 index 0000000..f431fbc --- /dev/null +++ b/internal/view/payment.templ @@ -0,0 +1,46 @@ +package view + +templ PaymentLine(payment *PaymentViewModel) { + + + + + + + + +} + +templ PaymentForm(payment *PaymentViewModel) { + + + + + + + + + + +} \ No newline at end of file diff --git a/internal/view/payment_templ.go b/internal/view/payment_templ.go new file mode 100644 index 0000000..cd577ff --- /dev/null +++ b/internal/view/payment_templ.go @@ -0,0 +1,147 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.3.819 +package view + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +func PaymentLine(payment *PaymentViewModel) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + +func PaymentForm(payment *PaymentViewModel) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var5 := templ.GetChildren(ctx) + if templ_7745c5c3_Var5 == nil { + templ_7745c5c3_Var5 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/justfile b/justfile index fa34875..fb26a22 100644 --- a/justfile +++ b/justfile @@ -48,3 +48,7 @@ format: # Lint the code lint: @golangci-lint run ./... + +pdf: + @go run cmd/pdf/main.go + @open output.html diff --git a/main.go b/main.go index 3a0b655..dd8a59d 100644 --- a/main.go +++ b/main.go @@ -53,7 +53,7 @@ func run(c context.Context, getEnv func(string) string) error { return fmt.Errorf("error connecting to the database %w", err) } - if err = database.Migrate(db, &booking.Booking{}, &booking.BookingRequest{}, &booking.Item{}); err != nil { + if err = database.Migrate(db, &booking.Booking{}, &booking.BookingRequest{}, &booking.Item{}, &booking.Payment{}); err != nil { return fmt.Errorf("error migrating the database %w", err) } diff --git a/scripts/init_payments_table.sh b/scripts/init_payments_table.sh new file mode 100644 index 0000000..7513add --- /dev/null +++ b/scripts/init_payments_table.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +DB_NAME="your_database_name" +DB_USER="your_username" +DB_HOST="your_host" # e.g., localhost or an IP address +DB_PORT="your_port" # Default PostgreSQL port is 5432 +SQL_FILE="payment_migration.sql" # File containing the SQL script + +# Check if the SQL file exists +if [ ! -f "$SQL_FILE" ]; then + echo "Error: SQL file '$SQL_FILE' not found." + exit 1 +fi + +# Execute the SQL script +psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$SQL_FILE" + +# Check the result of the execution +if [ $? -eq 0 ]; then + echo "SQL script executed successfully." +else + echo "Error: Failed to execute SQL script." + exit 1 +fi diff --git a/scripts/payment_migration.sql b/scripts/payment_migration.sql new file mode 100644 index 0000000..dc0d99a --- /dev/null +++ b/scripts/payment_migration.sql @@ -0,0 +1,10 @@ +INSERT INTO payments (created_at, updated_at, deleted_at, booking_id, amount, payment_method) +SELECT MIN(i.created_at) AS created_at, -- Use the earliest created_at timestamp for this payment + MAX(i.updated_at) AS updated_at, -- Use the latest updated_at timestamp for this payment + i.deleted_at, -- Use the deleted_at timestamp from items + i.booking_id, -- The associated booking_id + SUM(i.price * i.quantity) AS amount, -- Calculate total amount from price * quantity + i.payment_method -- The payment method +FROM items i +WHERE i.deleted_at IS NULL -- Exclude soft-deleted items +GROUP BY i.booking_id, i.payment_method, i.deleted_at;
ItemQuantityPrice (€)Payment MethodSub-total (€)
Total:") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
Total:") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Total) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 56, Col: 26} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 51, Col: 26} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -147,7 +145,7 @@ func BookingById(booking *BookingViewModel) templ.Component { var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s/items", booking.Url)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 72, Col: 51} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 67, Col: 51} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -165,7 +163,7 @@ func BookingById(booking *BookingViewModel) templ.Component { var templ_7745c5c3_Var9 string templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(item) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 84, Col: 28} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 79, Col: 28} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { @@ -178,7 +176,7 @@ func BookingById(booking *BookingViewModel) templ.Component { var templ_7745c5c3_Var10 string templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(item) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 84, Col: 37} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 79, Col: 37} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { @@ -201,7 +199,7 @@ func BookingById(booking *BookingViewModel) templ.Component { var templ_7745c5c3_Var11 string templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(paymentMethod) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 120, Col: 37} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 115, Col: 37} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { @@ -214,7 +212,7 @@ func BookingById(booking *BookingViewModel) templ.Component { var templ_7745c5c3_Var12 string templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(paymentMethod) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 120, Col: 55} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 115, Col: 55} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { @@ -229,6 +227,10 @@ func BookingById(booking *BookingViewModel) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + templ_7745c5c3_Err = PaymentModal(booking.PaymentUrl).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } return nil }) templ_7745c5c3_Err = layout.BaseLayout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) @@ -239,4 +241,46 @@ func BookingById(booking *BookingViewModel) templ.Component { }) } +func PaymentModal(paymentUrl string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var13 := templ.GetChildren(ctx) + if templ_7745c5c3_Var13 == nil { + templ_7745c5c3_Var13 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "

Add Payment

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + var _ = templruntime.GeneratedTemplate diff --git a/internal/view/booking_viewmodel.go b/internal/view/booking_viewmodel.go index db49756..cd1c148 100644 --- a/internal/view/booking_viewmodel.go +++ b/internal/view/booking_viewmodel.go @@ -15,11 +15,18 @@ type BookingViewModel struct { ExternalId string Platforms []string PlatformFees string - Items []ItemViewModel + Items ItemListViewModel ItemList []string PaymentMethods []string Url string PdfUrl templ.SafeURL + PaymentUrl string CancelUrl string Total string } + +type PaymentViewModel struct { + Amount string + PaymentMethod string + PaymentUrl string +} diff --git a/internal/view/item_list.templ b/internal/view/item_list.templ new file mode 100644 index 0000000..239dd9e --- /dev/null +++ b/internal/view/item_list.templ @@ -0,0 +1,35 @@ +package view + +templ ItemList(itemList ItemListViewModel) { +
Price (€)Payment MethodSub-total (€)
- { payment.Amount }{ payment.PaymentMethod } + +
Price (€)Payment MethodSub-total (€)
- ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(payment.Amount) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/item_list.templ`, Line: 25, Col: 27} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(payment.PaymentMethod) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/item_list.templ`, Line: 26, Col: 32} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
{ item.Item } { item.Quantity } { item.Price }{ item.PaymentMethod }{ item.PaymentStatus } { item.SubTotal } - if item.PaymentStatus != "Completed" { - - }
{ item.SubTotal } diff --git a/internal/view/line_item_templ.go b/internal/view/line_item_templ.go index c826bb4..502b3c4 100644 --- a/internal/view/line_item_templ.go +++ b/internal/view/line_item_templ.go @@ -68,82 +68,33 @@ func LineItem(item *ItemViewModel) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(item.PaymentMethod) + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(item.SubTotal) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/line_item.templ`, Line: 8, Col: 26} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/line_item.templ`, Line: 9, Col: 21} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(item.SubTotal) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/line_item.templ`, Line: 10, Col: 21} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if item.PaymentStatus != "Completed" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var13 string - templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(item.Quantity) + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(item.SubTotal) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/line_item.templ`, Line: 24, Col: 80} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/line_item.templ`, Line: 24, Col: 22} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\" name=\"quantity\" form=\"edit-item\">") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var17 string - templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(item.SubTotal) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/line_item.templ`, Line: 28, Col: 22} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
- { payment.Amount }{ payment.PaymentMethod } + +
+ + + + + +
- ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(payment.Amount) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/payment.templ`, Line: 7, Col: 24} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(payment.PaymentMethod) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/payment.templ`, Line: 8, Col: 29} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "