diff --git a/demo/demo.sql b/demo/demo.sql index bea7c69..de80f40 100644 --- a/demo/demo.sql +++ b/demo/demo.sql @@ -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.)'); diff --git a/deploy/add_campsite_type_option.sql b/deploy/add_campsite_type_option.sql index 29924d3..86cefdc 100644 --- a/deploy/add_campsite_type_option.sql +++ b/deploy/add_campsite_type_option.sql @@ -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; diff --git a/deploy/add_campsite_type_option@v3.sql b/deploy/add_campsite_type_option@v3.sql new file mode 100644 index 0000000..29924d3 --- /dev/null +++ b/deploy/add_campsite_type_option@v3.sql @@ -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; diff --git a/deploy/campsite_type_option__per_night.sql b/deploy/campsite_type_option__per_night.sql new file mode 100644 index 0000000..ea9edf8 --- /dev/null +++ b/deploy/campsite_type_option__per_night.sql @@ -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; diff --git a/deploy/campsite_type_option_cost__-cost_per_night.sql b/deploy/campsite_type_option_cost__-cost_per_night.sql new file mode 100644 index 0000000..0648f43 --- /dev/null +++ b/deploy/campsite_type_option_cost__-cost_per_night.sql @@ -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; diff --git a/deploy/campsite_type_option_cost__cost.sql b/deploy/campsite_type_option_cost__cost.sql new file mode 100644 index 0000000..bf7355e --- /dev/null +++ b/deploy/campsite_type_option_cost__cost.sql @@ -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; diff --git a/deploy/edit_campsite_type_option.sql b/deploy/edit_campsite_type_option.sql index 624e8d0..d67cfcf 100644 --- a/deploy/edit_campsite_type_option.sql +++ b/deploy/edit_campsite_type_option.sql @@ -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; diff --git a/deploy/edit_campsite_type_option@v3.sql b/deploy/edit_campsite_type_option@v3.sql new file mode 100644 index 0000000..624e8d0 --- /dev/null +++ b/deploy/edit_campsite_type_option@v3.sql @@ -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; diff --git a/deploy/set_campsite_type_option_cost.sql b/deploy/set_campsite_type_option_cost.sql index c5e0cc4..898038b 100644 --- a/deploy/set_campsite_type_option_cost.sql +++ b/deploy/set_campsite_type_option_cost.sql @@ -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 diff --git a/deploy/set_campsite_type_option_cost@v3.sql b/deploy/set_campsite_type_option_cost@v3.sql new file mode 100644 index 0000000..c5e0cc4 --- /dev/null +++ b/deploy/set_campsite_type_option_cost@v3.sql @@ -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; diff --git a/pkg/booking/cart.go b/pkg/booking/cart.go index b36e0b7..c43549c 100644 --- a/pkg/booking/cart.go +++ b/pkg/booking/cart.go @@ -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 diff --git a/pkg/campsite/types/option.go b/pkg/campsite/types/option.go index 19679c6..42b8926 100644 --- a/pkg/campsite/types/option.go +++ b/pkg/campsite/types/option.go @@ -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.")) } } } diff --git a/pkg/campsite/types/public.go b/pkg/campsite/types/public.go index 042a43c..02852bd 100644 --- a/pkg/campsite/types/public.go +++ b/pkg/campsite/types/public.go @@ -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) diff --git a/pkg/database/funcs.go b/pkg/database/funcs.go index 49fb17f..9b12d4f 100644 --- a/pkg/database/funcs.go +++ b/pkg/database/funcs.go @@ -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 } diff --git a/po/ca.po b/po/ca.po index e9640f1..ddd5dc9 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-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 \n" "Language-Team: Catalan \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 (2–10)" msgstr "Preu per nen (2–10)" #: 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 l’opció del tipus d’allotjament" #: 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 d’allotjament" @@ -1262,16 +1265,26 @@ msgctxt "title" msgid "Campsite Type Options" msgstr "Opcions del tipus d’allotjament" -#: 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 s’ha 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 s’ha 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" diff --git a/po/es.po b/po/es.po index c13be07..50b5b97 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-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 \n" "Language-Team: Spanish \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 (2–10)" msgstr "Precio por niño (2–10)" #: 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" diff --git a/po/fr.po b/po/fr.po index e2fe299..ebbadc1 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-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 \n" "Language-Team: French \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 (2–10)" msgstr "Prix per enfant (2–10)" #: 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 l’option Type d’emplacement 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 d’emplacement de camping" @@ -1262,16 +1265,26 @@ msgctxt "title" msgid "Campsite Type Options" msgstr "Options de type d’emplacement 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" diff --git a/revert/add_campsite_type_option.sql b/revert/add_campsite_type_option.sql index ff13e2e..8d9cede 100644 --- a/revert/add_campsite_type_option.sql +++ b/revert/add_campsite_type_option.sql @@ -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; diff --git a/revert/add_campsite_type_option@v3.sql b/revert/add_campsite_type_option@v3.sql new file mode 100644 index 0000000..ff13e2e --- /dev/null +++ b/revert/add_campsite_type_option@v3.sql @@ -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; diff --git a/revert/campsite_type_option__per_night.sql b/revert/campsite_type_option__per_night.sql new file mode 100644 index 0000000..b7537a8 --- /dev/null +++ b/revert/campsite_type_option__per_night.sql @@ -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; diff --git a/revert/campsite_type_option_cost__-cost_per_night.sql b/revert/campsite_type_option_cost__-cost_per_night.sql new file mode 100644 index 0000000..1d9874b --- /dev/null +++ b/revert/campsite_type_option_cost__-cost_per_night.sql @@ -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; diff --git a/revert/campsite_type_option_cost__cost.sql b/revert/campsite_type_option_cost__cost.sql new file mode 100644 index 0000000..9018f9f --- /dev/null +++ b/revert/campsite_type_option_cost__cost.sql @@ -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; diff --git a/revert/edit_campsite_type_option.sql b/revert/edit_campsite_type_option.sql index ec17581..8e60605 100644 --- a/revert/edit_campsite_type_option.sql +++ b/revert/edit_campsite_type_option.sql @@ -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; diff --git a/revert/edit_campsite_type_option@v3.sql b/revert/edit_campsite_type_option@v3.sql new file mode 100644 index 0000000..ec17581 --- /dev/null +++ b/revert/edit_campsite_type_option@v3.sql @@ -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; diff --git a/revert/set_campsite_type_option_cost.sql b/revert/set_campsite_type_option_cost.sql index 0fea3a3..d21882b 100644 --- a/revert/set_campsite_type_option_cost.sql +++ b/revert/set_campsite_type_option_cost.sql @@ -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; diff --git a/revert/set_campsite_type_option_cost@v3.sql b/revert/set_campsite_type_option_cost@v3.sql new file mode 100644 index 0000000..0fea3a3 --- /dev/null +++ b/revert/set_campsite_type_option_cost@v3.sql @@ -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; diff --git a/sqitch.plan b/sqitch.plan index ab0eb1f..1c3450e 100644 --- a/sqitch.plan +++ b/sqitch.plan @@ -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 # 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 # 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 # Remove dogs_allowed field from campsite_type +campsite_type_option__per_night [campsite_type_option] 2024-02-11T19:32:08Z jordi fita mas # 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 # 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 # 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 # 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 diff --git a/test/add_campsite_type_option.sql b/test/add_campsite_type_option.sql index 3ecbdc4..50e7428 100644 --- a/test/add_campsite_type_option.sql +++ b/test/add_campsite_type_option.sql @@ -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', '

