feat: get and update payment line

This commit is contained in:
Ruidy 2025-01-24 17:13:58 +01:00
parent e5ad26c8e3
commit 68c6f27763
No known key found for this signature in database
GPG key ID: E00F51288CB857CC
11 changed files with 292 additions and 11 deletions

View file

@ -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
}

View file

@ -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")

View file

@ -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)
}
}

View file

@ -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))
}

View file

@ -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

View file

@ -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
}

View file

@ -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
}

View file

@ -25,7 +25,7 @@ type BookingViewModel struct {
Total string
}
type Payment struct {
type PaymentViewModel struct {
Amount string
PaymentMethod string
PaymentUrl string

View file

@ -2,5 +2,5 @@ package view
type ItemListViewModel struct {
Items []ItemViewModel
Payments []Payment
Payments []PaymentViewModel
}

View file

@ -0,0 +1,46 @@
package view
templ PaymentLine(payment *PaymentViewModel) {
<tr class="hover">
<td></td>
<td></td>
<td>- { payment.Amount }</td>
<td>{ payment.PaymentMethod }</td>
<td></td>
<td class="flex gap-2">
<button class="btn btn-sm btn-outline" hx-get={ payment.PaymentUrl } hx-target="closest tr" hx-swap="outerHTML">Edit</button>
</td>
</tr>
}
templ PaymentForm(payment *PaymentViewModel) {
<tr class="hover">
<form hx-put={ payment.PaymentUrl } id="edit-payment" hx-target="closest tr" hx-swap="outerHTML">
<td></td>
<td></td>
<td>
<input
class="input input-bordered input-sm w-full"
type="number"
inputmode="decimal"
step="0.01"
value={ payment.Amount }
name="amount"
form="edit-payment"
/>
</td>
<td>
<input
class="input input-bordered input-sm w-full"
value={ payment.PaymentMethod }
name="paymentMethod"
form="edit-payment"
/>
</td>
<td></td>
<td>
<button class="btn btn-sm btn-primary" type="submit" form="edit-payment">Save</button>
</td>
</form>
</tr>
}

View file

@ -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, "<tr class=\"hover\"><td></td><td></td><td>- ")
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, "</td><td>")
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, "</td><td></td><td class=\"flex gap-2\"><button class=\"btn btn-sm btn-outline\" hx-get=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(payment.PaymentUrl)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/payment.templ`, Line: 11, Col: 69}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" hx-target=\"closest tr\" hx-swap=\"outerHTML\">Edit</button></td></tr>")
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, "<tr class=\"hover\"><form hx-put=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(payment.PaymentUrl)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/payment.templ`, Line: 18, Col: 35}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" id=\"edit-payment\" hx-target=\"closest tr\" hx-swap=\"outerHTML\"><td></td><td></td><td><input class=\"input input-bordered input-sm w-full\" type=\"number\" inputmode=\"decimal\" step=\"0.01\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, 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: 27, Col: 27}
}
_, 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, "\" name=\"amount\" form=\"edit-payment\"></td><td><input class=\"input input-bordered input-sm w-full\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, 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: 35, Col: 34}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" name=\"paymentMethod\" form=\"edit-payment\"></td><td></td><td><button class=\"btn btn-sm btn-primary\" type=\"submit\" form=\"edit-payment\">Save</button></td></form></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate