2023-10-13 10:45:54 +00:00
|
|
|
/*
|
|
|
|
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
*/
|
|
|
|
|
|
|
|
package database
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
“Finish” the new booking form
Had to bring the same fields that i have for a payment to booking,
except that some of those should be nullable, because it is unreasonable
to ask front desk to gather all customer data when they have a booking
via phone, for instance.
Therefore, i can not take advantage of the validation for customer data
that i use in the public-facing form, but, fortunately, most of the
validations where in separated functions, thus only had to rewrite that
one for this case.
I already have to create a booking from a payment, when receiving a
payment from the public instance, thus i made that function and reused
it here. Then i “overwrite” the newly created pre-booking with the
customer data from the form, and set is as confirmed, as we do not see
any point of allowing pre-bookings from employees.
2024-04-24 18:12:29 +00:00
|
|
|
"github.com/jackc/pgtype/zeronull"
|
2023-10-13 10:45:54 +00:00
|
|
|
"golang.org/x/text/language"
|
|
|
|
)
|
|
|
|
|
2024-01-27 21:51:41 +00:00
|
|
|
func (tx *Tx) AddAmenity(ctx context.Context, companyID int, label string, name string, info1 string, info2 string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select add_amenity($1, $2, $3, $4, $5)", companyID, label, name, info1, info2)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) EditAmenity(ctx context.Context, id int, label string, name string, info1 string, info2 string, active bool) error {
|
|
|
|
_, err := tx.Exec(ctx, "select edit_amenity($1, $2, $3, $4, $5, $6)", id, label, name, info1, info2, active)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateAmenity(ctx context.Context, id int, langTag language.Tag, name string, info1 string, info2 string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_amenity($1, $2, $3, $4, $5)", id, langTag, name, info1, info2)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) AddAmenityCarouselSlide(ctx context.Context, companyID int, label string, mediaID int, caption string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select add_amenity_carousel_slide($1, $2, $3, $4)", companyID, label, mediaID, caption)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateAmenityCarouselSlide(ctx context.Context, companyID int, label string, mediaID int, langTag language.Tag, caption string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_amenity_carousel_slide($1, $2, $3, $4, $5)", companyID, label, mediaID, langTag, caption)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) RemoveAmenityCarouselSlide(ctx context.Context, companyID int, label string, mediaID int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_amenity_carousel_slide($1, $2, $3)", companyID, label, mediaID)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) OrderAmenityCarousel(ctx context.Context, companyID int, label string, mediaIDs []int) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_amenity_carousel($1, $2, $3)", companyID, label, mediaIDs)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) AddAmenityFeature(ctx context.Context, companyID int, label string, iconName string, name string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select add_amenity_feature($1, $2, $3, $4)", companyID, label, iconName, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) EditAmenityFeature(ctx context.Context, id int, iconName string, name string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select edit_amenity_feature($1, $2, $3)", id, iconName, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateAmenityFeature(ctx context.Context, id int, langTag language.Tag, name string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_amenity_feature($1, $2, $3)", id, langTag, name)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) OrderAmenityFeatures(ctx context.Context, ids []int) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_amenity_features($1)", ids)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) RemoveAmenityFeature(ctx context.Context, id int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_amenity_feature($1)", id)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) RemoveAmenity(ctx context.Context, id int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_amenity($1)", id)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-26 21:27:54 +00:00
|
|
|
func (tx *Tx) AddCampsite(ctx context.Context, typeID int, label string, info1 string, info2 string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select add_campsite($1, $2, $3, $4)", typeID, label, info1, info2)
|
2024-01-25 19:48:39 +00:00
|
|
|
}
|
|
|
|
|
2024-01-26 21:27:54 +00:00
|
|
|
func (tx *Tx) EditCampsite(ctx context.Context, id int, typeID int, label string, info1 string, info2 string, active bool) error {
|
|
|
|
_, err := tx.Exec(ctx, "select edit_campsite($1, $2, $3, $4, $5, $6)", id, typeID, label, info1, info2, active)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateCampsite(ctx context.Context, id int, langTag language.Tag, info1 string, info2 string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_campsite($1, $2, $3, $4)", id, langTag, info1, info2)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) AddCampsiteCarouselSlide(ctx context.Context, label string, companyID int, mediaID int, caption string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select add_campsite_carousel_slide($1, $2, $3, $4)", companyID, label, mediaID, caption)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateCampsiteCarouselSlide(ctx context.Context, label string, companyID int, mediaID int, langTag language.Tag, caption string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_campsite_carousel_slide($1, $2, $3, $4, $5)", companyID, label, mediaID, langTag, caption)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) RemoveCampsiteCarouselSlide(ctx context.Context, label string, companyID int, mediaID int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_campsite_carousel_slide($1, $2, $3)", companyID, label, mediaID)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) OrderCampsiteCarousel(ctx context.Context, label string, companyID int, mediaIDs []int) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_campsite_carousel($1, $2, $3)", companyID, label, mediaIDs)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) AddCampsiteFeature(ctx context.Context, label string, companyID int, iconName string, name string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select add_campsite_feature($1, $2, $3, $4)", companyID, label, iconName, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) EditCampsiteFeature(ctx context.Context, id int, iconName string, name string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select edit_campsite_feature($1, $2, $3)", id, iconName, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateCampsiteFeature(ctx context.Context, id int, langTag language.Tag, name string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_campsite_feature($1, $2, $3)", id, langTag, name)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) OrderCampsiteFeatures(ctx context.Context, ids []int) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_campsite_features($1)", ids)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) RemoveCampsiteFeature(ctx context.Context, id int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_campsite_feature($1)", id)
|
2024-01-25 19:48:39 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
Add campsite_type_pet_cost relation to hold price of dogs in campsites
It is a separate relation, instead of having a field in campsite_type,
because not all campsite types allow dogs. I could have added a new
field to campsite_type, but then its values it would be meaningless for
campsites that do not allow dogs, and a nullable field is not a valid
solution because NULL means “unknown”, but we **do** know the price —
none.
A separate relation encodes the same information without ambiguities nor
null values, and, in fact, removed the dogs_allowed field from
campsite_type to prevent erroneous status, such as a campsite type that
allows dogs without having a cost — even if the cost is zero, it has to
be added to the new relation.
2024-02-10 05:18:30 +00:00
|
|
|
func (tx *Tx) AddCampsiteType(ctx context.Context, companyID int, mediaID int, name string, spiel string, info string, facilities string, description string, additionalInfo string, checkIn string, checkOut string, maxCampers int, minNights int, maxNights int, overflowAllowed bool, askZonePreferences bool) (string, error) {
|
|
|
|
return tx.GetText(ctx, "select add_campsite_type($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, int4range($12, $13), $14, $15)", companyID, mediaID, name, spiel, info, facilities, description, additionalInfo, checkIn, checkOut, maxCampers, minNights, maxNights+1, overflowAllowed, askZonePreferences)
|
2023-10-13 10:45:54 +00:00
|
|
|
}
|
|
|
|
|
Add campsite_type_pet_cost relation to hold price of dogs in campsites
It is a separate relation, instead of having a field in campsite_type,
because not all campsite types allow dogs. I could have added a new
field to campsite_type, but then its values it would be meaningless for
campsites that do not allow dogs, and a nullable field is not a valid
solution because NULL means “unknown”, but we **do** know the price —
none.
A separate relation encodes the same information without ambiguities nor
null values, and, in fact, removed the dogs_allowed field from
campsite_type to prevent erroneous status, such as a campsite type that
allows dogs without having a cost — even if the cost is zero, it has to
be added to the new relation.
2024-02-10 05:18:30 +00:00
|
|
|
func (tx *Tx) EditCampsiteType(ctx context.Context, slug string, mediaID int, name string, spiel string, info string, facilities string, description string, additionalInfo string, checkIn string, checkOut string, maxCampers int, minNights int, maxNights int, overflowAllowed bool, askZonePreferences bool, active bool) (string, error) {
|
|
|
|
return tx.GetText(ctx, "select edit_campsite_type($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, int4range($12, $13), $14, $15, $16)", slug, mediaID, name, spiel, info, facilities, description, additionalInfo, checkIn, checkOut, maxCampers, minNights, maxNights+1, overflowAllowed, askZonePreferences, active)
|
2023-10-13 10:45:54 +00:00
|
|
|
}
|
|
|
|
|
2023-12-20 18:52:14 +00:00
|
|
|
func (c *Conn) OrderCampsiteTypes(ctx context.Context, slugs []string) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_campsite_types($1)", slugs)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-22 19:19:19 +00:00
|
|
|
func (tx *Tx) TranslateCampsiteType(ctx context.Context, slug string, langTag language.Tag, name string, spiel string, info string, facilities string, description string, additionalInfo string, checkIn string, checkOut string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_campsite_type($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", slug, langTag, name, spiel, info, facilities, description, additionalInfo, checkIn, checkOut)
|
2023-10-13 10:45:54 +00:00
|
|
|
return err
|
|
|
|
}
|
Compute and show the “cart” for the booking form
I have to ask number and age ranges of hosts of guests for all campsite
types, not only those that have price options for adults, children, etc.
because i must compute the tourist tax for adults. These numbers will
be used to generate de rows for guests when actually creating the
booking, which is not done already.
To satisfy the campsite types that do have a price per guest, not only
per night, i had to add the prices for each range in the
campsite_type_cost relation. If a campsite type does not have price
per person, then that should be zero; the website then does not display
the price.
The minimal price for any campsite type is one adult for one night,
thus to compute the price i need at least the campsite type, the dates,
and the number of adults, that has a minimum of one. I changed the
order of the form to ask for these values first, so i can compute the
initial price as soon as possible. To help further, i show the
<fieldset>s progressively when visitors select options.
2024-02-04 05:37:25 +00:00
|
|
|
func (tx *Tx) SetCampsiteTypeCost(ctx context.Context, slug string, seasonID int, perNight string, perAdult string, perTeenager string, perChild string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select set_campsite_type_cost($1, $2, $3, $4, $5, $6)", slug, seasonID, perNight, perAdult, perTeenager, perChild)
|
2023-10-13 10:45:54 +00:00
|
|
|
return err
|
|
|
|
}
|
2023-10-13 17:05:17 +00:00
|
|
|
|
Add campsite_type_pet_cost relation to hold price of dogs in campsites
It is a separate relation, instead of having a field in campsite_type,
because not all campsite types allow dogs. I could have added a new
field to campsite_type, but then its values it would be meaningless for
campsites that do not allow dogs, and a nullable field is not a valid
solution because NULL means “unknown”, but we **do** know the price —
none.
A separate relation encodes the same information without ambiguities nor
null values, and, in fact, removed the dogs_allowed field from
campsite_type to prevent erroneous status, such as a campsite type that
allows dogs without having a cost — even if the cost is zero, it has to
be added to the new relation.
2024-02-10 05:18:30 +00:00
|
|
|
func (tx *Tx) SetCampsitePetTypeCost(ctx context.Context, slug string, cost string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select set_campsite_type_pet_cost($1, $2)", slug, cost)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) UnsetCampsitePetTypeCost(ctx context.Context, slug string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select unset_campsite_type_pet_cost($1)", slug)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-02-11 20:45:00 +00:00
|
|
|
func (tx *Tx) AddCampsiteTypeOption(ctx context.Context, typeSlug string, name string, min int, max int, perNight bool) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select add_campsite_type_option($1, $2, $3, $4, $5)", typeSlug, name, min, max, perNight)
|
2023-10-13 17:05:17 +00:00
|
|
|
}
|
|
|
|
|
2024-02-11 20:45:00 +00:00
|
|
|
func (tx *Tx) EditCampsiteTypeOption(ctx context.Context, id int, name string, min int, max int, perNight bool) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select edit_campsite_type_option($1, $2, $3, $4, $5)", id, name, min, max, perNight)
|
2023-10-13 17:05:17 +00:00
|
|
|
}
|
|
|
|
|
2024-02-11 20:45:00 +00:00
|
|
|
func (tx *Tx) SetCampsiteTypeOptionCost(ctx context.Context, id int, seasonID int, price string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select set_campsite_type_option_cost($1, $2, $3)", id, seasonID, price)
|
2023-10-13 17:05:17 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-10 20:52:49 +00:00
|
|
|
func (tx *Tx) TranslateCampsiteTypeOption(ctx context.Context, id int, langTag language.Tag, name string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_campsite_type_option($1, $2, $3)", id, langTag, name)
|
2023-10-13 17:05:17 +00:00
|
|
|
return err
|
|
|
|
}
|
2023-10-13 18:30:31 +00:00
|
|
|
|
2024-01-22 19:54:03 +00:00
|
|
|
func (c *Conn) RemoveCampsiteTypeOption(ctx context.Context, id int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_campsite_type_option($1)", id)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-12-20 18:52:14 +00:00
|
|
|
func (c *Conn) OrderCampsiteTypeOptions(ctx context.Context, ids []int) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_campsite_type_options($1)", ids)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) OrderCampsiteTypeCarousel(ctx context.Context, typeSlug string, media_ids []int) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_campsite_type_carousel($1, $2)", typeSlug, media_ids)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-10 20:52:49 +00:00
|
|
|
func (tx *Tx) AddCampsiteTypeFeature(ctx context.Context, typeSlug string, iconName string, name string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select add_campsite_type_feature($1, $2, $3)", typeSlug, iconName, name)
|
2023-10-13 18:30:31 +00:00
|
|
|
}
|
|
|
|
|
2024-01-10 20:52:49 +00:00
|
|
|
func (tx *Tx) EditCampsiteTypeFeature(ctx context.Context, id int, iconName string, name string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select edit_campsite_type_feature($1, $2, $3)", id, iconName, name)
|
2023-10-13 18:30:31 +00:00
|
|
|
}
|
|
|
|
|
2024-01-10 20:52:49 +00:00
|
|
|
func (tx *Tx) TranslateCampsiteTypeFeature(ctx context.Context, id int, langTag language.Tag, name string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_campsite_type_feature($1, $2, $3)", id, langTag, name)
|
2023-10-13 18:30:31 +00:00
|
|
|
return err
|
|
|
|
}
|
2023-10-27 14:04:43 +00:00
|
|
|
|
2023-12-21 16:33:01 +00:00
|
|
|
func (c *Conn) OrderCampsiteTypeFeatures(ctx context.Context, ids []int) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_campsite_type_features($1)", ids)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-26 21:54:19 +00:00
|
|
|
func (c *Conn) RemoveCampsiteTypeFeature(ctx context.Context, id int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_campsite_type_feature($1)", id)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-10 20:52:49 +00:00
|
|
|
func (tx *Tx) AddCampsiteTypeCarouselSlide(ctx context.Context, typeSlug string, mediaID int, caption string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select add_campsite_type_carousel_slide($1, $2, $3)", typeSlug, mediaID, caption)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateCampsiteTypeCarouselSlide(ctx context.Context, typeSlug string, mediaID int, langTag language.Tag, caption string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_campsite_type_carousel_slide($1, $2, $3, $4)", typeSlug, mediaID, langTag, caption)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-22 19:56:48 +00:00
|
|
|
func (c *Conn) RemoveCampsiteTypeCarouselSlide(ctx context.Context, typeSlug string, mediaID int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_campsite_type_carousel_slide($1, $2)", typeSlug, mediaID)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-10-27 14:04:43 +00:00
|
|
|
func (c *Conn) SetupRedsys(ctx context.Context, companyID int, merchantCode string, terminalNumber int, environment string, integration string, encryptKey string) error {
|
|
|
|
var encryptKeyParam interface{}
|
|
|
|
if encryptKey != "" {
|
|
|
|
encryptKeyParam = encryptKey
|
|
|
|
}
|
|
|
|
_, err := c.Exec(ctx, "select setup_redsys($1, $2, $3, $4, $5, $6)", companyID, merchantCode, terminalNumber, environment, integration, encryptKeyParam)
|
|
|
|
return err
|
|
|
|
}
|
2023-12-20 18:52:14 +00:00
|
|
|
|
|
|
|
func (c *Conn) OrderSeasons(ctx context.Context, slugs []string) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_seasons($1)", slugs)
|
|
|
|
return err
|
|
|
|
}
|
2023-12-21 20:17:04 +00:00
|
|
|
|
|
|
|
func (tx *Tx) SetupLocation(ctx context.Context, companyID int, directions string, mapEmbed string, openingHours string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select setup_location($1, $2, $3, $4)", companyID, directions, mapEmbed, openingHours)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateLocation(ctx context.Context, companyID int, langTag language.Tag, directions string, openingHours string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_location($1, $2, $3, $4)", companyID, langTag, directions, openingHours)
|
|
|
|
return err
|
|
|
|
}
|
2023-12-22 01:23:18 +00:00
|
|
|
|
|
|
|
func (tx *Tx) TranslateLegalText(ctx context.Context, companyID int, slug string, langTag language.Tag, name string, content string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_legal_text($1, $2, $3, $4, $5)", companyID, slug, langTag, name, content)
|
|
|
|
return err
|
|
|
|
}
|
2024-01-12 19:26:45 +00:00
|
|
|
|
|
|
|
func (tx *Tx) AddSeason(ctx context.Context, companyID int, name string, color string) (string, error) {
|
|
|
|
return tx.GetText(ctx, "select add_season($1, $2, $3)", companyID, name, color)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) EditSeason(ctx context.Context, slug string, name string, color string, active bool) error {
|
|
|
|
_, err := tx.Exec(ctx, "select edit_season($1, $2, $3, $4)", slug, name, color, active)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateSeason(ctx context.Context, slug string, langTag language.Tag, name string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_season($1, $2, $3)", slug, langTag, name)
|
|
|
|
return err
|
|
|
|
}
|
2024-01-12 20:06:12 +00:00
|
|
|
|
|
|
|
func (tx *Tx) AddService(ctx context.Context, companyID int, icon string, name string, description string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select add_service($1, $2, $3, $4)", companyID, icon, name, description)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) EditService(ctx context.Context, id int, icon string, name string, description string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select edit_service($1, $2, $3, $4)", id, icon, name, description)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateService(ctx context.Context, id int, langTag language.Tag, name string, description string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_service($1, $2, $3, $4)", id, langTag, name, description)
|
|
|
|
return err
|
|
|
|
}
|
2024-01-13 00:15:24 +00:00
|
|
|
|
|
|
|
func (c *Conn) OrderServices(ctx context.Context, ids []int) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_services($1)", ids)
|
|
|
|
return err
|
|
|
|
}
|
2024-01-16 00:25:25 +00:00
|
|
|
|
2024-01-16 17:12:38 +00:00
|
|
|
func (c *Conn) RemoveService(ctx context.Context, id int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_service($1)", id)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-16 00:25:25 +00:00
|
|
|
func (tx *Tx) AddSurroundingsHighlight(ctx context.Context, companyID int, mediaID int, name string, description string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select add_surroundings_highlight($1, $2, $3, $4)", companyID, mediaID, name, description)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) EditSurroundingsHighlight(ctx context.Context, id int, mediaID int, name string, description string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select edit_surroundings_highlight($1, $2, $3, $4)", id, mediaID, name, description)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateSurroundingsHighlight(ctx context.Context, id int, langTag language.Tag, name string, description string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_surroundings_highlight($1, $2, $3, $4)", id, langTag, name, description)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) OrderSurroundingsHighlights(ctx context.Context, ids []int) error {
|
|
|
|
_, err := c.Exec(ctx, "select order_surroundings_highlights($1)", ids)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) RemoveSurroundingsHighlight(ctx context.Context, id int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_surroundings_highlight($1)", id)
|
|
|
|
return err
|
|
|
|
}
|
2024-01-23 10:52:39 +00:00
|
|
|
|
2024-01-23 13:53:15 +00:00
|
|
|
func (tx *Tx) SetupSurroundingsAd(ctx context.Context, companyID int, mediaID int, title string, anchor string, href string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select setup_surroundings_ad($1, $2, $3, $4, $5)", companyID, mediaID, title, anchor, href)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateSurroundingsAd(ctx context.Context, companyID int, langTag language.Tag, title string, anchor string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_surroundings_ad($1, $2, $3, $4)", companyID, langTag, title, anchor)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conn) RemoveSurroundingsAd(ctx context.Context, companyID int) error {
|
|
|
|
_, err := c.Exec(ctx, "select remove_surroundings_ad($1)", companyID)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-23 10:52:39 +00:00
|
|
|
func (tx *Tx) SetupHome(ctx context.Context, companyID int, slogan string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select setup_home($1, $2)", companyID, slogan)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *Tx) TranslateHome(ctx context.Context, companyID int, langTag language.Tag, slogan string) error {
|
|
|
|
_, err := tx.Exec(ctx, "select translate_home($1, $2, $3)", companyID, langTag, slogan)
|
|
|
|
return err
|
|
|
|
}
|
Add payment relation and use it to compute the booking’s cart
I had to add the payment concept separate from the booking, unlike other
eCommerce solutions that subsume the two into a single “order”, like
WooCommerce, because bookings should be done in a separate Camper
instance that will sync to the public instance, but the payment is done
by the public instance. There will be a queue or something between
the public and the private instance to pass along the booking
information once the payment is complete, but the public instance still
needs to keep track of payments without creating bookings.
To compute the total for that payment i had to do the same as was doing
until now for the cart. To prevent duplications, or having functions
with complex return types, i now create a “draft” payment while the
user is filling in the form, and compute the cart there; from Go i only
have to retrieve the data from the relation, that simplifies the work,
actually.
Since the payment is computed way before customers enter their details,
i can not have that data in the same payment relation, unless i allow
NULL values. Allowing NULL values means that i can create a payment
without customer, thus i moved all customer details to a separate
relation. It still allows payment without customer, but at least there
are no NULL values.
Draft payments should be removed after a time, but i believe this needs
to be done in a cronjob or similar, not in the Go application.
To update the same payment while filling the same booking form, i now
have a hidden field with the payment slug. A competent developer would
have used a cookie or something like that; i am not competent.
2024-02-12 04:21:00 +00:00
|
|
|
|
2024-03-14 21:08:01 +00:00
|
|
|
func (c *Conn) ReadyPayment(ctx context.Context, paymentSlug string, customerName string, customerAddress string, customerPostCode string, customerCity string, customerCountryCode string, customerEmail string, customerPhone string, customerLangTag language.Tag) (int, error) {
|
|
|
|
return c.GetInt(ctx, "select ready_payment($1, $2, $3, $4, $5, $6, $7, $8, $9)", paymentSlug, customerName, customerAddress, customerPostCode, customerCity, customerCountryCode, customerEmail, customerPhone, customerLangTag)
|
2024-02-12 17:06:17 +00:00
|
|
|
}
|
“Finish” the new booking form
Had to bring the same fields that i have for a payment to booking,
except that some of those should be nullable, because it is unreasonable
to ask front desk to gather all customer data when they have a booking
via phone, for instance.
Therefore, i can not take advantage of the validation for customer data
that i use in the public-facing form, but, fortunately, most of the
validations where in separated functions, thus only had to rewrite that
one for this case.
I already have to create a booking from a payment, when receiving a
payment from the public instance, thus i made that function and reused
it here. Then i “overwrite” the newly created pre-booking with the
customer data from the form, and set is as confirmed, as we do not see
any point of allowing pre-bookings from employees.
2024-04-24 18:12:29 +00:00
|
|
|
|
|
|
|
func (tx *Tx) AddBookingFromPayment(ctx context.Context, paymentSlug string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select add_booking_from_payment($1)", paymentSlug)
|
|
|
|
}
|
|
|
|
|
2024-04-25 18:27:08 +00:00
|
|
|
func (tx *Tx) EditBookingFromPayment(ctx context.Context, bookingSlug string, paymentSlug string) (int, error) {
|
|
|
|
return tx.GetInt(ctx, "select edit_booking_from_payment($1, $2)", bookingSlug, paymentSlug)
|
|
|
|
}
|
|
|
|
|
“Finish” the new booking form
Had to bring the same fields that i have for a payment to booking,
except that some of those should be nullable, because it is unreasonable
to ask front desk to gather all customer data when they have a booking
via phone, for instance.
Therefore, i can not take advantage of the validation for customer data
that i use in the public-facing form, but, fortunately, most of the
validations where in separated functions, thus only had to rewrite that
one for this case.
I already have to create a booking from a payment, when receiving a
payment from the public instance, thus i made that function and reused
it here. Then i “overwrite” the newly created pre-booking with the
customer data from the form, and set is as confirmed, as we do not see
any point of allowing pre-bookings from employees.
2024-04-24 18:12:29 +00:00
|
|
|
func (tx *Tx) EditBooking(ctx context.Context, bookingID int, customerName string, customerAddress string, customerPostCode string, customerCity string, customerCountryCode string, customerEmail string, customerPhone string, customerLangTag language.Tag, bookingStatus string, campsiteIDs []int) error {
|
|
|
|
_, err := tx.Exec(ctx, "select edit_booking($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", bookingID, customerName, zeronull.Text(customerAddress), zeronull.Text(customerPostCode), zeronull.Text(customerCity), zeronull.Text(customerCountryCode), zeronull.Text(customerEmail), zeronull.Text(customerPhone), customerLangTag, bookingStatus, campsiteIDs)
|
|
|
|
return err
|
|
|
|
}
|