From 68c6f27763c92e59a2ae40e0933698b1ec822d13 Mon Sep 17 00:00:00 2001 From: Ruidy Date: Fri, 24 Jan 2025 17:13:58 +0100 Subject: [PATCH] feat: get and update payment line --- internal/repository/booking/pg_store.go | 19 +++ internal/server/handle_bookings.go | 27 ++++- internal/server/handle_payments.go | 24 +++- internal/server/routes.go | 2 + internal/service/booking/mocks_test.go | 10 ++ internal/service/booking/payment.go | 14 ++- internal/service/booking/service.go | 10 ++ internal/view/booking_viewmodel.go | 2 +- internal/view/item_list_viewmodel.go | 2 +- internal/view/payment.templ | 46 ++++++++ internal/view/payment_templ.go | 147 ++++++++++++++++++++++++ 11 files changed, 292 insertions(+), 11 deletions(-) create mode 100644 internal/view/payment.templ create mode 100644 internal/view/payment_templ.go diff --git a/internal/repository/booking/pg_store.go b/internal/repository/booking/pg_store.go index 8c00abb..6e57c98 100644 --- a/internal/repository/booking/pg_store.go +++ b/internal/repository/booking/pg_store.go @@ -143,3 +143,22 @@ func (ps *PgStore) CreatePayment(p *booking.Payment) (*booking.Payment, error) { } 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 9085154..e62da8f 100644 --- a/internal/server/handle_bookings.go +++ b/internal/server/handle_bookings.go @@ -150,8 +150,8 @@ func handleBookingPage(bs *booking.Service, hc *config.Host) echo.HandlerFunc { ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), } }), - Payments: u.Map(b.Payments, func(p booking.Payment) view.Payment { - return view.Payment{ + 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), @@ -360,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 index 49a995d..e234ab8 100644 --- a/internal/server/handle_payments.go +++ b/internal/server/handle_payments.go @@ -50,8 +50,8 @@ func handleCreatePayment(bs *booking.Service) echo.HandlerFunc { ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), } }), - Payments: u.Map(nb.Payments, func(p booking.Payment) view.Payment { - return view.Payment{ + 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), @@ -61,8 +61,20 @@ func handleCreatePayment(bs *booking.Service) echo.HandlerFunc { } } -type Payment struct { - BookingID int - Amount float64 - PaymentMethod string +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 45a96c3..9dc56aa 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -41,4 +41,6 @@ func (s Server) MountHandlers() { 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 500af71..dc16ac8 100644 --- a/internal/service/booking/mocks_test.go +++ b/internal/service/booking/mocks_test.go @@ -76,6 +76,16 @@ func (m *MockStore) CreatePayment(p *Payment) (*Payment, error) { 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 diff --git a/internal/service/booking/payment.go b/internal/service/booking/payment.go index 73d7728..4c945f8 100644 --- a/internal/service/booking/payment.go +++ b/internal/service/booking/payment.go @@ -1,6 +1,10 @@ package booking -import "gorm.io/gorm" +import ( + "log" + + "gorm.io/gorm" +) type Payment struct { gorm.Model @@ -9,3 +13,11 @@ type Payment struct { 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 cb3194e..0b39776 100644 --- a/internal/service/booking/service.go +++ b/internal/service/booking/service.go @@ -25,6 +25,8 @@ type Store interface { // Payment methods CreatePayment(p *Payment) (*Payment, error) + GetPayment(id int) (*Payment, error) + UpdatePayment(id int, amount float64, paymentMethod string) (*Payment, error) } type PdfClient interface { @@ -114,3 +116,11 @@ func (bs Service) CreatePayment(bid int, amount float64, paymentMethod string) ( 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/view/booking_viewmodel.go b/internal/view/booking_viewmodel.go index 74961aa..cd1c148 100644 --- a/internal/view/booking_viewmodel.go +++ b/internal/view/booking_viewmodel.go @@ -25,7 +25,7 @@ type BookingViewModel struct { Total string } -type Payment struct { +type PaymentViewModel struct { Amount string PaymentMethod string PaymentUrl string diff --git a/internal/view/item_list_viewmodel.go b/internal/view/item_list_viewmodel.go index 7070c0f..41cd716 100644 --- a/internal/view/item_list_viewmodel.go +++ b/internal/view/item_list_viewmodel.go @@ -2,5 +2,5 @@ package view type ItemListViewModel struct { Items []ItemViewModel - Payments []Payment + Payments []PaymentViewModel } 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) { + + + + - { payment.Amount } + { payment.PaymentMethod } + + + + + +} + +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 + } + 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, "") + 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