diff --git a/deploy/available_payment_status.sql b/deploy/available_payment_status.sql new file mode 100644 index 0000000..118a2bd --- /dev/null +++ b/deploy/available_payment_status.sql @@ -0,0 +1,33 @@ +-- Deploy camper:available_payment_status to pg +-- requires: payment_status +-- requires: payment_status_i18n + +begin; + +insert into camper.payment_status (payment_status, name) +values ('draft', 'Draft') + , ('pending', 'Pending') + , ('failed', 'Failed') + , ('completed', 'Completed') + , ('refunded', 'Refunded') +; + +insert into camper.payment_status_i18n (payment_status, lang_tag, name) +values ('draft', 'ca', 'Esborrany') + , ('pending', 'ca', 'Pendent') + , ('failed', 'ca', 'No realitzat') + , ('completed', 'ca', 'Completat') + , ('refunded', 'ca', 'Reemborsat') + , ('draft', 'es', 'Borrador') + , ('pending', 'es', 'Pendiente') + , ('failed', 'es', 'Fallido') + , ('completed', 'es', 'Completado') + , ('refunded', 'es', 'Reembolsado') + , ('draft', 'fr', 'Brouillon') + , ('pending', 'fr', 'En attente') + , ('failed', 'fr', 'Échouée') + , ('completed', 'fr', 'Terminée') + , ('refunded', 'fr', 'Remboursée') +; + +commit; diff --git a/deploy/draft_payment.sql b/deploy/draft_payment.sql new file mode 100644 index 0000000..594d9e0 --- /dev/null +++ b/deploy/draft_payment.sql @@ -0,0 +1,158 @@ +-- Deploy camper:draft_payment to pg +-- requires: roles +-- requires: schema_camper +-- requires: season_calendar +-- requires: season +-- requires: campsite_type +-- requires: campsite_type_pet_cost +-- requires: campsite_type_cost +-- requires: campsite_type_option_cost +-- requires: campsite_type_option +-- requires: payment +-- requires: payment_option + +begin; + +set search_path to camper, public; + +create type option_units as (option_id integer, units integer); + +create or replace function draft_payment(payment_slug uuid, arrival_date date, departure_date date, campsite_type_slug uuid, num_adults integer, num_teenagers integer, num_children integer, num_dogs integer, zone_preferences text, options option_units[]) returns uuid as +$$ +declare + pid integer; +begin + insert into payment ( + slug + , company_id + , campsite_type_id + , arrival_date + , departure_date + , subtotal_nights + , number_adults + , subtotal_adults + , number_teenagers + , subtotal_teenagers + , number_children + , subtotal_children + , number_dogs + , subtotal_dogs + , subtotal_tourist_tax + , total + , zone_preferences + ) + select coalesce(payment_slug, gen_random_uuid()) + , company_id + , campsite_type_id + , arrival_date + , departure_date + , sum(cost.cost_per_night * ceiling((num_adults::numeric + num_teenagers::numeric + num_children::numeric) / max_campers::numeric)::integer)::integer + , num_adults + , sum(cost_per_adult * num_adults)::integer + , num_teenagers + , sum(cost_per_teenager * num_teenagers)::integer + , num_children + , sum(cost_per_child * num_children)::integer + , num_dogs + , sum(case when num_dogs > 0 then coalesce(pet.cost_per_night, 0) else 0 end)::integer + , sum(tourist_tax * num_adults)::integer + , 0 + , coalesce(zone_preferences, '') + from generate_series(arrival_date, departure_date - 1, interval '1 day') as date(day) + left join season_calendar on season_range @> date.day::date + left join season using (season_id) + left join campsite_type using (company_id) + left join campsite_type_pet_cost as pet using (campsite_type_id) + left join campsite_type_cost as cost using (campsite_type_id, season_id) + left join company using (company_id) + where campsite_type.slug = campsite_type_slug + group by company_id + , campsite_type_id + on conflict (slug) do update + set company_id = excluded.company_id + , campsite_type_id = excluded.campsite_type_id + , arrival_date = excluded.arrival_date + , departure_date = excluded.departure_date + , subtotal_nights = excluded.subtotal_nights + , number_adults = excluded.number_adults + , subtotal_adults = excluded.subtotal_adults + , number_teenagers = excluded.number_teenagers + , subtotal_teenagers = excluded.subtotal_teenagers + , number_children = excluded.number_children + , subtotal_children = excluded.subtotal_children + , number_dogs = excluded.number_dogs + , subtotal_dogs = excluded.subtotal_dogs + , subtotal_tourist_tax = excluded.subtotal_tourist_tax + , total = excluded.total + , zone_preferences = excluded.zone_preferences + , updated_at = current_timestamp + returning payment_id, payment.slug + into pid, payment_slug + ; + + if array_length(coalesce(options, array[]::option_units[]), 1) > 0 then + delete + from payment_option + where payment_id = pid + and campsite_type_option_id not in ( + select campsite_type_option_id + from unnest(options) as option(campsite_type_option_id, units) + ); + + insert into payment_option ( + payment_id + , campsite_type_option_id + , units + , subtotal + ) + select pid + , campsite_type_option_id + , units + , case when per_night then sum(cost * units)::integer else max(cost * units)::integer end + from generate_series(arrival_date, departure_date - 1, interval '1 day') as date(day) + join season_calendar on season_range @> date.day::date + join campsite_type_option_cost using (season_id) + join campsite_type_option using (campsite_type_option_id) + join unnest(options) as option(campsite_type_option_id, units) using (campsite_type_option_id) + group by campsite_type_option_id + , units + , per_night + on conflict (payment_id, campsite_type_option_id) do update + set units = excluded.units + , subtotal = excluded.subtotal + ; + + with option as ( + select sum(subtotal)::integer as subtotal + from payment_option + where payment_id = pid + ) + update payment + set total = subtotal_nights + subtotal_adults + subtotal_teenagers + subtotal_children + subtotal_dogs + subtotal_tourist_tax + coalesce(option.subtotal, 0) + from option + where payment_id = pid + ; + else + delete + from payment_option + where payment_id = pid; + + update payment + set total = subtotal_nights + subtotal_adults + subtotal_teenagers + subtotal_children + subtotal_dogs + subtotal_tourist_tax + where payment_id = pid + ; + end if; + + + return payment_slug; +end; +$$ + language plpgsql +; + +revoke execute on function draft_payment(uuid, date, date, uuid, integer, integer, integer, integer, text, option_units[]) from public; +grant execute on function draft_payment(uuid, date, date, uuid, integer, integer, integer, integer, text, option_units[]) to guest; +grant execute on function draft_payment(uuid, date, date, uuid, integer, integer, integer, integer, text, option_units[]) to employee; +grant execute on function draft_payment(uuid, date, date, uuid, integer, integer, integer, integer, text, option_units[]) to admin; + +commit; diff --git a/deploy/payment.sql b/deploy/payment.sql new file mode 100644 index 0000000..e1f3828 --- /dev/null +++ b/deploy/payment.sql @@ -0,0 +1,40 @@ +-- Deploy camper:payment to pg +-- requires: roles +-- requires: schema_camper +-- requires: company +-- requires: campsite_type +-- requires: payment_status + +begin; + +set search_path to camper, public; + +create table payment ( + payment_id integer generated by default as identity primary key, + company_id integer not null references company, + slug uuid not null unique default gen_random_uuid(), + campsite_type_id integer not null references campsite_type, + arrival_date date not null, + departure_date date not null constraint departure_after_arrival check (departure_date > arrival_date), + subtotal_nights integer not null constraint subtotal_nights_not_negative check (subtotal_nights >= 0), + number_adults integer not null constraint number_adults_positive check (number_adults > 0), + subtotal_adults integer not null constraint subtotal_adults_not_negative check (subtotal_adults >= 0), + number_teenagers integer not null constraint number_teenagers_not_negative check (number_teenagers >= 0), + subtotal_teenagers integer not null constraint subtotal_teenagers_not_negative check (subtotal_teenagers >= 0), + number_children integer not null constraint number_children_not_negative check (number_children >= 0), + subtotal_children integer not null constraint subtotal_children_not_negative check (subtotal_children >= 0), + number_dogs integer not null constraint number_dogs_not_negative check (number_dogs >= 0), + subtotal_dogs integer not null constraint subtotal_dogs_not_negative check (subtotal_dogs >= 0), + subtotal_tourist_tax integer not null constraint subtotal_tourist_tax_not_negative check (subtotal_tourist_tax >= 0), + total integer not null constraint total_not_negative check (total >= 0), + zone_preferences text not null, + payment_status text not null default 'draft' references payment_status, + created_at timestamp with time zone not null default current_timestamp, + updated_at timestamp with time zone not null default current_timestamp +); + +grant select, insert, update on table payment to guest; +grant select, insert, update on table payment to employee; +grant select, insert, update, delete on table payment to admin; + +commit; diff --git a/deploy/payment_customer.sql b/deploy/payment_customer.sql new file mode 100644 index 0000000..7437663 --- /dev/null +++ b/deploy/payment_customer.sql @@ -0,0 +1,29 @@ +-- Deploy camper:payment_customer to pg +-- requires: roles +-- requires: schema_camper +-- requires: payment +-- requires: country +-- requires: country_code +-- requires: extension_pg_libphonenumber + +begin; + +set search_path to camper, public; + +create table payment_customer ( + payment_id integer not null primary key references payment, + full_name text not null, + address text not null, + postal_code text not null, + city text not null, + country_code country_code not null references country, + email email not null, + phone packed_phone_number not null, + acsi_card boolean not null +); + +grant select, insert on table payment_customer to guest; +grant select, insert, update on table payment_customer to employee; +grant select, insert, update, delete on table payment_customer to admin; + +commit; diff --git a/deploy/payment_option.sql b/deploy/payment_option.sql new file mode 100644 index 0000000..1b2c803 --- /dev/null +++ b/deploy/payment_option.sql @@ -0,0 +1,23 @@ +-- Deploy camper:payment_option to pg +-- requires: roles +-- requires: schema_camper +-- requires: payment +-- requires: campsite_type_option + +begin; + +set search_path to camper, public; + +create table payment_option ( + payment_id integer not null references payment, + campsite_type_option_id integer not null references campsite_type_option, + units integer not null constraint units_positive check (units > 0), + subtotal integer not null constraint subtotal_not_negative check (subtotal >= 0), + primary key (payment_id, campsite_type_option_id) +); + +grant select, insert, update, delete on table payment_option to guest; +grant select, insert, update, delete on table payment_option to employee; +grant select, insert, update, delete on table payment_option to admin; + +commit; diff --git a/deploy/payment_status.sql b/deploy/payment_status.sql new file mode 100644 index 0000000..1c7d937 --- /dev/null +++ b/deploy/payment_status.sql @@ -0,0 +1,17 @@ +-- Deploy camper:payment_status to pg +-- requires: roles +-- requires: schema_camper + +begin; + +set search_path to camper, public; + +create table payment_status ( + payment_status text not null primary key, + name text not null +); + +grant select on table payment_status to employee; +grant select on table payment_status to admin; + +commit; diff --git a/deploy/payment_status_i18n.sql b/deploy/payment_status_i18n.sql new file mode 100644 index 0000000..551598e --- /dev/null +++ b/deploy/payment_status_i18n.sql @@ -0,0 +1,21 @@ +-- Deploy camper:payment_status_i18n to pg +-- requires: roles +-- requires: schema_camper +-- requires: payment_status +-- requires: language + +begin; + +set search_path to camper, public; + +create table payment_status_i18n ( + payment_status text not null references payment_status, + lang_tag text not null references language, + name text not null, + primary key (payment_status, lang_tag) +); + +grant select on table payment_status_i18n to employee; +grant select on table payment_status_i18n to admin; + +commit; diff --git a/pkg/booking/cart.go b/pkg/booking/cart.go index c43549c..7fac263 100644 --- a/pkg/booking/cart.go +++ b/pkg/booking/cart.go @@ -5,8 +5,6 @@ import ( "strconv" "time" - "github.com/jackc/pgx/v4" - "dev.tandem.ws/tandem/camper/pkg/database" "dev.tandem.ws/tandem/camper/pkg/locale" ) @@ -61,75 +59,64 @@ func newBookingCart(ctx context.Context, conn *database.Conn, f *bookingForm, ca 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 } - optionIDs := make([]int, 0, len(typeOptions)) - optionUnits := make([]int, 0, len(typeOptions)) + 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 - optionIDs = append(optionIDs, option.ID) - optionUnits = append(optionUnits, units) + optionUnits = append(optionUnits, &database.OptionUnits{ + OptionID: option.ID, + Units: units, + }) } - row := conn.QueryRow(ctx, ` - with per_person as ( - select count(*) as num_nights - , sum(cost.cost_per_night * ceiling(($4::numeric + $5::numeric + $6::numeric) / max_campers::numeric)::integer)::integer as nights - , sum(cost_per_adult * $4)::integer as adults - , sum(cost_per_teenager * $5)::integer as teenagers - , sum(cost_per_child * $6)::integer as children - , sum(case when $7 > 0 then coalesce(pet.cost_per_night, 0) else 0 end)::integer as dogs - , sum(tourist_tax * $4)::integer as tourist_tax - , max(decimal_digits) as decimal_digits - from generate_series($1, $2, interval '1 day') as date(day) - left join season_calendar on season_range @> date.day::date - left join season using (season_id) - left join campsite_type using (company_id) - left join campsite_type_pet_cost as pet using (campsite_type_id) - left join campsite_type_cost as cost using (campsite_type_id, season_id) - left join company using (company_id) - left join currency using (currency_code) - where campsite_type.slug = $3 - ), per_option as ( - select campsite_type_option_id - , case when per_night then sum(cost * units)::integer else max(cost * units)::integer end as option_cost - from generate_series($1, $2, interval '1 day') as date(day) - join season_calendar on season_range @> date.day::date - join campsite_type_option_cost using (season_id) - join campsite_type_option using (campsite_type_option_id) - join unnest($8::integer[], $9::integer[]) as option_units(campsite_type_option_id, units) using (campsite_type_option_id) - group by campsite_type_option_id - , per_night - union all select -1, 0 - ) - select num_nights - , coalesce(to_price(nights, decimal_digits), '') - , coalesce(to_price(adults, decimal_digits), '') - , coalesce(to_price(teenagers, decimal_digits), '') - , coalesce(to_price(children, decimal_digits), '') - , coalesce(to_price(dogs, decimal_digits), '') - , coalesce(to_price(tourist_tax, decimal_digits), '') - , coalesce(to_price(nights + adults + teenagers + children + tourist_tax + sum(option_cost)::integer, decimal_digits), '') - , array_agg((campsite_type_option_id, to_price(option_cost, decimal_digits))) - from per_person, per_option - group by num_nights - , nights - , adults - , teenagers - , children - , dogs - , tourist_tax - , decimal_digits -`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, arrivalDate, departureDate.AddDate(0, 0, -1), campsiteType, numAdults, numTeenagers, numChildren, numDogs, optionIDs, optionUnits) + paymentSlug, err := conn.DraftPayment( + ctx, + f.PaymentSlug.Val, + arrivalDate, + departureDate, + campsiteType, + numAdults, + numTeenagers, + numChildren, + numDogs, + zonePreferences, + optionUnits, + ) + if err != nil { + return nil, err + } + f.PaymentSlug.Val = paymentSlug + row := conn.QueryRow(ctx, ` + select 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 payment + join company using (company_id) + join currency using (currency_code) + where payment.slug = $1 +`, paymentSlug) + + var paymentID int var numNights int var nights string var adults string @@ -138,8 +125,7 @@ func newBookingCart(ctx context.Context, conn *database.Conn, f *bookingForm, ca var dogs string var touristTax string var total string - var optionPrices database.RecordArray - if err = row.Scan(&numNights, &nights, &adults, &teenagers, &children, &dogs, &touristTax, &total, &optionPrices); err != nil { + if err = row.Scan(&paymentID, &numNights, &nights, &adults, &teenagers, &children, &dogs, &touristTax, &total); err != nil { if database.ErrorIsNotFound(err) { return cart, nil } @@ -161,26 +147,42 @@ func newBookingCart(ctx context.Context, conn *database.Conn, f *bookingForm, ca maybeAddLine(numChildren, children, locale.PgettextNoop("Child", "cart")) maybeAddLine(numDogs, dogs, locale.PgettextNoop("Dog", "cart")) - for _, el := range optionPrices.Elements { - optionID := el.Fields[0].Get() - if optionID == nil { - continue + 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 } - subtotal := el.Fields[1].Get() - if subtotal == nil { - continue - } - option := optionMap[int(optionID.(int32))] + option := optionMap[optionID] if option == nil { continue } - units, _ := strconv.Atoi(option.Input.Val) - maybeAddLine(units, subtotal.(string), option.Label) + maybeAddLine(units, subtotal, option.Label) + } + if rows.Err() != nil { + return nil, rows.Err() } maybeAddLine(numAdults, touristTax, locale.PgettextNoop("Tourist tax", "cart")) - if total != "" { + if total != "0.0" { cart.Total = total cart.Enabled = f.Guests.Error == nil } diff --git a/pkg/booking/public.go b/pkg/booking/public.go index e3a9b33..459cc55 100644 --- a/pkg/booking/public.go +++ b/pkg/booking/public.go @@ -141,6 +141,7 @@ func (p *publicPage) MustRender(w http.ResponseWriter, r *http.Request, user *au type bookingForm struct { CampsiteType *form.Select + PaymentSlug *form.Input Dates *DateFields Guests *bookingGuestFields Options *bookingOptionFields @@ -208,8 +209,12 @@ func newBookingForm(r *http.Request, company *auth.Company, conn *database.Conn, Name: "campsite_type", Options: form.MustGetOptions(r.Context(), conn, "select type.slug, coalesce(i18n.name, type.name) as l10n_name from campsite_type as type left join campsite_type_i18n as i18n on type.campsite_type_id = i18n.campsite_type_id and i18n.lang_tag = $1 where company_id = $2 and active order by position, l10n_name", l.Language, company.ID), }, + PaymentSlug: &form.Input{ + Name: "payment_slug", + }, } f.CampsiteType.FillValue(r) + f.PaymentSlug.FillValue(r) campsiteType := f.CampsiteType.String() if campsiteType == "" { return f, nil diff --git a/pkg/database/OptionUnits.go b/pkg/database/OptionUnits.go new file mode 100644 index 0000000..f8b33c8 --- /dev/null +++ b/pkg/database/OptionUnits.go @@ -0,0 +1,60 @@ +package database + +import ( + "fmt" + + "github.com/jackc/pgio" + "github.com/jackc/pgtype" +) + +type OptionUnits struct { + OptionID int + Units int +} + +func (src OptionUnits) EncodeBinary(ci *pgtype.ConnInfo, dst []byte) ([]byte, error) { + typeName := OptionUnitsTypeName + dt, ok := ci.DataTypeForName(typeName) + if !ok { + return nil, fmt.Errorf("unable to find oid for type name %v", typeName) + } + values := []interface{}{ + src.OptionID, + src.Units, + } + ct := pgtype.NewValue(dt.Value).(*pgtype.CompositeType) + if err := ct.Set(values); err != nil { + return nil, err + } + return ct.EncodeBinary(ci, dst) +} + +type OptionUnitsArray []*OptionUnits + +func (src OptionUnitsArray) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) { + typeName := OptionUnitsTypeName + dt, ok := ci.DataTypeForName(typeName) + if !ok { + return nil, fmt.Errorf("unable to find oid for type name %v", typeName) + } + + arrayHeader := pgtype.ArrayHeader{ + ElementOID: int32(dt.OID), + Dimensions: []pgtype.ArrayDimension{{Length: int32(len(src)), LowerBound: 1}}, + } + buf = arrayHeader.EncodeBinary(ci, buf) + for _, optionUnits := range src { + sp := len(buf) + buf = pgio.AppendInt32(buf, -1) + + elemBuf, err := optionUnits.EncodeBinary(ci, buf) + if err != nil { + return nil, err + } + if elemBuf != nil { + buf = elemBuf + pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4)) + } + } + return buf, nil +} diff --git a/pkg/database/funcs.go b/pkg/database/funcs.go index 9b12d4f..0b8097b 100644 --- a/pkg/database/funcs.go +++ b/pkg/database/funcs.go @@ -7,6 +7,7 @@ package database import ( "context" + "time" "golang.org/x/text/language" ) @@ -348,3 +349,11 @@ func (tx *Tx) TranslateHome(ctx context.Context, companyID int, langTag language _, err := tx.Exec(ctx, "select translate_home($1, $2, $3)", companyID, langTag, slogan) return err } + +func (c *Conn) DraftPayment(ctx context.Context, paymentSlug string, arrivalDate time.Time, departureDate time.Time, campsiteTypeSlug string, numAdults int, numTeenagers int, numChildren int, numDogs int, zonePreferences string, options OptionUnitsArray) (string, error) { + var paymentSlugParam *string + if paymentSlug != "" { + paymentSlugParam = &paymentSlug + } + return c.GetText(ctx, "select draft_payment($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", paymentSlugParam, arrivalDate, departureDate, campsiteTypeSlug, numAdults, numTeenagers, numChildren, numDogs, zonePreferences, options) +} diff --git a/pkg/database/types.go b/pkg/database/types.go index eee9ca1..fa71745 100644 --- a/pkg/database/types.go +++ b/pkg/database/types.go @@ -15,6 +15,7 @@ import ( const ( RedsysRequestTypeName = "redsys_request" RedsysSignedRequestTypeName = "redsys_signed_request" + OptionUnitsTypeName = "option_units" ) var ( @@ -84,6 +85,21 @@ func registerConnectionTypes(ctx context.Context, conn *pgx.Conn) error { return err } + optionUnitsType, err := pgtype.NewCompositeType( + OptionUnitsTypeName, + []pgtype.CompositeTypeField{ + {"option_id", pgtype.Int4OID}, + {"units", pgtype.Int4OID}, + }, + conn.ConnInfo(), + ) + if err != nil { + return err + } + if _, err = registerType(ctx, conn, optionUnitsType, optionUnitsType.TypeName()); err != nil { + return err + } + return nil } diff --git a/po/ca.po b/po/ca.po index 0a00f1e..1b3c3c9 100644 --- a/po/ca.po +++ b/po/ca.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-02-11 22:01+0100\n" +"POT-Creation-Date: 2024-02-12 05:10+0100\n" "PO-Revision-Date: 2024-02-06 10:04+0100\n" "Last-Translator: jordi fita mas \n" "Language-Team: Catalan \n" @@ -155,7 +155,7 @@ msgid "Discover" msgstr "Descobreix" #: web/templates/public/campsite/type.gohtml:49 -#: web/templates/public/booking/fields.gohtml:243 +#: web/templates/public/booking/fields.gohtml:245 msgctxt "action" msgid "Book" msgstr "Reserva" @@ -278,13 +278,13 @@ msgid "Sun" msgstr "dg" #: web/templates/public/campsite/dates.gohtml:4 -#: web/templates/public/booking/fields.gohtml:26 +#: web/templates/public/booking/fields.gohtml:28 msgctxt "input" msgid "Arrival date" msgstr "Data d’arribada" #: web/templates/public/campsite/dates.gohtml:15 -#: web/templates/public/booking/fields.gohtml:37 +#: web/templates/public/booking/fields.gohtml:39 msgctxt "input" msgid "Departure date" msgstr "Data de sortida" @@ -541,117 +541,117 @@ msgstr "Obertura" msgid "RTC #%s" msgstr "Núm. RTC %s" -#: web/templates/public/booking/fields.gohtml:13 +#: web/templates/public/booking/fields.gohtml:15 msgctxt "title" msgid "Accommodation" msgstr "Allotjaments" -#: web/templates/public/booking/fields.gohtml:23 +#: web/templates/public/booking/fields.gohtml:25 msgctxt "title" msgid "Booking Period" msgstr "Període de reserva" -#: web/templates/public/booking/fields.gohtml:50 +#: web/templates/public/booking/fields.gohtml:52 msgctxt "title" msgid "Guests" msgstr "Hostes" -#: web/templates/public/booking/fields.gohtml:54 +#: web/templates/public/booking/fields.gohtml:56 msgctxt "input" msgid "Adults aged 17 or older" msgstr "Adults de 17 anys o més" -#: web/templates/public/booking/fields.gohtml:65 +#: web/templates/public/booking/fields.gohtml:67 msgctxt "input" msgid "Teenagers from 11 to 16 years old" msgstr "Adolescents d’entre 11 i 16 anys" -#: web/templates/public/booking/fields.gohtml:76 +#: web/templates/public/booking/fields.gohtml:78 msgctxt "input" msgid "Children from 2 to 10 years old" msgstr "Nens d’entre 2 i 10 anys)" -#: web/templates/public/booking/fields.gohtml:86 +#: web/templates/public/booking/fields.gohtml:88 msgid "Note: Due to guest capacity, we have added more accomodations to the booking, but we cannot guarantee that they will be next to each other." msgstr "Nota: S’han afegit més allotjaments a la reserva degut a la capacitat de cadascuna, però no es garanteix que estiguin de costat." -#: web/templates/public/booking/fields.gohtml:94 +#: web/templates/public/booking/fields.gohtml:96 msgctxt "input" msgid "Dogs" msgstr "Gossos" -#: web/templates/public/booking/fields.gohtml:103 +#: web/templates/public/booking/fields.gohtml:105 msgid "Note: This accommodation does not allow dogs." msgstr "Nota: A aquest allotjament no s’hi permeten gossos." -#: web/templates/public/booking/fields.gohtml:113 +#: web/templates/public/booking/fields.gohtml:115 msgctxt "input" msgid "Area preferences (optional)" msgstr "Preferències d’àrea (opcional)" -#: web/templates/public/booking/fields.gohtml:115 +#: web/templates/public/booking/fields.gohtml:117 msgid "Campground map" msgstr "Mapa del càmping" -#: web/templates/public/booking/fields.gohtml:138 +#: web/templates/public/booking/fields.gohtml:140 msgctxt "title" msgid "Customer Details" msgstr "Detalls del client" -#: web/templates/public/booking/fields.gohtml:141 +#: web/templates/public/booking/fields.gohtml:143 msgctxt "input" msgid "Full name" msgstr "Nom i cognoms" -#: web/templates/public/booking/fields.gohtml:150 +#: web/templates/public/booking/fields.gohtml:152 msgctxt "input" msgid "Address (optional)" msgstr "Adreça (opcional)" -#: web/templates/public/booking/fields.gohtml:159 +#: web/templates/public/booking/fields.gohtml:161 msgctxt "input" msgid "Postcode (optional)" msgstr "Codi postal (opcional)" -#: web/templates/public/booking/fields.gohtml:168 +#: web/templates/public/booking/fields.gohtml:170 msgctxt "input" msgid "Town or village (optional)" msgstr "Població (opcional)" -#: web/templates/public/booking/fields.gohtml:177 +#: web/templates/public/booking/fields.gohtml:179 #: web/templates/admin/taxDetails.gohtml:101 msgctxt "input" msgid "Country" msgstr "País" -#: web/templates/public/booking/fields.gohtml:180 +#: web/templates/public/booking/fields.gohtml:182 msgid "Choose a country" msgstr "Esculli un país" -#: web/templates/public/booking/fields.gohtml:188 +#: web/templates/public/booking/fields.gohtml:190 #: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38 #: web/templates/admin/taxDetails.gohtml:53 msgctxt "input" msgid "Email" msgstr "Correu-e" -#: web/templates/public/booking/fields.gohtml:197 +#: web/templates/public/booking/fields.gohtml:199 #: web/templates/admin/taxDetails.gohtml:45 msgctxt "input" msgid "Phone" msgstr "Telèfon" -#: web/templates/public/booking/fields.gohtml:208 +#: web/templates/public/booking/fields.gohtml:210 msgctxt "input" msgid "ACSI card? (optional)" msgstr "Targeta ACSI? (opcional)" -#: web/templates/public/booking/fields.gohtml:215 +#: web/templates/public/booking/fields.gohtml:217 msgctxt "input" msgid "I have read and I accept %[1]sthe reservation conditions%[2]s" msgstr "He llegit i accepto %[1]sles condicions de reserves%[2]s" -#: web/templates/public/booking/fields.gohtml:232 +#: web/templates/public/booking/fields.gohtml:234 msgctxt "cart" msgid "Total" msgstr "Total" @@ -1990,12 +1990,12 @@ msgid "Slide image must be an image media type." msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge." #: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:217 -#: pkg/booking/public.go:577 +#: pkg/booking/public.go:583 msgid "Email can not be empty." msgstr "No podeu deixar el correu-e en blanc." #: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:218 -#: pkg/booking/public.go:578 +#: pkg/booking/public.go:584 msgid "This email is not valid. It should be like name@domain.com." msgstr "Aquest correu-e no és vàlid. Hauria de ser similar a nom@domini.com." @@ -2206,8 +2206,8 @@ msgctxt "header" msgid "Children (aged 2 to 10)" msgstr "Mainada (entre 2 i 10 anys)" -#: pkg/campsite/admin.go:275 pkg/booking/public.go:218 -#: pkg/booking/public.go:270 +#: pkg/campsite/admin.go:275 pkg/booking/public.go:224 +#: pkg/booking/public.go:276 msgid "Selected campsite type is not valid." msgstr "El tipus d’allotjament escollit no és vàlid." @@ -2363,7 +2363,7 @@ msgstr "No podeu deixar l’adreça de l’enllaç en blanc." msgid "This web address is not valid. It should be like https://domain.com/." msgstr "Aquesta adreça web no és vàlida. Hauria de ser similar a https://domini.com/." -#: pkg/company/admin.go:200 pkg/booking/public.go:564 +#: pkg/company/admin.go:200 pkg/booking/public.go:570 msgid "Selected country is not valid." msgstr "El país escollit no és vàlid." @@ -2383,11 +2383,11 @@ msgstr "No podeu deixar el NIF en blanc." msgid "This VAT number is not valid." msgstr "Aquest NIF no és vàlid." -#: pkg/company/admin.go:212 pkg/booking/public.go:580 +#: pkg/company/admin.go:212 pkg/booking/public.go:586 msgid "Phone can not be empty." msgstr "No podeu deixar el telèfon en blanc." -#: pkg/company/admin.go:213 pkg/booking/public.go:581 +#: pkg/company/admin.go:213 pkg/booking/public.go:587 msgid "This phone number is not valid." msgstr "Aquest número de telèfon no és vàlid." @@ -2407,7 +2407,7 @@ msgstr "No podeu deixar la província en blanc." msgid "Postal code can not be empty." msgstr "No podeu deixar el codi postal en blanc." -#: pkg/company/admin.go:227 pkg/booking/public.go:573 +#: pkg/company/admin.go:227 pkg/booking/public.go:579 msgid "This postal code is not valid." msgstr "Aquest codi postal no és vàlid." @@ -2447,32 +2447,32 @@ msgstr "No podeu deixar el fitxer del mèdia en blanc." msgid "Filename can not be empty." msgstr "No podeu deixar el nom del fitxer en blanc." -#: pkg/booking/cart.go:158 +#: pkg/booking/cart.go:144 msgctxt "cart" msgid "Night" msgstr "Nit" -#: pkg/booking/cart.go:159 +#: pkg/booking/cart.go:145 msgctxt "cart" msgid "Adult" msgstr "Adult" -#: pkg/booking/cart.go:160 +#: pkg/booking/cart.go:146 msgctxt "cart" msgid "Teenager" msgstr "Adolescent" -#: pkg/booking/cart.go:161 +#: pkg/booking/cart.go:147 msgctxt "cart" msgid "Child" msgstr "Nen" -#: pkg/booking/cart.go:162 +#: pkg/booking/cart.go:148 msgctxt "cart" msgid "Dog" msgstr "Gos" -#: pkg/booking/cart.go:181 +#: pkg/booking/cart.go:183 msgctxt "cart" msgid "Tourist tax" msgstr "Impost turístic" @@ -2534,124 +2534,124 @@ msgstr "La integració escollida no és vàlida." msgid "The merchant key is not valid." msgstr "Aquesta clau del comerç no és vàlid." -#: pkg/booking/public.go:319 pkg/booking/public.go:348 +#: pkg/booking/public.go:325 pkg/booking/public.go:354 msgid "Arrival date must be a valid date." msgstr "La data d’arribada ha de ser una data vàlida." -#: pkg/booking/public.go:333 pkg/booking/public.go:355 +#: pkg/booking/public.go:339 pkg/booking/public.go:361 msgid "Departure date must be a valid date." msgstr "La data de sortida ha de ser una data vàlida." -#: pkg/booking/public.go:347 +#: pkg/booking/public.go:353 msgid "Arrival date can not be empty" msgstr "No podeu deixar la data d’arribada en blanc." -#: pkg/booking/public.go:349 +#: pkg/booking/public.go:355 #, c-format msgid "Arrival date must be %s or after." msgstr "La data d’arribada ha de ser igual o posterior a %s." -#: pkg/booking/public.go:350 +#: pkg/booking/public.go:356 #, c-format msgid "Arrival date must be %s or before." msgstr "La data d’arribada ha de ser anterior o igual a %s." -#: pkg/booking/public.go:354 +#: pkg/booking/public.go:360 msgid "Departure date can not be empty" msgstr "No podeu deixar la data de sortida en blanc." -#: pkg/booking/public.go:356 +#: pkg/booking/public.go:362 #, c-format msgid "Departure date must be %s or after." msgstr "La data de sortida ha de ser igual o posterior a %s." -#: pkg/booking/public.go:357 +#: pkg/booking/public.go:363 #, c-format msgid "Departure date must be %s or before." msgstr "La data de sortida ha de ser anterior o igual a %s." -#: pkg/booking/public.go:399 +#: pkg/booking/public.go:405 #, c-format msgid "There can be at most %d guests in this accommodation." msgstr "Hi poden haver com a màxim %d convidats a aquest allotjament." -#: pkg/booking/public.go:419 +#: pkg/booking/public.go:425 msgid "Number of adults can not be empty" msgstr "No podeu deixar el número d’adults en blanc." -#: pkg/booking/public.go:420 +#: pkg/booking/public.go:426 msgid "Number of adults must be an integer." msgstr "El número d’adults ha de ser enter." -#: pkg/booking/public.go:421 +#: pkg/booking/public.go:427 msgid "There must be at least one adult." msgstr "Hi ha d’haver com a mínim un adult." -#: pkg/booking/public.go:424 +#: pkg/booking/public.go:430 msgid "Number of teenagers can not be empty" msgstr "No podeu deixar el número d’adolescents en blanc." -#: pkg/booking/public.go:425 +#: pkg/booking/public.go:431 msgid "Number of teenagers must be an integer." msgstr "El número d’adolescents ha de ser enter." -#: pkg/booking/public.go:426 +#: pkg/booking/public.go:432 msgid "Number of teenagers can not be negative." msgstr "El número d’adolescents no pot ser negatiu." -#: pkg/booking/public.go:429 +#: pkg/booking/public.go:435 msgid "Number of children can not be empty" msgstr "No podeu deixar el número de nens en blanc." -#: pkg/booking/public.go:430 +#: pkg/booking/public.go:436 msgid "Number of children must be an integer." msgstr "El número de nens ha de ser enter." -#: pkg/booking/public.go:431 +#: pkg/booking/public.go:437 msgid "Number of children can not be negative." msgstr "El número de nens no pot ser negatiu." -#: pkg/booking/public.go:434 +#: pkg/booking/public.go:440 msgid "Number of dogs can not be empty" msgstr "No podeu deixar el número de gossos en blanc." -#: pkg/booking/public.go:435 +#: pkg/booking/public.go:441 msgid "Number of dogs must be an integer." msgstr "El número de gossos ha de ser enter." -#: pkg/booking/public.go:436 +#: pkg/booking/public.go:442 msgid "Number of dogs can not be negative." msgstr "El número de gossos no pot ser negatiu." -#: pkg/booking/public.go:507 +#: pkg/booking/public.go:513 #, c-format msgid "%s can not be empty" msgstr "No podeu deixar %s en blanc." -#: pkg/booking/public.go:508 +#: pkg/booking/public.go:514 #, c-format msgid "%s must be an integer." msgstr "%s ha de ser un número enter." -#: pkg/booking/public.go:509 +#: pkg/booking/public.go:515 #, c-format msgid "%s must be %d or greater." msgstr "El valor de %s ha de ser com a mínim %d." -#: pkg/booking/public.go:510 +#: pkg/booking/public.go:516 #, c-format msgid "%s must be at most %d." msgstr "El valor de %s ha de ser com a màxim %d." -#: pkg/booking/public.go:568 +#: pkg/booking/public.go:574 msgid "Full name can not be empty." msgstr "No podeu deixar el nom i els cognoms en blanc." -#: pkg/booking/public.go:569 +#: pkg/booking/public.go:575 msgid "Full name must have at least one letter." msgstr "El nom i els cognoms han de tenir com a mínim una lletra." -#: pkg/booking/public.go:586 +#: pkg/booking/public.go:592 msgid "It is mandatory to agree to the reservation conditions." msgstr "És obligatori acceptar les condicions de reserves." diff --git a/po/es.po b/po/es.po index 0cece19..996b9aa 100644 --- a/po/es.po +++ b/po/es.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-02-11 22:01+0100\n" +"POT-Creation-Date: 2024-02-12 05:10+0100\n" "PO-Revision-Date: 2024-02-06 10:04+0100\n" "Last-Translator: jordi fita mas \n" "Language-Team: Spanish \n" @@ -155,7 +155,7 @@ msgid "Discover" msgstr "Descubre" #: web/templates/public/campsite/type.gohtml:49 -#: web/templates/public/booking/fields.gohtml:243 +#: web/templates/public/booking/fields.gohtml:245 msgctxt "action" msgid "Book" msgstr "Reservar" @@ -278,13 +278,13 @@ msgid "Sun" msgstr "do" #: web/templates/public/campsite/dates.gohtml:4 -#: web/templates/public/booking/fields.gohtml:26 +#: web/templates/public/booking/fields.gohtml:28 msgctxt "input" msgid "Arrival date" msgstr "Fecha de llegada" #: web/templates/public/campsite/dates.gohtml:15 -#: web/templates/public/booking/fields.gohtml:37 +#: web/templates/public/booking/fields.gohtml:39 msgctxt "input" msgid "Departure date" msgstr "Fecha de salida" @@ -541,117 +541,117 @@ msgstr "Apertura" msgid "RTC #%s" msgstr " RTC %s" -#: web/templates/public/booking/fields.gohtml:13 +#: web/templates/public/booking/fields.gohtml:15 msgctxt "title" msgid "Accommodation" msgstr "Alojamientos" -#: web/templates/public/booking/fields.gohtml:23 +#: web/templates/public/booking/fields.gohtml:25 msgctxt "title" msgid "Booking Period" msgstr "Periodo de reserva" -#: web/templates/public/booking/fields.gohtml:50 +#: web/templates/public/booking/fields.gohtml:52 msgctxt "title" msgid "Guests" msgstr "Huéspedes" -#: web/templates/public/booking/fields.gohtml:54 +#: web/templates/public/booking/fields.gohtml:56 msgctxt "input" msgid "Adults aged 17 or older" msgstr "Adultos de 17 años o más" -#: web/templates/public/booking/fields.gohtml:65 +#: web/templates/public/booking/fields.gohtml:67 msgctxt "input" msgid "Teenagers from 11 to 16 years old" msgstr "Adolescentes de 11 a 16 años" -#: web/templates/public/booking/fields.gohtml:76 +#: web/templates/public/booking/fields.gohtml:78 msgctxt "input" msgid "Children from 2 to 10 years old" msgstr "Niños de 2 a 10 años" -#: web/templates/public/booking/fields.gohtml:86 +#: web/templates/public/booking/fields.gohtml:88 msgid "Note: Due to guest capacity, we have added more accomodations to the booking, but we cannot guarantee that they will be next to each other." msgstr "Nota: Se han añadido alojamientos a la reserva debido a la capacidad de cada una, pero no se garantiza que estén de lado." -#: web/templates/public/booking/fields.gohtml:94 +#: web/templates/public/booking/fields.gohtml:96 msgctxt "input" msgid "Dogs" msgstr "Perros" -#: web/templates/public/booking/fields.gohtml:103 +#: web/templates/public/booking/fields.gohtml:105 msgid "Note: This accommodation does not allow dogs." msgstr "Nota: En este alojamiento no se permiten perros." -#: web/templates/public/booking/fields.gohtml:113 +#: web/templates/public/booking/fields.gohtml:115 msgctxt "input" msgid "Area preferences (optional)" msgstr "Preferencias de área (opcional)" -#: web/templates/public/booking/fields.gohtml:115 +#: web/templates/public/booking/fields.gohtml:117 msgid "Campground map" msgstr "Mapa del camping" -#: web/templates/public/booking/fields.gohtml:138 +#: web/templates/public/booking/fields.gohtml:140 msgctxt "title" msgid "Customer Details" msgstr "Detalles del cliente" -#: web/templates/public/booking/fields.gohtml:141 +#: web/templates/public/booking/fields.gohtml:143 msgctxt "input" msgid "Full name" msgstr "Nombre y apellidos" -#: web/templates/public/booking/fields.gohtml:150 +#: web/templates/public/booking/fields.gohtml:152 msgctxt "input" msgid "Address (optional)" msgstr "Dirección (opcional)" -#: web/templates/public/booking/fields.gohtml:159 +#: web/templates/public/booking/fields.gohtml:161 msgctxt "input" msgid "Postcode (optional)" msgstr "Código postal (opcional)" -#: web/templates/public/booking/fields.gohtml:168 +#: web/templates/public/booking/fields.gohtml:170 msgctxt "input" msgid "Town or village (optional)" msgstr "Población (opcional)" -#: web/templates/public/booking/fields.gohtml:177 +#: web/templates/public/booking/fields.gohtml:179 #: web/templates/admin/taxDetails.gohtml:101 msgctxt "input" msgid "Country" msgstr "País" -#: web/templates/public/booking/fields.gohtml:180 +#: web/templates/public/booking/fields.gohtml:182 msgid "Choose a country" msgstr "Escoja un país" -#: web/templates/public/booking/fields.gohtml:188 +#: web/templates/public/booking/fields.gohtml:190 #: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38 #: web/templates/admin/taxDetails.gohtml:53 msgctxt "input" msgid "Email" msgstr "Correo-e" -#: web/templates/public/booking/fields.gohtml:197 +#: web/templates/public/booking/fields.gohtml:199 #: web/templates/admin/taxDetails.gohtml:45 msgctxt "input" msgid "Phone" msgstr "Teléfono" -#: web/templates/public/booking/fields.gohtml:208 +#: web/templates/public/booking/fields.gohtml:210 msgctxt "input" msgid "ACSI card? (optional)" msgstr "¿Tarjeta ACSI? (opcional)" -#: web/templates/public/booking/fields.gohtml:215 +#: web/templates/public/booking/fields.gohtml:217 msgctxt "input" msgid "I have read and I accept %[1]sthe reservation conditions%[2]s" msgstr "He leído y acepto %[1]slas condiciones de reserva%[2]s" -#: web/templates/public/booking/fields.gohtml:232 +#: web/templates/public/booking/fields.gohtml:234 msgctxt "cart" msgid "Total" msgstr "Total" @@ -1990,12 +1990,12 @@ msgid "Slide image must be an image media type." msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen." #: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:217 -#: pkg/booking/public.go:577 +#: pkg/booking/public.go:583 msgid "Email can not be empty." msgstr "No podéis dejar el correo-e en blanco." #: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:218 -#: pkg/booking/public.go:578 +#: pkg/booking/public.go:584 msgid "This email is not valid. It should be like name@domain.com." msgstr "Este correo-e no es válido. Tiene que ser parecido a nombre@dominio.com." @@ -2206,8 +2206,8 @@ msgctxt "header" msgid "Children (aged 2 to 10)" msgstr "Niños (de 2 a 10 años)" -#: pkg/campsite/admin.go:275 pkg/booking/public.go:218 -#: pkg/booking/public.go:270 +#: pkg/campsite/admin.go:275 pkg/booking/public.go:224 +#: pkg/booking/public.go:276 msgid "Selected campsite type is not valid." msgstr "El tipo de alojamiento escogido no es válido." @@ -2363,7 +2363,7 @@ msgstr "No podéis dejar la dirección del enlace en blanco." msgid "This web address is not valid. It should be like https://domain.com/." msgstr "Esta dirección web no es válida. Tiene que ser parecido a https://dominio.com/." -#: pkg/company/admin.go:200 pkg/booking/public.go:564 +#: pkg/company/admin.go:200 pkg/booking/public.go:570 msgid "Selected country is not valid." msgstr "El país escogido no es válido." @@ -2383,11 +2383,11 @@ msgstr "No podéis dejar el NIF en blanco." msgid "This VAT number is not valid." msgstr "Este NIF no es válido." -#: pkg/company/admin.go:212 pkg/booking/public.go:580 +#: pkg/company/admin.go:212 pkg/booking/public.go:586 msgid "Phone can not be empty." msgstr "No podéis dejar el teléfono en blanco." -#: pkg/company/admin.go:213 pkg/booking/public.go:581 +#: pkg/company/admin.go:213 pkg/booking/public.go:587 msgid "This phone number is not valid." msgstr "Este teléfono no es válido." @@ -2407,7 +2407,7 @@ msgstr "No podéis dejar la provincia en blanco." msgid "Postal code can not be empty." msgstr "No podéis dejar el código postal en blanco." -#: pkg/company/admin.go:227 pkg/booking/public.go:573 +#: pkg/company/admin.go:227 pkg/booking/public.go:579 msgid "This postal code is not valid." msgstr "Este código postal no es válido." @@ -2447,32 +2447,32 @@ msgstr "No podéis dejar el archivo del medio en blanco." msgid "Filename can not be empty." msgstr "No podéis dejar el nombre del archivo en blanco." -#: pkg/booking/cart.go:158 +#: pkg/booking/cart.go:144 msgctxt "cart" msgid "Night" msgstr "Noche" -#: pkg/booking/cart.go:159 +#: pkg/booking/cart.go:145 msgctxt "cart" msgid "Adult" msgstr "Adulto" -#: pkg/booking/cart.go:160 +#: pkg/booking/cart.go:146 msgctxt "cart" msgid "Teenager" msgstr "Adolescente" -#: pkg/booking/cart.go:161 +#: pkg/booking/cart.go:147 msgctxt "cart" msgid "Child" msgstr "Niño" -#: pkg/booking/cart.go:162 +#: pkg/booking/cart.go:148 msgctxt "cart" msgid "Dog" msgstr "Perro" -#: pkg/booking/cart.go:181 +#: pkg/booking/cart.go:183 msgctxt "cart" msgid "Tourist tax" msgstr "Impuesto turístico" @@ -2534,124 +2534,124 @@ msgstr "La integración escogida no es válida." msgid "The merchant key is not valid." msgstr "Esta clave del comercio no es válida." -#: pkg/booking/public.go:319 pkg/booking/public.go:348 +#: pkg/booking/public.go:325 pkg/booking/public.go:354 msgid "Arrival date must be a valid date." msgstr "La fecha de llegada tiene que ser una fecha válida." -#: pkg/booking/public.go:333 pkg/booking/public.go:355 +#: pkg/booking/public.go:339 pkg/booking/public.go:361 msgid "Departure date must be a valid date." msgstr "La fecha de partida tiene que ser una fecha válida." -#: pkg/booking/public.go:347 +#: pkg/booking/public.go:353 msgid "Arrival date can not be empty" msgstr "No podéis dejar la fecha de llegada en blanco." -#: pkg/booking/public.go:349 +#: pkg/booking/public.go:355 #, c-format msgid "Arrival date must be %s or after." msgstr "La fecha de llegada tiene que ser igual o posterior a %s." -#: pkg/booking/public.go:350 +#: pkg/booking/public.go:356 #, c-format msgid "Arrival date must be %s or before." msgstr "La fecha de llegada tiene que ser anterior o igual a %s." -#: pkg/booking/public.go:354 +#: pkg/booking/public.go:360 msgid "Departure date can not be empty" msgstr "No podéis dejar la fecha de partida en blanco." -#: pkg/booking/public.go:356 +#: pkg/booking/public.go:362 #, c-format msgid "Departure date must be %s or after." msgstr "La fecha de partida tiene que igual o posterior a %s." -#: pkg/booking/public.go:357 +#: pkg/booking/public.go:363 #, c-format msgid "Departure date must be %s or before." msgstr "La fecha de partida tiene que ser anterior o igual a %s." -#: pkg/booking/public.go:399 +#: pkg/booking/public.go:405 #, c-format msgid "There can be at most %d guests in this accommodation." msgstr "Solo puede haber como máximo %d invitados en este alojamiento." -#: pkg/booking/public.go:419 +#: pkg/booking/public.go:425 msgid "Number of adults can not be empty" msgstr "No podéis dejar el número de adultos blanco." -#: pkg/booking/public.go:420 +#: pkg/booking/public.go:426 msgid "Number of adults must be an integer." msgstr "El número de adultos tiene que ser entero." -#: pkg/booking/public.go:421 +#: pkg/booking/public.go:427 msgid "There must be at least one adult." msgstr "Tiene que haber como mínimo un adulto." -#: pkg/booking/public.go:424 +#: pkg/booking/public.go:430 msgid "Number of teenagers can not be empty" msgstr "No podéis dejar el número de adolescentes en blanco." -#: pkg/booking/public.go:425 +#: pkg/booking/public.go:431 msgid "Number of teenagers must be an integer." msgstr "El número de adolescentes tiene que ser entero." -#: pkg/booking/public.go:426 +#: pkg/booking/public.go:432 msgid "Number of teenagers can not be negative." msgstr "El número de adolescentes no puede ser negativo." -#: pkg/booking/public.go:429 +#: pkg/booking/public.go:435 msgid "Number of children can not be empty" msgstr "No podéis dejar el número de niños en blanco." -#: pkg/booking/public.go:430 +#: pkg/booking/public.go:436 msgid "Number of children must be an integer." msgstr "El número de niños tiene que ser entero." -#: pkg/booking/public.go:431 +#: pkg/booking/public.go:437 msgid "Number of children can not be negative." msgstr "El número de niños no puede ser negativo." -#: pkg/booking/public.go:434 +#: pkg/booking/public.go:440 msgid "Number of dogs can not be empty" msgstr "No podéis dejar el número de perros en blanco." -#: pkg/booking/public.go:435 +#: pkg/booking/public.go:441 msgid "Number of dogs must be an integer." msgstr "El número de perros tiene que ser entero." -#: pkg/booking/public.go:436 +#: pkg/booking/public.go:442 msgid "Number of dogs can not be negative." msgstr "El número de perros no puede ser negativo." -#: pkg/booking/public.go:507 +#: pkg/booking/public.go:513 #, c-format msgid "%s can not be empty" msgstr "No podéis dejar %s en blanco." -#: pkg/booking/public.go:508 +#: pkg/booking/public.go:514 #, c-format msgid "%s must be an integer." msgstr "%s tiene que ser un número entero." -#: pkg/booking/public.go:509 +#: pkg/booking/public.go:515 #, c-format msgid "%s must be %d or greater." msgstr "%s tiene que ser como mínimo %d." -#: pkg/booking/public.go:510 +#: pkg/booking/public.go:516 #, c-format msgid "%s must be at most %d." msgstr "%s tiene que ser como máximo %d" -#: pkg/booking/public.go:568 +#: pkg/booking/public.go:574 msgid "Full name can not be empty." msgstr "No podéis dejar el nombre y los apellidos en blanco." -#: pkg/booking/public.go:569 +#: pkg/booking/public.go:575 msgid "Full name must have at least one letter." msgstr "El nombre y los apellidos tienen que tener como mínimo una letra." -#: pkg/booking/public.go:586 +#: pkg/booking/public.go:592 msgid "It is mandatory to agree to the reservation conditions." msgstr "Es obligatorio aceptar las condiciones de reserva." diff --git a/po/fr.po b/po/fr.po index e37293d..89495e0 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-02-11 22:01+0100\n" +"POT-Creation-Date: 2024-02-12 05:10+0100\n" "PO-Revision-Date: 2024-02-06 10:05+0100\n" "Last-Translator: Oriol Carbonell \n" "Language-Team: French \n" @@ -155,7 +155,7 @@ msgid "Discover" msgstr "Découvrir" #: web/templates/public/campsite/type.gohtml:49 -#: web/templates/public/booking/fields.gohtml:243 +#: web/templates/public/booking/fields.gohtml:245 msgctxt "action" msgid "Book" msgstr "Réserver" @@ -278,13 +278,13 @@ msgid "Sun" msgstr "Dim." #: web/templates/public/campsite/dates.gohtml:4 -#: web/templates/public/booking/fields.gohtml:26 +#: web/templates/public/booking/fields.gohtml:28 msgctxt "input" msgid "Arrival date" msgstr "Date d’arrivée" #: web/templates/public/campsite/dates.gohtml:15 -#: web/templates/public/booking/fields.gohtml:37 +#: web/templates/public/booking/fields.gohtml:39 msgctxt "input" msgid "Departure date" msgstr "Date de depart" @@ -541,117 +541,117 @@ msgstr "Ouverture" msgid "RTC #%s" msgstr "# RTC %s" -#: web/templates/public/booking/fields.gohtml:13 +#: web/templates/public/booking/fields.gohtml:15 msgctxt "title" msgid "Accommodation" msgstr "Hébergement" -#: web/templates/public/booking/fields.gohtml:23 +#: web/templates/public/booking/fields.gohtml:25 msgctxt "title" msgid "Booking Period" msgstr "Période de réservation" -#: web/templates/public/booking/fields.gohtml:50 +#: web/templates/public/booking/fields.gohtml:52 msgctxt "title" msgid "Guests" msgstr "Personnes logeant" -#: web/templates/public/booking/fields.gohtml:54 +#: web/templates/public/booking/fields.gohtml:56 msgctxt "input" msgid "Adults aged 17 or older" msgstr "Adultes âgés 17 ans ou plus" -#: web/templates/public/booking/fields.gohtml:65 +#: web/templates/public/booking/fields.gohtml:67 msgctxt "input" msgid "Teenagers from 11 to 16 years old" msgstr "Adolescents de 11 à 16 ans" -#: web/templates/public/booking/fields.gohtml:76 +#: web/templates/public/booking/fields.gohtml:78 msgctxt "input" msgid "Children from 2 to 10 years old" msgstr "Enfants de 2 à 10 ans" -#: web/templates/public/booking/fields.gohtml:86 +#: web/templates/public/booking/fields.gohtml:88 msgid "Note: Due to guest capacity, we have added more accomodations to the booking, but we cannot guarantee that they will be next to each other." msgstr "Remarque : En raison de la capacité d’accueils, nous avons ajouté d’autres hébergements à la réservation, mais nous ne pouvons garantir qu’ils seront côte à côte." -#: web/templates/public/booking/fields.gohtml:94 +#: web/templates/public/booking/fields.gohtml:96 msgctxt "input" msgid "Dogs" msgstr "Chiens" -#: web/templates/public/booking/fields.gohtml:103 +#: web/templates/public/booking/fields.gohtml:105 msgid "Note: This accommodation does not allow dogs." msgstr "Remarque : Dans cet hébergement les chiens ne sont pas acceptés." -#: web/templates/public/booking/fields.gohtml:113 +#: web/templates/public/booking/fields.gohtml:115 msgctxt "input" msgid "Area preferences (optional)" msgstr "Préférences de zone (facultatif)" -#: web/templates/public/booking/fields.gohtml:115 +#: web/templates/public/booking/fields.gohtml:117 msgid "Campground map" msgstr "Plan du camping" -#: web/templates/public/booking/fields.gohtml:138 +#: web/templates/public/booking/fields.gohtml:140 msgctxt "title" msgid "Customer Details" msgstr "Détails du client" -#: web/templates/public/booking/fields.gohtml:141 +#: web/templates/public/booking/fields.gohtml:143 msgctxt "input" msgid "Full name" msgstr "Nom et prénom" -#: web/templates/public/booking/fields.gohtml:150 +#: web/templates/public/booking/fields.gohtml:152 msgctxt "input" msgid "Address (optional)" msgstr "Adresse (Facultatif)" -#: web/templates/public/booking/fields.gohtml:159 +#: web/templates/public/booking/fields.gohtml:161 msgctxt "input" msgid "Postcode (optional)" msgstr "Code postal (Facultatif)" -#: web/templates/public/booking/fields.gohtml:168 +#: web/templates/public/booking/fields.gohtml:170 msgctxt "input" msgid "Town or village (optional)" msgstr "Ville (Facultatif)" -#: web/templates/public/booking/fields.gohtml:177 +#: web/templates/public/booking/fields.gohtml:179 #: web/templates/admin/taxDetails.gohtml:101 msgctxt "input" msgid "Country" msgstr "Pays" -#: web/templates/public/booking/fields.gohtml:180 +#: web/templates/public/booking/fields.gohtml:182 msgid "Choose a country" msgstr "Choisissez un pays" -#: web/templates/public/booking/fields.gohtml:188 +#: web/templates/public/booking/fields.gohtml:190 #: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38 #: web/templates/admin/taxDetails.gohtml:53 msgctxt "input" msgid "Email" msgstr "E-mail" -#: web/templates/public/booking/fields.gohtml:197 +#: web/templates/public/booking/fields.gohtml:199 #: web/templates/admin/taxDetails.gohtml:45 msgctxt "input" msgid "Phone" msgstr "Téléphone" -#: web/templates/public/booking/fields.gohtml:208 +#: web/templates/public/booking/fields.gohtml:210 msgctxt "input" msgid "ACSI card? (optional)" msgstr "Carte ACSI ? (Facultatif)" -#: web/templates/public/booking/fields.gohtml:215 +#: web/templates/public/booking/fields.gohtml:217 msgctxt "input" msgid "I have read and I accept %[1]sthe reservation conditions%[2]s" msgstr "J’ai lu et j’accepte %[1]sles conditions de réservation%[2]s" -#: web/templates/public/booking/fields.gohtml:232 +#: web/templates/public/booking/fields.gohtml:234 msgctxt "cart" msgid "Total" msgstr "Totale" @@ -1990,12 +1990,12 @@ msgid "Slide image must be an image media type." msgstr "L’image de la diapositive doit être de type média d’image." #: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:217 -#: pkg/booking/public.go:577 +#: pkg/booking/public.go:583 msgid "Email can not be empty." msgstr "L’e-mail ne peut pas être vide." #: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:218 -#: pkg/booking/public.go:578 +#: pkg/booking/public.go:584 msgid "This email is not valid. It should be like name@domain.com." msgstr "Cette adresse e-mail n’est pas valide. Il devrait en être name@domain.com." @@ -2206,8 +2206,8 @@ msgctxt "header" msgid "Children (aged 2 to 10)" msgstr "Enfants (de 2 à 10 anys)" -#: pkg/campsite/admin.go:275 pkg/booking/public.go:218 -#: pkg/booking/public.go:270 +#: pkg/campsite/admin.go:275 pkg/booking/public.go:224 +#: pkg/booking/public.go:276 msgid "Selected campsite type is not valid." msgstr "Le type d’emplacement sélectionné n’est pas valide." @@ -2363,7 +2363,7 @@ msgstr "L’addresse du lien ne peut pas être vide." msgid "This web address is not valid. It should be like https://domain.com/." msgstr "Cette adresse web n’est pas valide. Il devrait en être https://domain.com/." -#: pkg/company/admin.go:200 pkg/booking/public.go:564 +#: pkg/company/admin.go:200 pkg/booking/public.go:570 msgid "Selected country is not valid." msgstr "Le pays sélectionné n’est pas valide." @@ -2383,11 +2383,11 @@ msgstr "Le numéro de TVA ne peut pas être vide." msgid "This VAT number is not valid." msgstr "Ce numéro de TVA n’est pas valide." -#: pkg/company/admin.go:212 pkg/booking/public.go:580 +#: pkg/company/admin.go:212 pkg/booking/public.go:586 msgid "Phone can not be empty." msgstr "Le téléphone ne peut pas être vide." -#: pkg/company/admin.go:213 pkg/booking/public.go:581 +#: pkg/company/admin.go:213 pkg/booking/public.go:587 msgid "This phone number is not valid." msgstr "Ce numéro de téléphone n’est pas valide." @@ -2407,7 +2407,7 @@ msgstr "La province ne peut pas être vide." msgid "Postal code can not be empty." msgstr "Le code postal ne peut pas être vide." -#: pkg/company/admin.go:227 pkg/booking/public.go:573 +#: pkg/company/admin.go:227 pkg/booking/public.go:579 msgid "This postal code is not valid." msgstr "Ce code postal n’est pas valide." @@ -2447,32 +2447,32 @@ msgstr "Le fichier téléchargé ne peut pas être vide." msgid "Filename can not be empty." msgstr "Le nom de fichier ne peut pas être vide." -#: pkg/booking/cart.go:158 +#: pkg/booking/cart.go:144 msgctxt "cart" msgid "Night" msgstr "Nuit" -#: pkg/booking/cart.go:159 +#: pkg/booking/cart.go:145 msgctxt "cart" msgid "Adult" msgstr "Adulte" -#: pkg/booking/cart.go:160 +#: pkg/booking/cart.go:146 msgctxt "cart" msgid "Teenager" msgstr "Adolescent" -#: pkg/booking/cart.go:161 +#: pkg/booking/cart.go:147 msgctxt "cart" msgid "Child" msgstr "Enfant" -#: pkg/booking/cart.go:162 +#: pkg/booking/cart.go:148 msgctxt "cart" msgid "Dog" msgstr "Chien" -#: pkg/booking/cart.go:181 +#: pkg/booking/cart.go:183 msgctxt "cart" msgid "Tourist tax" msgstr "Taxe touristique" @@ -2534,124 +2534,124 @@ msgstr "L’intégration sélectionnée n’est pas valide." msgid "The merchant key is not valid." msgstr "La clé marchand n’est pas valide." -#: pkg/booking/public.go:319 pkg/booking/public.go:348 +#: pkg/booking/public.go:325 pkg/booking/public.go:354 msgid "Arrival date must be a valid date." msgstr "La date d’arrivée doit être une date valide." -#: pkg/booking/public.go:333 pkg/booking/public.go:355 +#: pkg/booking/public.go:339 pkg/booking/public.go:361 msgid "Departure date must be a valid date." msgstr "La date de départ doit être une date valide." -#: pkg/booking/public.go:347 +#: pkg/booking/public.go:353 msgid "Arrival date can not be empty" msgstr "La date d’arrivée ne peut pas être vide" -#: pkg/booking/public.go:349 +#: pkg/booking/public.go:355 #, c-format msgid "Arrival date must be %s or after." msgstr "La date d’arrivée doit être égale ou postérieure à %s." -#: pkg/booking/public.go:350 +#: pkg/booking/public.go:356 #, c-format msgid "Arrival date must be %s or before." msgstr "La date d’arrivée doit être antérieure ou égale à %s." -#: pkg/booking/public.go:354 +#: pkg/booking/public.go:360 msgid "Departure date can not be empty" msgstr "La date de départ ne peut pas être vide" -#: pkg/booking/public.go:356 +#: pkg/booking/public.go:362 #, c-format msgid "Departure date must be %s or after." msgstr "La date de départ doit être égale ou postérieure à %s." -#: pkg/booking/public.go:357 +#: pkg/booking/public.go:363 #, c-format msgid "Departure date must be %s or before." msgstr "La date de départ doit être antérieure ou égale à %s." -#: pkg/booking/public.go:399 +#: pkg/booking/public.go:405 #, c-format msgid "There can be at most %d guests in this accommodation." msgstr "Il peut y avoir au plus %d invités dans cet hébergement." -#: pkg/booking/public.go:419 +#: pkg/booking/public.go:425 msgid "Number of adults can not be empty" msgstr "Le nombre d’adultes ne peut pas être vide." -#: pkg/booking/public.go:420 +#: pkg/booking/public.go:426 msgid "Number of adults must be an integer." msgstr "Le nombre d’adultes doit être un entier." -#: pkg/booking/public.go:421 +#: pkg/booking/public.go:427 msgid "There must be at least one adult." msgstr "Il doit y avoir au moins un adulte." -#: pkg/booking/public.go:424 +#: pkg/booking/public.go:430 msgid "Number of teenagers can not be empty" msgstr "Le nombre d’adolescents ne peut pas être vide." -#: pkg/booking/public.go:425 +#: pkg/booking/public.go:431 msgid "Number of teenagers must be an integer." msgstr "Le nombre d’adolescents doit être un entier." -#: pkg/booking/public.go:426 +#: pkg/booking/public.go:432 msgid "Number of teenagers can not be negative." msgstr "Le nombre d’adolescents ne peut pas être négatif." -#: pkg/booking/public.go:429 +#: pkg/booking/public.go:435 msgid "Number of children can not be empty" msgstr "Le nombre d’enfants ne peut pas être vide." -#: pkg/booking/public.go:430 +#: pkg/booking/public.go:436 msgid "Number of children must be an integer." msgstr "Le nombre d’enfants doit être un entier." -#: pkg/booking/public.go:431 +#: pkg/booking/public.go:437 msgid "Number of children can not be negative." msgstr "Le nombre d’enfants ne peut pas être négatif." -#: pkg/booking/public.go:434 +#: pkg/booking/public.go:440 msgid "Number of dogs can not be empty" msgstr "Le nombre de chiens ne peut pas être vide." -#: pkg/booking/public.go:435 +#: pkg/booking/public.go:441 msgid "Number of dogs must be an integer." msgstr "Le nombre de chiens nuits être un entier." -#: pkg/booking/public.go:436 +#: pkg/booking/public.go:442 msgid "Number of dogs can not be negative." msgstr "Le nombre de chiens ne peut pas être négatif." -#: pkg/booking/public.go:507 +#: pkg/booking/public.go:513 #, c-format msgid "%s can not be empty" msgstr "%s ne peut pas être vide" -#: pkg/booking/public.go:508 +#: pkg/booking/public.go:514 #, c-format msgid "%s must be an integer." msgstr "%s doit être un entier." -#: pkg/booking/public.go:509 +#: pkg/booking/public.go:515 #, c-format msgid "%s must be %d or greater." msgstr "%s doit être %d ou plus." -#: pkg/booking/public.go:510 +#: pkg/booking/public.go:516 #, c-format msgid "%s must be at most %d." msgstr "%s doit être tout au plus %d." -#: pkg/booking/public.go:568 +#: pkg/booking/public.go:574 msgid "Full name can not be empty." msgstr "Le nom complet ne peut pas être vide." -#: pkg/booking/public.go:569 +#: pkg/booking/public.go:575 msgid "Full name must have at least one letter." msgstr "Le nom complet doit comporter au moins une lettre." -#: pkg/booking/public.go:586 +#: pkg/booking/public.go:592 msgid "It is mandatory to agree to the reservation conditions." msgstr "Il est obligatoire d’accepter les conditions de réservation." diff --git a/revert/available_payment_status.sql b/revert/available_payment_status.sql new file mode 100644 index 0000000..86cd93b --- /dev/null +++ b/revert/available_payment_status.sql @@ -0,0 +1,14 @@ +-- Revert camper:available_payment_status from pg + +begin; + +delete +from camper.payment_status_i18n +; + +delete +from camper.payment_status +; + + +commit; diff --git a/revert/draft_payment.sql b/revert/draft_payment.sql new file mode 100644 index 0000000..8a39434 --- /dev/null +++ b/revert/draft_payment.sql @@ -0,0 +1,9 @@ +-- Revert camper:draft_payment from pg + +begin; + +drop function if exists camper.draft_payment(uuid, date, date, uuid, integer, integer, integer, integer, text, camper.option_units[]); + +drop type if exists camper.option_units; + +commit; diff --git a/revert/payment.sql b/revert/payment.sql new file mode 100644 index 0000000..b1db524 --- /dev/null +++ b/revert/payment.sql @@ -0,0 +1,7 @@ +-- Revert camper:payment from pg + +begin; + +drop table if exists camper.payment; + +commit; diff --git a/revert/payment_customer.sql b/revert/payment_customer.sql new file mode 100644 index 0000000..c7cc48a --- /dev/null +++ b/revert/payment_customer.sql @@ -0,0 +1,7 @@ +-- Revert camper:payment_customer from pg + +begin; + +drop table if exists camper.payment_customer; + +commit; diff --git a/revert/payment_option.sql b/revert/payment_option.sql new file mode 100644 index 0000000..641d2d8 --- /dev/null +++ b/revert/payment_option.sql @@ -0,0 +1,7 @@ +-- Revert camper:payment_option from pg + +begin; + +drop table if exists camper.payment_option; + +commit; diff --git a/revert/payment_status.sql b/revert/payment_status.sql new file mode 100644 index 0000000..bff0e98 --- /dev/null +++ b/revert/payment_status.sql @@ -0,0 +1,7 @@ +-- Revert camper:payment_status from pg + +begin; + +drop table if exists camper.payment_status; + +commit; diff --git a/revert/payment_status_i18n.sql b/revert/payment_status_i18n.sql new file mode 100644 index 0000000..dcc723d --- /dev/null +++ b/revert/payment_status_i18n.sql @@ -0,0 +1,7 @@ +-- Revert camper:payment_status_i18n from pg + +begin; + +drop table if exists camper.payment_status_i18n; + +commit; diff --git a/sqitch.plan b/sqitch.plan index 1c3450e..5de135f 100644 --- a/sqitch.plan +++ b/sqitch.plan @@ -240,3 +240,10 @@ edit_campsite_type_option [edit_campsite_type_option@v3 campsite_type_option__pe campsite_type_option_cost__cost [campsite_type_option_cost] 2024-02-11T19:50:44Z jordi fita mas # Add cost field to campsite_type_option_cost set_campsite_type_option_cost [set_campsite_type_option_cost@v3 campsite_type_option_cost__cost] 2024-02-11T20:05:58Z jordi fita mas # Update cost instead of cost_per_night in set_campsite_type_option_cost campsite_type_option_cost__-cost_per_night [campsite_type_option_cost campsite_type_option_cost__cost] 2024-02-11T19:58:30Z jordi fita mas # Remove cost_per_night field from campsite_type_option_cost +payment_status [roles schema_camper] 2024-02-11T21:13:32Z jordi fita mas # Add relation of payment statuses +payment_status_i18n [roles schema_camper payment_status language] 2024-02-11T21:20:11Z jordi fita mas # Add relation for translation of payment status +available_payment_status [payment_status payment_status_i18n] 2024-02-11T21:22:38Z jordi fita mas # Add available payment statuses +payment [roles schema_camper company campsite_type payment_status] 2024-02-11T21:54:13Z jordi fita mas # Add relation for payments +payment_customer [roles schema_camper payment country country_code extension_pg_libphonenumber] 2024-02-12T00:10:20Z jordi fita mas # Add relation of payment customer +payment_option [roles schema_camper payment campsite_type_option] 2024-02-12T00:58:07Z jordi fita mas # Add relation of payment for campsite type options +draft_payment [roles schema_camper season_calendar season campsite_type campsite_type_pet_cost campsite_type_cost campsite_type_option_cost campsite_type_option payment payment_option] 2024-02-12T01:31:52Z jordi fita mas # Add function to create a payment draft diff --git a/test/draft_payment.sql b/test/draft_payment.sql new file mode 100644 index 0000000..c193b09 --- /dev/null +++ b/test/draft_payment.sql @@ -0,0 +1,137 @@ +-- Test draft_payment +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(13); + +set search_path to camper, public; + +select has_function('camper', 'draft_payment', array['uuid', 'date', 'date', 'uuid', 'integer', 'integer', 'integer', 'integer', 'text', 'option_units[]']); +select function_lang_is('camper', 'draft_payment', array['uuid', 'date', 'date', 'uuid', 'integer', 'integer', 'integer', 'integer', 'text', 'option_units[]'], 'plpgsql'); +select function_returns('camper', 'draft_payment', array['uuid', 'date', 'date', 'uuid', 'integer', 'integer', 'integer', 'integer', 'text', 'option_units[]'], 'uuid'); +select isnt_definer('camper', 'draft_payment', array['uuid', 'date', 'date', 'uuid', 'integer', 'integer', 'integer', 'integer', 'text', 'option_units[]']); +select volatility_is('camper', 'draft_payment', array['uuid', 'date', 'date', 'uuid', 'integer', 'integer', 'integer', 'integer', 'text', 'option_units[]'], 'volatile'); +select function_privs_are('camper', 'draft_payment', array ['uuid', 'date', 'date', 'uuid', 'integer', 'integer', 'integer', 'integer', 'text', 'option_units[]'], 'guest', array['EXECUTE']); +select function_privs_are('camper', 'draft_payment', array ['uuid', 'date', 'date', 'uuid', 'integer', 'integer', 'integer', 'integer', 'text', 'option_units[]'], 'employee', array['EXECUTE']); +select function_privs_are('camper', 'draft_payment', array ['uuid', 'date', 'date', 'uuid', 'integer', 'integer', 'integer', 'integer', 'text', 'option_units[]'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'draft_payment', array ['uuid', 'date', 'date', 'uuid', 'integer', 'integer', 'integer', 'integer', 'text', 'option_units[]'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate payment_option cascade; +truncate payment cascade; +truncate campsite_type_option_cost cascade; +truncate campsite_type_option cascade; +truncate campsite_type_pet_cost cascade; +truncate campsite_type_cost cascade; +truncate campsite_type cascade; +truncate media cascade; +truncate media_content cascade; +truncate season_calendar cascade; +truncate season cascade; +truncate company cascade; +reset client_min_messages; + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 350, 'ES', 'EUR', 'ca') +; + +insert into season (season_id, company_id, name) +values (4, 2, 'High') + , (6, 2, 'Shoulder') + , (8, 2, 'Offseason') +; + +insert into season_calendar (season_id, season_range) +values (4, '[2024-07-01,2024-08-30)') + , (6, '[2024-08-30,2024-09-03)') + , (8, '[2024-09-03,2024-09-08)') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (10, 2, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into campsite_type (campsite_type_id, slug, company_id, name, media_id, max_campers, bookable_nights, overflow_allowed) +values (12, 'c1b6f4fc-32c1-4cd5-b796-0c5059152a52', 2, 'Plots', 10, 6, '[1, 7]', true) + , (14, 'b065f4e3-2cc8-491d-a413-d015d7d00183', 2, 'Bungalow', 10, 6, '[1, 7]', false) +; + +insert into campsite_type_cost (campsite_type_id, season_id, cost_per_night, cost_per_adult, cost_per_teenager, cost_per_child) +values (12, 4, 400, 795, 795, 640) + , (12, 6, 200, 740, 740, 590) + , (12, 8, 0, 660, 660, 540) + , (14, 4, 17000, 0, 0, 0) + , (14, 6, 13500, 0, 0, 0) + , (14, 8, 10500, 0, 0, 0) +; + +insert into campsite_type_pet_cost (campsite_type_id, cost_per_night) +values (12, 350) +; + +insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range, per_night) +values (16, 12, 'Big tent', '[0, 4)', true) + , (18, 12, 'Car', '[0, 4)', true) + , (20, 12, 'Electricity', '[0, 5)', false) +; + +insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost) +values (16, 4, 800) + , (16, 6, 720) + , (16, 8, 620) + , (18, 4, 700) + , (18, 6, 630) + , (18, 8, 530) + , (20, 4, 690) + , (20, 6, 610) + , (20, 8, 590) +; + +insert into payment (payment_id, slug, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences, created_at, updated_at) +values (22, '7cccfe16-695e-486d-a6a5-1162fb85cafb', 2, 12, '2024-08-30', '2024-09-01', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '2024-01-01 01:01:01', '2024-01-01 01:01:01') +; + +insert into payment_option (payment_id, campsite_type_option_id, units, subtotal) +values (22, 16, 1, 0) + , (22, 18, 1, 0) +; + +select lives_ok( + $$ select draft_payment(null, '2024-08-29', '2024-09-03', 'b065f4e3-2cc8-491d-a413-d015d7d00183', 1, 2, 3, 0, null, null) $$, + 'Should be able to create a new draft for Bungalows' +); + +select lives_ok( + $$ select draft_payment('7cccfe16-695e-486d-a6a5-1162fb85cafb', '2024-08-28', '2024-09-04', 'c1b6f4fc-32c1-4cd5-b796-0c5059152a52', 2, 4, 6, 3, 'pref I before E', array[(16, 2), (20, 3)]::option_units[]) $$, + 'Should be able to update the draft for Plots' +); + +select bag_eq( + $$ select company_id, campsite_type_id, arrival_date::text, departure_date::text, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences, created_at, updated_at from payment $$, + $$ values (2, 12, '2024-08-28', '2024-09-04', 3200, 2, 10420, 4, 20840, 6, 25080, 3, 2450, 4900, 79160, 'pref I before E', '2024-01-01 01:01:01', current_timestamp) + , (2, 14, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, '', current_timestamp, current_timestamp) + $$, + 'Should have added and updated payments' +); + +select bag_eq( + $$ select payment_id, campsite_type_option_id, units, subtotal from payment_option $$, + $$ values (22, 16, 2, 10200) + , (22, 20, 3, 2070) + $$, + 'Should have added, updated, and removed payment options' +); + + +select * +from finish(); + +rollback; diff --git a/test/payment.sql b/test/payment.sql new file mode 100644 index 0000000..e7f78e0 --- /dev/null +++ b/test/payment.sql @@ -0,0 +1,239 @@ +-- Test payment +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(114); + +set search_path to camper, public; + +select has_table('payment'); +select has_pk('payment'); +select table_privs_are('payment', 'guest', array['SELECT', 'INSERT', 'UPDATE']); +select table_privs_are('payment', 'employee', array['SELECT', 'INSERT', 'UPDATE']); +select table_privs_are('payment', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('payment', 'authenticator', array[]::text[]); + +select has_column('payment', 'payment_id'); +select col_is_pk('payment', 'payment_id'); +select col_type_is('payment', 'payment_id', 'integer'); +select col_not_null('payment', 'payment_id'); +select col_hasnt_default('payment', 'payment_id'); + +select has_column('payment', 'company_id'); +select col_is_fk('payment', 'company_id'); +select fk_ok('payment', 'company_id', 'company', 'company_id'); +select col_type_is('payment', 'company_id', 'integer'); +select col_not_null('payment', 'company_id'); +select col_hasnt_default('payment', 'company_id'); + +select has_column('payment', 'slug'); +select col_is_unique('payment', 'slug'); +select col_type_is('payment', 'slug', 'uuid'); +select col_not_null('payment', 'slug'); +select col_has_default('payment', 'slug'); +select col_default_is('payment', 'slug', 'gen_random_uuid()'); + +select has_column('payment', 'campsite_type_id'); +select col_is_fk('payment', 'campsite_type_id'); +select fk_ok('payment', 'campsite_type_id', 'campsite_type', 'campsite_type_id'); +select col_type_is('payment', 'campsite_type_id', 'integer'); +select col_not_null('payment', 'campsite_type_id'); +select col_hasnt_default('payment', 'campsite_type_id'); + +select has_column('payment', 'arrival_date'); +select col_type_is('payment', 'arrival_date', 'date'); +select col_not_null('payment', 'arrival_date'); +select col_hasnt_default('payment', 'arrival_date'); + +select has_column('payment', 'departure_date'); +select col_type_is('payment', 'departure_date', 'date'); +select col_not_null('payment', 'departure_date'); +select col_hasnt_default('payment', 'departure_date'); + +select has_column('payment', 'subtotal_nights'); +select col_type_is('payment', 'subtotal_nights', 'integer'); +select col_not_null('payment', 'subtotal_nights'); +select col_hasnt_default('payment', 'subtotal_nights'); + +select has_column('payment', 'number_adults'); +select col_type_is('payment', 'number_adults', 'integer'); +select col_not_null('payment', 'number_adults'); +select col_hasnt_default('payment', 'number_adults'); + +select has_column('payment', 'subtotal_adults'); +select col_type_is('payment', 'subtotal_adults', 'integer'); +select col_not_null('payment', 'subtotal_adults'); +select col_hasnt_default('payment', 'subtotal_adults'); + +select has_column('payment', 'number_teenagers'); +select col_type_is('payment', 'number_teenagers', 'integer'); +select col_not_null('payment', 'number_teenagers'); +select col_hasnt_default('payment', 'number_teenagers'); + +select has_column('payment', 'subtotal_teenagers'); +select col_type_is('payment', 'subtotal_teenagers', 'integer'); +select col_not_null('payment', 'subtotal_teenagers'); +select col_hasnt_default('payment', 'subtotal_teenagers'); + +select has_column('payment', 'number_children'); +select col_type_is('payment', 'number_children', 'integer'); +select col_not_null('payment', 'number_children'); +select col_hasnt_default('payment', 'number_children'); + +select has_column('payment', 'subtotal_children'); +select col_type_is('payment', 'subtotal_children', 'integer'); +select col_not_null('payment', 'subtotal_children'); +select col_hasnt_default('payment', 'subtotal_children'); + +select has_column('payment', 'number_dogs'); +select col_type_is('payment', 'number_dogs', 'integer'); +select col_not_null('payment', 'number_dogs'); +select col_hasnt_default('payment', 'number_dogs'); + +select has_column('payment', 'subtotal_dogs'); +select col_type_is('payment', 'subtotal_dogs', 'integer'); +select col_not_null('payment', 'subtotal_dogs'); +select col_hasnt_default('payment', 'subtotal_dogs'); + +select has_column('payment', 'subtotal_tourist_tax'); +select col_type_is('payment', 'subtotal_tourist_tax', 'integer'); +select col_not_null('payment', 'subtotal_tourist_tax'); +select col_hasnt_default('payment', 'subtotal_tourist_tax'); + +select has_column('payment', 'total'); +select col_type_is('payment', 'total', 'integer'); +select col_not_null('payment', 'total'); +select col_hasnt_default('payment', 'total'); + +select has_column('payment', 'zone_preferences'); +select col_type_is('payment', 'zone_preferences', 'text'); +select col_not_null('payment', 'zone_preferences'); +select col_hasnt_default('payment', 'zone_preferences'); + +select has_column('payment', 'payment_status'); +select col_is_fk('payment', 'payment_status'); +select fk_ok('payment', 'payment_status', 'payment_status', 'payment_status'); +select col_type_is('payment', 'payment_status', 'text'); +select col_not_null('payment', 'payment_status'); +select col_has_default('payment', 'payment_status'); +select col_default_is('payment', 'payment_status', 'draft'); + +select has_column('payment', 'created_at'); +select col_type_is('payment', 'created_at', 'timestamp with time zone'); +select col_not_null('payment', 'created_at'); +select col_has_default('payment', 'created_at'); +select col_default_is('payment', 'created_at', 'CURRENT_TIMESTAMP'); + +select has_column('payment', 'updated_at'); +select col_type_is('payment', 'updated_at', 'timestamp with time zone'); +select col_not_null('payment', 'updated_at'); +select col_has_default('payment', 'updated_at'); +select col_default_is('payment', 'updated_at', 'CURRENT_TIMESTAMP'); + + +set client_min_messages to warning; +truncate payment cascade; +truncate campsite_type cascade; +truncate media cascade; +truncate media_content cascade; +truncate company cascade; +reset client_min_messages; + + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, description, max_campers, bookable_nights, active) +values (10, 1, 2, 'Type A', '

A

', 5, '[1, 7]', true) +; + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-07', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "departure_after_arrival"', + 'Should not be able to insert a payment with a departure date equal or before the arrival date (i.e., at least one night)' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "subtotal_nights_not_negative"', + 'Should not be able to insert a payment with negative subtotal for nights' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "number_adults_positive"', + 'Should not be able to insert a payment with no adults' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "subtotal_adults_not_negative"', + 'Should not be able to insert a payment with a negative subtotal for adults' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "number_teenagers_not_negative"', + 'Should not be able to insert a payment with a negative number of teenagers' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "subtotal_teenagers_not_negative"', + 'Should not be able to insert a payment with a negative subtotal for teenagers' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "number_children_not_negative"', + 'Should not be able to insert a payment with a negative number of children' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "subtotal_children_not_negative"', + 'Should not be able to insert a payment with a negative subtotal for children' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "number_dogs_not_negative"', + 'Should not be able to insert a payment with a negative number of dogs' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "subtotal_dogs_not_negative"', + 'Should not be able to insert a payment with a negative subtotal for dogs' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, '') $$, + '23514', 'new row for relation "payment" violates check constraint "subtotal_tourist_tax_not_negative"', + 'Should not be able to insert a payment with a negative subtotal for tourist tax' +); + +select throws_ok( + $$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-09', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, '') $$, + '23514', 'new row for relation "payment" violates check constraint "total_not_negative"', + 'Should not be able to insert a payment with a negative total' +); + + +select * +from finish(); + +rollback; + diff --git a/test/payment_customer.sql b/test/payment_customer.sql new file mode 100644 index 0000000..e6dcc8b --- /dev/null +++ b/test/payment_customer.sql @@ -0,0 +1,74 @@ +-- Test payment_customer +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(47); + +set search_path to camper, public; + +select has_table('payment_customer'); +select has_pk('payment_customer'); +select table_privs_are('payment_customer', 'guest', array['SELECT', 'INSERT']); +select table_privs_are('payment_customer', 'employee', array['SELECT', 'INSERT', 'UPDATE']); +select table_privs_are('payment_customer', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('payment_customer', 'authenticator', array[]::text[]); + +select has_column('payment_customer', 'payment_id'); +select col_is_pk('payment_customer', 'payment_id'); +select col_is_fk('payment_customer', 'payment_id'); +select fk_ok('payment_customer', 'payment_id', 'payment', 'payment_id'); +select col_type_is('payment_customer', 'payment_id', 'integer'); +select col_not_null('payment_customer', 'payment_id'); +select col_hasnt_default('payment_customer', 'payment_id'); + +select has_column('payment_customer', 'full_name'); +select col_type_is('payment_customer', 'full_name', 'text'); +select col_not_null('payment_customer', 'full_name'); +select col_hasnt_default('payment_customer', 'full_name'); + +select has_column('payment_customer', 'address'); +select col_type_is('payment_customer', 'address', 'text'); +select col_not_null('payment_customer', 'address'); +select col_hasnt_default('payment_customer', 'address'); + +select has_column('payment_customer', 'postal_code'); +select col_type_is('payment_customer', 'postal_code', 'text'); +select col_not_null('payment_customer', 'postal_code'); +select col_hasnt_default('payment_customer', 'postal_code'); + +select has_column('payment_customer', 'city'); +select col_type_is('payment_customer', 'city', 'text'); +select col_not_null('payment_customer', 'city'); +select col_hasnt_default('payment_customer', 'city'); + +select has_column('payment_customer', 'country_code'); +select col_is_fk('payment_customer', 'country_code'); +select fk_ok('payment_customer', 'country_code', 'country', 'country_code'); +select col_type_is('payment_customer', 'country_code', 'country_code'); +select col_not_null('payment_customer', 'country_code'); +select col_hasnt_default('payment_customer', 'country_code'); + +select has_column('payment_customer', 'email'); +select col_type_is('payment_customer', 'email', 'email'); +select col_not_null('payment_customer', 'email'); +select col_hasnt_default('payment_customer', 'email'); + +select has_column('payment_customer', 'phone'); +select col_type_is('payment_customer', 'phone', 'packed_phone_number'); +select col_not_null('payment_customer', 'phone'); +select col_hasnt_default('payment_customer', 'phone'); + +select has_column('payment_customer', 'acsi_card'); +select col_type_is('payment_customer', 'acsi_card', 'boolean'); +select col_not_null('payment_customer', 'acsi_card'); +select col_hasnt_default('payment_customer', 'acsi_card'); + + +select * +from finish(); + +rollback; + diff --git a/test/payment_option.sql b/test/payment_option.sql new file mode 100644 index 0000000..773207d --- /dev/null +++ b/test/payment_option.sql @@ -0,0 +1,97 @@ +-- Test payment_option +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(29); + +set search_path to camper, public; + +select has_table('payment_option'); +select has_pk('payment_option'); +select col_is_pk('payment_option', array['payment_id', 'campsite_type_option_id']); +select table_privs_are('payment_option', 'guest', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('payment_option', 'employee', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('payment_option', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('payment_option', 'authenticator', array[]::text[]); + +select has_column('payment_option', 'payment_id'); +select col_is_fk('payment_option', 'payment_id'); +select fk_ok('payment_option', 'payment_id', 'payment', 'payment_id'); +select col_type_is('payment_option', 'payment_id', 'integer'); +select col_not_null('payment_option', 'payment_id'); +select col_hasnt_default('payment_option', 'payment_id'); + +select has_column('payment_option', 'campsite_type_option_id'); +select col_is_fk('payment_option', 'campsite_type_option_id'); +select fk_ok('payment_option', 'campsite_type_option_id', 'campsite_type_option', 'campsite_type_option_id'); +select col_type_is('payment_option', 'campsite_type_option_id', 'integer'); +select col_not_null('payment_option', 'campsite_type_option_id'); +select col_hasnt_default('payment_option', 'campsite_type_option_id'); + +select has_column('payment_option', 'units'); +select col_type_is('payment_option', 'units', 'integer'); +select col_not_null('payment_option', 'units'); +select col_hasnt_default('payment_option', 'units'); + +select has_column('payment_option', 'subtotal'); +select col_type_is('payment_option', 'subtotal', 'integer'); +select col_not_null('payment_option', 'subtotal'); +select col_hasnt_default('payment_option', 'subtotal'); + + +set client_min_messages to warning; +truncate payment_option cascade; +truncate payment cascade; +truncate campsite_type_option cascade; +truncate campsite_type cascade; +truncate media cascade; +truncate media_content cascade; +truncate company cascade; +reset client_min_messages; + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, description, max_campers, bookable_nights, active) +values (10, 1, 2, 'Type A', '

A

', 5, '[1, 7]', true) +; + +insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range, per_night) +values (11, 10, 'Option 1', '[2, 2]', true) + , (12, 10, 'Option 2', '[4, 8]', true) +; + +insert into payment (payment_id, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) +values (15, 1, 10, '2024-07-07', '2024-07-08', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, '') +; + +select throws_ok( + $$ insert into payment_option (payment_id, campsite_type_option_id, units, subtotal) values (15, 11, 0, 0) $$, + '23514', 'new row for relation "payment_option" violates check constraint "units_positive"', + 'Should not be able to insert a payment option with zero units' +); + +select throws_ok( + $$ insert into payment_option (payment_id, campsite_type_option_id, units, subtotal) values (15, 12, 1, -1) $$, + '23514', 'new row for relation "payment_option" violates check constraint "subtotal_not_negative"', + 'Should not be able to insert a payment option with a negative subtotal' +); + + +select * +from finish(); + +rollback; + diff --git a/test/payment_status.sql b/test/payment_status.sql new file mode 100644 index 0000000..fb7ac14 --- /dev/null +++ b/test/payment_status.sql @@ -0,0 +1,35 @@ +-- Test payment_status +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(15); + +set search_path to camper, public; + +select has_table('payment_status'); +select has_pk('payment_status'); +select table_privs_are('payment_status', 'guest', array[]::text[]); +select table_privs_are('payment_status', 'employee', array['SELECT']); +select table_privs_are('payment_status', 'admin', array['SELECT']); +select table_privs_are('payment_status', 'authenticator', array[]::text[]); + +select has_column('payment_status', 'payment_status'); +select col_is_pk('payment_status', 'payment_status'); +select col_type_is('payment_status', 'payment_status', 'text'); +select col_not_null('payment_status', 'payment_status'); +select col_hasnt_default('payment_status', 'payment_status'); + +select has_column('payment_status', 'name'); +select col_type_is('payment_status', 'name', 'text'); +select col_not_null('payment_status', 'name'); +select col_hasnt_default('payment_status', 'name'); + + +select * +from finish(); + +rollback; + diff --git a/test/payment_status_i18n.sql b/test/payment_status_i18n.sql new file mode 100644 index 0000000..7b68ed6 --- /dev/null +++ b/test/payment_status_i18n.sql @@ -0,0 +1,44 @@ +-- Test payment_status_i18n +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(23); + +set search_path to camper, public; + +select has_table('payment_status_i18n'); +select has_pk('payment_status_i18n'); +select col_is_pk('payment_status_i18n', array['payment_status', 'lang_tag']); +select table_privs_are('payment_status_i18n', 'guest', array[]::text[]); +select table_privs_are('payment_status_i18n', 'employee', array['SELECT']); +select table_privs_are('payment_status_i18n', 'admin', array['SELECT']); +select table_privs_are('payment_status_i18n', 'authenticator', array[]::text[]); + +select has_column('payment_status_i18n', 'payment_status'); +select col_is_fk('payment_status_i18n', 'payment_status'); +select fk_ok('payment_status_i18n', 'payment_status', 'payment_status', 'payment_status'); +select col_type_is('payment_status_i18n', 'payment_status', 'text'); +select col_not_null('payment_status_i18n', 'payment_status'); +select col_hasnt_default('payment_status_i18n', 'payment_status'); + +select has_column('payment_status_i18n', 'lang_tag'); +select col_is_fk('payment_status_i18n', 'lang_tag'); +select fk_ok('payment_status_i18n', 'lang_tag', 'language', 'lang_tag'); +select col_type_is('payment_status_i18n', 'lang_tag', 'text'); +select col_not_null('payment_status_i18n', 'lang_tag'); +select col_hasnt_default('payment_status_i18n', 'lang_tag'); + +select has_column('payment_status_i18n', 'name'); +select col_type_is('payment_status_i18n', 'name', 'text'); +select col_not_null('payment_status_i18n', 'name'); +select col_hasnt_default('payment_status_i18n', 'name'); + + +select * +from finish(); + +rollback; + diff --git a/verify/available_payment_status.sql b/verify/available_payment_status.sql new file mode 100644 index 0000000..083cd9e --- /dev/null +++ b/verify/available_payment_status.sql @@ -0,0 +1,30 @@ +-- Verify camper:available_payment_status on pg + +begin; + +set search_path to camper; + +select 1 / count(*) from payment_status where payment_status = 'draft' and name = 'Draft'; +select 1 / count(*) from payment_status where payment_status = 'pending' and name = 'Pending'; +select 1 / count(*) from payment_status where payment_status = 'failed' and name = 'Failed'; +select 1 / count(*) from payment_status where payment_status = 'completed' and name = 'Completed'; +select 1 / count(*) from payment_status where payment_status = 'refunded' and name = 'Refunded'; + +select 1 / count(*) from payment_status_i18n where payment_status = 'draft' and lang_tag = 'ca' and name = 'Esborrany'; +select 1 / count(*) from payment_status_i18n where payment_status = 'pending' and lang_tag = 'ca' and name = 'Pendent'; +select 1 / count(*) from payment_status_i18n where payment_status = 'failed' and lang_tag = 'ca' and name = 'No realitzat'; +select 1 / count(*) from payment_status_i18n where payment_status = 'completed' and lang_tag = 'ca' and name = 'Completat'; +select 1 / count(*) from payment_status_i18n where payment_status = 'refunded' and lang_tag = 'ca' and name = 'Reemborsat'; + +select 1 / count(*) from payment_status_i18n where payment_status = 'draft' and lang_tag = 'es' and name = 'Borrador'; +select 1 / count(*) from payment_status_i18n where payment_status = 'pending' and lang_tag = 'es' and name = 'Pendiente'; +select 1 / count(*) from payment_status_i18n where payment_status = 'failed' and lang_tag = 'es' and name = 'Fallido'; +select 1 / count(*) from payment_status_i18n where payment_status = 'completed' and lang_tag = 'es' and name = 'Completado'; +select 1 / count(*) from payment_status_i18n where payment_status = 'refunded' and lang_tag = 'es' and name = 'Reembolsado'; + +select 1 / count(*) from payment_status_i18n where payment_status = 'draft' and lang_tag = 'fr' and name = 'Brouillon'; +select 1 / count(*) from payment_status_i18n where payment_status = 'failed' and lang_tag = 'fr' and name = 'Échouée'; +select 1 / count(*) from payment_status_i18n where payment_status = 'completed' and lang_tag = 'fr' and name = 'Terminée'; +select 1 / count(*) from payment_status_i18n where payment_status = 'refunded' and lang_tag = 'fr' and name = 'Remboursée'; + +rollback; diff --git a/verify/draft_payment.sql b/verify/draft_payment.sql new file mode 100644 index 0000000..653df13 --- /dev/null +++ b/verify/draft_payment.sql @@ -0,0 +1,7 @@ +-- Verify camper:draft_payment on pg + +begin; + +select has_function_privilege('camper.draft_payment(uuid, date, date, uuid, integer, integer, integer, integer, text, camper.option_units[])', 'execute'); + +rollback; diff --git a/verify/payment.sql b/verify/payment.sql new file mode 100644 index 0000000..b065d15 --- /dev/null +++ b/verify/payment.sql @@ -0,0 +1,29 @@ +-- Verify camper:payment on pg + +begin; + +select payment_id + , company_id + , slug + , campsite_type_id + , arrival_date + , departure_date + , subtotal_nights + , number_adults + , subtotal_adults + , number_teenagers + , subtotal_teenagers + , number_children + , subtotal_children + , number_dogs + , subtotal_dogs + , subtotal_tourist_tax + , total + , zone_preferences + , payment_status + , created_at + , updated_at +from camper.payment +where false; + +rollback; diff --git a/verify/payment_customer.sql b/verify/payment_customer.sql new file mode 100644 index 0000000..5b2b805 --- /dev/null +++ b/verify/payment_customer.sql @@ -0,0 +1,17 @@ +-- Verify camper:payment_customer on pg + +begin; + +select payment_id + , full_name + , address + , postal_code + , city + , country_code + , email + , phone + , acsi_card +from camper.payment_customer +where false; + +rollback; diff --git a/verify/payment_option.sql b/verify/payment_option.sql new file mode 100644 index 0000000..c63784f --- /dev/null +++ b/verify/payment_option.sql @@ -0,0 +1,12 @@ +-- Verify camper:payment_option on pg + +begin; + +select payment_id + , campsite_type_option_id + , units + , subtotal +from camper.payment_option +where false; + +rollback; diff --git a/verify/payment_status.sql b/verify/payment_status.sql new file mode 100644 index 0000000..0c763af --- /dev/null +++ b/verify/payment_status.sql @@ -0,0 +1,10 @@ +-- Verify camper:payment_status on pg + +begin; + +select payment_status + , name +from camper.payment_status +where false; + +rollback; diff --git a/verify/payment_status_i18n.sql b/verify/payment_status_i18n.sql new file mode 100644 index 0000000..9da6c40 --- /dev/null +++ b/verify/payment_status_i18n.sql @@ -0,0 +1,11 @@ +-- Verify camper:payment_status_i18n on pg + +begin; + +select payment_status + , lang_tag + , name +from camper.payment_status_i18n +where false; + +rollback; diff --git a/web/templates/public/booking/fields.gohtml b/web/templates/public/booking/fields.gohtml index 6ca6d47..6332b99 100644 --- a/web/templates/public/booking/fields.gohtml +++ b/web/templates/public/booking/fields.gohtml @@ -9,6 +9,8 @@ data-hx-get="/{{ currentLocale }}/booking" data-hx-trigger="change" > + +
{{( pgettext "Accommodation" "title" )}} {{ range .CampsiteType.Options -}}