201 lines
4.6 KiB
Go
201 lines
4.6 KiB
Go
package booking
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
"time"
|
|
|
|
"dev.tandem.ws/tandem/camper/pkg/database"
|
|
"dev.tandem.ws/tandem/camper/pkg/locale"
|
|
)
|
|
|
|
type bookingCart struct {
|
|
Lines []*cartLine
|
|
Total string
|
|
DownPayment string
|
|
Enabled bool
|
|
}
|
|
|
|
type cartLine struct {
|
|
Concept string
|
|
Units int
|
|
Subtotal string
|
|
}
|
|
|
|
func newBookingCart(ctx context.Context, conn *database.Conn, f *bookingForm, campsiteType string) (*bookingCart, error) {
|
|
cart := &bookingCart{
|
|
Total: "0.0",
|
|
}
|
|
if f.Dates == nil {
|
|
return cart, nil
|
|
}
|
|
arrivalDate, err := time.Parse(database.ISODateFormat, f.Dates.ArrivalDate.Val)
|
|
if err != nil {
|
|
return cart, nil
|
|
}
|
|
departureDate, err := time.Parse(database.ISODateFormat, f.Dates.DepartureDate.Val)
|
|
if err != nil {
|
|
return cart, nil
|
|
}
|
|
|
|
if f.Guests == nil {
|
|
return cart, nil
|
|
}
|
|
numAdults, err := strconv.Atoi(f.Guests.NumberAdults.Val)
|
|
if err != nil {
|
|
return cart, nil
|
|
}
|
|
numTeenagers, err := strconv.Atoi(f.Guests.NumberTeenagers.Val)
|
|
if err != nil {
|
|
return cart, nil
|
|
}
|
|
numChildren, err := strconv.Atoi(f.Guests.NumberChildren.Val)
|
|
if err != nil {
|
|
return cart, nil
|
|
}
|
|
numDogs := 0
|
|
if f.Guests.NumberDogs != nil {
|
|
numDogs, err = strconv.Atoi(f.Guests.NumberDogs.Val)
|
|
if err != nil {
|
|
return cart, nil
|
|
}
|
|
}
|
|
zonePreferences := ""
|
|
if f.Options != nil && f.Options.ZonePreferences != nil {
|
|
zonePreferences = f.Options.ZonePreferences.Val
|
|
}
|
|
|
|
optionMap := make(map[int]*campsiteTypeOption)
|
|
var typeOptions []*campsiteTypeOption
|
|
if f.Options != nil {
|
|
typeOptions = f.Options.Options
|
|
}
|
|
optionUnits := make([]*database.OptionUnits, 0, len(typeOptions))
|
|
for _, option := range typeOptions {
|
|
units, _ := strconv.Atoi(option.Input.Val)
|
|
if units < 1 {
|
|
continue
|
|
}
|
|
optionMap[option.ID] = option
|
|
optionUnits = append(optionUnits, &database.OptionUnits{
|
|
OptionID: option.ID,
|
|
Units: units,
|
|
})
|
|
}
|
|
|
|
row := conn.QueryRow(ctx, `
|
|
select payment.slug
|
|
, payment_id
|
|
, departure_date - arrival_date
|
|
, to_price(subtotal_nights, decimal_digits)
|
|
, to_price(subtotal_adults, decimal_digits)
|
|
, to_price(subtotal_teenagers, decimal_digits)
|
|
, to_price(subtotal_children, decimal_digits)
|
|
, to_price(subtotal_dogs, decimal_digits)
|
|
, to_price(subtotal_tourist_tax, decimal_digits)
|
|
, to_price(total, decimal_digits)
|
|
, to_price(payment.down_payment, decimal_digits)
|
|
from draft_payment($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) as payment
|
|
join currency using (currency_code)
|
|
`,
|
|
database.ZeroNullUUID(f.PaymentSlug.Val),
|
|
arrivalDate,
|
|
departureDate,
|
|
campsiteType,
|
|
numAdults,
|
|
numTeenagers,
|
|
numChildren,
|
|
numDogs,
|
|
zonePreferences,
|
|
database.OptionUnitsArray(optionUnits),
|
|
)
|
|
var paymentID int
|
|
var numNights int
|
|
var nights string
|
|
var adults string
|
|
var teenagers string
|
|
var children string
|
|
var dogs string
|
|
var touristTax string
|
|
var total string
|
|
var downPayment string
|
|
if err = row.Scan(
|
|
&f.PaymentSlug.Val,
|
|
&paymentID,
|
|
&numNights,
|
|
&nights,
|
|
&adults,
|
|
&teenagers,
|
|
&children,
|
|
&dogs,
|
|
&touristTax,
|
|
&total,
|
|
&downPayment,
|
|
); err != nil {
|
|
if database.ErrorIsNotFound(err) {
|
|
return cart, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
maybeAddLine := func(units int, subtotal string, concept string) {
|
|
if units > 0 && subtotal != "" {
|
|
cart.Lines = append(cart.Lines, &cartLine{
|
|
Concept: concept,
|
|
Units: units,
|
|
Subtotal: subtotal,
|
|
})
|
|
}
|
|
}
|
|
maybeAddLine(numNights, nights, locale.PgettextNoop("Night", "cart"))
|
|
maybeAddLine(numAdults, adults, locale.PgettextNoop("Adult", "cart"))
|
|
maybeAddLine(numTeenagers, teenagers, locale.PgettextNoop("Teenager", "cart"))
|
|
maybeAddLine(numChildren, children, locale.PgettextNoop("Child", "cart"))
|
|
maybeAddLine(numDogs, dogs, locale.PgettextNoop("Dog", "cart"))
|
|
|
|
rows, err := conn.Query(ctx, `
|
|
select campsite_type_option_id
|
|
, units
|
|
, to_price(subtotal, decimal_digits)
|
|
from payment_option
|
|
join payment using (payment_id)
|
|
join currency using (currency_code)
|
|
where payment_id = $1
|
|
`, paymentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
var optionID int
|
|
var units int
|
|
var subtotal string
|
|
err = rows.Scan(&optionID, &units, &subtotal)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
option := optionMap[optionID]
|
|
if option == nil {
|
|
continue
|
|
}
|
|
maybeAddLine(units, subtotal, option.Label)
|
|
}
|
|
if rows.Err() != nil {
|
|
return nil, rows.Err()
|
|
}
|
|
|
|
maybeAddLine(numAdults, touristTax, locale.PgettextNoop("Tourist tax", "cart"))
|
|
|
|
if total != "0.0" {
|
|
cart.Total = total
|
|
cart.Enabled = f.Guests.Error == nil
|
|
|
|
if downPayment != total {
|
|
cart.DownPayment = downPayment
|
|
}
|
|
}
|
|
|
|
return cart, nil
|
|
}
|