A

', 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' ); diff --git a/test/campsite_type_option.sql b/test/campsite_type_option.sql index f0780f8..49b38df 100644 --- a/test/campsite_type_option.sql +++ b/test/campsite_type_option.sql @@ -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' ); diff --git a/test/campsite_type_option_cost.sql b/test/campsite_type_option_cost.sql index d5c4736..2fe3c09 100644 --- a/test/campsite_type_option_cost.sql +++ b/test/campsite_type_option_cost.sql @@ -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; diff --git a/test/edit_campsite_type_option.sql b/test/edit_campsite_type_option.sql index 6dae754..0bbaa9b 100644 --- a/test/edit_campsite_type_option.sql +++ b/test/edit_campsite_type_option.sql @@ -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', '

A

', 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.' ); diff --git a/test/order_campsite_type_options.sql b/test/order_campsite_type_options.sql index 8a6d9f0..043ad65 100644 --- a/test/order_campsite_type_options.sql +++ b/test/order_campsite_type_options.sql @@ -46,12 +46,12 @@ insert into campsite_type (campsite_type_id, company_id, media_id, name, descrip values (3, 1, 2, 'Type A', '

A

', 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( diff --git a/test/remove_campsite_type_option.sql b/test/remove_campsite_type_option.sql index a399ad2..bf8061b 100644 --- a/test/remove_campsite_type_option.sql +++ b/test/remove_campsite_type_option.sql @@ -52,17 +52,17 @@ values (10, 1, '87452b88-b48f-48d3-bb6c-0296de64164e', 2, 'Type A', '

A

', , (11, 1, '9b6370f7-f941-46f2-bc6e-de455675bd0a', 3, 'Type B', '

B

', 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) $$, diff --git a/test/set_campsite_type_option_cost.sql b/test/set_campsite_type_option_cost.sql index 3686c3b..5e4128a 100644 --- a/test/set_campsite_type_option_cost.sql +++ b/test/set_campsite_type_option_cost.sql @@ -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) diff --git a/test/translate_campsite_type_option.sql b/test/translate_campsite_type_option.sql index 9526c5c..b0086b6 100644 --- a/test/translate_campsite_type_option.sql +++ b/test/translate_campsite_type_option.sql @@ -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', '

A

', 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) diff --git a/verify/add_campsite_type_option.sql b/verify/add_campsite_type_option.sql index b6b4086..5ae401e 100644 --- a/verify/add_campsite_type_option.sql +++ b/verify/add_campsite_type_option.sql @@ -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; diff --git a/verify/add_campsite_type_option@v3.sql b/verify/add_campsite_type_option@v3.sql new file mode 100644 index 0000000..b6b4086 --- /dev/null +++ b/verify/add_campsite_type_option@v3.sql @@ -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; diff --git a/verify/campsite_type_option__per_night.sql b/verify/campsite_type_option__per_night.sql new file mode 100644 index 0000000..99fe1f0 --- /dev/null +++ b/verify/campsite_type_option__per_night.sql @@ -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; diff --git a/verify/campsite_type_option_cost__-cost_per_night.sql b/verify/campsite_type_option_cost__-cost_per_night.sql new file mode 100644 index 0000000..50379cc --- /dev/null +++ b/verify/campsite_type_option_cost__-cost_per_night.sql @@ -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; diff --git a/verify/campsite_type_option_cost__cost.sql b/verify/campsite_type_option_cost__cost.sql new file mode 100644 index 0000000..41288c5 --- /dev/null +++ b/verify/campsite_type_option_cost__cost.sql @@ -0,0 +1,8 @@ +-- Verify camper:campsite_type_option_cost__cost on pg + +begin; + +select cost +from camper.campsite_type_option_cost; + +rollback; diff --git a/verify/edit_campsite_type_option.sql b/verify/edit_campsite_type_option.sql index df3d454..ee25077 100644 --- a/verify/edit_campsite_type_option.sql +++ b/verify/edit_campsite_type_option.sql @@ -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; diff --git a/verify/edit_campsite_type_option@v3.sql b/verify/edit_campsite_type_option@v3.sql new file mode 100644 index 0000000..df3d454 --- /dev/null +++ b/verify/edit_campsite_type_option@v3.sql @@ -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; diff --git a/verify/set_campsite_type_option_cost@v3.sql b/verify/set_campsite_type_option_cost@v3.sql new file mode 100644 index 0000000..2e60d5d --- /dev/null +++ b/verify/set_campsite_type_option_cost@v3.sql @@ -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; diff --git a/web/templates/admin/campsite/type/option/form.gohtml b/web/templates/admin/campsite/type/option/form.gohtml index a333901..72aa186 100644 --- a/web/templates/admin/campsite/type/option/form.gohtml +++ b/web/templates/admin/campsite/type/option/form.gohtml @@ -68,12 +68,20 @@ {{ with .Prices }}
{{( pgettext "Prices" "title" )}} + {{ with $.PerNight -}} + + {{ template "error-message" . }} + {{- end }} {{ range . }}
{{ .SeasonName }} - {{ with .PricePerNight -}} + {{ with .Price -}}