Allow campsite type option to be just per unit, not per unit per night

Customer told us that there are some options, such as towels, that have
a fixed price for the whole stay, not a per night price.  Thus, had to
add a boolean to know whether to use sum or max when computing the
cart’s total for each option.
This commit is contained in:
jordi fita mas 2024-02-11 21:45:00 +01:00
parent 92dba96b29
commit ea997a4154
45 changed files with 723 additions and 294 deletions

View File

@ -1250,16 +1250,14 @@ select set_campsite_type_cost (slug, 93, '165.00', '0.0', '0.0', '0.0') from cam
select set_campsite_type_cost (slug, 94, '125.00', '0.0', '0.0', '0.0') from campsite_type where campsite_type_id = 76;
alter table campsite_type_option alter column campsite_type_option_id restart with 102;
insert into campsite_type_option (campsite_type_id, name, range)
values (72, 'Tenda petita (màx. 2 pers.)', '[0, 3]')
, (72, 'Tenda gran', '[0, 3]')
, (72, 'Caravana', '[0, 3]')
, (72, 'Autocaravana', '[0, 3]')
, (72, 'Furgoneta', '[0, 3]')
, (72, 'Cotxe', '[0, 3]')
, (72, 'Moto', '[0, 3]')
, (72, 'Punt electricitat', '[0, 4]')
;
select add_campsite_type_option (slug, 'Tenda petita (màx. 2 pers.)', 0, 3, true) from campsite_type where campsite_type_id = 72;
select add_campsite_type_option (slug, 'Tenda gran', 0, 3, true) from campsite_type where campsite_type_id = 72;
select add_campsite_type_option (slug, 'Caravana', 0, 3, true) from campsite_type where campsite_type_id = 72;
select add_campsite_type_option (slug, 'Autocaravana', 0, 3, true) from campsite_type where campsite_type_id = 72;
select add_campsite_type_option (slug, 'Furgoneta', 0, 3, true) from campsite_type where campsite_type_id = 72;
select add_campsite_type_option (slug, 'Cotxe', 0, 3, true) from campsite_type where campsite_type_id = 72;
select add_campsite_type_option (slug, 'Moto', 0, 3, true) from campsite_type where campsite_type_id = 72;
select add_campsite_type_option (slug, 'Punt electricitat', 0, 4, true) from campsite_type where campsite_type_id = 72;
select translate_campsite_type_option(102, 'en', 'Small tent (2 pax max.)');
select translate_campsite_type_option(102, 'es', 'Tienda pequeña (máx. 2 pers.)');

View File

@ -3,15 +3,18 @@
-- requires: schema_camper
-- requires: campsite_type_option
-- requires: campsite_type
-- requires: campsite_type_option__per_night
begin;
set search_path to camper, public;
create or replace function add_campsite_type_option(type_slug uuid, name text, min integer, max integer) returns integer as
drop function if exists add_campsite_type_option(uuid, text, integer, integer);
create or replace function add_campsite_type_option(type_slug uuid, name text, min integer, max integer, per_night boolean) returns integer as
$$
insert into campsite_type_option (campsite_type_id, name, range)
select campsite_type_id, add_campsite_type_option.name, int4range(min, max, '[]')
insert into campsite_type_option (campsite_type_id, name, range, per_night)
select campsite_type_id, add_campsite_type_option.name, int4range(min, max, '[]'), per_night
from campsite_type
where slug = type_slug
returning campsite_type_option_id
@ -20,7 +23,7 @@ $$
language sql
;
revoke execute on function add_campsite_type_option(uuid, text, integer, integer) from public;
grant execute on function add_campsite_type_option(uuid, text, integer, integer) to admin;
revoke execute on function add_campsite_type_option(uuid, text, integer, integer, boolean) from public;
grant execute on function add_campsite_type_option(uuid, text, integer, integer, boolean) to admin;
commit;

View File

@ -0,0 +1,26 @@
-- Deploy camper:add_campsite_type_option to pg
-- requires: roles
-- requires: schema_camper
-- requires: campsite_type_option
-- requires: campsite_type
begin;
set search_path to camper, public;
create or replace function add_campsite_type_option(type_slug uuid, name text, min integer, max integer) returns integer as
$$
insert into campsite_type_option (campsite_type_id, name, range)
select campsite_type_id, add_campsite_type_option.name, int4range(min, max, '[]')
from campsite_type
where slug = type_slug
returning campsite_type_option_id
;
$$
language sql
;
revoke execute on function add_campsite_type_option(uuid, text, integer, integer) from public;
grant execute on function add_campsite_type_option(uuid, text, integer, integer) to admin;
commit;

View File

@ -0,0 +1,14 @@
-- Deploy camper:campsite_type_option__per_night to pg
-- requires: campsite_type_option
begin;
alter table camper.campsite_type_option
add column per_night boolean not null default true
;
alter table camper.campsite_type_option
alter column per_night drop default
;
commit;

View File

@ -0,0 +1,17 @@
-- Deploy camper:campsite_type_option_cost__-cost_per_night to pg
-- requires: campsite_type_option_cost
-- requires: campsite_type_option_cost__cost
begin;
set search_path to camper, public;
update campsite_type_option_cost
set cost = cost_per_night
;
alter table campsite_type_option_cost
drop column if exists cost_per_night
;
commit;

View File

@ -0,0 +1,20 @@
-- Deploy camper:campsite_type_option_cost__cost to pg
-- requires: campsite_type_option_cost
begin;
set search_path to camper, public;
alter table campsite_type_option_cost
rename constraint cost_not_negative to cost_per_night_not_negative
;
alter table campsite_type_option_cost
add column if not exists cost integer not null default 1 constraint cost_not_negative check(cost >= 0)
;
alter table campsite_type_option_cost
alter column cost drop default
;
commit;

View File

@ -2,16 +2,20 @@
-- requires: roles
-- requires: schema_camper
-- requires: campsite_type_option
-- requires: campsite_type_option__per_night
begin;
set search_path to camper, public;
create or replace function edit_campsite_type_option(option_id integer, name text, min integer, max integer) returns integer as
drop function if exists edit_campsite_type_option(integer, text, integer, integer);
create or replace function edit_campsite_type_option(option_id integer, name text, min integer, max integer, per_night boolean) returns integer as
$$
update campsite_type_option
set name = edit_campsite_type_option.name
, range = int4range(min, max, '[]')
, per_night = edit_campsite_type_option.per_night
where campsite_type_option_id = option_id
returning campsite_type_option_id
;
@ -19,7 +23,7 @@ $$
language sql
;
revoke execute on function edit_campsite_type_option(integer, text, integer, integer) from public;
grant execute on function edit_campsite_type_option(integer, text, integer, integer) to admin;
revoke execute on function edit_campsite_type_option(integer, text, integer, integer, boolean) from public;
grant execute on function edit_campsite_type_option(integer, text, integer, integer, boolean) to admin;
commit;

View File

@ -0,0 +1,25 @@
-- Deploy camper:edit_campsite_type_option to pg
-- requires: roles
-- requires: schema_camper
-- requires: campsite_type_option
begin;
set search_path to camper, public;
create or replace function edit_campsite_type_option(option_id integer, name text, min integer, max integer) returns integer as
$$
update campsite_type_option
set name = edit_campsite_type_option.name
, range = int4range(min, max, '[]')
where campsite_type_option_id = option_id
returning campsite_type_option_id
;
$$
language sql
;
revoke execute on function edit_campsite_type_option(integer, text, integer, integer) from public;
grant execute on function edit_campsite_type_option(integer, text, integer, integer) to admin;
commit;

View File

@ -3,17 +3,20 @@
-- requires: schema_camper
-- requires: campsite_type_option_cost
-- requires: parse_price
-- requires: campsite_type_option_cost__cost
begin;
set search_path to camper, public;
create or replace function set_campsite_type_option_cost(option_id integer, season_id integer, cost_per_night text, decimal_places integer default 2) returns void as
drop function if exists set_campsite_type_option_cost(integer, integer, text, integer);
create or replace function set_campsite_type_option_cost(option_id integer, season_id integer, cost text, decimal_places integer default 2) returns void as
$$
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night)
values (option_id, season_id, parse_price(cost_per_night, decimal_places))
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost)
values (option_id, season_id, parse_price(cost, decimal_places))
on conflict (campsite_type_option_id, season_id) do update
set cost_per_night = excluded.cost_per_night
set cost = excluded.cost
;
$$
language sql

View File

@ -0,0 +1,25 @@
-- Deploy camper:set_campsite_type_option_cost to pg
-- requires: roles
-- requires: schema_camper
-- requires: campsite_type_option_cost
-- requires: parse_price
begin;
set search_path to camper, public;
create or replace function set_campsite_type_option_cost(option_id integer, season_id integer, cost_per_night text, decimal_places integer default 2) returns void as
$$
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night)
values (option_id, season_id, parse_price(cost_per_night, decimal_places))
on conflict (campsite_type_option_id, season_id) do update
set cost_per_night = excluded.cost_per_night
;
$$
language sql
;
revoke execute on function set_campsite_type_option_cost(integer, integer, text, integer) from public;
grant execute on function set_campsite_type_option_cost(integer, integer, text, integer) to admin;
commit;

View File

