mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-11 21:26:50 +00:00
Some checks failed
CI / checks (push) Has been cancelled
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.
224 lines
5.9 KiB
Go
224 lines
5.9 KiB
Go
package booking
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
|
|
"github.com/rjNemo/rentease/internal/service/booking"
|
|
)
|
|
|
|
type PgStore struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewPgStore(db *gorm.DB) *PgStore {
|
|
return &PgStore{db}
|
|
}
|
|
|
|
func (ps *PgStore) All() []*booking.Line {
|
|
bookings := make([]*booking.Line, 0)
|
|
ps.db.Raw(`
|
|
select bookings.id, customer_name, "from", "to", platform, sum(price * quantity) as total, canceled
|
|
from bookings
|
|
left join items on bookings.id = items.booking_id
|
|
group by bookings.id
|
|
order by id desc;
|
|
`).
|
|
Scan(&bookings)
|
|
return bookings
|
|
}
|
|
|
|
func (ps *PgStore) Search(value string) []*booking.Line {
|
|
bookings := make([]*booking.Line, 0)
|
|
ps.db.Raw(`
|
|
select bookings.id, customer_name, "from", "to", platform, sum(price * quantity) as total, canceled
|
|
from bookings
|
|
left join items on bookings.id = items.booking_id
|
|
where customer_name ilike ?
|
|
group by bookings.id
|
|
order by id desc;
|
|
`, fmt.Sprintf("%%%s%%", value)).
|
|
Scan(&bookings)
|
|
return bookings
|
|
}
|
|
|
|
func (ps *PgStore) List(from, to time.Time) ([]*booking.Line, error) {
|
|
bookings := make([]*booking.Line, 0)
|
|
if err := ps.db.Raw(`
|
|
select bookings.id, customer_name, "from", "to", platform, sum(price * quantity) as total, platform_fees
|
|
from bookings
|
|
join items on bookings.id = items.booking_id
|
|
where "to" between ? and ?
|
|
and canceled = false
|
|
group by bookings.id
|
|
order by id desc;
|
|
`, from, to).
|
|
Scan(&bookings).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to list bookings: %w", err)
|
|
}
|
|
return bookings, nil
|
|
}
|
|
|
|
func (ps *PgStore) CardTotal(from, to time.Time) (float64, error) {
|
|
var total float64
|
|
if err := ps.db.Raw(`
|
|
select sum(total)
|
|
from (select sum(amount) as total
|
|
from bookings as b
|
|
join payments as p on b.id = p.booking_id
|
|
where "to" between ? and ?
|
|
and canceled = false
|
|
and p.payment_method = 'Card'
|
|
group by b.id) as t;
|
|
`, from, to).
|
|
Scan(&total).Error; err != nil {
|
|
return 0, fmt.Errorf("failed to get card total: %w", err)
|
|
}
|
|
return total, nil
|
|
}
|
|
|
|
func (ps *PgStore) Get(id int) (*booking.Booking, error) {
|
|
var b booking.Booking
|
|
res := ps.db.Preload("Items").Preload("Payments").First(&b, id)
|
|
if err := res.Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &b, nil
|
|
}
|
|
|
|
func (ps *PgStore) Create(b *booking.Booking) error {
|
|
return ps.db.Create(b).Error
|
|
}
|
|
|
|
func (ps *PgStore) Update(b *booking.Booking) error {
|
|
return ps.db.Model(&booking.Booking{}).Where("id = ?", b.ID).Updates(map[string]any{
|
|
"from": b.From,
|
|
"to": b.To,
|
|
"customer_name": b.Name,
|
|
"phone_number": b.PhoneNumber,
|
|
"email": b.Email,
|
|
"platform": b.Platform,
|
|
"external_id": b.ExternalID,
|
|
"customers": b.CustomerNumber,
|
|
"platform_fees": b.PlatformFees,
|
|
}).Error
|
|
}
|
|
|
|
func (ps *PgStore) Cancel(id int) error {
|
|
return ps.db.Model(&booking.Booking{}).Where("id = ?", id).Update("canceled", true).Error
|
|
}
|
|
|
|
// Item methods
|
|
func (ps *PgStore) CreateItem(i *booking.Item) error {
|
|
return ps.db.Create(i).Error
|
|
}
|
|
|
|
func (ps *PgStore) PayItem(id int) (*booking.Item, error) {
|
|
i := new(booking.Item)
|
|
if err := ps.db.Model(i).
|
|
Clauses(clause.Returning{}).
|
|
Where("id = ?", id).
|
|
Update("payment_status", "Completed").
|
|
Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return i, nil
|
|
}
|
|
|
|
func (ps *PgStore) GetItem(id int) (*booking.Item, error) {
|
|
i := &booking.Item{ID: id}
|
|
err := ps.db.First(i).Error
|
|
return i, err
|
|
}
|
|
|
|
func (ps *PgStore) UpdateItem(id int, item string, paymentMethod string, paymentStatus string, qty int, price float64) (*booking.Item, error) {
|
|
i := new(booking.Item)
|
|
err := ps.db.Model(i).
|
|
Clauses(clause.Returning{}).
|
|
Where("id = ?", id).
|
|
Updates(map[string]any{
|
|
"item": item,
|
|
"payment_method": paymentMethod,
|
|
"payment_status": paymentStatus,
|
|
"quantity": qty,
|
|
"price": price,
|
|
}).
|
|
Error
|
|
return i, err
|
|
}
|
|
|
|
func (ps *PgStore) CreatePayment(p *booking.Payment) (*booking.Payment, error) {
|
|
if err := ps.db.Create(p).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to create payment: %w", err)
|
|
}
|
|
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
|
|
}
|
|
|
|
func (ps *PgStore) UpsertStripePayment(p *booking.Payment) (*booking.Payment, error) {
|
|
if p.StripePaymentID == nil || *p.StripePaymentID == "" {
|
|
return nil, fmt.Errorf("stripe payment id is required")
|
|
}
|
|
|
|
existing := new(booking.Payment)
|
|
stripeID := *p.StripePaymentID
|
|
if err := ps.db.Where("stripe_payment_id = ?", stripeID).First(existing).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
if err := ps.db.Create(p).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to create stripe payment: %w", err)
|
|
}
|
|
return p, nil
|
|
}
|
|
return nil, fmt.Errorf("failed to lookup stripe payment: %w", err)
|
|
}
|
|
|
|
updates := map[string]any{
|
|
"amount": p.Amount,
|
|
"payment_method": p.PaymentMethod,
|
|
"stripe_status": p.StripeStatus,
|
|
"booking_id": p.BookingID,
|
|
}
|
|
|
|
if err := ps.db.Model(existing).
|
|
Clauses(clause.Returning{}).
|
|
Updates(updates).
|
|
Error; err != nil {
|
|
return nil, fmt.Errorf("failed to update stripe payment: %w", err)
|
|
}
|
|
|
|
return existing, nil
|
|
}
|
|
|
|
func (ps *PgStore) FindStripePayment(stripePaymentID string) (*booking.Payment, error) {
|
|
if stripePaymentID == "" {
|
|
return nil, fmt.Errorf("stripe payment id is required")
|
|
}
|
|
|
|
p := new(booking.Payment)
|
|
if err := ps.db.Where("stripe_payment_id = ?", stripePaymentID).First(p).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return p, nil
|
|
}
|