mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-10 12:46:53 +00:00
Introduce Stripe integration for automatic payment ingestion and refund tracking. Adds new fields to the payment model for Stripe IDs and status, Stripe client driver, sync service, cron job, manual API endpoint, and public webhook handler for real-time updates. Includes tests and documentation. Manual cash entry remains supported.
121 lines
3.3 KiB
Go
121 lines
3.3 KiB
Go
package booking
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"time"
|
|
|
|
"github.com/rjNemo/rentease/internal/config"
|
|
stripeclient "github.com/rjNemo/rentease/internal/driver/stripe"
|
|
)
|
|
|
|
type Store interface {
|
|
All() []*Line
|
|
Search(value string) []*Line
|
|
List(from, to time.Time) ([]*Line, error)
|
|
CardTotal(from, to time.Time) (float64, error)
|
|
Get(id int) *Booking
|
|
Create(b *Booking) error
|
|
Update(b *Booking) error
|
|
Cancel(id int) error
|
|
|
|
// Item methods
|
|
CreateItem(i *Item) error
|
|
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)
|
|
UpsertStripePayment(p *Payment) (*Payment, error)
|
|
FindStripePayment(stripePaymentID string) (*Payment, error)
|
|
}
|
|
|
|
type StripeClient interface {
|
|
ListPayments(ctx context.Context, params stripeclient.ListPaymentsParams) ([]stripeclient.Payment, error)
|
|
}
|
|
|
|
type PdfClient interface {
|
|
BuildInvoice(invoice Invoice) (string, error)
|
|
BuildReport(report ReportData, period string, month, year int) (string, error)
|
|
}
|
|
|
|
type CalendarClient interface {
|
|
Create(calendarID, name, description string, from, to time.Time) error
|
|
}
|
|
|
|
type parserClient interface {
|
|
Parse(rawContent string) (*Booking, error)
|
|
}
|
|
|
|
type Service struct {
|
|
store Store
|
|
parser parserClient
|
|
pdf PdfClient
|
|
logger *slog.Logger
|
|
stripe StripeClient
|
|
}
|
|
|
|
func NewService(logger *slog.Logger, store Store, parser parserClient, pdf PdfClient, stripe StripeClient) (*Service, error) {
|
|
svcLogger := logger
|
|
if svcLogger == nil {
|
|
svcLogger = slog.Default()
|
|
}
|
|
|
|
return &Service{
|
|
logger: svcLogger.With(slog.String("component", "booking_service")),
|
|
store: store,
|
|
parser: parser,
|
|
pdf: pdf,
|
|
stripe: stripe,
|
|
}, nil
|
|
}
|
|
|
|
func (bs Service) All() []*Line {
|
|
bs.logger.Info("fetching all bookings")
|
|
return bs.store.All()
|
|
}
|
|
|
|
func (bs Service) Search(value string) []*Line {
|
|
return bs.store.Search(value)
|
|
}
|
|
|
|
func (bs Service) Create(From time.Time, To time.Time, Name, PhoneNumber, Email, Platform string,
|
|
CustomerNumber int, PlatformFees float64, externalID *string,
|
|
) *Booking {
|
|
// TODO: return the error
|
|
b := NewBooking(From, To, Name, PhoneNumber, Email, Platform, CustomerNumber, PlatformFees, externalID)
|
|
err := bs.store.Create(b)
|
|
if err != nil {
|
|
bs.logger.Info("failed to create booking", slog.Any("err", err))
|
|
}
|
|
return b
|
|
}
|
|
|
|
func (bs Service) One(id int) *Booking {
|
|
return bs.store.Get(id)
|
|
}
|
|
|
|
// Update updates an existing booking with new data
|
|
func (bs Service) Update(id int, From time.Time, To time.Time, Name string, PhoneNumber string, Email string, Platform string,
|
|
CustomerNumber int, PlatformFees float64, externalID *string,
|
|
) *Booking {
|
|
b := NewBooking(From, To, Name, PhoneNumber, Email, Platform, CustomerNumber, PlatformFees, externalID).WithID(id)
|
|
if err := bs.store.Update(b); err != nil {
|
|
bs.logger.Info("failed to create booking", slog.Any("err", err))
|
|
}
|
|
return b
|
|
}
|
|
|
|
func (bs Service) Cancel(id int) {
|
|
err := bs.store.Cancel(id)
|
|
if err != nil {
|
|
bs.logger.Info("failed to create booking", slog.Any("err", err))
|
|
}
|
|
}
|
|
|
|
func (bs Service) BuildInvoice(b *Booking, hc *config.Host) (string, error) {
|
|
return bs.pdf.BuildInvoice(b.ToInvoice(hc))
|
|
}
|