@ -100,12 +100,14 @@ func newBookingCart(ctx context.Context, conn *database.Conn, f *bookingForm, ca
where campsite_type.slug = $3
), per_option as (
select campsite_type_option_id
, sum(cost_per_night * units)::integer as option_cost
, 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

View File

@ -160,7 +160,7 @@ func addOption(w http.ResponseWriter, r *http.Request, user *auth.User, company
}
processOptionForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
var err error
f.ID, err = tx.AddCampsiteTypeOption(ctx, typeSlug, f.Name[f.DefaultLang].Val, f.Min.Int(), f.Max.Int())
f.ID, err = tx.AddCampsiteTypeOption(ctx, typeSlug, f.Name[f.DefaultLang].Val, f.Min.Int(), f.Max.Int(), f.PerNight.Checked)
if err != nil {
return err
}
@ -186,7 +186,7 @@ func translateOptions(ctx context.Context, tx *database.Tx, company *auth.Compan
func editOption(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *optionForm) {
processOptionForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
if _, err := tx.EditCampsiteTypeOption(ctx, f.ID, f.Name[f.DefaultLang].Val, f.Min.Int(), f.Max.Int()); err != nil {
if _, err := tx.EditCampsiteTypeOption(ctx, f.ID, f.Name[f.DefaultLang].Val, f.Min.Int(), f.Max.Int(), f.PerNight.Checked); err != nil {
return err
}
if err := translateOptions(ctx, tx, company, f); err != nil {
@ -231,7 +231,7 @@ func processOptionForm(w http.ResponseWriter, r *http.Request, user *auth.User,
func setOptionPrices(ctx context.Context, tx *database.Tx, id int, prices map[int]*optionPriceForm) error {
for seasonID, p := range prices {
if err := tx.SetCampsiteTypeOptionCost(ctx, id, seasonID, p.PricePerNight.Val); err != nil {
if err := tx.SetCampsiteTypeOptionCost(ctx, id, seasonID, p.Price.Val); err != nil {
return err
}
}
@ -245,12 +245,13 @@ type optionForm struct {
Name form.I18nInput
Min *form.Input
Max *form.Input
PerNight *form.Checkbox
Prices map[int]*optionPriceForm
}
type optionPriceForm struct {
SeasonName string
PricePerNight *form.Input
SeasonName string
Price *form.Input
}
func newOptionForm(ctx context.Context, company *auth.Company, conn *database.Conn, typeSlug string) (*optionForm, error) {
@ -266,6 +267,10 @@ func newOptionForm(ctx context.Context, company *auth.Company, conn *database.Co
Name: "max",
Val: "1",
},
PerNight: &form.Checkbox{
Name: "per_night",
Checked: true,
},
}
rows, err := conn.Query(ctx, "select season_id, name from season where active and company_id = $1", company.ID)
@ -283,8 +288,8 @@ func newOptionForm(ctx context.Context, company *auth.Company, conn *database.Co
}
f.Prices[id] = &optionPriceForm{
SeasonName: name,
PricePerNight: &form.Input{
Name: fmt.Sprintf("season.%d.price_per_night", id),
Price: &form.Input{
Name: fmt.Sprintf("season.%d.price", id),
Val: "0",
},
}
@ -300,14 +305,16 @@ func (f *optionForm) FillFromDatabase(ctx context.Context, conn *database.Conn,
select option.name
, lower(range)::text
, (upper(range) - 1)::text
, per_night
, array_agg((lang_tag, i18n.name))
from campsite_type_option as option
left join campsite_type_option_i18n as i18n using (campsite_type_option_id)
where campsite_type_option_id = $1
group by option.name
, per_night
, range
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, id)
if err := row.Scan(&f.Name[f.DefaultLang].Val, &f.Min.Val, &f.Max.Val, &name); err != nil {
if err := row.Scan(&f.Name[f.DefaultLang].Val, &f.Min.Val, &f.Max.Val, &f.PerNight.Checked, &name); err != nil {
return err
}
if err := f.Name.FillArray(name); err != nil {
@ -316,7 +323,7 @@ func (f *optionForm) FillFromDatabase(ctx context.Context, conn *database.Conn,
rows, err := conn.Query(ctx, `
select season_id
, to_price(cost_per_night)
, to_price(cost)
from campsite_type_option
join campsite_type_option_cost using (campsite_type_option_id)
where campsite_type_option_id = $1
@ -333,7 +340,7 @@ func (f *optionForm) FillFromDatabase(ctx context.Context, conn *database.Conn,
return err
}
if p, ok := f.Prices[seasonID]; ok {
p.PricePerNight.Val = pricePerNight
p.Price.Val = pricePerNight
}
}
return rows.Err()
@ -346,8 +353,9 @@ func (f *optionForm) Parse(r *http.Request) error {
f.Name.FillValue(r)
f.Min.FillValue(r)
f.Max.FillValue(r)
f.PerNight.FillValue(r)
for _, p := range f.Prices {
p.PricePerNight.FillValue(r)
p.Price.FillValue(r)
}
return nil
}
@ -371,9 +379,9 @@ func (f *optionForm) Valid(l *locale.Locale) bool {
}
}
for _, p := range f.Prices {
if v.CheckRequired(p.PricePerNight, l.GettextNoop("Price per night can not be empty.")) {
if v.CheckValidDecimal(p.PricePerNight, l.GettextNoop("Price per night must be a decimal number.")) {
v.CheckMinDecimal(p.PricePerNight, 0.0, l.GettextNoop("Price per night must be zero or greater."))
if v.CheckRequired(p.Price, l.GettextNoop("Price can not be empty.")) {
if v.CheckValidDecimal(p.Price, l.GettextNoop("Price must be a decimal number.")) {
v.CheckMinDecimal(p.Price, 0.0, l.GettextNoop("Price must be zero or greater."))
}
}
}

View File

@ -104,8 +104,9 @@ type typePrice struct {
}
type optionPrice struct {
OptionName string
PricePerNight string
OptionName string
Price string
PerNight bool
}
type typeFeature struct {
@ -184,7 +185,7 @@ func collectPrices(ctx context.Context, conn *database.Conn, language language.T
, case when cost.cost_per_adult > 0 then to_price(coalesce(cost.cost_per_adult, 0)) else '' end
, case when cost.cost_per_teenager > 0 then to_price(coalesce(cost.cost_per_teenager, 0)) else '' end
, case when cost.cost_per_child > 0 then to_price(coalesce(cost.cost_per_child, 0)) else '' end
, array_agg((coalesce(option_i18n.name, option.name), to_price(coalesce(option_cost.cost_per_night, 0))) order by option.position) filter (where option.campsite_type_option_id is not null)
, array_agg((coalesce(option_i18n.name, option.name), to_price(coalesce(option_cost.cost, 0)), option.per_night) order by option.position) filter (where option.campsite_type_option_id is not null)
from season
left join season_i18n as i18n on season.season_id = i18n.season_id and i18n.lang_tag = $1
left join (
@ -233,7 +234,8 @@ func collectPrices(ctx context.Context, conn *database.Conn, language language.T
}
if pricePerNight != "" {
option := &optionPrice{
PricePerNight: pricePerNight,
Price: pricePerNight,
PerNight: true,
}
if pricePerAdult != "" || pricePerTeenager != "" || pricePerChild != "" || len(options.Elements) > 0 {
option.OptionName = campsiteName
@ -242,26 +244,30 @@ func collectPrices(ctx context.Context, conn *database.Conn, language language.T
}
if pricePerAdult != "" {
price.Options = append(price.Options, &optionPrice{
OptionName: locale.PgettextNoop("Adults", "header"),
PricePerNight: pricePerAdult,
OptionName: locale.PgettextNoop("Adults", "header"),
Price: pricePerAdult,
PerNight: true,
})
}
if pricePerTeenager != pricePerAdult && pricePerTeenager != "" {
price.Options = append(price.Options, &optionPrice{
OptionName: locale.PgettextNoop("Teenagers (aged 11 to 16)", "header"),
PricePerNight: pricePerTeenager,
OptionName: locale.PgettextNoop("Teenagers (aged 11 to 16)", "header"),
Price: pricePerTeenager,
PerNight: true,
})
}
if pricePerChild != "" {
price.Options = append(price.Options, &optionPrice{
OptionName: locale.PgettextNoop("Children (aged 2 to 10)", "header"),
PricePerNight: pricePerChild,
OptionName: locale.PgettextNoop("Children (aged 2 to 10)", "header"),
Price: pricePerChild,
PerNight: true,
})
}
for _, el := range options.Elements {
price.Options = append(price.Options, &optionPrice{
OptionName: el.Fields[0].Get().(string),
PricePerNight: el.Fields[1].Get().(string),
OptionName: el.Fields[0].Get().(string),
Price: el.Fields[1].Get().(string),
PerNight: el.Fields[2].Get().(bool),
})
}
prices = append(prices, price)

View File

@ -162,16 +162,16 @@ func (tx *Tx) UnsetCampsitePetTypeCost(ctx context.Context, slug string) error {
return err
}
func (tx *Tx) AddCampsiteTypeOption(ctx context.Context, typeSlug string, name string, min int, max int) (int, error) {
return tx.GetInt(ctx, "select add_campsite_type_option($1, $2, $3, $4)", typeSlug, name, min, max)
func (tx *Tx) AddCampsiteTypeOption(ctx context.Context, typeSlug string, name string, min int, max int, perNight bool) (int, error) {
return tx.GetInt(ctx, "select add_campsite_type_option($1, $2, $3, $4, $5)", typeSlug, name, min, max, perNight)
}
func (tx *Tx) EditCampsiteTypeOption(ctx context.Context, id int, name string, min int, max int) (int, error) {
return tx.GetInt(ctx, "select edit_campsite_type_option($1, $2, $3, $4)", id, name, min, max)
func (tx *Tx) EditCampsiteTypeOption(ctx context.Context, id int, name string, min int, max int, perNight bool) (int, error) {
return tx.GetInt(ctx, "select edit_campsite_type_option($1, $2, $3, $4, $5)", id, name, min, max, perNight)
}
func (tx *Tx) SetCampsiteTypeOptionCost(ctx context.Context, id int, seasonID int, pricePerNight string) error {
_, err := tx.Exec(ctx, "select set_campsite_type_option_cost($1, $2, $3)", id, seasonID, pricePerNight)
func (tx *Tx) SetCampsiteTypeOptionCost(ctx context.Context, id int, seasonID int, price string) error {
_, err := tx.Exec(ctx, "select set_campsite_type_option_cost($1, $2, $3)", id, seasonID, price)
return err
}

125
po/ca.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-02-10 06:05+0100\n"
"POT-Creation-Date: 2024-02-11 21:35+0100\n"
"PO-Revision-Date: 2024-02-06 10:04+0100\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Catalan <ca@dodds.net>\n"
@ -95,7 +95,7 @@ msgid "The campsite offers many different services."
msgstr "El càmping disposa de diversos serveis."
#: web/templates/public/amenity.gohtml:39
#: web/templates/public/campsite/type.gohtml:106
#: web/templates/public/campsite/type.gohtml:114
#: web/templates/public/campsite/page.gohtml:39
msgctxt "title"
msgid "Features"
@ -168,65 +168,69 @@ msgstr "Calendari"
#: web/templates/public/campsite/type.gohtml:68
#: web/templates/admin/campsite/type/form.gohtml:153
#: web/templates/admin/campsite/type/option/form.gohtml:70
#: web/templates/admin/campsite/type/option/form.gohtml:71
msgctxt "title"
msgid "Prices"
msgstr "Preus"
#: web/templates/public/campsite/type.gohtml:81
#: web/templates/public/campsite/type.gohtml:82
msgid "%s: %s/night"
msgstr "%s: %s/nit"
#: web/templates/public/campsite/type.gohtml:83
#: web/templates/public/campsite/type.gohtml:84
msgid "%s: %s"
msgstr "%s: %s"
#: web/templates/public/campsite/type.gohtml:88
msgid "%s/night"
msgstr "%s/nit"
#: web/templates/public/campsite/type.gohtml:88
#: web/templates/public/campsite/type.gohtml:96
msgid "*Minimum %d nights per stay"
msgstr "*Mínim %d nits per estada"
#: web/templates/public/campsite/type.gohtml:93
#: web/templates/public/campsite/type.gohtml:101
msgid "10 % VAT included."
msgstr "IVA del 10 % inclòs."
#: web/templates/public/campsite/type.gohtml:94
#: web/templates/public/campsite/type.gohtml:102
msgid "Tourist tax: %s/night per person aged 17 or older."
msgstr "Impost turístic: %s/nit per persona major de 16 anys."
#: web/templates/public/campsite/type.gohtml:96
#: web/templates/public/campsite/type.gohtml:104
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
msgstr "Gossos: %s/nit, lligats, acompanyats i el mínim de lladrucs."
#: web/templates/public/campsite/type.gohtml:98
#: web/templates/public/campsite/type.gohtml:106
msgid "No dogs allowed."
msgstr "No es permeten gossos."
#: web/templates/public/campsite/type.gohtml:117
#: web/templates/public/campsite/type.gohtml:125
msgctxt "title"
msgid "Info"
msgstr "Informació"
#: web/templates/public/campsite/type.gohtml:121
#: web/templates/public/campsite/type.gohtml:129
msgctxt "title"
msgid "Facilities"
msgstr "Equipaments"
#: web/templates/public/campsite/type.gohtml:125
#: web/templates/public/campsite/type.gohtml:133
msgctxt "title"
msgid "Description"
msgstr "Descripció"
#: web/templates/public/campsite/type.gohtml:129
#: web/templates/public/campsite/type.gohtml:137
msgctxt "title"
msgid "Additional Information"
msgstr "Informació addicional"
#: web/templates/public/campsite/type.gohtml:132
#: web/templates/public/campsite/type.gohtml:140
msgctxt "time"
msgid "Check-in"
msgstr "Entrada"
#: web/templates/public/campsite/type.gohtml:136
#: web/templates/public/campsite/type.gohtml:144
msgctxt "time"
msgid "Check-out"
msgstr "Sortida"
@ -677,7 +681,7 @@ msgstr "Àlies"
#: web/templates/admin/campsite/feature/form.gohtml:50
#: web/templates/admin/campsite/type/feature/form.gohtml:59
#: web/templates/admin/campsite/type/form.gohtml:51
#: web/templates/admin/campsite/type/option/form.gohtml:41
#: web/templates/admin/campsite/type/option/form.gohtml:42
#: web/templates/admin/season/form.gohtml:50
#: web/templates/admin/services/form.gohtml:53
#: web/templates/admin/profile.gohtml:29
@ -701,7 +705,7 @@ msgstr "Contingut"
#: web/templates/admin/campsite/type/feature/form.gohtml:74
#: web/templates/admin/campsite/type/carousel/form.gohtml:59
#: web/templates/admin/campsite/type/form.gohtml:287
#: web/templates/admin/campsite/type/option/form.gohtml:90
#: web/templates/admin/campsite/type/option/form.gohtml:99
#: web/templates/admin/season/form.gohtml:73
#: web/templates/admin/services/form.gohtml:81
#: web/templates/admin/surroundings/form.gohtml:69
@ -723,7 +727,7 @@ msgstr "Actualitza"
#: web/templates/admin/campsite/type/feature/form.gohtml:76
#: web/templates/admin/campsite/type/carousel/form.gohtml:61
#: web/templates/admin/campsite/type/form.gohtml:289
#: web/templates/admin/campsite/type/option/form.gohtml:92
#: web/templates/admin/campsite/type/option/form.gohtml:101
#: web/templates/admin/season/form.gohtml:75
#: web/templates/admin/services/form.gohtml:83
#: web/templates/admin/surroundings/form.gohtml:71
@ -1196,7 +1200,6 @@ msgid "Price per child (210)"
msgstr "Preu per nen (210)"
#: web/templates/admin/campsite/type/form.gohtml:171
#: web/templates/admin/campsite/type/option/form.gohtml:76
msgctxt "input"
msgid "Price per night"
msgstr "Preu per nit"
@ -1244,13 +1247,13 @@ msgid "Additional Information"
msgstr "Informació addicional"
#: web/templates/admin/campsite/type/option/form.gohtml:8
#: web/templates/admin/campsite/type/option/form.gohtml:32
#: web/templates/admin/campsite/type/option/form.gohtml:33
msgctxt "title"
msgid "Edit Campsite Type Option"
msgstr "Edició de lopció del tipus dallotjament"
#: web/templates/admin/campsite/type/option/form.gohtml:10
#: web/templates/admin/campsite/type/option/form.gohtml:34
#: web/templates/admin/campsite/type/option/form.gohtml:35
msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nova opció del tipus dallotjament"
@ -1262,16 +1265,26 @@ msgctxt "title"
msgid "Campsite Type Options"
msgstr "Opcions del tipus dallotjament"
#: web/templates/admin/campsite/type/option/form.gohtml:54
#: web/templates/admin/campsite/type/option/form.gohtml:55
msgctxt "input"
msgid "Minimum"
msgstr "Mínim"
#: web/templates/admin/campsite/type/option/form.gohtml:62
#: web/templates/admin/campsite/type/option/form.gohtml:63
msgctxt "input"
msgid "Maximum"
msgstr "Màxim"
#: web/templates/admin/campsite/type/option/form.gohtml:76
msgctxt "campsite type"
msgid "Per night"
msgstr "Per nit"
#: web/templates/admin/campsite/type/option/form.gohtml:85
msgctxt "input"
msgid "Price"
msgstr "Preu"
#: web/templates/admin/campsite/type/option/index.gohtml:16
msgctxt "action"
msgid "Add Option"
@ -1934,7 +1947,7 @@ msgstr "Estat"
msgid "No booking found."
msgstr "No sha trobat cap reserva."
#: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:357
#: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:365
#: pkg/campsite/types/feature.go:272 pkg/campsite/types/admin.go:577
#: pkg/campsite/feature.go:269 pkg/season/admin.go:412
#: pkg/services/admin.go:316 pkg/surroundings/admin.go:340
@ -1942,7 +1955,7 @@ msgstr "No sha trobat cap reserva."
msgid "Name can not be empty."
msgstr "No podeu deixar el nom en blanc."
#: pkg/legal/admin.go:259 pkg/campsite/types/option.go:358
#: pkg/legal/admin.go:259 pkg/campsite/types/option.go:366
#: pkg/campsite/types/feature.go:273 pkg/campsite/types/admin.go:578
#: pkg/campsite/feature.go:270 pkg/amenity/feature.go:270
msgid "Name must have at least one letter."
@ -2011,41 +2024,41 @@ msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida."
msgid "Access forbidden"
msgstr "Accés prohibit"
#: pkg/campsite/types/option.go:361
#: pkg/campsite/types/option.go:369
msgid "Minimum can not be empty."
msgstr "No podeu deixar el mínim en blanc."
#: pkg/campsite/types/option.go:362
#: pkg/campsite/types/option.go:370
msgid "Minimum must be an integer number."
msgstr "El valor del mínim ha de ser un número enter."
#: pkg/campsite/types/option.go:364
#: pkg/campsite/types/option.go:372
msgid "Minimum must be zero or greater."
msgstr "El valor del mínim ha de ser com a mínim zero."
#: pkg/campsite/types/option.go:367
#: pkg/campsite/types/option.go:375
msgid "Maximum can not be empty."
msgstr "No podeu deixar el màxim en blanc."
#: pkg/campsite/types/option.go:368
#: pkg/campsite/types/option.go:376
msgid "Maximum must be an integer number."
msgstr "El valor del màxim ha de ser un número enter."
#: pkg/campsite/types/option.go:370
#: pkg/campsite/types/option.go:378
msgid "Maximum must be equal or greater than minimum."
msgstr "El valor del màxim ha de ser igual o superir al del mínim."
#: pkg/campsite/types/option.go:374 pkg/campsite/types/admin.go:610
msgid "Price per night can not be empty."
msgstr "No podeu deixar el preu per nit en blanc."
#: pkg/campsite/types/option.go:382
msgid "Price can not be empty."
msgstr "No podeu deixar el preu en blanc."
#: pkg/campsite/types/option.go:375 pkg/campsite/types/admin.go:611
msgid "Price per night must be a decimal number."
msgstr "El preu per nit ha de ser un número decimal."
#: pkg/campsite/types/option.go:383
msgid "Price must be a decimal number."
msgstr "El preu ha de ser un número decimal."
#: pkg/campsite/types/option.go:376 pkg/campsite/types/admin.go:612
msgid "Price per night must be zero or greater."
msgstr "El preu per nit ha de ser com a mínim zero."
#: pkg/campsite/types/option.go:384
msgid "Price must be zero or greater."
msgstr "El preu ha de ser com a mínim zero."
#: pkg/campsite/types/feature.go:271 pkg/campsite/feature.go:268
#: pkg/services/admin.go:315 pkg/amenity/feature.go:268
@ -2126,6 +2139,18 @@ msgstr "El preu dels gossos ha de ser un número decimal."
msgid "Dogs price must be zero or greater."
msgstr "El preu dels gossos ha de ser com a mínim zero."
#: pkg/campsite/types/admin.go:610
msgid "Price per night can not be empty."
msgstr "No podeu deixar el preu per nit en blanc."
#: pkg/campsite/types/admin.go:611
msgid "Price per night must be a decimal number."
msgstr "El preu per nit ha de ser un número decimal."
#: pkg/campsite/types/admin.go:612
msgid "Price per night must be zero or greater."
msgstr "El preu per nit ha de ser com a mínim zero."
#: pkg/campsite/types/admin.go:615
msgid "Price per adult can not be empty."
msgstr "No podeu deixar el preu per adult en blanc."
@ -2162,17 +2187,17 @@ msgstr "El preu per nen ha de ser un número decimal."
msgid "Price per child must be zero or greater."
msgstr "El preu per nen ha de ser com a mínim zero."
#: pkg/campsite/types/public.go:245
#: pkg/campsite/types/public.go:247
msgctxt "header"
msgid "Adults"
msgstr "Adults"
#: pkg/campsite/types/public.go:251
#: pkg/campsite/types/public.go:254
msgctxt "header"
msgid "Teenagers (aged 11 to 16)"
msgstr "Adolescents (entre 11 i 16 anys)"
#: pkg/campsite/types/public.go:257
#: pkg/campsite/types/public.go:261
msgctxt "header"
msgid "Children (aged 2 to 10)"
msgstr "Mainada (entre 2 i 10 anys)"
@ -2418,32 +2443,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:156
#: pkg/booking/cart.go:158
msgctxt "cart"
msgid "Night"
msgstr "Nit"
#: pkg/booking/cart.go:157
#: pkg/booking/cart.go:159
msgctxt "cart"
msgid "Adult"
msgstr "Adult"
#: pkg/booking/cart.go:158
#: pkg/booking/cart.go:160
msgctxt "cart"
msgid "Teenager"
msgstr "Adolescent"
#: pkg/booking/cart.go:159
#: pkg/booking/cart.go:161
msgctxt "cart"
msgid "Child"
msgstr "Nen"
#: pkg/booking/cart.go:160
#: pkg/booking/cart.go:162
msgctxt "cart"
msgid "Dog"
msgstr "Gos"
#: pkg/booking/cart.go:179
#: pkg/booking/cart.go:181
msgctxt "cart"
msgid "Tourist tax"
msgstr "Impost turístic"

125
po/es.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-02-10 06:05+0100\n"
"POT-Creation-Date: 2024-02-11 21:35+0100\n"
"PO-Revision-Date: 2024-02-06 10:04+0100\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Spanish <es@tp.org.es>\n"
@ -95,7 +95,7 @@ msgid "The campsite offers many different services."
msgstr "El camping dispone de varios servicios."
#: web/templates/public/amenity.gohtml:39
#: web/templates/public/campsite/type.gohtml:106
#: web/templates/public/campsite/type.gohtml:114
#: web/templates/public/campsite/page.gohtml:39
msgctxt "title"
msgid "Features"
@ -168,65 +168,69 @@ msgstr "Calendario"
#: web/templates/public/campsite/type.gohtml:68
#: web/templates/admin/campsite/type/form.gohtml:153
#: web/templates/admin/campsite/type/option/form.gohtml:70
#: web/templates/admin/campsite/type/option/form.gohtml:71
msgctxt "title"
msgid "Prices"
msgstr "Precios"
#: web/templates/public/campsite/type.gohtml:81
#: web/templates/public/campsite/type.gohtml:82
msgid "%s: %s/night"
msgstr "%s: %s/noche"
#: web/templates/public/campsite/type.gohtml:83
#: web/templates/public/campsite/type.gohtml:84
msgid "%s: %s"
msgstr "%s: %s"
#: web/templates/public/campsite/type.gohtml:88
msgid "%s/night"
msgstr "%s/noche"
#: web/templates/public/campsite/type.gohtml:88
#: web/templates/public/campsite/type.gohtml:96
msgid "*Minimum %d nights per stay"
msgstr "*Mínimo %d noches por estancia"
#: web/templates/public/campsite/type.gohtml:93
#: web/templates/public/campsite/type.gohtml:101
msgid "10 % VAT included."
msgstr "IVA del 10 % incluido."
#: web/templates/public/campsite/type.gohtml:94
#: web/templates/public/campsite/type.gohtml:102
msgid "Tourist tax: %s/night per person aged 17 or older."
msgstr "Impuesto turístico: %s/noche por persona mayor de 16 años."
#: web/templates/public/campsite/type.gohtml:96
#: web/templates/public/campsite/type.gohtml:104
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
msgstr "Perros: %s/noche, atados, acompañados y con mínimo de ladrido."
#: web/templates/public/campsite/type.gohtml:98
#: web/templates/public/campsite/type.gohtml:106
msgid "No dogs allowed."
msgstr "No se permiten perros"
#: web/templates/public/campsite/type.gohtml:117
#: web/templates/public/campsite/type.gohtml:125
msgctxt "title"
msgid "Info"
msgstr "Información"
#: web/templates/public/campsite/type.gohtml:121
#: web/templates/public/campsite/type.gohtml:129
msgctxt "title"
msgid "Facilities"
msgstr "Equipamiento"
#: web/templates/public/campsite/type.gohtml:125
#: web/templates/public/campsite/type.gohtml:133
msgctxt "title"
msgid "Description"
msgstr "Descripción"
#: web/templates/public/campsite/type.gohtml:129
#: web/templates/public/campsite/type.gohtml:137
msgctxt "title"
msgid "Additional Information"
msgstr "Información adicional"
#: web/templates/public/campsite/type.gohtml:132
#: web/templates/public/campsite/type.gohtml:140
msgctxt "time"
msgid "Check-in"
msgstr "Entrada"
#: web/templates/public/campsite/type.gohtml:136
#: web/templates/public/campsite/type.gohtml:144
msgctxt "time"
msgid "Check-out"
msgstr "Salida"
@ -677,7 +681,7 @@ msgstr "Álias"
#: web/templates/admin/campsite/feature/form.gohtml:50
#: web/templates/admin/campsite/type/feature/form.gohtml:59
#: web/templates/admin/campsite/type/form.gohtml:51
#: web/templates/admin/campsite/type/option/form.gohtml:41
#: web/templates/admin/campsite/type/option/form.gohtml:42
#: web/templates/admin/season/form.gohtml:50
#: web/templates/admin/services/form.gohtml:53
#: web/templates/admin/profile.gohtml:29
@ -701,7 +705,7 @@ msgstr "Contenido"
#: web/templates/admin/campsite/type/feature/form.gohtml:74
#: web/templates/admin/campsite/type/carousel/form.gohtml:59
#: web/templates/admin/campsite/type/form.gohtml:287
#: web/templates/admin/campsite/type/option/form.gohtml:90
#: web/templates/admin/campsite/type/option/form.gohtml:99
#: web/templates/admin/season/form.gohtml:73
#: web/templates/admin/services/form.gohtml:81
#: web/templates/admin/surroundings/form.gohtml:69
@ -723,7 +727,7 @@ msgstr "Actualizar"
#: web/templates/admin/campsite/type/feature/form.gohtml:76
#: web/templates/admin/campsite/type/carousel/form.gohtml:61
#: web/templates/admin/campsite/type/form.gohtml:289
#: web/templates/admin/campsite/type/option/form.gohtml:92
#: web/templates/admin/campsite/type/option/form.gohtml:101
#: web/templates/admin/season/form.gohtml:75
#: web/templates/admin/services/form.gohtml:83
#: web/templates/admin/surroundings/form.gohtml:71
@ -1196,7 +1200,6 @@ msgid "Price per child (210)"
msgstr "Precio por niño (210)"
#: web/templates/admin/campsite/type/form.gohtml:171
#: web/templates/admin/campsite/type/option/form.gohtml:76
msgctxt "input"
msgid "Price per night"
msgstr "Precio por noche"
@ -1244,13 +1247,13 @@ msgid "Additional Information"
msgstr "Información adicional"
#: web/templates/admin/campsite/type/option/form.gohtml:8
#: web/templates/admin/campsite/type/option/form.gohtml:32
#: web/templates/admin/campsite/type/option/form.gohtml:33
msgctxt "title"
msgid "Edit Campsite Type Option"
msgstr "Edición de la opción del tipo de alojamiento"
#: web/templates/admin/campsite/type/option/form.gohtml:10
#: web/templates/admin/campsite/type/option/form.gohtml:34
#: web/templates/admin/campsite/type/option/form.gohtml:35
msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nueva opción del tipo de alojamiento"
@ -1262,16 +1265,26 @@ msgctxt "title"
msgid "Campsite Type Options"
msgstr "Opciones del tipo de alojamiento"
#: web/templates/admin/campsite/type/option/form.gohtml:54
#: web/templates/admin/campsite/type/option/form.gohtml:55
msgctxt "input"
msgid "Minimum"
msgstr "Mínimo"
#: web/templates/admin/campsite/type/option/form.gohtml:62
#: web/templates/admin/campsite/type/option/form.gohtml:63
msgctxt "input"
msgid "Maximum"
msgstr "Màximo"
#: web/templates/admin/campsite/type/option/form.gohtml:76
msgctxt "campsite type"
msgid "Per night"
msgstr "Por noche"
#: web/templates/admin/campsite/type/option/form.gohtml:85
msgctxt "input"
msgid "Price"
msgstr "Precio"
#: web/templates/admin/campsite/type/option/index.gohtml:16
msgctxt "action"
msgid "Add Option"
@ -1934,7 +1947,7 @@ msgstr "Estado"
msgid "No booking found."
msgstr "No se ha encontrado ninguna reserva."
#: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:357
#: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:365
#: pkg/campsite/types/feature.go:272 pkg/campsite/types/admin.go:577
#: pkg/campsite/feature.go:269 pkg/season/admin.go:412
#: pkg/services/admin.go:316 pkg/surroundings/admin.go:340
@ -1942,7 +1955,7 @@ msgstr "No se ha encontrado ninguna reserva."
msgid "Name can not be empty."
msgstr "No podéis dejar el nombre en blanco."
#: pkg/legal/admin.go:259 pkg/campsite/types/option.go:358
#: pkg/legal/admin.go:259 pkg/campsite/types/option.go:366
#: pkg/campsite/types/feature.go:273 pkg/campsite/types/admin.go:578
#: pkg/campsite/feature.go:270 pkg/amenity/feature.go:270
msgid "Name must have at least one letter."
@ -2011,41 +2024,41 @@ msgstr "El archivo tiene que ser una imagen PNG o JPEG válida."
msgid "Access forbidden"
msgstr "Acceso prohibido"
#: pkg/campsite/types/option.go:361
#: pkg/campsite/types/option.go:369
msgid "Minimum can not be empty."
msgstr "No podéis dejar el mínimo en blanco."
#: pkg/campsite/types/option.go:362
#: pkg/campsite/types/option.go:370
msgid "Minimum must be an integer number."
msgstr "El valor de mínimo tiene que ser un número entero."
#: pkg/campsite/types/option.go:364
#: pkg/campsite/types/option.go:372
msgid "Minimum must be zero or greater."
msgstr "El valor de mínimo tiene que ser como mínimo cero."
#: pkg/campsite/types/option.go:367
#: pkg/campsite/types/option.go:375
msgid "Maximum can not be empty."
msgstr "No podéis dejar el máxmimo en blanco."
#: pkg/campsite/types/option.go:368
#: pkg/campsite/types/option.go:376
msgid "Maximum must be an integer number."
msgstr "El valor del máximo tiene que ser un número entero."
#: pkg/campsite/types/option.go:370
#: pkg/campsite/types/option.go:378
msgid "Maximum must be equal or greater than minimum."
msgstr "El valor del máximo tiene que ser igual o mayor al del mínimo."
#: pkg/campsite/types/option.go:374 pkg/campsite/types/admin.go:610
msgid "Price per night can not be empty."
msgstr "No podéis dejar el precio por noche en blanco."
#: pkg/campsite/types/option.go:382
msgid "Price can not be empty."
msgstr "No podéis dejar el precio en blanco."
#: pkg/campsite/types/option.go:375 pkg/campsite/types/admin.go:611
msgid "Price per night must be a decimal number."
msgstr "El precio por noche tiene que ser un número decimal."
#: pkg/campsite/types/option.go:383
msgid "Price must be a decimal number."
msgstr "El precio tiene que ser un número decimal."
#: pkg/campsite/types/option.go:376 pkg/campsite/types/admin.go:612
msgid "Price per night must be zero or greater."
msgstr "El precio por noche tiene que ser como mínimo cero."
#: pkg/campsite/types/option.go:384
msgid "Price must be zero or greater."
msgstr "El precio tiene que ser como mínimo cero."
#: pkg/campsite/types/feature.go:271 pkg/campsite/feature.go:268
#: pkg/services/admin.go:315 pkg/amenity/feature.go:268
@ -2126,6 +2139,18 @@ msgstr "El precio de los perros tiene que ser un número decimal."
msgid "Dogs price must be zero or greater."
msgstr "El precio de los perros tiene que ser como mínimo cero."
#: pkg/campsite/types/admin.go:610
msgid "Price per night can not be empty."
msgstr "No podéis dejar el precio por noche en blanco."
#: pkg/campsite/types/admin.go:611
msgid "Price per night must be a decimal number."
msgstr "El precio por noche tiene que ser un número decimal."
#: pkg/campsite/types/admin.go:612
msgid "Price per night must be zero or greater."
msgstr "El precio por noche tiene que ser como mínimo cero."
#: pkg/campsite/types/admin.go:615
msgid "Price per adult can not be empty."
msgstr "No podéis dejar el precio por adulto en blanco."
@ -2162,17 +2187,17 @@ msgstr "El precio por niño tiene que ser un número decimal."
msgid "Price per child must be zero or greater."
msgstr "El precio por niño tiene que ser como mínimo cero."
#: pkg/campsite/types/public.go:245
#: pkg/campsite/types/public.go:247
msgctxt "header"
msgid "Adults"
msgstr "Adultos"
#: pkg/campsite/types/public.go:251
#: pkg/campsite/types/public.go:254
msgctxt "header"
msgid "Teenagers (aged 11 to 16)"
msgstr "Adolescentes (de 11 a 16 años)"
#: pkg/campsite/types/public.go:257
#: pkg/campsite/types/public.go:261
msgctxt "header"
msgid "Children (aged 2 to 10)"
msgstr "Niños (de 2 a 10 años)"
@ -2418,32 +2443,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:156
#: pkg/booking/cart.go:158
msgctxt "cart"
msgid "Night"
msgstr "Noche"
#: pkg/booking/cart.go:157
#: pkg/booking/cart.go:159
msgctxt "cart"
msgid "Adult"
msgstr "Adulto"
#: pkg/booking/cart.go:158
#: pkg/booking/cart.go:160
msgctxt "cart"
msgid "Teenager"
msgstr "Adolescente"
#: pkg/booking/cart.go:159
#: pkg/booking/cart.go:161
msgctxt "cart"
msgid "Child"
msgstr "Niño"
#: pkg/booking/cart.go:160
#: pkg/booking/cart.go:162
msgctxt "cart"
msgid "Dog"
msgstr "Perro"
#: pkg/booking/cart.go:179
#: pkg/booking/cart.go:181
msgctxt "cart"
msgid "Tourist tax"
msgstr "Impuesto turístico"

125
po/fr.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-02-10 06:05+0100\n"
"POT-Creation-Date: 2024-02-11 21:35+0100\n"
"PO-Revision-Date: 2024-02-06 10:05+0100\n"
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
"Language-Team: French <traduc@traduc.org>\n"
@ -95,7 +95,7 @@ msgid "The campsite offers many different services."
msgstr "Le camping propose de nombreux services différents."
#: web/templates/public/amenity.gohtml:39
#: web/templates/public/campsite/type.gohtml:106
#: web/templates/public/campsite/type.gohtml:114
#: web/templates/public/campsite/page.gohtml:39
msgctxt "title"
msgid "Features"
@ -168,65 +168,69 @@ msgstr "Calendrier"
#: web/templates/public/campsite/type.gohtml:68
#: web/templates/admin/campsite/type/form.gohtml:153
#: web/templates/admin/campsite/type/option/form.gohtml:70
#: web/templates/admin/campsite/type/option/form.gohtml:71
msgctxt "title"
msgid "Prices"
msgstr "Prix"
#: web/templates/public/campsite/type.gohtml:81
#: web/templates/public/campsite/type.gohtml:82
msgid "%s: %s/night"
msgstr "%s : %s/nuit"
#: web/templates/public/campsite/type.gohtml:83
#: web/templates/public/campsite/type.gohtml:84
msgid "%s: %s"
msgstr "%s : %s"
#: web/templates/public/campsite/type.gohtml:88
msgid "%s/night"
msgstr "%s/nuit"
#: web/templates/public/campsite/type.gohtml:88
#: web/templates/public/campsite/type.gohtml:96
msgid "*Minimum %d nights per stay"
msgstr "*Minimum %d nuits par séjour"
#: web/templates/public/campsite/type.gohtml:93
#: web/templates/public/campsite/type.gohtml:101
msgid "10 % VAT included."
msgstr "10 % TVA incluse."
#: web/templates/public/campsite/type.gohtml:94
#: web/templates/public/campsite/type.gohtml:102
msgid "Tourist tax: %s/night per person aged 17 or older."
msgstr "Taxe touristique: %s/nuit par personne de plus de 16 ans."
#: web/templates/public/campsite/type.gohtml:96
#: web/templates/public/campsite/type.gohtml:104
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
msgstr "Chiens : %s/nuit, attachés, accompagnés et aboiements minimes."
#: web/templates/public/campsite/type.gohtml:98
#: web/templates/public/campsite/type.gohtml:106
msgid "No dogs allowed."
msgstr "Chiens interdits."
#: web/templates/public/campsite/type.gohtml:117
#: web/templates/public/campsite/type.gohtml:125
msgctxt "title"
msgid "Info"
msgstr "Info"
#: web/templates/public/campsite/type.gohtml:121
#: web/templates/public/campsite/type.gohtml:129
msgctxt "title"
msgid "Facilities"
msgstr "Installations"
#: web/templates/public/campsite/type.gohtml:125
#: web/templates/public/campsite/type.gohtml:133
msgctxt "title"
msgid "Description"
msgstr "Description"
#: web/templates/public/campsite/type.gohtml:129
#: web/templates/public/campsite/type.gohtml:137
msgctxt "title"
msgid "Additional Information"
msgstr "Informations Complémentaires"
#: web/templates/public/campsite/type.gohtml:132
#: web/templates/public/campsite/type.gohtml:140
msgctxt "time"
msgid "Check-in"
msgstr "Arrivée"
#: web/templates/public/campsite/type.gohtml:136
#: web/templates/public/campsite/type.gohtml:144
msgctxt "time"
msgid "Check-out"
msgstr "Départ"
@ -677,7 +681,7 @@ msgstr "Slug"
#: web/templates/admin/campsite/feature/form.gohtml:50
#: web/templates/admin/campsite/type/feature/form.gohtml:59
#: web/templates/admin/campsite/type/form.gohtml:51
#: web/templates/admin/campsite/type/option/form.gohtml:41
#: web/templates/admin/campsite/type/option/form.gohtml:42
#: web/templates/admin/season/form.gohtml:50
#: web/templates/admin/services/form.gohtml:53
#: web/templates/admin/profile.gohtml:29
@ -701,7 +705,7 @@ msgstr "Contenu"
#: web/templates/admin/campsite/type/feature/form.gohtml:74
#: web/templates/admin/campsite/type/carousel/form.gohtml:59
#: web/templates/admin/campsite/type/form.gohtml:287
#: web/templates/admin/campsite/type/option/form.gohtml:90
#: web/templates/admin/campsite/type/option/form.gohtml:99
#: web/templates/admin/season/form.gohtml:73
#: web/templates/admin/services/form.gohtml:81
#: web/templates/admin/surroundings/form.gohtml:69
@ -723,7 +727,7 @@ msgstr "Mettre à jour"
#: web/templates/admin/campsite/type/feature/form.gohtml:76
#: web/templates/admin/campsite/type/carousel/form.gohtml:61
#: web/templates/admin/campsite/type/form.gohtml:289
#: web/templates/admin/campsite/type/option/form.gohtml:92
#: web/templates/admin/campsite/type/option/form.gohtml:101
#: web/templates/admin/season/form.gohtml:75
#: web/templates/admin/services/form.gohtml:83
#: web/templates/admin/surroundings/form.gohtml:71
@ -1196,7 +1200,6 @@ msgid "Price per child (210)"
msgstr "Prix per enfant (210)"
#: web/templates/admin/campsite/type/form.gohtml:171
#: web/templates/admin/campsite/type/option/form.gohtml:76
msgctxt "input"
msgid "Price per night"
msgstr "Prix par nuit"
@ -1244,13 +1247,13 @@ msgid "Additional Information"
msgstr "Informations Complémentaires"
#: web/templates/admin/campsite/type/option/form.gohtml:8
#: web/templates/admin/campsite/type/option/form.gohtml:32
#: web/templates/admin/campsite/type/option/form.gohtml:33
msgctxt "title"
msgid "Edit Campsite Type Option"
msgstr "Modifier loption Type demplacement de camping"
#: web/templates/admin/campsite/type/option/form.gohtml:10
#: web/templates/admin/campsite/type/option/form.gohtml:34
#: web/templates/admin/campsite/type/option/form.gohtml:35
msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nouvelle option de type demplacement de camping"
@ -1262,16 +1265,26 @@ msgctxt "title"
msgid "Campsite Type Options"
msgstr "Options de type demplacement de camping"
#: web/templates/admin/campsite/type/option/form.gohtml:54
#: web/templates/admin/campsite/type/option/form.gohtml:55
msgctxt "input"
msgid "Minimum"
msgstr "Minimum"
#: web/templates/admin/campsite/type/option/form.gohtml:62
#: web/templates/admin/campsite/type/option/form.gohtml:63
msgctxt "input"
msgid "Maximum"
msgstr "Maximum"
#: web/templates/admin/campsite/type/option/form.gohtml:76
msgctxt "campsite type"
msgid "Per night"
msgstr "Par nuit"
#: web/templates/admin/campsite/type/option/form.gohtml:85
msgctxt "input"
msgid "Price"
msgstr "Prix"
#: web/templates/admin/campsite/type/option/index.gohtml:16
msgctxt "action"
msgid "Add Option"
@ -1934,7 +1947,7 @@ msgstr "Statut"
msgid "No booking found."
msgstr "Aucune réservation trouvée."
#: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:357
#: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:365
#: pkg/campsite/types/feature.go:272 pkg/campsite/types/admin.go:577
#: pkg/campsite/feature.go:269 pkg/season/admin.go:412
#: pkg/services/admin.go:316 pkg/surroundings/admin.go:340
@ -1942,7 +1955,7 @@ msgstr "Aucune réservation trouvée."
msgid "Name can not be empty."
msgstr "Le nom ne peut pas être laissé vide."
#: pkg/legal/admin.go:259 pkg/campsite/types/option.go:358
#: pkg/legal/admin.go:259 pkg/campsite/types/option.go:366
#: pkg/campsite/types/feature.go:273 pkg/campsite/types/admin.go:578
#: pkg/campsite/feature.go:270 pkg/amenity/feature.go:270
msgid "Name must have at least one letter."
@ -2011,41 +2024,41 @@ msgstr "Le fichier doit être une image PNG ou JPEG valide."
msgid "Access forbidden"
msgstr "Accès interdit"
#: pkg/campsite/types/option.go:361
#: pkg/campsite/types/option.go:369
msgid "Minimum can not be empty."
msgstr "Le minimum ne peut pas être vide."
#: pkg/campsite/types/option.go:362
#: pkg/campsite/types/option.go:370
msgid "Minimum must be an integer number."
msgstr "Le minimum doit être un nombre entier."
#: pkg/campsite/types/option.go:364
#: pkg/campsite/types/option.go:372
msgid "Minimum must be zero or greater."
msgstr "Le minimum doit être égal ou supérieur à zéro."
#: pkg/campsite/types/option.go:367
#: pkg/campsite/types/option.go:375
msgid "Maximum can not be empty."
msgstr "Le maximum ne peut pas être vide."
#: pkg/campsite/types/option.go:368
#: pkg/campsite/types/option.go:376
msgid "Maximum must be an integer number."
msgstr "Le maximum doit être un nombre entier."
#: pkg/campsite/types/option.go:370
#: pkg/campsite/types/option.go:378
msgid "Maximum must be equal or greater than minimum."
msgstr "Le maximum doit être égal ou supérieur au minimum."
#: pkg/campsite/types/option.go:374 pkg/campsite/types/admin.go:610
msgid "Price per night can not be empty."
msgstr "Le prix par nuit ne peut pas être vide."
#: pkg/campsite/types/option.go:382
msgid "Price can not be empty."
msgstr "Le prix ne peut pas être vide."
#: pkg/campsite/types/option.go:375 pkg/campsite/types/admin.go:611
msgid "Price per night must be a decimal number."
msgstr "Le prix par nuit doit être un nombre décimal."
#: pkg/campsite/types/option.go:383
msgid "Price must be a decimal number."
msgstr "Le prix doit être un nombre décimal."
#: pkg/campsite/types/option.go:376 pkg/campsite/types/admin.go:612
msgid "Price per night must be zero or greater."
msgstr "Le prix par nuit doit être égal ou supérieur."
#: pkg/campsite/types/option.go:384
msgid "Price must be zero or greater."
msgstr "Le prix doit être égal ou supérieur à zéro."
#: pkg/campsite/types/feature.go:271 pkg/campsite/feature.go:268
#: pkg/services/admin.go:315 pkg/amenity/feature.go:268
@ -2126,6 +2139,18 @@ msgstr "Le prix des chiens doit être un nombre décimal."
msgid "Dogs price must be zero or greater."
msgstr "Le prix de chiens doit être égal ou supérieur à zéro."
#: pkg/campsite/types/admin.go:610
msgid "Price per night can not be empty."
msgstr "Le prix par nuit ne peut pas être vide."
#: pkg/campsite/types/admin.go:611
msgid "Price per night must be a decimal number."
msgstr "Le prix par nuit doit être un nombre décimal."
#: pkg/campsite/types/admin.go:612
msgid "Price per night must be zero or greater."
msgstr "Le prix par nuit doit être égal ou supérieur."
#: pkg/campsite/types/admin.go:615
msgid "Price per adult can not be empty."
msgstr "Le prix par adulte ne peut pas être vide."
@ -2162,17 +2187,17 @@ msgstr "Le prix par enfant doit être un nombre décimal."
msgid "Price per child must be zero or greater."
msgstr "Le prix par enfant doit être égal ou supérieur."
#: pkg/campsite/types/public.go:245
#: pkg/campsite/types/public.go:247
msgctxt "header"
msgid "Adults"
msgstr "Adultes"
#: pkg/campsite/types/public.go:251
#: pkg/campsite/types/public.go:254
msgctxt "header"
msgid "Teenagers (aged 11 to 16)"
msgstr "Adolescents (de 11 à 16 anys)"
#: pkg/campsite/types/public.go:257
#: pkg/campsite/types/public.go:261
msgctxt "header"
msgid "Children (aged 2 to 10)"
msgstr "Enfants (de 2 à 10 anys)"
@ -2418,32 +2443,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:156
#: pkg/booking/cart.go:158
msgctxt "cart"
msgid "Night"
msgstr "Nuit"
#: pkg/booking/cart.go:157
#: pkg/booking/cart.go:159
msgctxt "cart"
msgid "Adult"
msgstr "Adulte"
#: pkg/booking/cart.go:158
#: pkg/booking/cart.go:160
msgctxt "cart"
msgid "Teenager"
msgstr "Adolescent"
#: pkg/booking/cart.go:159
#: pkg/booking/cart.go:161
msgctxt "cart"
msgid "Child"
msgstr "Enfant"
#: pkg/booking/cart.go:160
#: pkg/booking/cart.go:162
msgctxt "cart"
msgid "Dog"
msgstr "Chien"
#: pkg/booking/cart.go:179
#: pkg/booking/cart.go:181
msgctxt "cart"
msgid "Tourist tax"
msgstr "Taxe touristique"

View File

@ -1,7 +1,28 @@
-- Revert camper:add_campsite_type_option from pg
-- Deploy camper:add_campsite_type_option to pg
-- requires: roles
-- requires: schema_camper
-- requires: campsite_type_option
-- requires: campsite_type
begin;
drop function if exists camper.add_campsite_type_option(uuid, text, integer, integer);
set search_path to camper, public;
drop function if exists add_campsite_type_option(uuid, text, integer, integer, boolean);
create or replace function add_campsite_type_option(type_slug uuid, name text, min integer, max integer) returns integer as
$$
insert into campsite_type_option (campsite_type_id, name, range)
select campsite_type_id, add_campsite_type_option.name, int4range(min, max, '[]')
from campsite_type
where slug = type_slug
returning campsite_type_option_id
;
$$
language sql
;
revoke execute on function add_campsite_type_option(uuid, text, integer, integer) from public;
grant execute on function add_campsite_type_option(uuid, text, integer, integer) to admin;
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:add_campsite_type_option from pg
begin;
drop function if exists camper.add_campsite_type_option(uuid, text, integer, integer);
commit;

View File

@ -0,0 +1,9 @@
-- Revert camper:campsite_type_option__per_night from pg
begin;
alter table camper.campsite_type_option
drop column if exists per_night
;
commit;

View File

@ -0,0 +1,20 @@
-- Revert camper:campsite_type_option_cost__-cost_per_night from pg
begin;
set search_path to camper, public;
alter table campsite_type_option_cost
add column if not exists cost_per_night integer not null default 1 constraint cost_per_night_not_negative check(cost_per_night >= 0)
;
alter table campsite_type_option_cost
alter column cost_per_night drop default
;
update campsite_type_option_cost
set cost_per_night = cost
;
commit;

View File

@ -0,0 +1,15 @@
-- Revert camper:campsite_type_option_cost__cost from pg
begin;
set search_path to camper, public;
alter table campsite_type_option_cost
drop column if exists cost
;
alter table campsite_type_option_cost
rename constraint cost_per_night_not_negative to cost_not_negative
;
commit;

View File

@ -1,7 +1,27 @@
-- Revert camper:edit_campsite_type_option from pg
-- Deploy camper:edit_campsite_type_option to pg
-- requires: roles
-- requires: schema_camper
-- requires: campsite_type_option
begin;
drop function if exists camper.edit_campsite_type_option(integer, text, integer, integer);
set search_path to camper, public;
drop function if exists edit_campsite_type_option(integer, text, integer, integer, boolean);
create or replace function edit_campsite_type_option(option_id integer, name text, min integer, max integer) returns integer as
$$
update campsite_type_option
set name = edit_campsite_type_option.name
, range = int4range(min, max, '[]')
where campsite_type_option_id = option_id
returning campsite_type_option_id
;
$$
language sql
;
revoke execute on function edit_campsite_type_option(integer, text, integer, integer) from public;
grant execute on function edit_campsite_type_option(integer, text, integer, integer) to admin;
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:edit_campsite_type_option from pg
begin;
drop function if exists camper.edit_campsite_type_option(integer, text, integer, integer);
commit;

View File

@ -1,7 +1,27 @@
-- Revert camper:set_campsite_type_option_cost from pg
-- Deploy camper:set_campsite_type_option_cost to pg
-- requires: roles
-- requires: schema_camper
-- requires: campsite_type_option_cost
-- requires: parse_price
begin;
drop function if exists camper.set_campsite_type_option_cost(integer, integer, text, integer);
set search_path to camper, public;
drop function if exists set_campsite_type_option_cost(integer, integer, text, integer);
create or replace function set_campsite_type_option_cost(option_id integer, season_id integer, cost_per_night text, decimal_places integer default 2) returns void as
$$
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night)
values (option_id, season_id, parse_price(cost_per_night, decimal_places))
on conflict (campsite_type_option_id, season_id) do update
set cost_per_night = excluded.cost_per_night
;
$$
language sql
;
revoke execute on function set_campsite_type_option_cost(integer, integer, text, integer) from public;
grant execute on function set_campsite_type_option_cost(integer, integer, text, integer) to admin;
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:set_campsite_type_option_cost from pg
begin;
drop function if exists camper.set_campsite_type_option_cost(integer, integer, text, integer);
commit;

View File

@ -234,3 +234,9 @@ unset_campsite_type_pet_cost [roles schema_camper campsite_type campsite_type_pe
add_campsite_type [add_campsite_type@v3 campsite_type__bookable_nights] 2024-01-31T20:46:47Z jordi fita mas <jordi@tandem.blog> # Add bookable_nights param to, and remove dogs_allowed param from add_campsite_type
edit_campsite_type [edit_campsite_type@v3 campsite_type__bookable_nights] 2024-01-31T20:51:40Z jordi fita mas <jordi@tandem.blog> # Add bookable_nights param to, and remove dogs_allowed param from edit_campsite_type
campsite_type__-dogs_allowed [campsite_type campsite_type_pet_cost set_campsite_type_pet_cost] 2024-02-10T04:15:00Z jordi fita mas <jordi@tandem.blog> # Remove dogs_allowed field from campsite_type
campsite_type_option__per_night [campsite_type_option] 2024-02-11T19:32:08Z jordi fita mas <jordi@tandem.blog> # Add per_night boolean to campsite_type_option
add_campsite_type_option [add_campsite_type_option@v3 campsite_type_option__per_night] 2024-02-11T19:43:51Z jordi fita mas <jordi@tandem.blog> # Add per_night parameter to add_campsite_type_option
edit_campsite_type_option [edit_campsite_type_option@v3 campsite_type_option__per_night] 2024-02-11T19:46:26Z jordi fita mas <jordi@tandem.blog> # Add per_night parameter to edit_campsite_type_option
campsite_type_option_cost__cost [campsite_type_option_cost] 2024-02-11T19:50:44Z jordi fita mas <jordi@tandem.blog> # 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 <jordi@tandem.blog> # 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 <jordi@tandem.blog> # Remove cost_per_night field from campsite_type_option_cost

View File

@ -9,15 +9,15 @@ select plan(13);
set search_path to camper, public;
select has_function('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer']);
select function_lang_is('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer'], 'sql');
select function_returns('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer'], 'integer');
select isnt_definer('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer']);
select volatility_is('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer'], 'volatile');
select function_privs_are('camper', 'add_campsite_type_option', array ['uuid', 'text', 'integer', 'integer'], 'guest', array[]::text[]);
select function_privs_are('camper', 'add_campsite_type_option', array ['uuid', 'text', 'integer', 'integer'], 'employee', array[]::text[]);
select function_privs_are('camper', 'add_campsite_type_option', array ['uuid', 'text', 'integer', 'integer'], 'admin', array['EXECUTE']);
select function_privs_are('camper', 'add_campsite_type_option', array ['uuid', 'text', 'integer', 'integer'], 'authenticator', array[]::text[]);
select has_function('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer', 'boolean']);
select function_lang_is('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer', 'boolean'], 'sql');
select function_returns('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer', 'boolean'], 'integer');
select isnt_definer('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer', 'boolean']);
select volatility_is('camper', 'add_campsite_type_option', array['uuid', 'text', 'integer', 'integer', 'boolean'], 'volatile');
select function_privs_are('camper', 'add_campsite_type_option', array ['uuid', 'text', 'integer', 'integer', 'boolean'], 'guest', array[]::text[]);
select function_privs_are('camper', 'add_campsite_type_option', array ['uuid', 'text', 'integer', 'integer', 'boolean'], 'employee', array[]::text[]);
select function_privs_are('camper', 'add_campsite_type_option', array ['uuid', 'text', 'integer', 'integer', 'boolean'], 'admin', array['EXECUTE']);
select function_privs_are('camper', 'add_campsite_type_option', array ['uuid', 'text', 'integer', 'integer', 'boolean'], 'authenticator', array[]::text[]);
set client_min_messages to warning;
@ -48,19 +48,19 @@ values (3, 1, '87452b88-b48f-48d3-bb6c-0296de64164e', 2, 'Type A', '<p>A</p>', t
;
select lives_ok(
$$ select add_campsite_type_option('87452b88-b48f-48d3-bb6c-0296de64164e', 'Option 1', 0, 10) $$,
$$ select add_campsite_type_option('87452b88-b48f-48d3-bb6c-0296de64164e', 'Option 1', 0, 10, true) $$,
'Should be able to add an option to the first campsite type'
);
select lives_ok(
$$ select add_campsite_type_option('9ae5cf87-cd69-4541-b5a5-75f937cc9e58', 'Option 2', 5, 15) $$,
$$ select add_campsite_type_option('9ae5cf87-cd69-4541-b5a5-75f937cc9e58', 'Option 2', 5, 15, false) $$,
'Should be able to add an option to the second campsite type'
);
select bag_eq(
$$ select campsite_type_id, name, range from campsite_type_option $$,
$$ values (3, 'Option 1', '[0, 10]'::int4range)
, (4, 'Option 2', '[5, 15]'::int4range)
$$ select campsite_type_id, name, range, per_night from campsite_type_option $$,
$$ values (3, 'Option 1', '[0, 10]'::int4range, true)
, (4, 'Option 2', '[5, 15]'::int4range, false)
$$,
'Should have added all two campsite type options'
);

View File

@ -5,7 +5,7 @@ reset client_min_messages;
begin;
select plan(45);
select plan(49);
set search_path to camper, public;
@ -39,6 +39,11 @@ select col_type_is('campsite_type_option', 'range', 'int4range');
select col_not_null('campsite_type_option', 'range');
select col_hasnt_default('campsite_type_option', 'range');
select has_column('campsite_type_option', 'per_night');
select col_type_is('campsite_type_option', 'per_night', 'boolean');
select col_not_null('campsite_type_option', 'per_night');
select col_hasnt_default('campsite_type_option', 'per_night');
select has_column('campsite_type_option', 'position');
select col_type_is('campsite_type_option', 'position', 'integer');
select col_not_null('campsite_type_option', 'position');
@ -91,9 +96,9 @@ values (16, 2, 'Wooden lodge', 6, 7, '[1, 7]')
, (18, 4, 'Bungalow', 8, 6, '[2, 6]')
;
insert into campsite_type_option (campsite_type_id, name, range)
values (16, 'Option 16.1', '[2, 2]')
, (18, 'Option 18.1', '[4, 8]')
insert into campsite_type_option (campsite_type_id, name, range, per_night)
values (16, 'Option 16.1', '[2, 2]', true)
, (18, 'Option 18.1', '[4, 8]', true)
;
prepare campsite_option_data as
@ -114,7 +119,7 @@ reset role;
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2');
select lives_ok(
$$ insert into campsite_type_option(campsite_type_id, name, range) values (16, 'Option 16.2', '[3, 3]') $$,
$$ insert into campsite_type_option(campsite_type_id, name, range, per_night) values (16, 'Option 16.2', '[3, 3]', false) $$,
'Admin from company 2 should be able to insert a new campsite type option to that company.'
);
@ -155,7 +160,7 @@ select bag_eq(
);
select throws_ok(
$$ insert into campsite_type_option (campsite_type_id, name, range) values (18, 'Option 18.2', '[5, 5]') $$,
$$ insert into campsite_type_option (campsite_type_id, name, range, per_night) values (18, 'Option 18.2', '[5, 5]', true) $$,
'42501', 'new row violates row-level security policy for table "campsite_type_option"',
'Admin from company 2 should NOT be able to insert new campsite type options to company 4.'
);
@ -193,13 +198,13 @@ select bag_eq(
);
select throws_ok(
$$ insert into campsite_type_option (campsite_type_id, name, range) values (16, ' ', '[5, 6]') $$,
$$ insert into campsite_type_option (campsite_type_id, name, range, per_night) values (16, ' ', '[5, 6]', true) $$,
'23514', 'new row for relation "campsite_type_option" violates check constraint "name_not_empty"',
'Should not be able to insert campsite type options with a blank name.'
);
select throws_ok(
$$ insert into campsite_type_option (campsite_type_id, name, range) values (16, 'Option 16.2', '[-1, 1]') $$,
$$ insert into campsite_type_option (campsite_type_id, name, range, per_night) values (16, 'Option 16.2', '[-1, 1]', true) $$,
'23514', 'new row for relation "campsite_type_option" violates check constraint "range_not_negative"',
'Should not be able to insert campsite type options with a range starting with a negative number'
);

View File

@ -31,10 +31,10 @@ select col_type_is('campsite_type_option_cost', 'season_id', 'integer');
select col_not_null('campsite_type_option_cost', 'season_id');
select col_hasnt_default('campsite_type_option_cost', 'season_id');
select has_column('campsite_type_option_cost', 'cost_per_night');
select col_type_is('campsite_type_option_cost', 'cost_per_night', 'integer');
select col_not_null('campsite_type_option_cost', 'cost_per_night');
select col_hasnt_default('campsite_type_option_cost', 'cost_per_night');
select has_column('campsite_type_option_cost', 'cost');
select col_type_is('campsite_type_option_cost', 'cost', 'integer');
select col_not_null('campsite_type_option_cost', 'cost');
select col_hasnt_default('campsite_type_option_cost', 'cost');
set client_min_messages to warning;
@ -91,18 +91,18 @@ values (26, 2, 'Low')
, (29, 4, 'Mid')
;
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range)
values (17, 16, 'Option 16.1', '[1, 16]')
, (19, 18, 'Option 18.1', '[1, 18]')
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range, per_night)
values (17, 16, 'Option 16.1', '[1, 16]', true)
, (19, 18, 'Option 18.1', '[1, 18]', true)
;
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night)
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost)
values (17, 26, 2)
, (19, 28, 4)
;
prepare option_cost_data as
select campsite_type_option_id, season_id, cost_per_night
select campsite_type_option_id, season_id, cost
from campsite_type_option_cost
;
@ -119,7 +119,7 @@ reset role;
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2');
select lives_ok(
$$ insert into campsite_type_option_cost(campsite_type_option_id, season_id, cost_per_night) values (17, 27, 3) $$,
$$ insert into campsite_type_option_cost(campsite_type_option_id, season_id, cost) values (17, 27, 3) $$,
'Admin from company 2 should be able to insert a new option cost to that company.'
);
@ -133,7 +133,7 @@ select bag_eq(
);
select lives_ok(
$$ update campsite_type_option_cost set cost_per_night = 6 where campsite_type_option_id = 17 and season_id = 27 $$,
$$ update campsite_type_option_cost set cost = 6 where campsite_type_option_id = 17 and season_id = 27 $$,
'Admin from company 2 should be able to update option cost of that company.'
);
@ -160,30 +160,30 @@ select bag_eq(
);
select throws_ok(
$$ insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night) values (19, 29, 5) $$,
$$ insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost) values (19, 29, 5) $$,
'42501', 'new row violates row-level security policy for table "campsite_type_option_cost"',
'Admin from company 2 should NOT be able to insert new option costs to company 4.'
);
select throws_ok(
$$ insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night) values (19, 27, 5) $$,
$$ insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost) values (19, 27, 5) $$,
'42501', 'new row violates row-level security policy for table "campsite_type_option_cost"',
'Admin from company 2 should NOT be able to insert new row with a campsite type from company 4.'
);
select throws_ok(
$$ insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night) values (17, 29, 5) $$,
$$ insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost) values (17, 29, 5) $$,
'42501', 'new row violates row-level security policy for table "campsite_type_option_cost"',
'Admin from company 2 should NOT be able to insert new row with a season from company 4.'
);
select lives_ok(
$$ update campsite_type_option_cost set cost_per_night = 1 where campsite_type_option_id = 19 $$,
$$ update campsite_type_option_cost set cost = 1 where campsite_type_option_id = 19 $$,
'Admin from company 2 should not be able to update campsite types of company 4, but no error if campsite_type_option_id is not changed.'
);
select lives_ok(
$$ update campsite_type_option_cost set cost_per_night = 1 where season_id = 28 $$,
$$ update campsite_type_option_cost set cost = 1 where season_id = 28 $$,
'Admin from company 2 should not be able to update seasons of company 4, but no error if season_id is not changed.'
);
@ -226,9 +226,9 @@ select bag_eq(
);
select throws_ok(
$$ insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night) values (17, 27, -1) $$,
$$ insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost) values (17, 27, -1) $$,
'23514', 'new row for relation "campsite_type_option_cost" violates check constraint "cost_not_negative"',
'Should not be able to insert option costs with negative cost per night.'
'Should not be able to insert option costs with negative cost.'
);
reset role;

View File

@ -9,15 +9,15 @@ select plan(13);
set search_path to camper, public;
select has_function('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer']);
select function_lang_is('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer'], 'sql');
select function_returns('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer'], 'integer');
select isnt_definer('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer']);
select volatility_is('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer'], 'volatile');
select function_privs_are('camper', 'edit_campsite_type_option', array ['integer', 'text', 'integer', 'integer'], 'guest', array[]::text[]);
select function_privs_are('camper', 'edit_campsite_type_option', array ['integer', 'text', 'integer', 'integer'], 'employee', array[]::text[]);
select function_privs_are('camper', 'edit_campsite_type_option', array ['integer', 'text', 'integer', 'integer'], 'admin', array['EXECUTE']);
select function_privs_are('camper', 'edit_campsite_type_option', array ['integer', 'text', 'integer', 'integer'], 'authenticator', array[]::text[]);
select has_function('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer', 'boolean']);
select function_lang_is('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer', 'boolean'], 'sql');
select function_returns('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer', 'boolean'], 'integer');
select isnt_definer('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer', 'boolean']);
select volatility_is('camper', 'edit_campsite_type_option', array['integer', 'text', 'integer', 'integer', 'boolean'], 'volatile');
select function_privs_are('camper', 'edit_campsite_type_option', array ['integer', 'text', 'integer', 'integer', 'boolean'], 'guest', array[]::text[]);
select function_privs_are('camper', 'edit_campsite_type_option', array ['integer', 'text', 'integer', 'integer', 'boolean'], 'employee', array[]::text[]);
select function_privs_are('camper', 'edit_campsite_type_option', array ['integer', 'text', 'integer', 'integer', 'boolean'], 'admin', array['EXECUTE']);
select function_privs_are('camper', 'edit_campsite_type_option', array ['integer', 'text', 'integer', 'integer', 'boolean'], 'authenticator', array[]::text[]);
set client_min_messages to warning;
@ -46,25 +46,25 @@ insert into campsite_type (campsite_type_id, company_id, media_id, name, descrip
values (3, 1, 2, 'Type A', '<p>A</p>', true, 4, '[1, 7]')
;
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range)
values (4, 3, 'Option 1', '[0, 10]')
, (5, 3, 'Option 2', '[5, 15]')
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range, per_night)
values (4, 3, 'Option 1', '[0, 10]', true)
, (5, 3, 'Option 2', '[5, 15]', false)
;
select lives_ok(
$$ select edit_campsite_type_option(4, 'Option A', 1, 11) $$,
$$ select edit_campsite_type_option(4, 'Option A', 1, 11, false) $$,
'Should be able to edit the first option'
);
select lives_ok(
$$ select edit_campsite_type_option(5, 'Option B', 6, 14) $$,
$$ select edit_campsite_type_option(5, 'Option B', 6, 14, true) $$,
'Should be able to edit the second option'
);
select bag_eq(
$$ select campsite_type_option_id, campsite_type_id, name, range from campsite_type_option $$,
$$ values (4, 3, 'Option A', '[1, 11]'::int4range)
, (5, 3, 'Option B', '[6, 14]'::int4range)
$$ select campsite_type_option_id, campsite_type_id, name, range, per_night from campsite_type_option $$,
$$ values (4, 3, 'Option A', '[1, 11]'::int4range, false)
, (5, 3, 'Option B', '[6, 14]'::int4range, true)
$$,
'Should have updated all campsite type options.'
);

View File

@ -46,12 +46,12 @@ insert into campsite_type (campsite_type_id, company_id, media_id, name, descrip
values (3, 1, 2, 'Type A', '<p>A</p>', true, 4, '[1, 7]')
;
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range)
values (4, 3, '1', '[0, 10]')
, (5, 3, '2', '[0, 10]')
, (6, 3, '3', '[0, 10]')
, (7, 3, '4', '[0, 10]')
, (8, 3, '5', '[0, 10]')
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range, per_night)
values (4, 3, '1', '[0, 10]', true)
, (5, 3, '2', '[0, 10]', true)
, (6, 3, '3', '[0, 10]', true)
, (7, 3, '4', '[0, 10]', true)
, (8, 3, '5', '[0, 10]', true)
;
select lives_ok(

View File

@ -52,17 +52,17 @@ values (10, 1, '87452b88-b48f-48d3-bb6c-0296de64164e', 2, 'Type A', '<p>A</p>',
, (11, 1, '9b6370f7-f941-46f2-bc6e-de455675bd0a', 3, 'Type B', '<p>B</p>', 4, '[2, 6]', false)
;
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range)
values (12, 10, 'Option 1', '[0, 1]')
, (13, 10, 'Option 2', '[0, 1]')
, (14, 11, 'Option 3', '[0, 1]')
, (15, 11, 'Option 4', '[0, 1]')
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range, per_night)
values (12, 10, 'Option 1', '[0, 1]', true)
, (13, 10, 'Option 2', '[0, 1]', true)
, (14, 11, 'Option 3', '[0, 1]', true)
, (15, 11, 'Option 4', '[0, 1]', true)
;
insert into season (season_id, company_id, name)
values (16, 1, 'High')
;
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night)
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost)
values (12, 16, 44)
, (13, 16, 54)
, (14, 16, 74)
@ -109,7 +109,7 @@ select bag_eq(
);
select bag_eq(
$$ select campsite_type_option_id, season_id, cost_per_night from campsite_type_option_cost $$,
$$ select campsite_type_option_id, season_id, cost from campsite_type_option_cost $$,
$$ values (13, 16, 54)
, (14, 16, 74)
$$,

View File

@ -53,11 +53,11 @@ values (4, 1, 'High')
, (6, 1, 'Low')
;
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range)
values (7, 3, 'Test Option', '[1, 100]')
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range, per_night)
values (7, 3, 'Test Option', '[1, 100]', true)
;
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost_per_night)
insert into campsite_type_option_cost (campsite_type_option_id, season_id, cost)
values (7, 4, 44)
, (7, 5, 55)
;
@ -78,7 +78,7 @@ select lives_ok(
);
select bag_eq(
$$ select campsite_type_option_id, season_id, cost_per_night from campsite_type_option_cost $$,
$$ select campsite_type_option_id, season_id, cost from campsite_type_option_cost $$,
$$ values (7, 4, 1234)
, (7, 5, 0)
, (7, 6, 321)

View File

@ -45,9 +45,9 @@ insert into campsite_type (campsite_type_id, company_id, slug, media_id, name, d
values (3, 1, '87452b88-b48f-48d3-bb6c-0296de64164e', 2, 'Type A', '<p>A</p>', true, 4, '[1, 7]')
;
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range)
values (4, 3, 'Option 1', '[1, 1]')
, (5, 3, 'Option 2', '[1, 2]')
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range, per_night)
values (4, 3, 'Option 1', '[1, 1]', true)
, (5, 3, 'Option 2', '[1, 2]', true)
;
insert into campsite_type_option_i18n (campsite_type_option_id, lang_tag, name)

View File

@ -2,6 +2,6 @@
begin;
select has_function_privilege('camper.add_campsite_type_option(uuid, text, integer, integer)', 'execute');
select has_function_privilege('camper.add_campsite_type_option(uuid, text, integer, integer, boolean)', 'execute');
rollback;

View File

@ -0,0 +1,7 @@
-- Verify camper:add_campsite_type_option on pg
begin;
select has_function_privilege('camper.add_campsite_type_option(uuid, text, integer, integer)', 'execute');
rollback;

View File

@ -0,0 +1,10 @@
-- Verify camper:campsite_type_option__per_night on pg
begin;
select per_night
from camper.campsite_type_option
where false
;
rollback;

View File

@ -0,0 +1,11 @@
-- Verify camper:campsite_type_option_cost__-cost_per_night on pg
begin;
select 1 / (1 - count(*))
from pg_attribute
where attrelid = 'camper.campsite_type_option_cost'::regclass
and attname = 'cost_per_night'
;
rollback;

View File

@ -0,0 +1,8 @@
-- Verify camper:campsite_type_option_cost__cost on pg
begin;
select cost
from camper.campsite_type_option_cost;
rollback;

View File

@ -2,6 +2,6 @@
begin;
select has_function_privilege('camper.edit_campsite_type_option(integer, text, integer, integer)', 'execute');
select has_function_privilege('camper.edit_campsite_type_option(integer, text, integer, integer, boolean)', 'execute');
rollback;

View File

@ -0,0 +1,7 @@
-- Verify camper:edit_campsite_type_option on pg
begin;
select has_function_privilege('camper.edit_campsite_type_option(integer, text, integer, integer)', 'execute');
rollback;

View File

@ -0,0 +1,7 @@
-- Verify camper:set_campsite_type_option_cost on pg
begin;
select has_function_privilege('camper.set_campsite_type_option_cost(integer, integer, text, integer)', 'execute');
rollback;

View File

@ -68,12 +68,20 @@
{{ with .Prices }}
<fieldset>
<legend>{{( pgettext "Prices" "title" )}}</legend>
{{ with $.PerNight -}}
<label>
<input type="checkbox" name="{{ .Name }}" {{ if .Checked}}checked{{ end }}
{{ template "error-attrs" . }}>
{{( pgettext "Per night" "campsite type" )}}<br>
</label>
{{ template "error-message" . }}
{{- end }}
{{ range . }}
<fieldset>
<legend>{{ .SeasonName }}</legend>
{{ with .PricePerNight -}}
{{ with .Price -}}
<label>
{{( pgettext "Price per night" "input")}}<br>
{{( pgettext "Price" "input")}}<br>
<input type="number" name="{{ .Name }}" value="{{ .Val }}" min="0" step="0.01"
required {{ template "error-attrs" . }}><br>
{{ template "error-message" . }}

View File

@ -78,9 +78,17 @@
{{ range .Options }}
<dd x-show="open">
{{- if .OptionName -}}
{{ printf (gettext "%s: %s/night") .OptionName (formatPrice .PricePerNight) }}
{{ if .PerNight -}}
{{ printf (gettext "%s: %s/night") .OptionName (formatPrice .Price) }}
{{- else -}}
{{ printf (gettext "%s: %s") .OptionName (formatPrice .Price) }}
{{- end }}
{{- else -}}
{{ printf (gettext "%s/night") (formatPrice .PricePerNight) }}
{{ if .PerNight -}}
{{ printf (gettext "%s/night") (formatPrice .Price) }}
{{- else -}}
{{ formatPrice .Price }}
{{- end }}
{{- end -}}
</dd>
{{- end }}