rentease/internal/service/booking/stripe_payment_link.go
Ruidy 91a9a74750
Some checks are pending
CI / checks (push) Waiting to run
feat(stripe): add payment link creation for bookings
Introduce backend and frontend support for generating Stripe payment
links
for outstanding booking balances. Adds a new POST endpoint to create
payment
links, updates booking view to include a Stripe button, and integrates
error handling and feedback for payment link creation. Refactors view
models and templates to support the new feature.
2025-11-01 17:22:13 +01:00

75 lines
1.8 KiB
Go

package booking
import (
"context"
"errors"
"fmt"
"math"
"strings"
stripeclient "github.com/rjNemo/rentease/internal/driver/stripe"
)
// ErrBookingNotFound indicates that a booking could not be retrieved from the datastore.
var ErrBookingNotFound = errors.New("booking not found")
// ErrNoOutstandingBalance indicates that the booking has already been fully paid.
var ErrNoOutstandingBalance = errors.New("booking has no outstanding balance")
// CreateStripePaymentLink generates a Stripe payment link for the outstanding balance of a booking.
func (bs Service) CreateStripePaymentLink(ctx context.Context, bookingID int) (string, error) {
if bs.stripe == nil {
return "", ErrStripeClientNotConfigured
}
b := bs.store.Get(bookingID)
if b == nil || b.ID == 0 {
return "", ErrBookingNotFound
}
outstanding := calculateOutstandingBalance(b)
if outstanding <= 0 {
return "", ErrNoOutstandingBalance
}
description := fmt.Sprintf("Payment for booking %d", b.ID)
if name := strings.TrimSpace(b.Name); name != "" {
description = fmt.Sprintf("Payment for %s", name)
}
url, err := bs.stripe.CreatePaymentLink(ctx, stripeclient.CreatePaymentLinkParams{
Amount: outstanding,
Currency: "eur",
BookingID: uint(b.ID),
Description: description,
PaymentMethodTypes: []string{"card", "sepa_debit"},
})
if err != nil {
return "", err
}
return url, nil
}
func calculateOutstandingBalance(b *Booking) float64 {
if b == nil {
return 0
}
var total float64
for _, item := range b.Items {
total += item.Price * float64(item.Quantity)
}
var paid float64
for _, payment := range b.Payments {
paid += payment.Amount
}
outstanding := total - paid
outstanding = math.Round(outstanding*100) / 100
if outstanding < 0 {
return 0
}
return outstanding
}