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 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) from draft_payment($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) as payment join company using (company_id) 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 if err = row.Scan(&f.PaymentSlug.Val, &paymentID, &numNights, &nights, &adults, &teenagers, &children, &dogs, &touristTax, &total); 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 company using (company_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 } return cart, nil }