rentease/internal/service/booking/stripe_payment_link.go
Ruidy afc61e02f1
Some checks failed
CI / checks (push) Has been cancelled
refactor: improve booking error handling and responses
Refactor booking retrieval to return errors instead of nil values,
enabling more robust error handling throughout the booking, payment,
and PDF endpoints. Add custom HTTP error page rendering for not found
and internal server errors. Update interfaces and tests to match new
method signatures. This improves user feedback and code maintainability.
2025-11-17 19:26:45 +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
}