Add check-in form

I based the form from the documentation given by the Mossos
d’Esquadra[0], required by law.

https://registreviatgers.mossos.gencat.cat/mossos_hotels/AppJava/fitxaviatger.do?reqCode=create
This commit is contained in:
jordi fita mas 2024-04-26 17:09:36 +02:00
parent c9e8165f83
commit f2b24a83a3
51 changed files with 2243 additions and 254 deletions

View File

@ -0,0 +1,39 @@
-- Deploy camper:available_id_document_types to pg
-- requires: id_document_type
-- requires: id_document_type_i18n
begin;
set search_path to camper;
insert into id_document_type (id_document_type_id, name)
values ('D', 'DNI')
, ('P', 'Passport')
, ('C', 'Driving license')
, ('I', 'Identification document')
, ('N', 'Spanish residence permit')
, ('X', 'Residence permit from another Member State of the European Union')
;
insert into id_document_type_i18n (id_document_type_id, lang_tag, name)
values ('D', 'ca', 'DNI')
, ('P', 'ca', 'Passaport')
, ('C', 'ca', 'Permís de conduir')
, ('I', 'ca', 'Carta o document didentitat')
, ('N', 'ca', 'Permís de residència espanyol')
, ('X', 'ca', 'Permís de residència dun altre estat membre de la Unió Europea')
, ('D', 'es', 'DNI')
, ('P', 'es', 'Pasaporte')
, ('C', 'es', 'Permiso de conducir')
, ('I', 'es', 'Carta o documento de identidad')
, ('N', 'es', 'Permiso de residencia español')
, ('X', 'es', 'Permiso de residencia de otro Estado Miembro de la Unión Europea')
, ('D', 'fr', 'DNI')
, ('P', 'fr', 'Passeport')
, ('C', 'fr', 'Permis de conduire')
, ('I', 'fr', 'Carte didentité')
, ('N', 'fr', 'Permis de séjour espagnol')
, ('X', 'fr', 'Titre de séjour dun autre État membre de lUnion européenne')
;
commit;

View File

@ -0,0 +1,23 @@
-- Deploy camper:available_sexes to pg
-- requires: sex
-- requires: sex_i18n
begin;
set search_path to camper;
insert into sex (sex_id, name)
values ('F', 'Female')
, ('M', 'Male')
;
insert into sex_i18n (sex_id, lang_tag, name)
values ('F', 'ca', 'Femení')
, ('M', 'ca', 'Masculí')
, ('F', 'es', 'Femenino')
, ('M', 'es', 'Masculino')
, ('F', 'fr', 'Féminin')
, ('M', 'fr', 'Masculin')
;
commit;

35
deploy/booking_guest.sql Normal file
View File

@ -0,0 +1,35 @@
-- Deploy camper:booking_guest to pg
-- requires: roles
-- requires: schema_camper
-- requires: booking
-- requires: sex
-- requires: id_document_type
-- requires: extension_pg_libphonenumber
begin;
set search_path to camper, public;
create table booking_guest (
booking_guest_id integer generated by default as identity primary key,
booking_id integer not null references booking,
id_document_type_id varchar(1) not null references id_document_type,
id_document_number text not null,
id_document_issue_date date,
given_name text not null,
first_surname text not null,
second_surname text not null,
sex_id varchar(1) not null references sex,
birthdate date not null,
country_code country_code not null references country,
phone packed_phone_number,
address text not null,
created_at timestamp with time zone not null default current_timestamp,
updated_at timestamp with time zone not null default current_timestamp,
unique (booking_id, id_document_type_id, id_document_number)
);
grant select, insert, update, delete on table booking_guest to employee;
grant select, insert, update, delete on table booking_guest to admin;
commit;

View File

@ -0,0 +1,75 @@
-- Deploy camper:check_in_guests to pg
-- requires: roles
-- requires: schema_camper
-- requires: booking
-- requires: booking_guest
-- requires: checked_in_guest
-- requires: extension_pg_libphonenumber
begin;
set search_path to camper, public;
create or replace function check_in_guests(bid integer, guests checked_in_guest[]) returns void as
$$
insert into booking_guest
( booking_id
, id_document_type_id
, id_document_number
, id_document_issue_date
, given_name
, first_surname
, second_surname
, sex_id
, birthdate
, country_code
, phone
, address
)
select bid
, id_document_type_id
, id_document_number
, id_document_issue_date
, given_name
, first_surname
, second_surname
, sex_id
, birthdate
, country_code
, case when phone is null or phone = '' then null else parse_packed_phone_number(phone, country_code) end
, address
from unnest(guests) as guest
on conflict (booking_id, id_document_type_id, id_document_number) do update
set id_document_type_id = excluded.id_document_type_id
, id_document_number = excluded.id_document_number
, id_document_issue_date = excluded.id_document_issue_date
, given_name = excluded.given_name
, first_surname = excluded.first_surname
, second_surname = excluded.second_surname
, sex_id = excluded.sex_id
, birthdate = excluded.birthdate
, country_code = excluded.country_code
, phone = excluded.phone
, address = excluded.address
, updated_at = current_timestamp
;
delete from booking_guest
where booking_id = bid
and updated_at < current_timestamp
;
update booking
set booking_status = 'checked-in'
where booking_id = bid
and booking_status in ('created', 'confirmed')
;
$$
language sql
;
revoke execute on function check_in_guests(integer, checked_in_guest[]) from public;
grant execute on function check_in_guests(integer, checked_in_guest[]) to employee;
grant execute on function check_in_guests(integer, checked_in_guest[]) to admin;
commit;

View File

@ -0,0 +1,22 @@
-- Deploy camper:checked_in_guest to pg
-- requires: schema_camper
begin;
set search_path to camper, public;
create type checked_in_guest as (
id_document_type_id varchar(1),
id_document_number text,
id_document_issue_date date,
given_name text,
first_surname text,
second_surname text,
sex_id varchar(1),
birthdate date,
country_code country_code,
phone text,
address text
);
commit;

View File

@ -0,0 +1,17 @@
-- Deploy camper:id_document_type to pg
-- requires: roles
-- requires: schema_camper
begin;
set search_path to camper, public;
create table id_document_type (
id_document_type_id varchar(1) primary key,
name text not null
);
grant select on table id_document_type to employee;
grant select on table id_document_type to admin;
commit;

View File

@ -0,0 +1,21 @@
-- Deploy camper:id_document_type_i18n to pg
-- requires: roles
-- requires: schema_camper
-- requires: id_document_type
-- requires: language
begin;
set search_path to camper, public;
create table id_document_type_i18n (
id_document_type_id varchar(1) not null references id_document_type,
lang_tag text not null references language,
name text not null,
primary key (id_document_type_id, lang_tag)
);
grant select on table id_document_type_i18n to employee;
grant select on table id_document_type_i18n to admin;
commit;

17
deploy/sex.sql Normal file
View File

@ -0,0 +1,17 @@
-- Deploy camper:sex to pg
-- requires: roles
-- requires: schema_camper
begin;
set search_path to camper, public;
create table sex (
sex_id varchar(1) primary key,
name text not null
);
grant select on table sex to employee;
grant select on table sex to admin;
commit;

21
deploy/sex_i18n.sql Normal file
View File

@ -0,0 +1,21 @@
-- Deploy camper:sex_i18n to pg
-- requires: roles
-- requires: schema_camper
-- requires: sex
-- requires: language
begin;
set search_path to camper, public;
create table sex_i18n (
sex_id varchar(1) not null references sex,
lang_tag text not null references language,
name text not null,
primary key (sex_id, lang_tag)
);
grant select on sex_i18n to employee;
grant select on sex_i18n to admin;
commit;

View File

@ -113,6 +113,22 @@ func (h *AdminHandler) bookingHandler(user *auth.User, company *auth.Company, co
default: default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut) httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
} }
case "check-in":
switch r.Method {
case http.MethodGet:
serveCheckInForm(w, r, user, company, conn, slug)
case http.MethodPost:
checkInBooking(w, r, user, company, conn, slug)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost)
}
case "guest":
switch r.Method {
case http.MethodGet:
serveGuestForm(w, r, user, company, conn, slug)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet)
}
default: default:
http.NotFound(w, r) http.NotFound(w, r)
} }

339
pkg/booking/checkin.go Normal file
View File

@ -0,0 +1,339 @@
package booking
import (
"context"
"dev.tandem.ws/tandem/camper/pkg/auth"
"dev.tandem.ws/tandem/camper/pkg/database"
"dev.tandem.ws/tandem/camper/pkg/form"
httplib "dev.tandem.ws/tandem/camper/pkg/http"
"dev.tandem.ws/tandem/camper/pkg/locale"
"dev.tandem.ws/tandem/camper/pkg/template"
"github.com/jackc/pgx/v4"
"math"
"net/http"
"time"
)
func serveCheckInForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, slug string) {
f := newCheckinForm(slug)
if err := f.FillFromDatabase(r.Context(), conn, user.Locale); err != nil {
panic(err)
}
f.MustRender(w, r, user, company)
}
func serveGuestForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, slug string) {
f, err := newGuestForm(r.Context(), conn, user.Locale, slug)
if err != nil {
panic(err)
}
f.MustRender(w, r, user, company)
}
func checkInBooking(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, slug string) {
f := newCheckinForm(slug)
if err := f.Parse(r, user, conn); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if err := user.VerifyCSRFToken(r); err != nil {
http.Error(w, err.Error(), http.StatusForbidden)
return
}
if ok, err := f.Valid(r.Context(), conn, user.Locale); err != nil {
panic(err)
} else if !ok {
if !httplib.IsHTMxRequest(r) {
w.WriteHeader(http.StatusUnprocessableEntity)
}
f.MustRender(w, r, user, company)
}
guests := make([]*database.CheckedInGuest, 0, len(f.Guests))
for _, g := range f.Guests {
guests = append(guests, g.checkedInGuest())
}
if err := conn.CheckInGuests(r.Context(), f.Slug, guests); err != nil {
panic(err)
}
httplib.Redirect(w, r, "/admin/bookings", http.StatusSeeOther)
}
type checkInForm struct {
Slug string
Guests []*guestForm
}
func newCheckinForm(slug string) *checkInForm {
return &checkInForm{
Slug: slug,
}
}
func (f *checkInForm) FillFromDatabase(ctx context.Context, conn *database.Conn, l *locale.Locale) error {
documentTypes := mustGetDocumentTypeOptions(ctx, conn, l)
sexes := mustGetSexOptions(ctx, conn, l)
countries := mustGetCountryOptions(ctx, conn, l)
rows, err := conn.Query(ctx, `
select array[id_document_type_id]
, id_document_number
, coalesce(id_document_issue_date::text, '')
, given_name
, first_surname
, second_surname
, array[sex_id]
, birthdate::text
, array[guest.country_code::text]
, coalesce(guest.phone::text, '')
, guest.address
from booking_guest as guest
join booking using (booking_id)
where slug = $1
`, f.Slug)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
guest := newGuestFormWithOptions(documentTypes, sexes, countries, nil)
if err := guest.FillFromRow(rows); err != nil {
return err
}
f.Guests = append(f.Guests, guest)
}
if len(f.Guests) == 0 {
var numberGuests int
var country []string
row := conn.QueryRow(ctx, "select number_adults + number_teenagers, array[coalesce(country_code, '')] from booking where slug = $1", f.Slug)
if err = row.Scan(&numberGuests, &country); err != nil {
return err
}
guests := make([]*guestForm, 0, numberGuests)
for i := 0; i < numberGuests; i++ {
guests = append(guests, newGuestFormWithOptions(documentTypes, sexes, countries, country))
}
f.Guests = guests
}
return nil
}
func mustGetDocumentTypeOptions(ctx context.Context, conn *database.Conn, l *locale.Locale) []*form.Option {
return form.MustGetOptions(ctx, conn, "select idt.id_document_type_id::text, coalesce(i18n.name, idt.name) as l10n_name from id_document_type as idt left join id_document_type_i18n as i18n on idt.id_document_type_id = i18n.id_document_type_id and i18n.lang_tag = $1 order by l10n_name", l.Language)
}
func mustGetSexOptions(ctx context.Context, conn *database.Conn, l *locale.Locale) []*form.Option {
return form.MustGetOptions(ctx, conn, "select sex.sex_id::text, coalesce(i18n.name, sex.name) as l10n_name from sex left join sex_i18n as i18n on sex.sex_id = i18n.sex_id and i18n.lang_tag = $1 order by l10n_name", l.Language)
}
func (f *checkInForm) Parse(r *http.Request, user *auth.User, conn *database.Conn) error {
if err := r.ParseForm(); err != nil {
return err
}
documentTypes := mustGetDocumentTypeOptions(r.Context(), conn, user.Locale)
sexes := mustGetSexOptions(r.Context(), conn, user.Locale)
countries := mustGetCountryOptions(r.Context(), conn, user.Locale)
guest := newGuestFormWithOptions(documentTypes, sexes, countries, nil)
count := guest.count(r)
f.Guests = make([]*guestForm, 0, count)
guest.FillValueIndex(r, 0)
f.Guests = append(f.Guests, guest)
for i := 1; i < count; i++ {
guest = newGuestFormWithOptions(documentTypes, sexes, countries, nil)
guest.FillValueIndex(r, i)
f.Guests = append(f.Guests, guest)
}
return nil
}
func (f *checkInForm) Valid(ctx context.Context, conn *database.Conn, l *locale.Locale) (bool, error) {
allOK := true
for _, g := range f.Guests {
if ok, err := g.Valid(ctx, conn, l); err != nil {
return false, err
} else if !ok {
allOK = false
}
}
return allOK, nil
}
func (f *checkInForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdminFiles(w, r, user, company, f, "booking/checkin.gohtml", "booking/guest.gohtml")
}
type guestForm struct {
IDDocumentType *form.Select
IDDocumentNumber *form.Input
IDDocumentDate *form.Input
GivenName *form.Input
FirstSurname *form.Input
SecondSurname *form.Input
Sex *form.Select
Birthdate *form.Input
Country *form.Select
Address *form.Input
Phone *form.Input
}
func newGuestForm(ctx context.Context, conn *database.Conn, l *locale.Locale, slug string) (*guestForm, error) {
documentTypes := mustGetDocumentTypeOptions(ctx, conn, l)
sexes := mustGetSexOptions(ctx, conn, l)
countries := mustGetCountryOptions(ctx, conn, l)
var country []string
row := conn.QueryRow(ctx, "select array[coalesce(country_code, '')] from booking where slug = $1", slug)
if err := row.Scan(&country); err != nil {
return nil, err
}
return newGuestFormWithOptions(documentTypes, sexes, countries, country), nil
}
func newGuestFormWithOptions(documentTypes []*form.Option, sexes []*form.Option, countries []*form.Option, selectedCountry []string) *guestForm {
return &guestForm{
IDDocumentType: &form.Select{
Name: "id_document_type",
Options: documentTypes,
},
IDDocumentNumber: &form.Input{
Name: "id_document_number",
},
IDDocumentDate: &form.Input{
Name: "id_document_date",
},
GivenName: &form.Input{
Name: "given_name",
},
FirstSurname: &form.Input{
Name: "first_surname",
},
SecondSurname: &form.Input{
Name: "second_surname",
},
Sex: &form.Select{
Name: "sex",
Options: sexes,
},
Birthdate: &form.Input{
Name: "birthdate",
},
Country: &form.Select{
Name: "country",
Options: countries,
Selected: selectedCountry,
},
Address: &form.Input{
Name: "address",
},
Phone: &form.Input{
Name: "phone",
},
}
}
func (f *guestForm) count(r *http.Request) int {
keys := []string{f.IDDocumentType.Name, f.IDDocumentNumber.Name, f.IDDocumentDate.Name, f.GivenName.Name, f.FirstSurname.Name, f.SecondSurname.Name, f.Sex.Name, f.Birthdate.Name, f.Country.Name, f.Address.Name, f.Phone.Name}
min := math.MaxInt
for _, key := range keys {
l := len(r.Form[key])
if len(r.Form[key]) < min {
min = l
}
}
return min
}
func (f *guestForm) FillValueIndex(r *http.Request, idx int) {
f.IDDocumentType.FillValueIndex(r, idx)
f.IDDocumentNumber.FillValueIndex(r, idx)
f.IDDocumentDate.FillValueIndex(r, idx)
f.GivenName.FillValueIndex(r, idx)
f.FirstSurname.FillValueIndex(r, idx)
f.SecondSurname.FillValueIndex(r, idx)
f.Sex.FillValueIndex(r, idx)
f.Birthdate.FillValueIndex(r, idx)
f.Country.FillValueIndex(r, idx)
f.Address.FillValueIndex(r, idx)
f.Phone.FillValueIndex(r, idx)
}
func (f *guestForm) FillFromRow(row pgx.Rows) error {
return row.Scan(
&f.IDDocumentType.Selected,
&f.IDDocumentNumber.Val,
&f.IDDocumentDate.Val,
&f.GivenName.Val,
&f.FirstSurname.Val,
&f.SecondSurname.Val,
&f.Sex.Selected,
&f.Birthdate.Val,
&f.Country.Selected,
&f.Phone.Val,
&f.Address.Val,
)
}
func (f *guestForm) Valid(ctx context.Context, conn *database.Conn, l *locale.Locale) (bool, error) {
v := form.NewValidator(l)
today := time.Now()
yesterday := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, time.UTC)
v.CheckSelectedOptions(f.IDDocumentType, l.GettextNoop("Selected ID document type is not valid."))
v.CheckRequired(f.IDDocumentNumber, l.GettextNoop("ID document number can not be empty."))
if f.IDDocumentDate.Val != "" {
if v.CheckValidDate(f.IDDocumentDate, l.GettextNoop("ID document issue date must be a valid date.")) {
v.CheckMaxDate(f.IDDocumentDate, yesterday, l.Gettext("ID document issue date must be in the past."))
}
}
v.CheckRequired(f.GivenName, l.GettextNoop("Full name can not be empty."))
v.CheckRequired(f.FirstSurname, l.GettextNoop("Full name can not be empty."))
v.CheckSelectedOptions(f.Sex, l.GettextNoop("Selected sex is not valid."))
if v.CheckRequired(f.Birthdate, l.GettextNoop("Birthdate can not be empty")) {
if v.CheckValidDate(f.Birthdate, l.GettextNoop("Birthdate must be a valid date.")) {
v.CheckMaxDate(f.Birthdate, yesterday, l.Gettext("Birthdate must be in the past."))
}
}
var country string
if v.CheckSelectedOptions(f.Country, l.GettextNoop("Selected country is not valid.")) {
country = f.Country.Selected[0]
}
if f.Phone.Val != "" && country != "" {
if _, err := v.CheckValidPhone(ctx, conn, f.Phone, country, l.GettextNoop("This phone number is not valid.")); err != nil {
return false, err
}
}
return v.AllOK, nil
}
func (f *guestForm) checkedInGuest() *database.CheckedInGuest {
birthdate, err := time.Parse(database.ISODateFormat, f.Birthdate.Val)
if err != nil {
panic(err)
}
issueDate, err := time.Parse(database.ISODateFormat, f.IDDocumentDate.Val)
if err != nil {
issueDate = time.Time{}
}
return &database.CheckedInGuest{
IDDocumentType: f.IDDocumentType.String(),
IDDocumentNumber: f.IDDocumentNumber.Val,
IDDocumentIssueDate: issueDate,
GivenName: f.GivenName.Val,
FirstSurname: f.FirstSurname.Val,
SecondSurname: f.SecondSurname.Val,
Sex: f.Sex.String(),
Birthdate: birthdate,
CountryCode: f.Country.String(),
Phone: f.Phone.Val,
Address: f.Address.Val,
}
}
func (f *guestForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdminNoLayout(w, r, user, company, "booking/guest.gohtml", f)
}

View File

@ -547,7 +547,7 @@ func newBookingCustomerFields(ctx context.Context, conn *database.Conn, l *local
}, },
Country: &form.Select{ Country: &form.Select{
Name: "country", Name: "country",
Options: form.MustGetOptions(ctx, conn, "select country.country_code, coalesce(i18n.name, country.name) as l10n_name from country left join country_i18n as i18n on country.country_code = i18n.country_code and i18n.lang_tag = $1 order by l10n_name", l.Language), Options: mustGetCountryOptions(ctx, conn, l),
}, },
Email: &form.Input{ Email: &form.Input{
Name: "email", Name: "email",
@ -561,6 +561,10 @@ func newBookingCustomerFields(ctx context.Context, conn *database.Conn, l *local
} }
} }
func mustGetCountryOptions(ctx context.Context, conn *database.Conn, l *locale.Locale) []*form.Option {
return form.MustGetOptions(ctx, conn, "select country.country_code, coalesce(i18n.name, country.name) as l10n_name from country left join country_i18n as i18n on country.country_code = i18n.country_code and i18n.lang_tag = $1 order by l10n_name", l.Language)
}
func (f *bookingCustomerFields) FillValues(r *http.Request) { func (f *bookingCustomerFields) FillValues(r *http.Request) {
f.FullName.FillValue(r) f.FullName.FillValue(r)
f.Address.FillValue(r) f.Address.FillValue(r)

View File

@ -0,0 +1,84 @@
package database
import (
"fmt"
"time"
"github.com/jackc/pgio"
"github.com/jackc/pgtype"
)
type CheckedInGuest struct {
IDDocumentType string
IDDocumentNumber string
IDDocumentIssueDate time.Time
GivenName string
FirstSurname string
SecondSurname string
Sex string
Birthdate time.Time
CountryCode string
Phone string
Address string
}
func (src CheckedInGuest) EncodeBinary(ci *pgtype.ConnInfo, dst []byte) ([]byte, error) {
typeName := CheckedInGuestTypeName
dt, ok := ci.DataTypeForName(typeName)
if !ok {
return nil, fmt.Errorf("unable to find oid for type name %v", typeName)
}
var idDocumentIssueDate interface{}
var noDate time.Time
if src.IDDocumentIssueDate != noDate {
idDocumentIssueDate = src.IDDocumentIssueDate
}
values := []interface{}{
src.IDDocumentType,
src.IDDocumentNumber,
idDocumentIssueDate,
src.GivenName,
src.FirstSurname,
src.SecondSurname,
src.Sex,
src.Birthdate,
src.CountryCode,
src.Phone,
src.Address,
}
ct := pgtype.NewValue(dt.Value).(*pgtype.CompositeType)
if err := ct.Set(values); err != nil {
return nil, err
}
return ct.EncodeBinary(ci, dst)
}
type CheckedInGuestArray []*CheckedInGuest
func (src CheckedInGuestArray) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
typeName := CheckedInGuestTypeName
dt, ok := ci.DataTypeForName(typeName)
if !ok {
return nil, fmt.Errorf("unable to find oid for type name %v", typeName)
}
arrayHeader := pgtype.ArrayHeader{
ElementOID: int32(dt.OID),
Dimensions: []pgtype.ArrayDimension{{Length: int32(len(src)), LowerBound: 1}},
}
buf = arrayHeader.EncodeBinary(ci, buf)
for _, optionUnits := range src {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := optionUnits.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}

View File

@ -365,3 +365,8 @@ func (tx *Tx) EditBooking(ctx context.Context, bookingID int, customerName strin
_, err := tx.Exec(ctx, "select edit_booking($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", bookingID, customerName, zeronull.Text(customerAddress), zeronull.Text(customerPostCode), zeronull.Text(customerCity), zeronull.Text(customerCountryCode), zeronull.Text(customerEmail), zeronull.Text(customerPhone), customerLangTag, bookingStatus, campsiteIDs) _, err := tx.Exec(ctx, "select edit_booking($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", bookingID, customerName, zeronull.Text(customerAddress), zeronull.Text(customerPostCode), zeronull.Text(customerCity), zeronull.Text(customerCountryCode), zeronull.Text(customerEmail), zeronull.Text(customerPhone), customerLangTag, bookingStatus, campsiteIDs)
return err return err
} }
func (c *Conn) CheckInGuests(ctx context.Context, bookingSlug string, guests []*CheckedInGuest) error {
_, err := c.Exec(ctx, "select check_in_guests(booking_id, $2) from booking where slug = $1", bookingSlug, CheckedInGuestArray(guests))
return err
}

View File

@ -13,6 +13,7 @@ import (
) )
const ( const (
CheckedInGuestTypeName = "checked_in_guest"
OptionUnitsTypeName = "option_units" OptionUnitsTypeName = "option_units"
RedsysRequestTypeName = "redsys_request" RedsysRequestTypeName = "redsys_request"
RedsysResponseTypeName = "redsys_response" RedsysResponseTypeName = "redsys_response"
@ -125,6 +126,30 @@ func registerConnectionTypes(ctx context.Context, conn *pgx.Conn) error {
return err return err
} }
checkedInGuestType, err := pgtype.NewCompositeType(
CheckedInGuestTypeName,
[]pgtype.CompositeTypeField{
{"id_document_type_id", pgtype.VarcharOID},
{"id_document_number", pgtype.TextOID},
{"id_document_issue_date", pgtype.DateOID},
{"given_name", pgtype.TextOID},
{"first_surname", pgtype.TextOID},
{"second_surname", pgtype.TextOID},
{"sex_id", pgtype.VarcharOID},
{"birthdate", pgtype.DateOID},
{"country_code", pgtype.TextOID},
{"phone", pgtype.TextOID},
{"address", pgtype.TextOID},
},
conn.ConnInfo(),
)
if err != nil {
return err
}
if _, err = registerType(ctx, conn, checkedInGuestType, checkedInGuestType.TypeName()); err != nil {
return err
}
return nil return nil
} }

View File

@ -28,8 +28,17 @@ func (input *Input) setError(err error) {
} }
func (input *Input) FillValue(r *http.Request) { func (input *Input) FillValue(r *http.Request) {
input.Val = strings.TrimSpace(r.FormValue(input.Name)) input.FillValueIndex(r, 0)
} }
func (input *Input) FillValueIndex(r *http.Request, idx int) {
var val string
if vs := r.Form[input.Name]; len(vs) > idx {
val = vs[idx]
}
input.Val = strings.TrimSpace(val)
}
func (input *Input) Value() (driver.Value, error) { func (input *Input) Value() (driver.Value, error) {
return input.Val, nil return input.Val, nil
} }

View File

@ -48,7 +48,18 @@ func (s *Select) FillValue(r *http.Request) {
s.Selected = r.Form[s.Name] s.Selected = r.Form[s.Name]
} }
func (s *Select) FillValueIndex(r *http.Request, idx int) {
if vs := r.Form[s.Name]; len(vs) > idx {
s.Selected = []string{vs[idx]}
} else {
s.Selected = nil
}
}
func (s *Select) ValidOptionsSelected() bool { func (s *Select) ValidOptionsSelected() bool {
if len(s.Selected) == 0 {
return false
}
for _, selected := range s.Selected { for _, selected := range s.Selected {
if !s.isValidOption(selected) { if !s.isValidOption(selected) {
return false return false

View File

@ -117,6 +117,9 @@ func mustRenderLayout(w io.Writer, user *auth.User, company *auth.Company, templ
"formatDateAttr": func(time time.Time) string { "formatDateAttr": func(time time.Time) string {
return time.Format(database.ISODateFormat) return time.Format(database.ISODateFormat)
}, },
"today": func() string {
return time.Now().Format(database.ISODateFormat)
},
"queryEscape": func(s string) string { "queryEscape": func(s string) string {
return url.QueryEscape(s) return url.QueryEscape(s)
}, },

291
po/ca.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: camper\n" "Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-04-24 19:59+0200\n" "POT-Creation-Date: 2024-04-26 16:53+0200\n"
"PO-Revision-Date: 2024-02-06 10:04+0100\n" "PO-Revision-Date: 2024-02-06 10:04+0100\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n" "Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Catalan <ca@dodds.net>\n" "Language-Team: Catalan <ca@dodds.net>\n"
@ -116,7 +116,7 @@ msgstr "Reserva"
#: web/templates/mail/payment/details.gotxt:16 #: web/templates/mail/payment/details.gotxt:16
#: web/templates/public/booking/fields.gohtml:14 #: web/templates/public/booking/fields.gohtml:14
#: web/templates/admin/payment/details.gohtml:74 #: web/templates/admin/payment/details.gohtml:74
#: web/templates/admin/booking/fields.gohtml:12 #: web/templates/admin/booking/fields.gohtml:13
msgctxt "title" msgctxt "title"
msgid "Accommodation" msgid "Accommodation"
msgstr "Allotjament" msgstr "Allotjament"
@ -155,7 +155,7 @@ msgstr "No"
#: web/templates/public/campsite/dates.gohtml:4 #: web/templates/public/campsite/dates.gohtml:4
#: web/templates/public/booking/fields.gohtml:30 #: web/templates/public/booking/fields.gohtml:30
#: web/templates/admin/payment/details.gohtml:86 #: web/templates/admin/payment/details.gohtml:86
#: web/templates/admin/booking/fields.gohtml:31 #: web/templates/admin/booking/fields.gohtml:32
msgctxt "input" msgctxt "input"
msgid "Arrival date" msgid "Arrival date"
msgstr "Data darribada" msgstr "Data darribada"
@ -164,7 +164,7 @@ msgstr "Data darribada"
#: web/templates/public/campsite/dates.gohtml:15 #: web/templates/public/campsite/dates.gohtml:15
#: web/templates/public/booking/fields.gohtml:41 #: web/templates/public/booking/fields.gohtml:41
#: web/templates/admin/payment/details.gohtml:90 #: web/templates/admin/payment/details.gohtml:90
#: web/templates/admin/booking/fields.gohtml:42 #: web/templates/admin/booking/fields.gohtml:43
msgctxt "input" msgctxt "input"
msgid "Departure date" msgid "Departure date"
msgstr "Data de sortida" msgstr "Data de sortida"
@ -178,7 +178,7 @@ msgstr "Nits"
#: web/templates/mail/payment/details.gotxt:22 #: web/templates/mail/payment/details.gotxt:22
#: web/templates/public/booking/fields.gohtml:60 #: web/templates/public/booking/fields.gohtml:60
#: web/templates/admin/payment/details.gohtml:98 #: web/templates/admin/payment/details.gohtml:98
#: web/templates/admin/booking/fields.gohtml:92 #: web/templates/admin/booking/fields.gohtml:93
msgctxt "input" msgctxt "input"
msgid "Adults aged 17 or older" msgid "Adults aged 17 or older"
msgstr "Adults de 17 anys o més" msgstr "Adults de 17 anys o més"
@ -186,7 +186,7 @@ msgstr "Adults de 17 anys o més"
#: web/templates/mail/payment/details.gotxt:23 #: web/templates/mail/payment/details.gotxt:23
#: web/templates/public/booking/fields.gohtml:71 #: web/templates/public/booking/fields.gohtml:71
#: web/templates/admin/payment/details.gohtml:102 #: web/templates/admin/payment/details.gohtml:102
#: web/templates/admin/booking/fields.gohtml:108 #: web/templates/admin/booking/fields.gohtml:109
msgctxt "input" msgctxt "input"
msgid "Teenagers from 11 to 16 years old" msgid "Teenagers from 11 to 16 years old"
msgstr "Adolescents dentre 11 i 16 anys" msgstr "Adolescents dentre 11 i 16 anys"
@ -194,7 +194,7 @@ msgstr "Adolescents dentre 11 i 16 anys"
#: web/templates/mail/payment/details.gotxt:24 #: web/templates/mail/payment/details.gotxt:24
#: web/templates/public/booking/fields.gohtml:82 #: web/templates/public/booking/fields.gohtml:82
#: web/templates/admin/payment/details.gohtml:106 #: web/templates/admin/payment/details.gohtml:106
#: web/templates/admin/booking/fields.gohtml:124 #: web/templates/admin/booking/fields.gohtml:125
msgctxt "input" msgctxt "input"
msgid "Children from 2 to 10 years old" msgid "Children from 2 to 10 years old"
msgstr "Nens dentre 2 i 10 anys" msgstr "Nens dentre 2 i 10 anys"
@ -202,14 +202,14 @@ msgstr "Nens dentre 2 i 10 anys"
#: web/templates/mail/payment/details.gotxt:25 #: web/templates/mail/payment/details.gotxt:25
#: web/templates/public/booking/fields.gohtml:100 #: web/templates/public/booking/fields.gohtml:100
#: web/templates/admin/payment/details.gohtml:110 #: web/templates/admin/payment/details.gohtml:110
#: web/templates/admin/booking/fields.gohtml:139 #: web/templates/admin/booking/fields.gohtml:140
msgctxt "input" msgctxt "input"
msgid "Dogs" msgid "Dogs"
msgstr "Gossos" msgstr "Gossos"
#: web/templates/mail/payment/details.gotxt:26 #: web/templates/mail/payment/details.gotxt:26
#: web/templates/admin/payment/details.gohtml:114 #: web/templates/admin/payment/details.gohtml:114
#: web/templates/admin/booking/fields.gohtml:166 pkg/booking/cart.go:244 #: web/templates/admin/booking/fields.gohtml:167 pkg/booking/cart.go:242
msgctxt "cart" msgctxt "cart"
msgid "Tourist tax" msgid "Tourist tax"
msgstr "Impost turístic" msgstr "Impost turístic"
@ -239,7 +239,7 @@ msgstr "Opcions del tipus dallotjament"
#: web/templates/mail/payment/details.gotxt:39 #: web/templates/mail/payment/details.gotxt:39
#: web/templates/public/booking/fields.gohtml:146 #: web/templates/public/booking/fields.gohtml:146
#: web/templates/admin/payment/details.gohtml:140 #: web/templates/admin/payment/details.gohtml:140
#: web/templates/admin/booking/fields.gohtml:187 #: web/templates/admin/booking/fields.gohtml:188
msgctxt "title" msgctxt "title"
msgid "Customer Details" msgid "Customer Details"
msgstr "Detalls del client" msgstr "Detalls del client"
@ -247,7 +247,7 @@ msgstr "Detalls del client"
#: web/templates/mail/payment/details.gotxt:41 #: web/templates/mail/payment/details.gotxt:41
#: web/templates/public/booking/fields.gohtml:149 #: web/templates/public/booking/fields.gohtml:149
#: web/templates/admin/payment/details.gohtml:143 #: web/templates/admin/payment/details.gohtml:143
#: web/templates/admin/booking/fields.gohtml:190 #: web/templates/admin/booking/fields.gohtml:191
msgctxt "input" msgctxt "input"
msgid "Full name" msgid "Full name"
msgstr "Nom i cognoms" msgstr "Nom i cognoms"
@ -930,7 +930,7 @@ msgstr "Menú"
#: web/templates/admin/campsite/type/option/index.gohtml:10 #: web/templates/admin/campsite/type/option/index.gohtml:10
#: web/templates/admin/campsite/type/index.gohtml:10 #: web/templates/admin/campsite/type/index.gohtml:10
#: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:95 #: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:95
#: web/templates/admin/booking/fields.gohtml:265 #: web/templates/admin/booking/fields.gohtml:266
msgctxt "title" msgctxt "title"
msgid "Campsites" msgid "Campsites"
msgstr "Allotjaments" msgstr "Allotjaments"
@ -978,6 +978,7 @@ msgid "Booking Period"
msgstr "Període de reserva" msgstr "Període de reserva"
#: web/templates/public/booking/fields.gohtml:56 #: web/templates/public/booking/fields.gohtml:56
#: web/templates/admin/booking/checkin.gohtml:20
msgctxt "title" msgctxt "title"
msgid "Guests" msgid "Guests"
msgstr "Hostes" msgstr "Hostes"
@ -987,18 +988,18 @@ msgid "Note: Due to guest capacity, we have added more accommodations to the boo
msgstr "Nota: Shan afegit més allotjaments a la reserva degut a la capacitat de cadascuna, però <strong>no</strong> es garanteix que estiguin de costat." msgstr "Nota: Shan afegit més allotjaments a la reserva degut a la capacitat de cadascuna, però <strong>no</strong> es garanteix que estiguin de costat."
#: web/templates/public/booking/fields.gohtml:109 #: web/templates/public/booking/fields.gohtml:109
#: web/templates/admin/booking/fields.gohtml:178 #: web/templates/admin/booking/fields.gohtml:179
msgid "Note: This accommodation does <strong>not</strong> allow dogs." msgid "Note: This accommodation does <strong>not</strong> allow dogs."
msgstr "Nota: A aquest allotjament <strong>no</strong> shi permeten gossos." msgstr "Nota: A aquest allotjament <strong>no</strong> shi permeten gossos."
#: web/templates/public/booking/fields.gohtml:121 #: web/templates/public/booking/fields.gohtml:121
#: web/templates/admin/booking/fields.gohtml:55 #: web/templates/admin/booking/fields.gohtml:56
msgctxt "input" msgctxt "input"
msgid "Area preferences (optional)" msgid "Area preferences (optional)"
msgstr "Preferències dàrea (opcional)" msgstr "Preferències dàrea (opcional)"
#: web/templates/public/booking/fields.gohtml:123 #: web/templates/public/booking/fields.gohtml:123
#: web/templates/admin/booking/fields.gohtml:59 #: web/templates/admin/booking/fields.gohtml:60
msgid "Campground map" msgid "Campground map"
msgstr "Mapa del càmping" msgstr "Mapa del càmping"
@ -1008,12 +1009,13 @@ msgid "Town or village"
msgstr "Població" msgstr "Població"
#: web/templates/public/booking/fields.gohtml:193 #: web/templates/public/booking/fields.gohtml:193
#: web/templates/admin/booking/fields.gohtml:203 #: web/templates/admin/booking/fields.gohtml:204
#: web/templates/admin/booking/guest.gohtml:109
msgid "Choose a country" msgid "Choose a country"
msgstr "Esculli un país" msgstr "Esculli un país"
#: web/templates/public/booking/fields.gohtml:247 #: web/templates/public/booking/fields.gohtml:247
#: web/templates/admin/booking/fields.gohtml:258 #: web/templates/admin/booking/fields.gohtml:259
msgctxt "input" msgctxt "input"
msgid "ACSI card? (optional)" msgid "ACSI card? (optional)"
msgstr "Targeta ACSI? (opcional)" msgstr "Targeta ACSI? (opcional)"
@ -1098,8 +1100,8 @@ msgid "Down payment"
msgstr "A compte" msgstr "A compte"
#: web/templates/admin/payment/index.gohtml:24 #: web/templates/admin/payment/index.gohtml:24
#: web/templates/admin/booking/fields.gohtml:74 #: web/templates/admin/booking/fields.gohtml:75
#: web/templates/admin/booking/fields.gohtml:172 #: web/templates/admin/booking/fields.gohtml:173
msgctxt "header" msgctxt "header"
msgid "Total" msgid "Total"
msgstr "Total" msgstr "Total"
@ -1194,7 +1196,7 @@ msgstr "Contingut"
#: web/templates/admin/amenity/form.gohtml:91 #: web/templates/admin/amenity/form.gohtml:91
#: web/templates/admin/home/index.gohtml:34 #: web/templates/admin/home/index.gohtml:34
#: web/templates/admin/media/form.gohtml:39 #: web/templates/admin/media/form.gohtml:39
#: web/templates/admin/booking/fields.gohtml:272 #: web/templates/admin/booking/form.gohtml:45
msgctxt "action" msgctxt "action"
msgid "Update" msgid "Update"
msgstr "Actualitza" msgstr "Actualitza"
@ -1214,7 +1216,7 @@ msgstr "Actualitza"
#: web/templates/admin/amenity/feature/form.gohtml:67 #: web/templates/admin/amenity/feature/form.gohtml:67
#: web/templates/admin/amenity/carousel/form.gohtml:52 #: web/templates/admin/amenity/carousel/form.gohtml:52
#: web/templates/admin/amenity/form.gohtml:93 #: web/templates/admin/amenity/form.gohtml:93
#: web/templates/admin/booking/fields.gohtml:274 #: web/templates/admin/booking/form.gohtml:47
msgctxt "action" msgctxt "action"
msgid "Add" msgid "Add"
msgstr "Afegeix" msgstr "Afegeix"
@ -2161,7 +2163,7 @@ msgid "Add Amenity"
msgstr "Afegeix instaŀlació" msgstr "Afegeix instaŀlació"
#: web/templates/admin/amenity/index.gohtml:20 #: web/templates/admin/amenity/index.gohtml:20
#: web/templates/admin/booking/grid.gohtml:13 #: web/templates/admin/booking/grid.gohtml:15
msgctxt "header" msgctxt "header"
msgid "Label" msgid "Label"
msgstr "Etiqueta" msgstr "Etiqueta"
@ -2204,7 +2206,8 @@ msgid "Logout"
msgstr "Surt" msgstr "Surt"
#: web/templates/admin/layout.gohtml:92 #: web/templates/admin/layout.gohtml:92
#: web/templates/admin/booking/form.gohtml:15 #: web/templates/admin/booking/form.gohtml:19
#: web/templates/admin/booking/checkin.gohtml:10
#: web/templates/admin/booking/index.gohtml:6 #: web/templates/admin/booking/index.gohtml:6
#: web/templates/admin/booking/index.gohtml:16 #: web/templates/admin/booking/index.gohtml:16
msgctxt "title" msgctxt "title"
@ -2312,51 +2315,53 @@ msgctxt "title"
msgid "Upload Media" msgid "Upload Media"
msgstr "Pujada de mèdia" msgstr "Pujada de mèdia"
#: web/templates/admin/booking/fields.gohtml:18 #: web/templates/admin/booking/fields.gohtml:19
msgid "Choose an accommodation" msgid "Choose an accommodation"
msgstr "Esculliu un allotjament" msgstr "Esculliu un allotjament"
#: web/templates/admin/booking/fields.gohtml:72 #: web/templates/admin/booking/fields.gohtml:73
msgctxt "header" msgctxt "header"
msgid "Units" msgid "Units"
msgstr "Unitats" msgstr "Unitats"
#: web/templates/admin/booking/fields.gohtml:73 #: web/templates/admin/booking/fields.gohtml:74
msgctxt "header" msgctxt "header"
msgid "Decription" msgid "Decription"
msgstr "Descripció" msgstr "Descripció"
#: web/templates/admin/booking/fields.gohtml:80 pkg/booking/cart.go:234 #: web/templates/admin/booking/fields.gohtml:81 pkg/booking/cart.go:232
msgctxt "cart" msgctxt "cart"
msgid "Night" msgid "Night"
msgstr "Nit" msgstr "Nit"
#: web/templates/admin/booking/fields.gohtml:199 #: web/templates/admin/booking/fields.gohtml:200
msgctxt "input" msgctxt "input"
msgid "Country (optional)" msgid "Country (optional)"
msgstr "País (opcional)" msgstr "País (opcional)"
#: web/templates/admin/booking/fields.gohtml:211 #: web/templates/admin/booking/fields.gohtml:212
#: web/templates/admin/booking/guest.gohtml:128
msgctxt "input" msgctxt "input"
msgid "Address (optional)" msgid "Address (optional)"
msgstr "Adreça (opcional)" msgstr "Adreça (opcional)"
#: web/templates/admin/booking/fields.gohtml:220 #: web/templates/admin/booking/fields.gohtml:221
msgctxt "input" msgctxt "input"
msgid "Postcode (optional)" msgid "Postcode (optional)"
msgstr "Codi postal (opcional)" msgstr "Codi postal (opcional)"
#: web/templates/admin/booking/fields.gohtml:229 #: web/templates/admin/booking/fields.gohtml:230
msgctxt "input" msgctxt "input"
msgid "Town or village (optional)" msgid "Town or village (optional)"
msgstr "Població (opcional)" msgstr "Població (opcional)"
#: web/templates/admin/booking/fields.gohtml:238 #: web/templates/admin/booking/fields.gohtml:239
msgctxt "input" msgctxt "input"
msgid "Email (optional)" msgid "Email (optional)"
msgstr "Correu-e (opcional)" msgstr "Correu-e (opcional)"
#: web/templates/admin/booking/fields.gohtml:247 #: web/templates/admin/booking/fields.gohtml:248
#: web/templates/admin/booking/guest.gohtml:117
msgctxt "input" msgctxt "input"
msgid "Phone (optional)" msgid "Phone (optional)"
msgstr "Telèfon (opcional)" msgstr "Telèfon (opcional)"
@ -2371,6 +2376,31 @@ msgctxt "title"
msgid "New Booking" msgid "New Booking"
msgstr "Nova reserva" msgstr "Nova reserva"
#: web/templates/admin/booking/form.gohtml:25
msgctxt "action"
msgid "Check-in Booking"
msgstr "Registra la reserva"
#: web/templates/admin/booking/checkin.gohtml:6
msgctxt "title"
msgid "Check-in Booking"
msgstr "Registre de la reserva"
#: web/templates/admin/booking/checkin.gohtml:15
msgctxt "action"
msgid "Edit Booking"
msgstr "Edita la reserva"
#: web/templates/admin/booking/checkin.gohtml:26
msgctxt "action"
msgid "Check-in"
msgstr "Registra"
#: web/templates/admin/booking/checkin.gohtml:31
msgctxt "action"
msgid "Add another guest"
msgstr "Afegeix un altre hoste"
#: web/templates/admin/booking/index.gohtml:14 #: web/templates/admin/booking/index.gohtml:14
msgctxt "action" msgctxt "action"
msgid "Add Booking" msgid "Add Booking"
@ -2400,6 +2430,64 @@ msgstr "Nom del titular"
msgid "No booking found." msgid "No booking found."
msgstr "No sha trobat cap reserva." msgstr "No sha trobat cap reserva."
#: web/templates/admin/booking/guest.gohtml:5
msgctxt "action"
msgid "Remove"
msgstr "Esborra"
#: web/templates/admin/booking/guest.gohtml:8
msgctxt "input"
msgid "ID document number"
msgstr "Número de document didentitat"
#: web/templates/admin/booking/guest.gohtml:20
msgctxt "input"
msgid "ID document type"
msgstr "Tipus de document"
#: web/templates/admin/booking/guest.gohtml:25
msgid "Choose an ID document type"
msgstr "Esculli un tipus de document"
#: web/templates/admin/booking/guest.gohtml:33
msgctxt "input"
msgid "ID document issue date (if any)"
msgstr "Data dexpedició (si hi consta)"
#: web/templates/admin/booking/guest.gohtml:44
msgctxt "input"
msgid "First surname"
msgstr "Primer cognom"
#: web/templates/admin/booking/guest.gohtml:56
msgctxt "input"
msgid "Second surname (if has one)"
msgstr "Segon cognom (si en té)"
#: web/templates/admin/booking/guest.gohtml:67
msgctxt "input"
msgid "Given name"
msgstr "Nom"
#: web/templates/admin/booking/guest.gohtml:79
msgctxt "input"
msgid "Sex"
msgstr "Sexe"
#: web/templates/admin/booking/guest.gohtml:84
msgid "Choose a sex"
msgstr "Esculli un sexe"
#: web/templates/admin/booking/guest.gohtml:92
msgctxt "input"
msgid "Birthdate"
msgstr "Data de naixement"
#: web/templates/admin/booking/guest.gohtml:104
msgctxt "input"
msgid "Nationality"
msgstr "Nacionalitat"
#: pkg/payment/settings.go:37 #: pkg/payment/settings.go:37
msgctxt "redsys environment" msgctxt "redsys environment"
msgid "Test" msgid "Test"
@ -2501,12 +2589,12 @@ msgid "Slide image must be an image media type."
msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge." msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge."
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:224 #: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:224
#: pkg/booking/public.go:545 #: pkg/booking/public.go:596
msgid "Email can not be empty." msgid "Email can not be empty."
msgstr "No podeu deixar el correu-e en blanc." msgstr "No podeu deixar el correu-e en blanc."
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:225 #: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:225
#: pkg/booking/admin.go:316 pkg/booking/public.go:546 #: pkg/booking/admin.go:437 pkg/booking/public.go:597
msgid "This email is not valid. It should be like name@domain.com." msgid "This email is not valid. It should be like name@domain.com."
msgstr "Aquest correu-e no és vàlid. Hauria de ser similar a nom@domini.com." msgstr "Aquest correu-e no és vàlid. Hauria de ser similar a nom@domini.com."
@ -2717,8 +2805,8 @@ msgctxt "header"
msgid "Children (aged 2 to 10)" msgid "Children (aged 2 to 10)"
msgstr "Mainada (entre 2 i 10 anys)" msgstr "Mainada (entre 2 i 10 anys)"
#: pkg/campsite/admin.go:280 pkg/booking/admin.go:292 pkg/booking/public.go:173 #: pkg/campsite/admin.go:280 pkg/booking/admin.go:413 pkg/booking/public.go:177
#: pkg/booking/public.go:228 #: pkg/booking/public.go:232
msgid "Selected campsite type is not valid." msgid "Selected campsite type is not valid."
msgstr "El tipus dallotjament escollit no és vàlid." msgstr "El tipus dallotjament escollit no és vàlid."
@ -2814,7 +2902,8 @@ msgstr "No podeu deixar ladreça de lenllaç en blanc."
msgid "This web address is not valid. It should be like https://domain.com/." msgid "This web address is not valid. It should be like https://domain.com/."
msgstr "Aquesta adreça web no és vàlida. Hauria de ser similar a https://domini.com/." msgstr "Aquesta adreça web no és vàlida. Hauria de ser similar a https://domini.com/."
#: pkg/company/admin.go:207 pkg/booking/public.go:530 #: pkg/company/admin.go:207 pkg/booking/checkin.go:301
#: pkg/booking/public.go:581
msgid "Selected country is not valid." msgid "Selected country is not valid."
msgstr "El país escollit no és vàlid." msgstr "El país escollit no és vàlid."
@ -2834,15 +2923,16 @@ msgstr "No podeu deixar el NIF en blanc."
msgid "This VAT number is not valid." msgid "This VAT number is not valid."
msgstr "Aquest NIF no és vàlid." msgstr "Aquest NIF no és vàlid."
#: pkg/company/admin.go:219 pkg/booking/public.go:548 #: pkg/company/admin.go:219 pkg/booking/public.go:599
msgid "Phone can not be empty." msgid "Phone can not be empty."
msgstr "No podeu deixar el telèfon en blanc." msgstr "No podeu deixar el telèfon en blanc."
#: pkg/company/admin.go:220 pkg/booking/admin.go:321 pkg/booking/public.go:549 #: pkg/company/admin.go:220 pkg/booking/checkin.go:305 pkg/booking/admin.go:442
#: pkg/booking/public.go:600
msgid "This phone number is not valid." msgid "This phone number is not valid."
msgstr "Aquest número de telèfon no és vàlid." msgstr "Aquest número de telèfon no és vàlid."
#: pkg/company/admin.go:230 pkg/booking/public.go:538 #: pkg/company/admin.go:230 pkg/booking/public.go:589
msgid "Address can not be empty." msgid "Address can not be empty."
msgstr "No podeu deixar ladreça en blanc." msgstr "No podeu deixar ladreça en blanc."
@ -2854,11 +2944,11 @@ msgstr "No podeu deixar la població en blanc."
msgid "Province can not be empty." msgid "Province can not be empty."
msgstr "No podeu deixar la província en blanc." msgstr "No podeu deixar la província en blanc."
#: pkg/company/admin.go:233 pkg/booking/public.go:540 #: pkg/company/admin.go:233 pkg/booking/public.go:591
msgid "Postcode can not be empty." msgid "Postcode can not be empty."
msgstr "No podeu deixar el codi postal en blanc." msgstr "No podeu deixar el codi postal en blanc."
#: pkg/company/admin.go:234 pkg/booking/admin.go:311 pkg/booking/public.go:541 #: pkg/company/admin.go:234 pkg/booking/admin.go:432 pkg/booking/public.go:592
msgid "This postcode is not valid." msgid "This postcode is not valid."
msgstr "Aquest codi postal no és vàlid." msgstr "Aquest codi postal no és vàlid."
@ -2910,169 +3000,202 @@ msgstr "No podeu deixar el fitxer del mèdia en blanc."
msgid "Filename can not be empty." msgid "Filename can not be empty."
msgstr "No podeu deixar el nom del fitxer en blanc." msgstr "No podeu deixar el nom del fitxer en blanc."
#: pkg/booking/cart.go:235 #: pkg/booking/checkin.go:285
msgid "Selected ID document type is not valid."
msgstr "El tipus de document didentitat escollit no és vàlid."
#: pkg/booking/checkin.go:286
msgid "ID document number can not be empty."
msgstr "No podeu deixar el número document didentitat en blanc."
#: pkg/booking/checkin.go:288
msgid "ID document issue date must be a valid date."
msgstr "La data dexpedició del document didentitat ha de ser una data vàlida."
#: pkg/booking/checkin.go:289
msgid "ID document issue date must be in the past."
msgstr "La data dexpedició del document didentitat ha de ser al passat."
#: pkg/booking/checkin.go:292 pkg/booking/checkin.go:293
#: pkg/booking/admin.go:425 pkg/booking/public.go:585
msgid "Full name can not be empty."
msgstr "No podeu deixar el nom i els cognoms en blanc."
#: pkg/booking/checkin.go:294
msgid "Selected sex is not valid."
msgstr "El sexe escollit no és vàlid."
#: pkg/booking/checkin.go:295
msgid "Birthdate can not be empty"
msgstr "No podeu deixar la data de naixement en blanc."
#: pkg/booking/checkin.go:296
msgid "Birthdate must be a valid date."
msgstr "La data de naixement ha de ser una data vàlida."
#: pkg/booking/checkin.go:297
msgid "Birthdate must be in the past."
msgstr "La data de naixement ha de ser al passat."
#: pkg/booking/cart.go:233
msgctxt "cart" msgctxt "cart"
msgid "Adult" msgid "Adult"
msgstr "Adult" msgstr "Adult"
#: pkg/booking/cart.go:236 #: pkg/booking/cart.go:234
msgctxt "cart" msgctxt "cart"
msgid "Teenager" msgid "Teenager"
msgstr "Adolescent" msgstr "Adolescent"
#: pkg/booking/cart.go:237 #: pkg/booking/cart.go:235
msgctxt "cart" msgctxt "cart"
msgid "Child" msgid "Child"
msgstr "Nen" msgstr "Nen"
#: pkg/booking/cart.go:238 #: pkg/booking/cart.go:236
msgctxt "cart" msgctxt "cart"
msgid "Dog" msgid "Dog"
msgstr "Gos" msgstr "Gos"
#: pkg/booking/admin.go:144 #: pkg/booking/admin.go:217
msgctxt "filename" msgctxt "filename"
msgid "bookings.ods" msgid "bookings.ods"
msgstr "reserves.ods" msgstr "reserves.ods"
#: pkg/booking/admin.go:304 pkg/booking/public.go:534 #: pkg/booking/admin.go:426 pkg/booking/public.go:586
msgid "Full name can not be empty."
msgstr "No podeu deixar el nom i els cognoms en blanc."
#: pkg/booking/admin.go:305 pkg/booking/public.go:535
msgid "Full name must have at least one letter." msgid "Full name must have at least one letter."
msgstr "El nom i els cognoms han de tenir com a mínim una lletra." msgstr "El nom i els cognoms han de tenir com a mínim una lletra."
#: pkg/booking/admin.go:310 #: pkg/booking/admin.go:431
msgid "Country can not be empty to validate the postcode." msgid "Country can not be empty to validate the postcode."
msgstr "No podeu deixar el país en blanc per validar el codi postal." msgstr "No podeu deixar el país en blanc per validar el codi postal."
#: pkg/booking/admin.go:320 #: pkg/booking/admin.go:441
msgid "Country can not be empty to validate the phone." msgid "Country can not be empty to validate the phone."
msgstr "No podeu deixar el país en blanc per validar el telèfon." msgstr "No podeu deixar el país en blanc per validar el telèfon."
#: pkg/booking/admin.go:327 #: pkg/booking/admin.go:448
msgid "You must select at least one accommodation." msgid "You must select at least one accommodation."
msgstr "Heu descollir com a mínim un allotjament." msgstr "Heu descollir com a mínim un allotjament."
#: pkg/booking/admin.go:333 #: pkg/booking/admin.go:454
msgid "The selected accommodations have no available openings in the requested dates." msgid "The selected accommodations have no available openings in the requested dates."
msgstr "Els allotjaments escollits no estan disponibles a les dates demanades." msgstr "Els allotjaments escollits no estan disponibles a les dates demanades."
#: pkg/booking/public.go:277 pkg/booking/public.go:306 #: pkg/booking/public.go:284 pkg/booking/public.go:313
msgid "Arrival date must be a valid date." msgid "Arrival date must be a valid date."
msgstr "La data darribada ha de ser una data vàlida." msgstr "La data darribada ha de ser una data vàlida."
#: pkg/booking/public.go:291 pkg/booking/public.go:313 #: pkg/booking/public.go:298 pkg/booking/public.go:320
msgid "Departure date must be a valid date." msgid "Departure date must be a valid date."
msgstr "La data de sortida ha de ser una data vàlida." msgstr "La data de sortida ha de ser una data vàlida."
#: pkg/booking/public.go:305 #: pkg/booking/public.go:312
msgid "Arrival date can not be empty" msgid "Arrival date can not be empty"
msgstr "No podeu deixar la data darribada en blanc." msgstr "No podeu deixar la data darribada en blanc."
#: pkg/booking/public.go:307 #: pkg/booking/public.go:314
#, c-format #, c-format
msgid "Arrival date must be %s or after." msgid "Arrival date must be %s or after."
msgstr "La data darribada ha de ser igual o posterior a %s." msgstr "La data darribada ha de ser igual o posterior a %s."
#: pkg/booking/public.go:308 #: pkg/booking/public.go:315
#, c-format #, c-format
msgid "Arrival date must be %s or before." msgid "Arrival date must be %s or before."
msgstr "La data darribada ha de ser anterior o igual a %s." msgstr "La data darribada ha de ser anterior o igual a %s."
#: pkg/booking/public.go:312 #: pkg/booking/public.go:319
msgid "Departure date can not be empty" msgid "Departure date can not be empty"
msgstr "No podeu deixar la data de sortida en blanc." msgstr "No podeu deixar la data de sortida en blanc."
#: pkg/booking/public.go:314 #: pkg/booking/public.go:321
#, c-format #, c-format
msgid "Departure date must be %s or after." msgid "Departure date must be %s or after."
msgstr "La data de sortida ha de ser igual o posterior a %s." msgstr "La data de sortida ha de ser igual o posterior a %s."
#: pkg/booking/public.go:315 #: pkg/booking/public.go:322
#, c-format #, c-format
msgid "Departure date must be %s or before." msgid "Departure date must be %s or before."
msgstr "La data de sortida ha de ser anterior o igual a %s." msgstr "La data de sortida ha de ser anterior o igual a %s."
#: pkg/booking/public.go:369 #: pkg/booking/public.go:380
#, c-format #, c-format
msgid "There can be at most %d guests in this accommodation." msgid "There can be at most %d guests in this accommodation."
msgstr "Hi poden haver com a màxim %d convidats a aquest allotjament." msgstr "Hi poden haver com a màxim %d convidats a aquest allotjament."
#: pkg/booking/public.go:389 #: pkg/booking/public.go:400
msgid "Number of adults can not be empty" msgid "Number of adults can not be empty"
msgstr "No podeu deixar el número dadults en blanc." msgstr "No podeu deixar el número dadults en blanc."
#: pkg/booking/public.go:390 #: pkg/booking/public.go:401
msgid "Number of adults must be an integer." msgid "Number of adults must be an integer."
msgstr "El número dadults ha de ser enter." msgstr "El número dadults ha de ser enter."
#: pkg/booking/public.go:391 #: pkg/booking/public.go:402
msgid "There must be at least one adult." msgid "There must be at least one adult."
msgstr "Hi ha dhaver com a mínim un adult." msgstr "Hi ha dhaver com a mínim un adult."
#: pkg/booking/public.go:394 #: pkg/booking/public.go:405
msgid "Number of teenagers can not be empty" msgid "Number of teenagers can not be empty"
msgstr "No podeu deixar el número dadolescents en blanc." msgstr "No podeu deixar el número dadolescents en blanc."
#: pkg/booking/public.go:395 #: pkg/booking/public.go:406
msgid "Number of teenagers must be an integer." msgid "Number of teenagers must be an integer."
msgstr "El número dadolescents ha de ser enter." msgstr "El número dadolescents ha de ser enter."
#: pkg/booking/public.go:396 #: pkg/booking/public.go:407
msgid "Number of teenagers can not be negative." msgid "Number of teenagers can not be negative."
msgstr "El número dadolescents no pot ser negatiu." msgstr "El número dadolescents no pot ser negatiu."
#: pkg/booking/public.go:399 #: pkg/booking/public.go:410
msgid "Number of children can not be empty" msgid "Number of children can not be empty"
msgstr "No podeu deixar el número de nens en blanc." msgstr "No podeu deixar el número de nens en blanc."
#: pkg/booking/public.go:400 #: pkg/booking/public.go:411
msgid "Number of children must be an integer." msgid "Number of children must be an integer."
msgstr "El número de nens ha de ser enter." msgstr "El número de nens ha de ser enter."
#: pkg/booking/public.go:401 #: pkg/booking/public.go:412
msgid "Number of children can not be negative." msgid "Number of children can not be negative."
msgstr "El número de nens no pot ser negatiu." msgstr "El número de nens no pot ser negatiu."
#: pkg/booking/public.go:404 #: pkg/booking/public.go:415
msgid "Number of dogs can not be empty" msgid "Number of dogs can not be empty"
msgstr "No podeu deixar el número de gossos en blanc." msgstr "No podeu deixar el número de gossos en blanc."
#: pkg/booking/public.go:405 #: pkg/booking/public.go:416
msgid "Number of dogs must be an integer." msgid "Number of dogs must be an integer."
msgstr "El número de gossos ha de ser enter." msgstr "El número de gossos ha de ser enter."
#: pkg/booking/public.go:406 #: pkg/booking/public.go:417
msgid "Number of dogs can not be negative." msgid "Number of dogs can not be negative."
msgstr "El número de gossos no pot ser negatiu." msgstr "El número de gossos no pot ser negatiu."
#: pkg/booking/public.go:477 #: pkg/booking/public.go:524
#, c-format #, c-format
msgid "%s can not be empty" msgid "%s can not be empty"
msgstr "No podeu deixar %s en blanc." msgstr "No podeu deixar %s en blanc."
#: pkg/booking/public.go:478 #: pkg/booking/public.go:525
#, c-format #, c-format
msgid "%s must be an integer." msgid "%s must be an integer."
msgstr "%s ha de ser un número enter." msgstr "%s ha de ser un número enter."
#: pkg/booking/public.go:479 #: pkg/booking/public.go:526
#, c-format #, c-format
msgid "%s must be %d or greater." msgid "%s must be %d or greater."
msgstr "El valor de %s ha de ser com a mínim %d." msgstr "El valor de %s ha de ser com a mínim %d."
#: pkg/booking/public.go:480 #: pkg/booking/public.go:527
#, c-format #, c-format
msgid "%s must be at most %d." msgid "%s must be at most %d."
msgstr "El valor de %s ha de ser com a màxim %d." msgstr "El valor de %s ha de ser com a màxim %d."
#: pkg/booking/public.go:539 #: pkg/booking/public.go:590
msgid "Town or village can not be empty." msgid "Town or village can not be empty."
msgstr "No podeu deixar la població en blanc." msgstr "No podeu deixar la població en blanc."
#: pkg/booking/public.go:554 #: pkg/booking/public.go:605
msgid "It is mandatory to agree to the reservation conditions." msgid "It is mandatory to agree to the reservation conditions."
msgstr "És obligatori acceptar les condicions de reserves." msgstr "És obligatori acceptar les condicions de reserves."

291
po/es.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: camper\n" "Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-04-24 19:59+0200\n" "POT-Creation-Date: 2024-04-26 16:53+0200\n"
"PO-Revision-Date: 2024-02-06 10:04+0100\n" "PO-Revision-Date: 2024-02-06 10:04+0100\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n" "Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Spanish <es@tp.org.es>\n" "Language-Team: Spanish <es@tp.org.es>\n"
@ -116,7 +116,7 @@ msgstr "Reserva"
#: web/templates/mail/payment/details.gotxt:16 #: web/templates/mail/payment/details.gotxt:16
#: web/templates/public/booking/fields.gohtml:14 #: web/templates/public/booking/fields.gohtml:14
#: web/templates/admin/payment/details.gohtml:74 #: web/templates/admin/payment/details.gohtml:74
#: web/templates/admin/booking/fields.gohtml:12 #: web/templates/admin/booking/fields.gohtml:13
msgctxt "title" msgctxt "title"
msgid "Accommodation" msgid "Accommodation"
msgstr "Alojamientos" msgstr "Alojamientos"
@ -155,7 +155,7 @@ msgstr "No"
#: web/templates/public/campsite/dates.gohtml:4 #: web/templates/public/campsite/dates.gohtml:4
#: web/templates/public/booking/fields.gohtml:30 #: web/templates/public/booking/fields.gohtml:30
#: web/templates/admin/payment/details.gohtml:86 #: web/templates/admin/payment/details.gohtml:86
#: web/templates/admin/booking/fields.gohtml:31 #: web/templates/admin/booking/fields.gohtml:32
msgctxt "input" msgctxt "input"
msgid "Arrival date" msgid "Arrival date"
msgstr "Fecha de llegada" msgstr "Fecha de llegada"
@ -164,7 +164,7 @@ msgstr "Fecha de llegada"
#: web/templates/public/campsite/dates.gohtml:15 #: web/templates/public/campsite/dates.gohtml:15
#: web/templates/public/booking/fields.gohtml:41 #: web/templates/public/booking/fields.gohtml:41
#: web/templates/admin/payment/details.gohtml:90 #: web/templates/admin/payment/details.gohtml:90
#: web/templates/admin/booking/fields.gohtml:42 #: web/templates/admin/booking/fields.gohtml:43
msgctxt "input" msgctxt "input"
msgid "Departure date" msgid "Departure date"
msgstr "Fecha de salida" msgstr "Fecha de salida"
@ -178,7 +178,7 @@ msgstr "Noches"
#: web/templates/mail/payment/details.gotxt:22 #: web/templates/mail/payment/details.gotxt:22
#: web/templates/public/booking/fields.gohtml:60 #: web/templates/public/booking/fields.gohtml:60
#: web/templates/admin/payment/details.gohtml:98 #: web/templates/admin/payment/details.gohtml:98
#: web/templates/admin/booking/fields.gohtml:92 #: web/templates/admin/booking/fields.gohtml:93
msgctxt "input" msgctxt "input"
msgid "Adults aged 17 or older" msgid "Adults aged 17 or older"
msgstr "Adultos de 17 años o más" msgstr "Adultos de 17 años o más"
@ -186,7 +186,7 @@ msgstr "Adultos de 17 años o más"
#: web/templates/mail/payment/details.gotxt:23 #: web/templates/mail/payment/details.gotxt:23
#: web/templates/public/booking/fields.gohtml:71 #: web/templates/public/booking/fields.gohtml:71
#: web/templates/admin/payment/details.gohtml:102 #: web/templates/admin/payment/details.gohtml:102
#: web/templates/admin/booking/fields.gohtml:108 #: web/templates/admin/booking/fields.gohtml:109
msgctxt "input" msgctxt "input"
msgid "Teenagers from 11 to 16 years old" msgid "Teenagers from 11 to 16 years old"
msgstr "Adolescentes de 11 a 16 años" msgstr "Adolescentes de 11 a 16 años"
@ -194,7 +194,7 @@ msgstr "Adolescentes de 11 a 16 años"
#: web/templates/mail/payment/details.gotxt:24 #: web/templates/mail/payment/details.gotxt:24
#: web/templates/public/booking/fields.gohtml:82 #: web/templates/public/booking/fields.gohtml:82
#: web/templates/admin/payment/details.gohtml:106 #: web/templates/admin/payment/details.gohtml:106
#: web/templates/admin/booking/fields.gohtml:124 #: web/templates/admin/booking/fields.gohtml:125
msgctxt "input" msgctxt "input"
msgid "Children from 2 to 10 years old" msgid "Children from 2 to 10 years old"
msgstr "Niños de 2 a 10 años" msgstr "Niños de 2 a 10 años"
@ -202,14 +202,14 @@ msgstr "Niños de 2 a 10 años"
#: web/templates/mail/payment/details.gotxt:25 #: web/templates/mail/payment/details.gotxt:25
#: web/templates/public/booking/fields.gohtml:100 #: web/templates/public/booking/fields.gohtml:100
#: web/templates/admin/payment/details.gohtml:110 #: web/templates/admin/payment/details.gohtml:110
#: web/templates/admin/booking/fields.gohtml:139 #: web/templates/admin/booking/fields.gohtml:140
msgctxt "input" msgctxt "input"
msgid "Dogs" msgid "Dogs"
msgstr "Perros" msgstr "Perros"
#: web/templates/mail/payment/details.gotxt:26 #: web/templates/mail/payment/details.gotxt:26
#: web/templates/admin/payment/details.gohtml:114 #: web/templates/admin/payment/details.gohtml:114
#: web/templates/admin/booking/fields.gohtml:166 pkg/booking/cart.go:244 #: web/templates/admin/booking/fields.gohtml:167 pkg/booking/cart.go:242
msgctxt "cart" msgctxt "cart"
msgid "Tourist tax" msgid "Tourist tax"
msgstr "Impuesto turístico" msgstr "Impuesto turístico"
@ -239,7 +239,7 @@ msgstr "Opciones del tipo de alojamiento"
#: web/templates/mail/payment/details.gotxt:39 #: web/templates/mail/payment/details.gotxt:39
#: web/templates/public/booking/fields.gohtml:146 #: web/templates/public/booking/fields.gohtml:146
#: web/templates/admin/payment/details.gohtml:140 #: web/templates/admin/payment/details.gohtml:140
#: web/templates/admin/booking/fields.gohtml:187 #: web/templates/admin/booking/fields.gohtml:188
msgctxt "title" msgctxt "title"
msgid "Customer Details" msgid "Customer Details"
msgstr "Detalles del cliente" msgstr "Detalles del cliente"
@ -247,7 +247,7 @@ msgstr "Detalles del cliente"
#: web/templates/mail/payment/details.gotxt:41 #: web/templates/mail/payment/details.gotxt:41
#: web/templates/public/booking/fields.gohtml:149 #: web/templates/public/booking/fields.gohtml:149
#: web/templates/admin/payment/details.gohtml:143 #: web/templates/admin/payment/details.gohtml:143
#: web/templates/admin/booking/fields.gohtml:190 #: web/templates/admin/booking/fields.gohtml:191
msgctxt "input" msgctxt "input"
msgid "Full name" msgid "Full name"
msgstr "Nombre y apellidos" msgstr "Nombre y apellidos"
@ -930,7 +930,7 @@ msgstr "Menú"
#: web/templates/admin/campsite/type/option/index.gohtml:10 #: web/templates/admin/campsite/type/option/index.gohtml:10
#: web/templates/admin/campsite/type/index.gohtml:10 #: web/templates/admin/campsite/type/index.gohtml:10
#: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:95 #: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:95
#: web/templates/admin/booking/fields.gohtml:265 #: web/templates/admin/booking/fields.gohtml:266
msgctxt "title" msgctxt "title"
msgid "Campsites" msgid "Campsites"
msgstr "Alojamientos" msgstr "Alojamientos"
@ -978,6 +978,7 @@ msgid "Booking Period"
msgstr "Periodo de reserva" msgstr "Periodo de reserva"
#: web/templates/public/booking/fields.gohtml:56 #: web/templates/public/booking/fields.gohtml:56
#: web/templates/admin/booking/checkin.gohtml:20
msgctxt "title" msgctxt "title"
msgid "Guests" msgid "Guests"
msgstr "Huéspedes" msgstr "Huéspedes"
@ -987,18 +988,18 @@ msgid "Note: Due to guest capacity, we have added more accommodations to the boo
msgstr "Nota: Se han añadido alojamientos a la reserva debido a la capacidad de cada una, pero <strong>no</strong> se garantiza que estén de lado." msgstr "Nota: Se han añadido alojamientos a la reserva debido a la capacidad de cada una, pero <strong>no</strong> se garantiza que estén de lado."
#: web/templates/public/booking/fields.gohtml:109 #: web/templates/public/booking/fields.gohtml:109
#: web/templates/admin/booking/fields.gohtml:178 #: web/templates/admin/booking/fields.gohtml:179
msgid "Note: This accommodation does <strong>not</strong> allow dogs." msgid "Note: This accommodation does <strong>not</strong> allow dogs."
msgstr "Nota: En este alojamiento <strong>no</strong> se permiten perros." msgstr "Nota: En este alojamiento <strong>no</strong> se permiten perros."
#: web/templates/public/booking/fields.gohtml:121 #: web/templates/public/booking/fields.gohtml:121
#: web/templates/admin/booking/fields.gohtml:55 #: web/templates/admin/booking/fields.gohtml:56
msgctxt "input" msgctxt "input"
msgid "Area preferences (optional)" msgid "Area preferences (optional)"
msgstr "Preferencias de área (opcional)" msgstr "Preferencias de área (opcional)"
#: web/templates/public/booking/fields.gohtml:123 #: web/templates/public/booking/fields.gohtml:123
#: web/templates/admin/booking/fields.gohtml:59 #: web/templates/admin/booking/fields.gohtml:60
msgid "Campground map" msgid "Campground map"
msgstr "Mapa del camping" msgstr "Mapa del camping"
@ -1008,12 +1009,13 @@ msgid "Town or village"
msgstr "Población" msgstr "Población"
#: web/templates/public/booking/fields.gohtml:193 #: web/templates/public/booking/fields.gohtml:193
#: web/templates/admin/booking/fields.gohtml:203 #: web/templates/admin/booking/fields.gohtml:204
#: web/templates/admin/booking/guest.gohtml:109
msgid "Choose a country" msgid "Choose a country"
msgstr "Escoja un país" msgstr "Escoja un país"
#: web/templates/public/booking/fields.gohtml:247 #: web/templates/public/booking/fields.gohtml:247
#: web/templates/admin/booking/fields.gohtml:258 #: web/templates/admin/booking/fields.gohtml:259
msgctxt "input" msgctxt "input"
msgid "ACSI card? (optional)" msgid "ACSI card? (optional)"
msgstr "¿Tarjeta ACSI? (opcional)" msgstr "¿Tarjeta ACSI? (opcional)"
@ -1098,8 +1100,8 @@ msgid "Down payment"
msgstr "A cuenta" msgstr "A cuenta"
#: web/templates/admin/payment/index.gohtml:24 #: web/templates/admin/payment/index.gohtml:24
#: web/templates/admin/booking/fields.gohtml:74 #: web/templates/admin/booking/fields.gohtml:75
#: web/templates/admin/booking/fields.gohtml:172 #: web/templates/admin/booking/fields.gohtml:173
msgctxt "header" msgctxt "header"
msgid "Total" msgid "Total"
msgstr "Total" msgstr "Total"
@ -1194,7 +1196,7 @@ msgstr "Contenido"
#: web/templates/admin/amenity/form.gohtml:91 #: web/templates/admin/amenity/form.gohtml:91
#: web/templates/admin/home/index.gohtml:34 #: web/templates/admin/home/index.gohtml:34
#: web/templates/admin/media/form.gohtml:39 #: web/templates/admin/media/form.gohtml:39
#: web/templates/admin/booking/fields.gohtml:272 #: web/templates/admin/booking/form.gohtml:45
msgctxt "action" msgctxt "action"
msgid "Update" msgid "Update"
msgstr "Actualizar" msgstr "Actualizar"
@ -1214,7 +1216,7 @@ msgstr "Actualizar"
#: web/templates/admin/amenity/feature/form.gohtml:67 #: web/templates/admin/amenity/feature/form.gohtml:67
#: web/templates/admin/amenity/carousel/form.gohtml:52 #: web/templates/admin/amenity/carousel/form.gohtml:52
#: web/templates/admin/amenity/form.gohtml:93 #: web/templates/admin/amenity/form.gohtml:93
#: web/templates/admin/booking/fields.gohtml:274 #: web/templates/admin/booking/form.gohtml:47
msgctxt "action" msgctxt "action"
msgid "Add" msgid "Add"
msgstr "Añadir" msgstr "Añadir"
@ -2161,7 +2163,7 @@ msgid "Add Amenity"
msgstr "Añadir instalación" msgstr "Añadir instalación"
#: web/templates/admin/amenity/index.gohtml:20 #: web/templates/admin/amenity/index.gohtml:20
#: web/templates/admin/booking/grid.gohtml:13 #: web/templates/admin/booking/grid.gohtml:15
msgctxt "header" msgctxt "header"
msgid "Label" msgid "Label"
msgstr "Etiqueta" msgstr "Etiqueta"
@ -2204,7 +2206,8 @@ msgid "Logout"
msgstr "Salir" msgstr "Salir"
#: web/templates/admin/layout.gohtml:92 #: web/templates/admin/layout.gohtml:92
#: web/templates/admin/booking/form.gohtml:15 #: web/templates/admin/booking/form.gohtml:19
#: web/templates/admin/booking/checkin.gohtml:10
#: web/templates/admin/booking/index.gohtml:6 #: web/templates/admin/booking/index.gohtml:6
#: web/templates/admin/booking/index.gohtml:16 #: web/templates/admin/booking/index.gohtml:16
msgctxt "title" msgctxt "title"
@ -2312,51 +2315,53 @@ msgctxt "title"
msgid "Upload Media" msgid "Upload Media"
msgstr "Subida de medio" msgstr "Subida de medio"
#: web/templates/admin/booking/fields.gohtml:18 #: web/templates/admin/booking/fields.gohtml:19
msgid "Choose an accommodation" msgid "Choose an accommodation"
msgstr "Escoja un alojamiento" msgstr "Escoja un alojamiento"
#: web/templates/admin/booking/fields.gohtml:72 #: web/templates/admin/booking/fields.gohtml:73
msgctxt "header" msgctxt "header"
msgid "Units" msgid "Units"
msgstr "Unidades" msgstr "Unidades"
#: web/templates/admin/booking/fields.gohtml:73 #: web/templates/admin/booking/fields.gohtml:74
msgctxt "header" msgctxt "header"
msgid "Decription" msgid "Decription"
msgstr "Descripción" msgstr "Descripción"
#: web/templates/admin/booking/fields.gohtml:80 pkg/booking/cart.go:234 #: web/templates/admin/booking/fields.gohtml:81 pkg/booking/cart.go:232
msgctxt "cart" msgctxt "cart"
msgid "Night" msgid "Night"
msgstr "Noche" msgstr "Noche"
#: web/templates/admin/booking/fields.gohtml:199 #: web/templates/admin/booking/fields.gohtml:200
msgctxt "input" msgctxt "input"
msgid "Country (optional)" msgid "Country (optional)"
msgstr "País (opcional)" msgstr "País (opcional)"
#: web/templates/admin/booking/fields.gohtml:211 #: web/templates/admin/booking/fields.gohtml:212
#: web/templates/admin/booking/guest.gohtml:128
msgctxt "input" msgctxt "input"
msgid "Address (optional)" msgid "Address (optional)"
msgstr "Dirección (opcional)" msgstr "Dirección (opcional)"
#: web/templates/admin/booking/fields.gohtml:220 #: web/templates/admin/booking/fields.gohtml:221
msgctxt "input" msgctxt "input"
msgid "Postcode (optional)" msgid "Postcode (optional)"
msgstr "Código postal (opcional)" msgstr "Código postal (opcional)"
#: web/templates/admin/booking/fields.gohtml:229 #: web/templates/admin/booking/fields.gohtml:230
msgctxt "input" msgctxt "input"
msgid "Town or village (optional)" msgid "Town or village (optional)"
msgstr "Población (opcional)" msgstr "Población (opcional)"
#: web/templates/admin/booking/fields.gohtml:238 #: web/templates/admin/booking/fields.gohtml:239
msgctxt "input" msgctxt "input"
msgid "Email (optional)" msgid "Email (optional)"
msgstr "Correo-e (opcional)" msgstr "Correo-e (opcional)"
#: web/templates/admin/booking/fields.gohtml:247 #: web/templates/admin/booking/fields.gohtml:248
#: web/templates/admin/booking/guest.gohtml:117
msgctxt "input" msgctxt "input"
msgid "Phone (optional)" msgid "Phone (optional)"
msgstr "Teléfono (opcional)" msgstr "Teléfono (opcional)"
@ -2371,6 +2376,31 @@ msgctxt "title"
msgid "New Booking" msgid "New Booking"
msgstr "Nueva reserva" msgstr "Nueva reserva"
#: web/templates/admin/booking/form.gohtml:25
msgctxt "action"
msgid "Check-in Booking"
msgstr "Registrar reserva"
#: web/templates/admin/booking/checkin.gohtml:6
msgctxt "title"
msgid "Check-in Booking"
msgstr "Registro de la reserva"
#: web/templates/admin/booking/checkin.gohtml:15
msgctxt "action"
msgid "Edit Booking"
msgstr "Editar la reserva"
#: web/templates/admin/booking/checkin.gohtml:26
msgctxt "action"
msgid "Check-in"
msgstr "Registrar"
#: web/templates/admin/booking/checkin.gohtml:31
msgctxt "action"
msgid "Add another guest"
msgstr "Añadir otro huésped"
#: web/templates/admin/booking/index.gohtml:14 #: web/templates/admin/booking/index.gohtml:14
msgctxt "action" msgctxt "action"
msgid "Add Booking" msgid "Add Booking"
@ -2400,6 +2430,64 @@ msgstr "Nombre del titular"
msgid "No booking found." msgid "No booking found."
msgstr "No se ha encontrado ninguna reserva." msgstr "No se ha encontrado ninguna reserva."
#: web/templates/admin/booking/guest.gohtml:5
msgctxt "action"
msgid "Remove"
msgstr "Borrar"
#: web/templates/admin/booking/guest.gohtml:8
msgctxt "input"
msgid "ID document number"
msgstr "Número de documento de identidad"
#: web/templates/admin/booking/guest.gohtml:20
msgctxt "input"
msgid "ID document type"
msgstr "Tipo de documento"
#: web/templates/admin/booking/guest.gohtml:25
msgid "Choose an ID document type"
msgstr "Escoja un tipo de documento"
#: web/templates/admin/booking/guest.gohtml:33
msgctxt "input"
msgid "ID document issue date (if any)"
msgstr "Fecha expedición del documento (si hay)"
#: web/templates/admin/booking/guest.gohtml:44
msgctxt "input"
msgid "First surname"
msgstr "Primer apellido"
#: web/templates/admin/booking/guest.gohtml:56
msgctxt "input"
msgid "Second surname (if has one)"
msgstr "Segundo apellido (si tiene)"
#: web/templates/admin/booking/guest.gohtml:67
msgctxt "input"
msgid "Given name"
msgstr "Nombre"
#: web/templates/admin/booking/guest.gohtml:79
msgctxt "input"
msgid "Sex"
msgstr "Sexo"
#: web/templates/admin/booking/guest.gohtml:84
msgid "Choose a sex"
msgstr "Escoja un sexo"
#: web/templates/admin/booking/guest.gohtml:92
msgctxt "input"
msgid "Birthdate"
msgstr "Fecha de nacimiento"
#: web/templates/admin/booking/guest.gohtml:104
msgctxt "input"
msgid "Nationality"
msgstr "Nacionalidad"
#: pkg/payment/settings.go:37 #: pkg/payment/settings.go:37
msgctxt "redsys environment" msgctxt "redsys environment"
msgid "Test" msgid "Test"
@ -2501,12 +2589,12 @@ msgid "Slide image must be an image media type."
msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen." msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen."
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:224 #: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:224
#: pkg/booking/public.go:545 #: pkg/booking/public.go:596
msgid "Email can not be empty." msgid "Email can not be empty."
msgstr "No podéis dejar el correo-e en blanco." msgstr "No podéis dejar el correo-e en blanco."
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:225 #: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:225
#: pkg/booking/admin.go:316 pkg/booking/public.go:546 #: pkg/booking/admin.go:437 pkg/booking/public.go:597
msgid "This email is not valid. It should be like name@domain.com." msgid "This email is not valid. It should be like name@domain.com."
msgstr "Este correo-e no es válido. Tiene que ser parecido a nombre@dominio.com." msgstr "Este correo-e no es válido. Tiene que ser parecido a nombre@dominio.com."
@ -2717,8 +2805,8 @@ msgctxt "header"
msgid "Children (aged 2 to 10)" msgid "Children (aged 2 to 10)"
msgstr "Niños (de 2 a 10 años)" msgstr "Niños (de 2 a 10 años)"
#: pkg/campsite/admin.go:280 pkg/booking/admin.go:292 pkg/booking/public.go:173 #: pkg/campsite/admin.go:280 pkg/booking/admin.go:413 pkg/booking/public.go:177
#: pkg/booking/public.go:228 #: pkg/booking/public.go:232
msgid "Selected campsite type is not valid." msgid "Selected campsite type is not valid."
msgstr "El tipo de alojamiento escogido no es válido." msgstr "El tipo de alojamiento escogido no es válido."
@ -2814,7 +2902,8 @@ msgstr "No podéis dejar la dirección del enlace en blanco."
msgid "This web address is not valid. It should be like https://domain.com/." msgid "This web address is not valid. It should be like https://domain.com/."
msgstr "Esta dirección web no es válida. Tiene que ser parecido a https://dominio.com/." msgstr "Esta dirección web no es válida. Tiene que ser parecido a https://dominio.com/."
#: pkg/company/admin.go:207 pkg/booking/public.go:530 #: pkg/company/admin.go:207 pkg/booking/checkin.go:301
#: pkg/booking/public.go:581
msgid "Selected country is not valid." msgid "Selected country is not valid."
msgstr "El país escogido no es válido." msgstr "El país escogido no es válido."
@ -2834,15 +2923,16 @@ msgstr "No podéis dejar el NIF en blanco."
msgid "This VAT number is not valid." msgid "This VAT number is not valid."
msgstr "Este NIF no es válido." msgstr "Este NIF no es válido."
#: pkg/company/admin.go:219 pkg/booking/public.go:548 #: pkg/company/admin.go:219 pkg/booking/public.go:599
msgid "Phone can not be empty." msgid "Phone can not be empty."
msgstr "No podéis dejar el teléfono en blanco." msgstr "No podéis dejar el teléfono en blanco."
#: pkg/company/admin.go:220 pkg/booking/admin.go:321 pkg/booking/public.go:549 #: pkg/company/admin.go:220 pkg/booking/checkin.go:305 pkg/booking/admin.go:442
#: pkg/booking/public.go:600
msgid "This phone number is not valid." msgid "This phone number is not valid."
msgstr "Este teléfono no es válido." msgstr "Este teléfono no es válido."
#: pkg/company/admin.go:230 pkg/booking/public.go:538 #: pkg/company/admin.go:230 pkg/booking/public.go:589
msgid "Address can not be empty." msgid "Address can not be empty."
msgstr "No podéis dejar la dirección en blanco." msgstr "No podéis dejar la dirección en blanco."
@ -2854,11 +2944,11 @@ msgstr "No podéis dejar la población en blanco."
msgid "Province can not be empty." msgid "Province can not be empty."
msgstr "No podéis dejar la provincia en blanco." msgstr "No podéis dejar la provincia en blanco."
#: pkg/company/admin.go:233 pkg/booking/public.go:540 #: pkg/company/admin.go:233 pkg/booking/public.go:591
msgid "Postcode can not be empty." msgid "Postcode can not be empty."
msgstr "No podéis dejar el código postal en blanco." msgstr "No podéis dejar el código postal en blanco."
#: pkg/company/admin.go:234 pkg/booking/admin.go:311 pkg/booking/public.go:541 #: pkg/company/admin.go:234 pkg/booking/admin.go:432 pkg/booking/public.go:592
msgid "This postcode is not valid." msgid "This postcode is not valid."
msgstr "Este código postal no es válido." msgstr "Este código postal no es válido."
@ -2910,169 +3000,202 @@ msgstr "No podéis dejar el archivo del medio en blanco."
msgid "Filename can not be empty." msgid "Filename can not be empty."
msgstr "No podéis dejar el nombre del archivo en blanco." msgstr "No podéis dejar el nombre del archivo en blanco."
#: pkg/booking/cart.go:235 #: pkg/booking/checkin.go:285
msgid "Selected ID document type is not valid."
msgstr "El tipo de documento de identidad escogido no es válido."
#: pkg/booking/checkin.go:286
msgid "ID document number can not be empty."
msgstr "No podéis dejar el número del documento de identidad en blanco."
#: pkg/booking/checkin.go:288
msgid "ID document issue date must be a valid date."
msgstr "La fecha de expedición del documento de identidad tiene que ser una fecha válida."
#: pkg/booking/checkin.go:289
msgid "ID document issue date must be in the past."
msgstr "La fecha de expedición del documento de identidad tiene que ser del pasado."
#: pkg/booking/checkin.go:292 pkg/booking/checkin.go:293
#: pkg/booking/admin.go:425 pkg/booking/public.go:585
msgid "Full name can not be empty."
msgstr "No podéis dejar el nombre y los apellidos en blanco."
#: pkg/booking/checkin.go:294
msgid "Selected sex is not valid."
msgstr "El sexo escogido no es válido."
#: pkg/booking/checkin.go:295
msgid "Birthdate can not be empty"
msgstr "No podéis dejar la fecha de nacimiento en blanco."
#: pkg/booking/checkin.go:296
msgid "Birthdate must be a valid date."
msgstr "La fecha de nacimiento tiene que ser una fecha válida."
#: pkg/booking/checkin.go:297
msgid "Birthdate must be in the past."
msgstr "La fecha de nacimiento tiene que ser del pasado."
#: pkg/booking/cart.go:233
msgctxt "cart" msgctxt "cart"
msgid "Adult" msgid "Adult"
msgstr "Adulto" msgstr "Adulto"
#: pkg/booking/cart.go:236 #: pkg/booking/cart.go:234
msgctxt "cart" msgctxt "cart"
msgid "Teenager" msgid "Teenager"
msgstr "Adolescente" msgstr "Adolescente"
#: pkg/booking/cart.go:237 #: pkg/booking/cart.go:235
msgctxt "cart" msgctxt "cart"
msgid "Child" msgid "Child"
msgstr "Niño" msgstr "Niño"
#: pkg/booking/cart.go:238 #: pkg/booking/cart.go:236
msgctxt "cart" msgctxt "cart"
msgid "Dog" msgid "Dog"
msgstr "Perro" msgstr "Perro"
#: pkg/booking/admin.go:144 #: pkg/booking/admin.go:217
msgctxt "filename" msgctxt "filename"
msgid "bookings.ods" msgid "bookings.ods"
msgstr "reservas.ods" msgstr "reservas.ods"
#: pkg/booking/admin.go:304 pkg/booking/public.go:534 #: pkg/booking/admin.go:426 pkg/booking/public.go:586
msgid "Full name can not be empty."
msgstr "No podéis dejar el nombre y los apellidos en blanco."
#: pkg/booking/admin.go:305 pkg/booking/public.go:535
msgid "Full name must have at least one letter." msgid "Full name must have at least one letter."
msgstr "El nombre y los apellidos tienen que tener como mínimo una letra." msgstr "El nombre y los apellidos tienen que tener como mínimo una letra."
#: pkg/booking/admin.go:310 #: pkg/booking/admin.go:431
msgid "Country can not be empty to validate the postcode." msgid "Country can not be empty to validate the postcode."
msgstr "No podéis dejar el país en blanco para validar el código postal." msgstr "No podéis dejar el país en blanco para validar el código postal."
#: pkg/booking/admin.go:320 #: pkg/booking/admin.go:441
msgid "Country can not be empty to validate the phone." msgid "Country can not be empty to validate the phone."
msgstr "No podéis dejar el país en blanco para validar el teléfono." msgstr "No podéis dejar el país en blanco para validar el teléfono."
#: pkg/booking/admin.go:327 #: pkg/booking/admin.go:448
msgid "You must select at least one accommodation." msgid "You must select at least one accommodation."
msgstr "Tenéis que seleccionar como mínimo un alojamiento." msgstr "Tenéis que seleccionar como mínimo un alojamiento."
#: pkg/booking/admin.go:333 #: pkg/booking/admin.go:454
msgid "The selected accommodations have no available openings in the requested dates." msgid "The selected accommodations have no available openings in the requested dates."
msgstr "Los alojamientos seleccionados no tienen disponibilidad en las fechas pedidas." msgstr "Los alojamientos seleccionados no tienen disponibilidad en las fechas pedidas."
#: pkg/booking/public.go:277 pkg/booking/public.go:306 #: pkg/booking/public.go:284 pkg/booking/public.go:313
msgid "Arrival date must be a valid date." msgid "Arrival date must be a valid date."
msgstr "La fecha de llegada tiene que ser una fecha válida." msgstr "La fecha de llegada tiene que ser una fecha válida."
#: pkg/booking/public.go:291 pkg/booking/public.go:313 #: pkg/booking/public.go:298 pkg/booking/public.go:320
msgid "Departure date must be a valid date." msgid "Departure date must be a valid date."
msgstr "La fecha de partida tiene que ser una fecha válida." msgstr "La fecha de partida tiene que ser una fecha válida."
#: pkg/booking/public.go:305 #: pkg/booking/public.go:312
msgid "Arrival date can not be empty" msgid "Arrival date can not be empty"
msgstr "No podéis dejar la fecha de llegada en blanco." msgstr "No podéis dejar la fecha de llegada en blanco."
#: pkg/booking/public.go:307 #: pkg/booking/public.go:314
#, c-format #, c-format
msgid "Arrival date must be %s or after." msgid "Arrival date must be %s or after."
msgstr "La fecha de llegada tiene que ser igual o posterior a %s." msgstr "La fecha de llegada tiene que ser igual o posterior a %s."
#: pkg/booking/public.go:308 #: pkg/booking/public.go:315
#, c-format #, c-format
msgid "Arrival date must be %s or before." msgid "Arrival date must be %s or before."
msgstr "La fecha de llegada tiene que ser anterior o igual a %s." msgstr "La fecha de llegada tiene que ser anterior o igual a %s."
#: pkg/booking/public.go:312 #: pkg/booking/public.go:319
msgid "Departure date can not be empty" msgid "Departure date can not be empty"
msgstr "No podéis dejar la fecha de partida en blanco." msgstr "No podéis dejar la fecha de partida en blanco."
#: pkg/booking/public.go:314 #: pkg/booking/public.go:321
#, c-format #, c-format
msgid "Departure date must be %s or after." msgid "Departure date must be %s or after."
msgstr "La fecha de partida tiene que igual o posterior a %s." msgstr "La fecha de partida tiene que igual o posterior a %s."
#: pkg/booking/public.go:315 #: pkg/booking/public.go:322
#, c-format #, c-format
msgid "Departure date must be %s or before." msgid "Departure date must be %s or before."
msgstr "La fecha de partida tiene que ser anterior o igual a %s." msgstr "La fecha de partida tiene que ser anterior o igual a %s."
#: pkg/booking/public.go:369 #: pkg/booking/public.go:380
#, c-format #, c-format
msgid "There can be at most %d guests in this accommodation." msgid "There can be at most %d guests in this accommodation."
msgstr "Solo puede haber como máximo %d invitados en este alojamiento." msgstr "Solo puede haber como máximo %d invitados en este alojamiento."
#: pkg/booking/public.go:389 #: pkg/booking/public.go:400
msgid "Number of adults can not be empty" msgid "Number of adults can not be empty"
msgstr "No podéis dejar el número de adultos blanco." msgstr "No podéis dejar el número de adultos blanco."
#: pkg/booking/public.go:390 #: pkg/booking/public.go:401
msgid "Number of adults must be an integer." msgid "Number of adults must be an integer."
msgstr "El número de adultos tiene que ser entero." msgstr "El número de adultos tiene que ser entero."
#: pkg/booking/public.go:391 #: pkg/booking/public.go:402
msgid "There must be at least one adult." msgid "There must be at least one adult."
msgstr "Tiene que haber como mínimo un adulto." msgstr "Tiene que haber como mínimo un adulto."
#: pkg/booking/public.go:394 #: pkg/booking/public.go:405
msgid "Number of teenagers can not be empty" msgid "Number of teenagers can not be empty"
msgstr "No podéis dejar el número de adolescentes en blanco." msgstr "No podéis dejar el número de adolescentes en blanco."
#: pkg/booking/public.go:395 #: pkg/booking/public.go:406
msgid "Number of teenagers must be an integer." msgid "Number of teenagers must be an integer."
msgstr "El número de adolescentes tiene que ser entero." msgstr "El número de adolescentes tiene que ser entero."
#: pkg/booking/public.go:396 #: pkg/booking/public.go:407
msgid "Number of teenagers can not be negative." msgid "Number of teenagers can not be negative."
msgstr "El número de adolescentes no puede ser negativo." msgstr "El número de adolescentes no puede ser negativo."
#: pkg/booking/public.go:399 #: pkg/booking/public.go:410
msgid "Number of children can not be empty" msgid "Number of children can not be empty"
msgstr "No podéis dejar el número de niños en blanco." msgstr "No podéis dejar el número de niños en blanco."
#: pkg/booking/public.go:400 #: pkg/booking/public.go:411
msgid "Number of children must be an integer." msgid "Number of children must be an integer."
msgstr "El número de niños tiene que ser entero." msgstr "El número de niños tiene que ser entero."
#: pkg/booking/public.go:401 #: pkg/booking/public.go:412
msgid "Number of children can not be negative." msgid "Number of children can not be negative."
msgstr "El número de niños no puede ser negativo." msgstr "El número de niños no puede ser negativo."
#: pkg/booking/public.go:404 #: pkg/booking/public.go:415
msgid "Number of dogs can not be empty" msgid "Number of dogs can not be empty"
msgstr "No podéis dejar el número de perros en blanco." msgstr "No podéis dejar el número de perros en blanco."
#: pkg/booking/public.go:405 #: pkg/booking/public.go:416
msgid "Number of dogs must be an integer." msgid "Number of dogs must be an integer."
msgstr "El número de perros tiene que ser entero." msgstr "El número de perros tiene que ser entero."
#: pkg/booking/public.go:406 #: pkg/booking/public.go:417
msgid "Number of dogs can not be negative." msgid "Number of dogs can not be negative."
msgstr "El número de perros no puede ser negativo." msgstr "El número de perros no puede ser negativo."
#: pkg/booking/public.go:477 #: pkg/booking/public.go:524
#, c-format #, c-format
msgid "%s can not be empty" msgid "%s can not be empty"
msgstr "No podéis dejar %s en blanco." msgstr "No podéis dejar %s en blanco."
#: pkg/booking/public.go:478 #: pkg/booking/public.go:525
#, c-format #, c-format
msgid "%s must be an integer." msgid "%s must be an integer."
msgstr "%s tiene que ser un número entero." msgstr "%s tiene que ser un número entero."
#: pkg/booking/public.go:479 #: pkg/booking/public.go:526
#, c-format #, c-format
msgid "%s must be %d or greater." msgid "%s must be %d or greater."
msgstr "%s tiene que ser como mínimo %d." msgstr "%s tiene que ser como mínimo %d."
#: pkg/booking/public.go:480 #: pkg/booking/public.go:527
#, c-format #, c-format
msgid "%s must be at most %d." msgid "%s must be at most %d."
msgstr "%s tiene que ser como máximo %d" msgstr "%s tiene que ser como máximo %d"
#: pkg/booking/public.go:539 #: pkg/booking/public.go:590
msgid "Town or village can not be empty." msgid "Town or village can not be empty."
msgstr "No podéis dejar la población en blanco." msgstr "No podéis dejar la población en blanco."
#: pkg/booking/public.go:554 #: pkg/booking/public.go:605
msgid "It is mandatory to agree to the reservation conditions." msgid "It is mandatory to agree to the reservation conditions."
msgstr "Es obligatorio aceptar las condiciones de reserva." msgstr "Es obligatorio aceptar las condiciones de reserva."

291
po/fr.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: camper\n" "Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-04-24 19:59+0200\n" "POT-Creation-Date: 2024-04-26 16:53+0200\n"
"PO-Revision-Date: 2024-02-06 10:05+0100\n" "PO-Revision-Date: 2024-02-06 10:05+0100\n"
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n" "Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
"Language-Team: French <traduc@traduc.org>\n" "Language-Team: French <traduc@traduc.org>\n"
@ -116,7 +116,7 @@ msgstr "Réservation"
#: web/templates/mail/payment/details.gotxt:16 #: web/templates/mail/payment/details.gotxt:16
#: web/templates/public/booking/fields.gohtml:14 #: web/templates/public/booking/fields.gohtml:14
#: web/templates/admin/payment/details.gohtml:74 #: web/templates/admin/payment/details.gohtml:74
#: web/templates/admin/booking/fields.gohtml:12 #: web/templates/admin/booking/fields.gohtml:13
msgctxt "title" msgctxt "title"
msgid "Accommodation" msgid "Accommodation"
msgstr "Hébergement" msgstr "Hébergement"
@ -155,7 +155,7 @@ msgstr "Non"
#: web/templates/public/campsite/dates.gohtml:4 #: web/templates/public/campsite/dates.gohtml:4
#: web/templates/public/booking/fields.gohtml:30 #: web/templates/public/booking/fields.gohtml:30
#: web/templates/admin/payment/details.gohtml:86 #: web/templates/admin/payment/details.gohtml:86
#: web/templates/admin/booking/fields.gohtml:31 #: web/templates/admin/booking/fields.gohtml:32
msgctxt "input" msgctxt "input"
msgid "Arrival date" msgid "Arrival date"
msgstr "Date darrivée" msgstr "Date darrivée"
@ -164,7 +164,7 @@ msgstr "Date darrivée"
#: web/templates/public/campsite/dates.gohtml:15 #: web/templates/public/campsite/dates.gohtml:15
#: web/templates/public/booking/fields.gohtml:41 #: web/templates/public/booking/fields.gohtml:41
#: web/templates/admin/payment/details.gohtml:90 #: web/templates/admin/payment/details.gohtml:90
#: web/templates/admin/booking/fields.gohtml:42 #: web/templates/admin/booking/fields.gohtml:43
msgctxt "input" msgctxt "input"
msgid "Departure date" msgid "Departure date"
msgstr "Date de depart" msgstr "Date de depart"
@ -178,7 +178,7 @@ msgstr "Nuits"
#: web/templates/mail/payment/details.gotxt:22 #: web/templates/mail/payment/details.gotxt:22
#: web/templates/public/booking/fields.gohtml:60 #: web/templates/public/booking/fields.gohtml:60
#: web/templates/admin/payment/details.gohtml:98 #: web/templates/admin/payment/details.gohtml:98
#: web/templates/admin/booking/fields.gohtml:92 #: web/templates/admin/booking/fields.gohtml:93
msgctxt "input" msgctxt "input"
msgid "Adults aged 17 or older" msgid "Adults aged 17 or older"
msgstr "Adultes âgés 17 ans ou plus" msgstr "Adultes âgés 17 ans ou plus"
@ -186,7 +186,7 @@ msgstr "Adultes âgés 17 ans ou plus"
#: web/templates/mail/payment/details.gotxt:23 #: web/templates/mail/payment/details.gotxt:23
#: web/templates/public/booking/fields.gohtml:71 #: web/templates/public/booking/fields.gohtml:71
#: web/templates/admin/payment/details.gohtml:102 #: web/templates/admin/payment/details.gohtml:102
#: web/templates/admin/booking/fields.gohtml:108 #: web/templates/admin/booking/fields.gohtml:109
msgctxt "input" msgctxt "input"
msgid "Teenagers from 11 to 16 years old" msgid "Teenagers from 11 to 16 years old"
msgstr "Adolescents de 11 à 16 ans" msgstr "Adolescents de 11 à 16 ans"
@ -194,7 +194,7 @@ msgstr "Adolescents de 11 à 16 ans"
#: web/templates/mail/payment/details.gotxt:24 #: web/templates/mail/payment/details.gotxt:24
#: web/templates/public/booking/fields.gohtml:82 #: web/templates/public/booking/fields.gohtml:82
#: web/templates/admin/payment/details.gohtml:106 #: web/templates/admin/payment/details.gohtml:106
#: web/templates/admin/booking/fields.gohtml:124 #: web/templates/admin/booking/fields.gohtml:125
msgctxt "input" msgctxt "input"
msgid "Children from 2 to 10 years old" msgid "Children from 2 to 10 years old"
msgstr "Enfants de 2 à 10 ans" msgstr "Enfants de 2 à 10 ans"
@ -202,14 +202,14 @@ msgstr "Enfants de 2 à 10 ans"
#: web/templates/mail/payment/details.gotxt:25 #: web/templates/mail/payment/details.gotxt:25
#: web/templates/public/booking/fields.gohtml:100 #: web/templates/public/booking/fields.gohtml:100
#: web/templates/admin/payment/details.gohtml:110 #: web/templates/admin/payment/details.gohtml:110
#: web/templates/admin/booking/fields.gohtml:139 #: web/templates/admin/booking/fields.gohtml:140
msgctxt "input" msgctxt "input"
msgid "Dogs" msgid "Dogs"
msgstr "Chiens" msgstr "Chiens"
#: web/templates/mail/payment/details.gotxt:26 #: web/templates/mail/payment/details.gotxt:26
#: web/templates/admin/payment/details.gohtml:114 #: web/templates/admin/payment/details.gohtml:114
#: web/templates/admin/booking/fields.gohtml:166 pkg/booking/cart.go:244 #: web/templates/admin/booking/fields.gohtml:167 pkg/booking/cart.go:242
msgctxt "cart" msgctxt "cart"
msgid "Tourist tax" msgid "Tourist tax"
msgstr "Taxe touristique" msgstr "Taxe touristique"
@ -239,7 +239,7 @@ msgstr "Options de type demplacement de camping"
#: web/templates/mail/payment/details.gotxt:39 #: web/templates/mail/payment/details.gotxt:39
#: web/templates/public/booking/fields.gohtml:146 #: web/templates/public/booking/fields.gohtml:146
#: web/templates/admin/payment/details.gohtml:140 #: web/templates/admin/payment/details.gohtml:140
#: web/templates/admin/booking/fields.gohtml:187 #: web/templates/admin/booking/fields.gohtml:188
msgctxt "title" msgctxt "title"
msgid "Customer Details" msgid "Customer Details"
msgstr "Détails du client" msgstr "Détails du client"
@ -247,7 +247,7 @@ msgstr "Détails du client"
#: web/templates/mail/payment/details.gotxt:41 #: web/templates/mail/payment/details.gotxt:41
#: web/templates/public/booking/fields.gohtml:149 #: web/templates/public/booking/fields.gohtml:149
#: web/templates/admin/payment/details.gohtml:143 #: web/templates/admin/payment/details.gohtml:143
#: web/templates/admin/booking/fields.gohtml:190 #: web/templates/admin/booking/fields.gohtml:191
msgctxt "input" msgctxt "input"
msgid "Full name" msgid "Full name"
msgstr "Nom et prénom" msgstr "Nom et prénom"
@ -930,7 +930,7 @@ msgstr "Menu"
#: web/templates/admin/campsite/type/option/index.gohtml:10 #: web/templates/admin/campsite/type/option/index.gohtml:10
#: web/templates/admin/campsite/type/index.gohtml:10 #: web/templates/admin/campsite/type/index.gohtml:10
#: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:95 #: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:95
#: web/templates/admin/booking/fields.gohtml:265 #: web/templates/admin/booking/fields.gohtml:266
msgctxt "title" msgctxt "title"
msgid "Campsites" msgid "Campsites"
msgstr "Locatifs" msgstr "Locatifs"
@ -978,6 +978,7 @@ msgid "Booking Period"
msgstr "Période de réservation" msgstr "Période de réservation"
#: web/templates/public/booking/fields.gohtml:56 #: web/templates/public/booking/fields.gohtml:56
#: web/templates/admin/booking/checkin.gohtml:20
msgctxt "title" msgctxt "title"
msgid "Guests" msgid "Guests"
msgstr "Personnes logeant" msgstr "Personnes logeant"
@ -987,18 +988,18 @@ msgid "Note: Due to guest capacity, we have added more accommodations to the boo
msgstr "Remarque : En raison de la capacité daccueils, nous avons ajouté dautres hébergements à la réservation, mais nous <strong>ne pouvons</strong> garantir quils seront côte à côte." msgstr "Remarque : En raison de la capacité daccueils, nous avons ajouté dautres hébergements à la réservation, mais nous <strong>ne pouvons</strong> garantir quils seront côte à côte."
#: web/templates/public/booking/fields.gohtml:109 #: web/templates/public/booking/fields.gohtml:109
#: web/templates/admin/booking/fields.gohtml:178 #: web/templates/admin/booking/fields.gohtml:179
msgid "Note: This accommodation does <strong>not</strong> allow dogs." msgid "Note: This accommodation does <strong>not</strong> allow dogs."
msgstr "Remarque : Dans cet hébergement les chiens <strong>ne</strong> sont pas acceptés." msgstr "Remarque : Dans cet hébergement les chiens <strong>ne</strong> sont pas acceptés."
#: web/templates/public/booking/fields.gohtml:121 #: web/templates/public/booking/fields.gohtml:121
#: web/templates/admin/booking/fields.gohtml:55 #: web/templates/admin/booking/fields.gohtml:56
msgctxt "input" msgctxt "input"
msgid "Area preferences (optional)" msgid "Area preferences (optional)"
msgstr "Préférences de zone (facultatif)" msgstr "Préférences de zone (facultatif)"
#: web/templates/public/booking/fields.gohtml:123 #: web/templates/public/booking/fields.gohtml:123
#: web/templates/admin/booking/fields.gohtml:59 #: web/templates/admin/booking/fields.gohtml:60
msgid "Campground map" msgid "Campground map"
msgstr "Plan du camping" msgstr "Plan du camping"
@ -1008,12 +1009,13 @@ msgid "Town or village"
msgstr "Ville" msgstr "Ville"
#: web/templates/public/booking/fields.gohtml:193 #: web/templates/public/booking/fields.gohtml:193
#: web/templates/admin/booking/fields.gohtml:203 #: web/templates/admin/booking/fields.gohtml:204
#: web/templates/admin/booking/guest.gohtml:109
msgid "Choose a country" msgid "Choose a country"
msgstr "Choisissez un pays" msgstr "Choisissez un pays"
#: web/templates/public/booking/fields.gohtml:247 #: web/templates/public/booking/fields.gohtml:247
#: web/templates/admin/booking/fields.gohtml:258 #: web/templates/admin/booking/fields.gohtml:259
msgctxt "input" msgctxt "input"
msgid "ACSI card? (optional)" msgid "ACSI card? (optional)"
msgstr "Carte ACSI ? (facultatif)" msgstr "Carte ACSI ? (facultatif)"
@ -1098,8 +1100,8 @@ msgid "Down payment"
msgstr "Acompte" msgstr "Acompte"
#: web/templates/admin/payment/index.gohtml:24 #: web/templates/admin/payment/index.gohtml:24
#: web/templates/admin/booking/fields.gohtml:74 #: web/templates/admin/booking/fields.gohtml:75
#: web/templates/admin/booking/fields.gohtml:172 #: web/templates/admin/booking/fields.gohtml:173
msgctxt "header" msgctxt "header"
msgid "Total" msgid "Total"
msgstr "Totale" msgstr "Totale"
@ -1194,7 +1196,7 @@ msgstr "Contenu"
#: web/templates/admin/amenity/form.gohtml:91 #: web/templates/admin/amenity/form.gohtml:91
#: web/templates/admin/home/index.gohtml:34 #: web/templates/admin/home/index.gohtml:34
#: web/templates/admin/media/form.gohtml:39 #: web/templates/admin/media/form.gohtml:39
#: web/templates/admin/booking/fields.gohtml:272 #: web/templates/admin/booking/form.gohtml:45
msgctxt "action" msgctxt "action"
msgid "Update" msgid "Update"
msgstr "Mettre à jour" msgstr "Mettre à jour"
@ -1214,7 +1216,7 @@ msgstr "Mettre à jour"
#: web/templates/admin/amenity/feature/form.gohtml:67 #: web/templates/admin/amenity/feature/form.gohtml:67
#: web/templates/admin/amenity/carousel/form.gohtml:52 #: web/templates/admin/amenity/carousel/form.gohtml:52
#: web/templates/admin/amenity/form.gohtml:93 #: web/templates/admin/amenity/form.gohtml:93
#: web/templates/admin/booking/fields.gohtml:274 #: web/templates/admin/booking/form.gohtml:47
msgctxt "action" msgctxt "action"
msgid "Add" msgid "Add"
msgstr "Ajouter" msgstr "Ajouter"
@ -2161,7 +2163,7 @@ msgid "Add Amenity"
msgstr "Ajouter un installation" msgstr "Ajouter un installation"
#: web/templates/admin/amenity/index.gohtml:20 #: web/templates/admin/amenity/index.gohtml:20
#: web/templates/admin/booking/grid.gohtml:13 #: web/templates/admin/booking/grid.gohtml:15
msgctxt "header" msgctxt "header"
msgid "Label" msgid "Label"
msgstr "Label" msgstr "Label"
@ -2204,7 +2206,8 @@ msgid "Logout"
msgstr "Déconnexion" msgstr "Déconnexion"
#: web/templates/admin/layout.gohtml:92 #: web/templates/admin/layout.gohtml:92
#: web/templates/admin/booking/form.gohtml:15 #: web/templates/admin/booking/form.gohtml:19
#: web/templates/admin/booking/checkin.gohtml:10
#: web/templates/admin/booking/index.gohtml:6 #: web/templates/admin/booking/index.gohtml:6
#: web/templates/admin/booking/index.gohtml:16 #: web/templates/admin/booking/index.gohtml:16
msgctxt "title" msgctxt "title"
@ -2312,51 +2315,53 @@ msgctxt "title"
msgid "Upload Media" msgid "Upload Media"
msgstr "Envoyer un fichier" msgstr "Envoyer un fichier"
#: web/templates/admin/booking/fields.gohtml:18 #: web/templates/admin/booking/fields.gohtml:19
msgid "Choose an accommodation" msgid "Choose an accommodation"
msgstr "Choisissez un hébergement" msgstr "Choisissez un hébergement"
#: web/templates/admin/booking/fields.gohtml:72 #: web/templates/admin/booking/fields.gohtml:73
msgctxt "header" msgctxt "header"
msgid "Units" msgid "Units"
msgstr "Unités" msgstr "Unités"
#: web/templates/admin/booking/fields.gohtml:73 #: web/templates/admin/booking/fields.gohtml:74
msgctxt "header" msgctxt "header"
msgid "Decription" msgid "Decription"
msgstr "Description" msgstr "Description"
#: web/templates/admin/booking/fields.gohtml:80 pkg/booking/cart.go:234 #: web/templates/admin/booking/fields.gohtml:81 pkg/booking/cart.go:232
msgctxt "cart" msgctxt "cart"
msgid "Night" msgid "Night"
msgstr "Nuit" msgstr "Nuit"
#: web/templates/admin/booking/fields.gohtml:199 #: web/templates/admin/booking/fields.gohtml:200
msgctxt "input" msgctxt "input"
msgid "Country (optional)" msgid "Country (optional)"
msgstr "Pays (facultatif)" msgstr "Pays (facultatif)"
#: web/templates/admin/booking/fields.gohtml:211 #: web/templates/admin/booking/fields.gohtml:212
#: web/templates/admin/booking/guest.gohtml:128
msgctxt "input" msgctxt "input"
msgid "Address (optional)" msgid "Address (optional)"
msgstr "Adresse (facultatif)" msgstr "Adresse (facultatif)"
#: web/templates/admin/booking/fields.gohtml:220 #: web/templates/admin/booking/fields.gohtml:221
msgctxt "input" msgctxt "input"
msgid "Postcode (optional)" msgid "Postcode (optional)"
msgstr "Code postal (facultatif)" msgstr "Code postal (facultatif)"
#: web/templates/admin/booking/fields.gohtml:229 #: web/templates/admin/booking/fields.gohtml:230
msgctxt "input" msgctxt "input"
msgid "Town or village (optional)" msgid "Town or village (optional)"
msgstr "Ville (facultatif)" msgstr "Ville (facultatif)"
#: web/templates/admin/booking/fields.gohtml:238 #: web/templates/admin/booking/fields.gohtml:239
msgctxt "input" msgctxt "input"
msgid "Email (optional)" msgid "Email (optional)"
msgstr "E-mail (facultatif)" msgstr "E-mail (facultatif)"
#: web/templates/admin/booking/fields.gohtml:247 #: web/templates/admin/booking/fields.gohtml:248
#: web/templates/admin/booking/guest.gohtml:117
msgctxt "input" msgctxt "input"
msgid "Phone (optional)" msgid "Phone (optional)"
msgstr "Téléphone (facultatif)" msgstr "Téléphone (facultatif)"
@ -2371,6 +2376,31 @@ msgctxt "title"
msgid "New Booking" msgid "New Booking"
msgstr "Nouvelle réservation" msgstr "Nouvelle réservation"
#: web/templates/admin/booking/form.gohtml:25
msgctxt "action"
msgid "Check-in Booking"
msgstr "Enregistrer réservation"
#: web/templates/admin/booking/checkin.gohtml:6
msgctxt "title"
msgid "Check-in Booking"
msgstr "Enregistrement de la réservation"
#: web/templates/admin/booking/checkin.gohtml:15
msgctxt "action"
msgid "Edit Booking"
msgstr "Modifier la réservation"
#: web/templates/admin/booking/checkin.gohtml:26
msgctxt "action"
msgid "Check-in"
msgstr "Enregitrer"
#: web/templates/admin/booking/checkin.gohtml:31
msgctxt "action"
msgid "Add another guest"
msgstr "Ajouter un autre invité"
#: web/templates/admin/booking/index.gohtml:14 #: web/templates/admin/booking/index.gohtml:14
msgctxt "action" msgctxt "action"
msgid "Add Booking" msgid "Add Booking"
@ -2400,6 +2430,64 @@ msgstr "Nom du titulaire"
msgid "No booking found." msgid "No booking found."
msgstr "Aucune réservation trouvée." msgstr "Aucune réservation trouvée."
#: web/templates/admin/booking/guest.gohtml:5
msgctxt "action"
msgid "Remove"
msgstr "Retirer"
#: web/templates/admin/booking/guest.gohtml:8
msgctxt "input"
msgid "ID document number"
msgstr "Numéro de document didentité"
#: web/templates/admin/booking/guest.gohtml:20
msgctxt "input"
msgid "ID document type"
msgstr "Type de document didentité"
#: web/templates/admin/booking/guest.gohtml:25
msgid "Choose an ID document type"
msgstr "Choisissez un type de document didentité"
#: web/templates/admin/booking/guest.gohtml:33
msgctxt "input"
msgid "ID document issue date (if any)"
msgstr "Date de délivrance du document didentité (si j'en ai)"
#: web/templates/admin/booking/guest.gohtml:44
msgctxt "input"
msgid "First surname"
msgstr "Premier nom"
#: web/templates/admin/booking/guest.gohtml:56
msgctxt "input"
msgid "Second surname (if has one)"
msgstr "Deuxième nom"
#: web/templates/admin/booking/guest.gohtml:67
msgctxt "input"
msgid "Given name"
msgstr "Prénom"
#: web/templates/admin/booking/guest.gohtml:79
msgctxt "input"
msgid "Sex"
msgstr "Sexe"
#: web/templates/admin/booking/guest.gohtml:84
msgid "Choose a sex"
msgstr "Choisissez un sexe"
#: web/templates/admin/booking/guest.gohtml:92
msgctxt "input"
msgid "Birthdate"
msgstr "Date de naissance"
#: web/templates/admin/booking/guest.gohtml:104
msgctxt "input"
msgid "Nationality"
msgstr "Nationalité"
#: pkg/payment/settings.go:37 #: pkg/payment/settings.go:37
msgctxt "redsys environment" msgctxt "redsys environment"
msgid "Test" msgid "Test"
@ -2501,12 +2589,12 @@ msgid "Slide image must be an image media type."
msgstr "Limage de la diapositive doit être de type média dimage." msgstr "Limage de la diapositive doit être de type média dimage."
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:224 #: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:224
#: pkg/booking/public.go:545 #: pkg/booking/public.go:596
msgid "Email can not be empty." msgid "Email can not be empty."
msgstr "Le-mail ne peut pas être vide." msgstr "Le-mail ne peut pas être vide."
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:225 #: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:225
#: pkg/booking/admin.go:316 pkg/booking/public.go:546 #: pkg/booking/admin.go:437 pkg/booking/public.go:597
msgid "This email is not valid. It should be like name@domain.com." msgid "This email is not valid. It should be like name@domain.com."
msgstr "Cette adresse e-mail nest pas valide. Il devrait en être name@domain.com." msgstr "Cette adresse e-mail nest pas valide. Il devrait en être name@domain.com."
@ -2717,8 +2805,8 @@ msgctxt "header"
msgid "Children (aged 2 to 10)" msgid "Children (aged 2 to 10)"
msgstr "Enfants (de 2 à 10 anys)" msgstr "Enfants (de 2 à 10 anys)"
#: pkg/campsite/admin.go:280 pkg/booking/admin.go:292 pkg/booking/public.go:173 #: pkg/campsite/admin.go:280 pkg/booking/admin.go:413 pkg/booking/public.go:177
#: pkg/booking/public.go:228 #: pkg/booking/public.go:232
msgid "Selected campsite type is not valid." msgid "Selected campsite type is not valid."
msgstr "Le type demplacement sélectionné nest pas valide." msgstr "Le type demplacement sélectionné nest pas valide."
@ -2814,7 +2902,8 @@ msgstr "Laddresse du lien ne peut pas être vide."
msgid "This web address is not valid. It should be like https://domain.com/." msgid "This web address is not valid. It should be like https://domain.com/."
msgstr "Cette adresse web nest pas valide. Il devrait en être https://domain.com/." msgstr "Cette adresse web nest pas valide. Il devrait en être https://domain.com/."
#: pkg/company/admin.go:207 pkg/booking/public.go:530 #: pkg/company/admin.go:207 pkg/booking/checkin.go:301
#: pkg/booking/public.go:581
msgid "Selected country is not valid." msgid "Selected country is not valid."
msgstr "Le pays sélectionné nest pas valide." msgstr "Le pays sélectionné nest pas valide."
@ -2834,15 +2923,16 @@ msgstr "Le numéro de TVA ne peut pas être vide."
msgid "This VAT number is not valid." msgid "This VAT number is not valid."
msgstr "Ce numéro de TVA nest pas valide." msgstr "Ce numéro de TVA nest pas valide."
#: pkg/company/admin.go:219 pkg/booking/public.go:548 #: pkg/company/admin.go:219 pkg/booking/public.go:599
msgid "Phone can not be empty." msgid "Phone can not be empty."
msgstr "Le téléphone ne peut pas être vide." msgstr "Le téléphone ne peut pas être vide."
#: pkg/company/admin.go:220 pkg/booking/admin.go:321 pkg/booking/public.go:549 #: pkg/company/admin.go:220 pkg/booking/checkin.go:305 pkg/booking/admin.go:442
#: pkg/booking/public.go:600
msgid "This phone number is not valid." msgid "This phone number is not valid."
msgstr "Ce numéro de téléphone nest pas valide." msgstr "Ce numéro de téléphone nest pas valide."
#: pkg/company/admin.go:230 pkg/booking/public.go:538 #: pkg/company/admin.go:230 pkg/booking/public.go:589
msgid "Address can not be empty." msgid "Address can not be empty."
msgstr "Ladresse ne peut pas être vide." msgstr "Ladresse ne peut pas être vide."
@ -2854,11 +2944,11 @@ msgstr "La ville ne peut pas être vide."
msgid "Province can not be empty." msgid "Province can not be empty."
msgstr "La province ne peut pas être vide." msgstr "La province ne peut pas être vide."
#: pkg/company/admin.go:233 pkg/booking/public.go:540 #: pkg/company/admin.go:233 pkg/booking/public.go:591
msgid "Postcode can not be empty." msgid "Postcode can not be empty."
msgstr "Le code postal ne peut pas être vide." msgstr "Le code postal ne peut pas être vide."
#: pkg/company/admin.go:234 pkg/booking/admin.go:311 pkg/booking/public.go:541 #: pkg/company/admin.go:234 pkg/booking/admin.go:432 pkg/booking/public.go:592
msgid "This postcode is not valid." msgid "This postcode is not valid."
msgstr "Ce code postal nest pas valide." msgstr "Ce code postal nest pas valide."
@ -2910,169 +3000,202 @@ msgstr "Le fichier téléchargé ne peut pas être vide."
msgid "Filename can not be empty." msgid "Filename can not be empty."
msgstr "Le nom de fichier ne peut pas être vide." msgstr "Le nom de fichier ne peut pas être vide."
#: pkg/booking/cart.go:235 #: pkg/booking/checkin.go:285
msgid "Selected ID document type is not valid."
msgstr "Le type de document didentité sélectionné nest pas valide."
#: pkg/booking/checkin.go:286
msgid "ID document number can not be empty."
msgstr "Le numéro de documento didentité ne peut pas être vide."
#: pkg/booking/checkin.go:288
msgid "ID document issue date must be a valid date."
msgstr "La date de délivrance du document didentité doit être une date valide."
#: pkg/booking/checkin.go:289
msgid "ID document issue date must be in the past."
msgstr "La ate de délivrance du document didentité doit être du passé."
#: pkg/booking/checkin.go:292 pkg/booking/checkin.go:293
#: pkg/booking/admin.go:425 pkg/booking/public.go:585
msgid "Full name can not be empty."
msgstr "Le nom complet ne peut pas être vide."
#: pkg/booking/checkin.go:294
msgid "Selected sex is not valid."
msgstr "Le sexe sélectionné nest pas valide."
#: pkg/booking/checkin.go:295
msgid "Birthdate can not be empty"
msgstr "La date de naissance ne peut pas être vide."
#: pkg/booking/checkin.go:296
msgid "Birthdate must be a valid date."
msgstr "La date de naissance doit être une date valide."
#: pkg/booking/checkin.go:297
msgid "Birthdate must be in the past."
msgstr "La date de naissance doit être du passé."
#: pkg/booking/cart.go:233
msgctxt "cart" msgctxt "cart"
msgid "Adult" msgid "Adult"
msgstr "Adulte" msgstr "Adulte"
#: pkg/booking/cart.go:236 #: pkg/booking/cart.go:234
msgctxt "cart" msgctxt "cart"
msgid "Teenager" msgid "Teenager"
msgstr "Adolescent" msgstr "Adolescent"
#: pkg/booking/cart.go:237 #: pkg/booking/cart.go:235
msgctxt "cart" msgctxt "cart"
msgid "Child" msgid "Child"
msgstr "Enfant" msgstr "Enfant"
#: pkg/booking/cart.go:238 #: pkg/booking/cart.go:236
msgctxt "cart" msgctxt "cart"
msgid "Dog" msgid "Dog"
msgstr "Chien" msgstr "Chien"
#: pkg/booking/admin.go:144 #: pkg/booking/admin.go:217
msgctxt "filename" msgctxt "filename"
msgid "bookings.ods" msgid "bookings.ods"
msgstr "reservations.ods" msgstr "reservations.ods"
#: pkg/booking/admin.go:304 pkg/booking/public.go:534 #: pkg/booking/admin.go:426 pkg/booking/public.go:586
msgid "Full name can not be empty."
msgstr "Le nom complet ne peut pas être vide."
#: pkg/booking/admin.go:305 pkg/booking/public.go:535
msgid "Full name must have at least one letter." msgid "Full name must have at least one letter."
msgstr "Le nom complet doit comporter au moins une lettre." msgstr "Le nom complet doit comporter au moins une lettre."
#: pkg/booking/admin.go:310 #: pkg/booking/admin.go:431
msgid "Country can not be empty to validate the postcode." msgid "Country can not be empty to validate the postcode."
msgstr "Le pays ne peut pas être vide pour valider le code postal." msgstr "Le pays ne peut pas être vide pour valider le code postal."
#: pkg/booking/admin.go:320 #: pkg/booking/admin.go:441
msgid "Country can not be empty to validate the phone." msgid "Country can not be empty to validate the phone."
msgstr "Le pays ne peut pas être vide pour valider le téléphone." msgstr "Le pays ne peut pas être vide pour valider le téléphone."
#: pkg/booking/admin.go:327 #: pkg/booking/admin.go:448
msgid "You must select at least one accommodation." msgid "You must select at least one accommodation."
msgstr "Vous devez sélectionner au moins un hébergement." msgstr "Vous devez sélectionner au moins un hébergement."
#: pkg/booking/admin.go:333 #: pkg/booking/admin.go:454
msgid "The selected accommodations have no available openings in the requested dates." msgid "The selected accommodations have no available openings in the requested dates."
msgstr "Les hébergements sélectionnés nont pas de disponibilités aux dates demandées." msgstr "Les hébergements sélectionnés nont pas de disponibilités aux dates demandées."
#: pkg/booking/public.go:277 pkg/booking/public.go:306 #: pkg/booking/public.go:284 pkg/booking/public.go:313
msgid "Arrival date must be a valid date." msgid "Arrival date must be a valid date."
msgstr "La date darrivée doit être une date valide." msgstr "La date darrivée doit être une date valide."
#: pkg/booking/public.go:291 pkg/booking/public.go:313 #: pkg/booking/public.go:298 pkg/booking/public.go:320
msgid "Departure date must be a valid date." msgid "Departure date must be a valid date."
msgstr "La date de départ doit être une date valide." msgstr "La date de départ doit être une date valide."
#: pkg/booking/public.go:305 #: pkg/booking/public.go:312
msgid "Arrival date can not be empty" msgid "Arrival date can not be empty"
msgstr "La date darrivée ne peut pas être vide" msgstr "La date darrivée ne peut pas être vide"
#: pkg/booking/public.go:307 #: pkg/booking/public.go:314
#, c-format #, c-format
msgid "Arrival date must be %s or after." msgid "Arrival date must be %s or after."
msgstr "La date darrivée doit être égale ou postérieure à %s." msgstr "La date darrivée doit être égale ou postérieure à %s."
#: pkg/booking/public.go:308 #: pkg/booking/public.go:315
#, c-format #, c-format
msgid "Arrival date must be %s or before." msgid "Arrival date must be %s or before."
msgstr "La date darrivée doit être antérieure ou égale à %s." msgstr "La date darrivée doit être antérieure ou égale à %s."
#: pkg/booking/public.go:312 #: pkg/booking/public.go:319
msgid "Departure date can not be empty" msgid "Departure date can not be empty"
msgstr "La date de départ ne peut pas être vide" msgstr "La date de départ ne peut pas être vide"
#: pkg/booking/public.go:314 #: pkg/booking/public.go:321
#, c-format #, c-format
msgid "Departure date must be %s or after." msgid "Departure date must be %s or after."
msgstr "La date de départ doit être égale ou postérieure à %s." msgstr "La date de départ doit être égale ou postérieure à %s."
#: pkg/booking/public.go:315 #: pkg/booking/public.go:322
#, c-format #, c-format
msgid "Departure date must be %s or before." msgid "Departure date must be %s or before."
msgstr "La date de départ doit être antérieure ou égale à %s." msgstr "La date de départ doit être antérieure ou égale à %s."
#: pkg/booking/public.go:369 #: pkg/booking/public.go:380
#, c-format #, c-format
msgid "There can be at most %d guests in this accommodation." msgid "There can be at most %d guests in this accommodation."
msgstr "Il peut y avoir au plus %d invités dans cet hébergement." msgstr "Il peut y avoir au plus %d invités dans cet hébergement."
#: pkg/booking/public.go:389 #: pkg/booking/public.go:400
msgid "Number of adults can not be empty" msgid "Number of adults can not be empty"
msgstr "Le nombre dadultes ne peut pas être vide." msgstr "Le nombre dadultes ne peut pas être vide."
#: pkg/booking/public.go:390 #: pkg/booking/public.go:401
msgid "Number of adults must be an integer." msgid "Number of adults must be an integer."
msgstr "Le nombre dadultes doit être un entier." msgstr "Le nombre dadultes doit être un entier."
#: pkg/booking/public.go:391 #: pkg/booking/public.go:402
msgid "There must be at least one adult." msgid "There must be at least one adult."
msgstr "Il doit y avoir au moins un adulte." msgstr "Il doit y avoir au moins un adulte."
#: pkg/booking/public.go:394 #: pkg/booking/public.go:405
msgid "Number of teenagers can not be empty" msgid "Number of teenagers can not be empty"
msgstr "Le nombre dadolescents ne peut pas être vide." msgstr "Le nombre dadolescents ne peut pas être vide."
#: pkg/booking/public.go:395 #: pkg/booking/public.go:406
msgid "Number of teenagers must be an integer." msgid "Number of teenagers must be an integer."
msgstr "Le nombre dadolescents doit être un entier." msgstr "Le nombre dadolescents doit être un entier."
#: pkg/booking/public.go:396 #: pkg/booking/public.go:407
msgid "Number of teenagers can not be negative." msgid "Number of teenagers can not be negative."
msgstr "Le nombre dadolescents ne peut pas être négatif." msgstr "Le nombre dadolescents ne peut pas être négatif."
#: pkg/booking/public.go:399 #: pkg/booking/public.go:410
msgid "Number of children can not be empty" msgid "Number of children can not be empty"
msgstr "Le nombre denfants ne peut pas être vide." msgstr "Le nombre denfants ne peut pas être vide."
#: pkg/booking/public.go:400 #: pkg/booking/public.go:411
msgid "Number of children must be an integer." msgid "Number of children must be an integer."
msgstr "Le nombre denfants doit être un entier." msgstr "Le nombre denfants doit être un entier."
#: pkg/booking/public.go:401 #: pkg/booking/public.go:412
msgid "Number of children can not be negative." msgid "Number of children can not be negative."
msgstr "Le nombre denfants ne peut pas être négatif." msgstr "Le nombre denfants ne peut pas être négatif."
#: pkg/booking/public.go:404 #: pkg/booking/public.go:415
msgid "Number of dogs can not be empty" msgid "Number of dogs can not be empty"
msgstr "Le nombre de chiens ne peut pas être vide." msgstr "Le nombre de chiens ne peut pas être vide."
#: pkg/booking/public.go:405 #: pkg/booking/public.go:416
msgid "Number of dogs must be an integer." msgid "Number of dogs must be an integer."
msgstr "Le nombre de chiens nuits être un entier." msgstr "Le nombre de chiens nuits être un entier."
#: pkg/booking/public.go:406 #: pkg/booking/public.go:417
msgid "Number of dogs can not be negative." msgid "Number of dogs can not be negative."
msgstr "Le nombre de chiens ne peut pas être négatif." msgstr "Le nombre de chiens ne peut pas être négatif."
#: pkg/booking/public.go:477 #: pkg/booking/public.go:524
#, c-format #, c-format
msgid "%s can not be empty" msgid "%s can not be empty"
msgstr "%s ne peut pas être vide" msgstr "%s ne peut pas être vide"
#: pkg/booking/public.go:478 #: pkg/booking/public.go:525
#, c-format #, c-format
msgid "%s must be an integer." msgid "%s must be an integer."
msgstr "%s doit être un entier." msgstr "%s doit être un entier."
#: pkg/booking/public.go:479 #: pkg/booking/public.go:526
#, c-format #, c-format
msgid "%s must be %d or greater." msgid "%s must be %d or greater."
msgstr "%s doit être %d ou plus." msgstr "%s doit être %d ou plus."
#: pkg/booking/public.go:480 #: pkg/booking/public.go:527
#, c-format #, c-format
msgid "%s must be at most %d." msgid "%s must be at most %d."
msgstr "%s doit être tout au plus %d." msgstr "%s doit être tout au plus %d."
#: pkg/booking/public.go:539 #: pkg/booking/public.go:590
msgid "Town or village can not be empty." msgid "Town or village can not be empty."
msgstr "La ville ne peut pas être vide." msgstr "La ville ne peut pas être vide."
#: pkg/booking/public.go:554 #: pkg/booking/public.go:605
msgid "It is mandatory to agree to the reservation conditions." msgid "It is mandatory to agree to the reservation conditions."
msgstr "Il est obligatoire daccepter les conditions de réservation." msgstr "Il est obligatoire daccepter les conditions de réservation."

View File

@ -0,0 +1,10 @@
-- Revert camper:available_id_document_types from pg
begin;
set search_path to camper;
delete from id_document_type_i18n;
delete from id_document_type;
commit;

View File

@ -0,0 +1,10 @@
-- Revert camper:available_sexes from pg
begin;
set search_path to camper;
delete from sex_i18n;
delete from sex;
commit;

7
revert/booking_guest.sql Normal file
View File

@ -0,0 +1,7 @@
-- Revert camper:booking_guest from pg
begin;
drop table if exists camper.booking_guest;
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:check_in_guests from pg
begin;
drop function if exists camper.check_in_guests(integer, camper.checked_in_guest[]);
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:checked_in_guest from pg
begin;
drop type if exists camper.checked_in_guest;
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:id_document_type from pg
begin;
drop table if exists camper.id_document_type;
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:id_document_type_i18n from pg
begin;
drop table if exists camper.id_document_type_i18n;
commit;

7
revert/sex.sql Normal file
View File

@ -0,0 +1,7 @@
-- Revert camper:sex from pg
begin;
drop table if exists camper.sex;
commit;

7
revert/sex_i18n.sql Normal file
View File

@ -0,0 +1,7 @@
-- Revert camper:sex_i18n from pg
begin;
drop table if exists camper.sex_i18n;
commit;

View File

@ -290,3 +290,12 @@ booking_option [roles schema_camper booking campsite_type_option positive_intege
add_booking_from_payment [roles schema_camper booking booking__payment_fields booking__stay booking_option payment payment__acsi_card payment_customer payment_option] 2024-04-24T11:23:22Z jordi fita mas <jordi@tandem.blog> # Add function to create a pre-booking from a payment add_booking_from_payment [roles schema_camper booking booking__payment_fields booking__stay booking_option payment payment__acsi_card payment_customer payment_option] 2024-04-24T11:23:22Z jordi fita mas <jordi@tandem.blog> # Add function to create a pre-booking from a payment
edit_booking [roles schema_camper booking booking__payment_fields booking__stay booking_campsite] 2024-04-24T16:27:10Z jordi fita mas <jordi@tandem.blog> # Add function to update a booking edit_booking [roles schema_camper booking booking__payment_fields booking__stay booking_campsite] 2024-04-24T16:27:10Z jordi fita mas <jordi@tandem.blog> # Add function to update a booking
edit_booking_from_payment [roles schema_camper booking booking__payment_fields booking__stay booking_option payment payment__acsi_card payment_option] 2024-04-25T17:18:41Z jordi fita mas <jordi@tandem.blog> # Add function to edit a booking from a payment edit_booking_from_payment [roles schema_camper booking booking__payment_fields booking__stay booking_option payment payment__acsi_card payment_option] 2024-04-25T17:18:41Z jordi fita mas <jordi@tandem.blog> # Add function to edit a booking from a payment
sex [roles schema_camper] 2024-04-25T22:02:27Z jordi fita mas <jordi@tandem.blog> # Add sex relation
sex_i18n [roles schema_camper sex language] 2024-04-25T22:06:21Z jordi fita mas <jordi@tandem.blog> # Add relation of sex translations
available_sexes [sex sex_i18n] 2024-04-25T22:09:27Z jordi fita mas <jordi@tandem.blog> # Add available sexes
id_document_type [roles schema_camper] 2024-04-25T22:26:47Z jordi fita mas <jordi@tandem.blog> # Add relation of identity document type
id_document_type_i18n [roles schema_camper id_document_type language] 2024-04-25T22:29:20Z jordi fita mas <jordi@tandem.blog> # Add relation for translations of ID document types
available_id_document_types [id_document_type id_document_type_i18n] 2024-04-25T22:32:05Z jordi fita mas <jordi@tandem.blog> # Add available ID document types
booking_guest [roles schema_camper booking sex id_document_type extension_pg_libphonenumber] 2024-04-26T09:40:17Z jordi fita mas <jordi@tandem.blog> # Add relation of booking guests
checked_in_guest [schema_camper] 2024-04-26T09:58:54Z jordi fita mas <jordi@tandem.blog> # Add type for checked-in guest
check_in_guests [roles schema_camper booking booking_guest checked_in_guest extension_pg_libphonenumber] 2024-04-26T10:31:53Z jordi fita mas <jordi@tandem.blog> # Add function to check-in guests

111
test/booking_guest.sql Normal file
View File

@ -0,0 +1,111 @@
-- Test booking_guest
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(78);
set search_path to camper, public;
select has_table('booking_guest');
select has_pk('booking_guest');
select col_is_unique('booking_guest', array['booking_id', 'id_document_type_id', 'id_document_number']);
select table_privs_are('booking_guest', 'guest', array[]::text[]);
select table_privs_are('booking_guest', 'employee', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
select table_privs_are('booking_guest', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
select table_privs_are('booking_guest', 'authenticator', array[]::text[]);
select has_column('booking_guest', 'booking_guest_id');
select col_is_pk('booking_guest', 'booking_guest_id');
select col_type_is('booking_guest', 'booking_guest_id', 'integer');
select col_not_null('booking_guest', 'booking_guest_id');
select col_hasnt_default('booking_guest', 'booking_guest_id');
select has_column('booking_guest', 'booking_id');
select col_is_fk('booking_guest', 'booking_id');
select fk_ok('booking_guest', 'booking_id', 'booking', 'booking_id');
select col_type_is('booking_guest', 'booking_id', 'integer');
select col_not_null('booking_guest', 'booking_id');
select col_hasnt_default('booking_guest', 'booking_id');
select has_column('booking_guest', 'id_document_type_id');
select col_is_fk('booking_guest', 'id_document_type_id');
select fk_ok('booking_guest', 'id_document_type_id', 'id_document_type', 'id_document_type_id');
select col_type_is('booking_guest', 'id_document_type_id', 'character varying(1)');
select col_not_null('booking_guest', 'id_document_type_id');
select col_hasnt_default('booking_guest', 'id_document_type_id');
select has_column('booking_guest', 'id_document_number');
select col_type_is('booking_guest', 'id_document_number', 'text');
select col_not_null('booking_guest', 'id_document_number');
select col_hasnt_default('booking_guest', 'id_document_number');
select has_column('booking_guest', 'id_document_issue_date');
select col_type_is('booking_guest', 'id_document_issue_date', 'date');
select col_is_null('booking_guest', 'id_document_issue_date');
select col_hasnt_default('booking_guest', 'id_document_issue_date');
select has_column('booking_guest', 'given_name');
select col_type_is('booking_guest', 'given_name', 'text');
select col_not_null('booking_guest', 'given_name');
select col_hasnt_default('booking_guest', 'given_name');
select has_column('booking_guest', 'first_surname');
select col_type_is('booking_guest', 'first_surname', 'text');
select col_not_null('booking_guest', 'first_surname');
select col_hasnt_default('booking_guest', 'first_surname');
select has_column('booking_guest', 'second_surname');
select col_type_is('booking_guest', 'second_surname', 'text');
select col_not_null('booking_guest', 'second_surname');
select col_hasnt_default('booking_guest', 'second_surname');
select has_column('booking_guest', 'sex_id');
select col_is_fk('booking_guest', 'sex_id');
select fk_ok('booking_guest', 'sex_id', 'sex', 'sex_id');
select col_type_is('booking_guest', 'sex_id', 'character varying(1)');
select col_not_null('booking_guest', 'sex_id');
select col_hasnt_default('booking_guest', 'sex_id');
select has_column('booking_guest', 'birthdate');
select col_type_is('booking_guest', 'birthdate', 'date');
select col_not_null('booking_guest', 'birthdate');
select col_hasnt_default('booking_guest', 'birthdate');
select has_column('booking_guest', 'country_code');
select col_is_fk('booking_guest', 'country_code');
select fk_ok('booking_guest', 'country_code', 'country', 'country_code');
select col_type_is('booking_guest', 'country_code', 'country_code');
select col_not_null('booking_guest', 'country_code');
select col_hasnt_default('booking_guest', 'country_code');
select has_column('booking_guest', 'phone');
select col_type_is('booking_guest', 'phone', 'packed_phone_number');
select col_is_null('booking_guest', 'phone');
select col_hasnt_default('booking_guest', 'phone');
select has_column('booking_guest', 'address');
select col_type_is('booking_guest', 'address', 'text');
select col_not_null('booking_guest', 'address');
select col_hasnt_default('booking_guest', 'address');
select has_column('booking_guest', 'created_at');
select col_type_is('booking_guest', 'created_at', 'timestamp with time zone');
select col_not_null('booking_guest', 'created_at');
select col_has_default('booking_guest', 'created_at');
select col_default_is('booking_guest', 'created_at', 'CURRENT_TIMESTAMP');
select has_column('booking_guest', 'updated_at');
select col_type_is('booking_guest', 'updated_at', 'timestamp with time zone');
select col_not_null('booking_guest', 'updated_at');
select col_has_default('booking_guest', 'updated_at');
select col_default_is('booking_guest', 'updated_at', 'CURRENT_TIMESTAMP');
select *
from finish();
rollback;

89
test/check_in_guests.sql Normal file
View File

@ -0,0 +1,89 @@
-- Test check_in_guests
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(13);
set search_path to camper, public;
select has_function('camper', 'check_in_guests', array['integer', 'checked_in_guest[]']);
select function_lang_is('camper', 'check_in_guests', array['integer', 'checked_in_guest[]'], 'sql');
select function_returns('camper', 'check_in_guests', array['integer', 'checked_in_guest[]'], 'void');
select isnt_definer('camper', 'check_in_guests', array['integer', 'checked_in_guest[]']);
select volatility_is('camper', 'check_in_guests', array['integer', 'checked_in_guest[]'], 'volatile');
select function_privs_are('camper', 'check_in_guests', array ['integer', 'checked_in_guest[]'], 'guest', array[]::text[]);
select function_privs_are('camper', 'check_in_guests', array ['integer', 'checked_in_guest[]'], 'employee', array['EXECUTE']);
select function_privs_are('camper', 'check_in_guests', array ['integer', 'checked_in_guest[]'], 'admin', array['EXECUTE']);
select function_privs_are('camper', 'check_in_guests', array ['integer', 'checked_in_guest[]'], 'authenticator', array[]::text[]);
set client_min_messages to warning;
truncate booking_guest cascade;
truncate booking cascade;
truncate campsite_type cascade;
truncate media cascade;
truncate media_content cascade;
truncate company cascade;
reset client_min_messages;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, tourist_tax_max_days, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 7, 'ES', 'EUR', 'ca')
;
insert into media_content (media_type, bytes)
values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};')
;
insert into media (media_id, company_id, original_filename, content_hash)
values (6, 2, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};'))
;
insert into campsite_type (campsite_type_id, company_id, name, media_id, max_campers, bookable_nights)
values (12, 2, 'Wooden lodge', 6, 7, '[1, 7]')
;
insert into booking (booking_id, company_id, campsite_type_id, holder_name, stay, acsi_card, currency_code, zone_preferences, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, booking_status)
values (14, 2, 12, 'Holder 2', daterange('2024-01-18', '2024-01-29'), false, 'EUR', '', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 'confirmed')
, (16, 2, 12, 'Holder 4', daterange('2024-01-28', '2024-01-29'), true, 'USD', 'None', 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'invoiced')
;
insert into booking_guest (booking_id, id_document_type_id, id_document_number, id_document_issue_date, given_name, first_surname, second_surname, sex_id, birthdate, country_code, phone, address, created_at, updated_at)
values (14, 'D', '4444444A', '2022-01-01', 'Given', 'First', 'Last', 'F', '1991-07-02', 'ES', '+32 977 977 977', 'Fake St., 123', '2023-03-03 03:03:03', '2023-03-03 03:03:03')
, (16, 'P', '123456-ABC', '2020-12-20', 'Mah', 'Name', '', 'M', '1980-03-31', 'JP', '123 123 123', 'Dunno', '2022-02-02 02:02:02', '2022-02-02 02:02:02')
;
select lives_ok(
$$ select check_in_guests(14, array[('C', 'UABCA', null, 'Jan-Michael', 'Vincent', '', 'M', '1944-07-15', 'US', '5673159097', 'One Rabbit Road'), ('D', '4444444A', '2021-02-02', 'Gibbon', 'Di', 'Luffy', 'M', '1981-09-25', 'GB', null, '')]::checked_in_guest[]) $$,
'Should be able to check-in guests for the first booking'
);
select lives_ok(
$$ select check_in_guests(16, array[('I', 'Huh?', '1999-09-09', 'Mayumi', 'Tanaka', '', 'F', '1955-01-15', 'JP', '5083262771', 'Somewhere')]::checked_in_guest[]) $$,
'Should be able to check-in guests for the second booking'
);
select bag_eq (
$$ select booking_id, booking_status from booking $$,
$$ values (14, 'checked-in')
, (16, 'invoiced')
$$,
'Should have updated the status if it was created or confirmed'
);
select bag_eq (
$$ select booking_id, id_document_type_id::text, id_document_number, id_document_issue_date::text, given_name, first_surname, second_surname, sex_id::text, birthdate::text, country_code::text, phone::text, address, created_at, updated_at from booking_guest $$,
$$ values (14, 'C', 'UABCA', null, 'Jan-Michael', 'Vincent', '', 'M', '1944-07-15', 'US', '+1 567-315-9097', 'One Rabbit Road', current_timestamp, current_timestamp)
, (14, 'D', '4444444A', '2021-02-02', 'Gibbon', 'Di', 'Luffy', 'M', '1981-09-25', 'GB', null, '', '2023-03-03 03:03:03', current_timestamp)
, (16, 'I', 'Huh?', '1999-09-09', 'Mayumi', 'Tanaka', '', 'F', '1955-01-15', 'JP', '+81 50-8326-2771', 'Somewhere', current_timestamp, current_timestamp)
$$,
'Should have updated guest information'
);
select *
from finish();
rollback;

30
test/checked_in_guest.sql Normal file
View File

@ -0,0 +1,30 @@
-- Test checked_in_guest
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(13);
set search_path to camper, public;
select has_composite('camper', 'checked_in_guest', 'Composite type camper.checked_in_guest should exist');
select columns_are('camper', 'checked_in_guest', array['id_document_type_id', 'id_document_number', 'id_document_issue_date', 'given_name', 'first_surname', 'second_surname', 'sex_id', 'birthdate', 'country_code', 'phone', 'address']);
select col_type_is('camper'::name, 'checked_in_guest'::name, 'id_document_type_id'::name, 'character varying(1)');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'id_document_number'::name, 'text');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'id_document_issue_date'::name, 'date');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'given_name'::name, 'text');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'first_surname'::name, 'text');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'second_surname'::name, 'text');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'sex_id'::name, 'character varying(1)');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'birthdate'::name, 'date');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'country_code'::name, 'country_code');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'phone'::name, 'text');
select col_type_is('camper'::name, 'checked_in_guest'::name, 'address'::name, 'text');
select *
from finish();
rollback;

35
test/id_document_type.sql Normal file
View File

@ -0,0 +1,35 @@
-- Test id_document_type
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(15);
set search_path to camper, public;
select has_table('id_document_type');
select has_pk('id_document_type');
select table_privs_are('id_document_type', 'guest', array[]::text[]);
select table_privs_are('id_document_type', 'employee', array['SELECT']);
select table_privs_are('id_document_type', 'admin', array['SELECT']);
select table_privs_are('id_document_type', 'authenticator', array[]::text[]);
select has_column('id_document_type', 'id_document_type_id');
select col_is_pk('id_document_type', 'id_document_type_id');
select col_type_is('id_document_type', 'id_document_type_id', 'character varying(1)');
select col_not_null('id_document_type', 'id_document_type_id');
select col_hasnt_default('id_document_type', 'id_document_type_id');
select has_column('id_document_type', 'name');
select col_type_is('id_document_type', 'name', 'text');
select col_not_null('id_document_type', 'name');
select col_hasnt_default('id_document_type', 'name');
select *
from finish();
rollback;

View File

@ -0,0 +1,44 @@
-- Test id_document_type_i18n
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(23);
set search_path to camper, public;
select has_table('id_document_type_i18n');
select has_pk('id_document_type_i18n');
select col_is_pk('id_document_type_i18n', array['id_document_type_id', 'lang_tag']);
select table_privs_are('id_document_type_i18n', 'guest', array[]::text[]);
select table_privs_are('id_document_type_i18n', 'employee', array['SELECT']);
select table_privs_are('id_document_type_i18n', 'admin', array['SELECT']);
select table_privs_are('id_document_type_i18n', 'authenticator', array[]::text[]);
select has_column('id_document_type_i18n', 'id_document_type_id');
select col_is_fk('id_document_type_i18n', 'id_document_type_id');
select fk_ok('id_document_type_i18n', 'id_document_type_id', 'id_document_type', 'id_document_type_id');
select col_type_is('id_document_type_i18n', 'id_document_type_id', 'character varying(1)');
select col_not_null('id_document_type_i18n', 'id_document_type_id');
select col_hasnt_default('id_document_type_i18n', 'id_document_type_id');
select has_column('id_document_type_i18n', 'lang_tag');
select col_is_fk('id_document_type_i18n', 'lang_tag');
select fk_ok('id_document_type_i18n', 'lang_tag', 'language', 'lang_tag');
select col_type_is('id_document_type_i18n', 'lang_tag', 'text');
select col_not_null('id_document_type_i18n', 'lang_tag');
select col_hasnt_default('id_document_type_i18n', 'lang_tag');
select has_column('id_document_type_i18n', 'name');
select col_type_is('id_document_type_i18n', 'name', 'text');
select col_not_null('id_document_type_i18n', 'name');
select col_hasnt_default('id_document_type_i18n', 'name');
select *
from finish();
rollback;

34
test/sex.sql Normal file
View File

@ -0,0 +1,34 @@
-- Test sex
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(15);
set search_path to camper, public;
select has_table('sex');
select has_pk('sex');
select table_privs_are('sex', 'guest', array[]::text[]);
select table_privs_are('sex', 'employee', array['SELECT']);
select table_privs_are('sex', 'admin', array['SELECT']);
select table_privs_are('sex', 'authenticator', array[]::text[]);
select has_column('sex', 'sex_id');
select col_is_pk('sex', 'sex_id');
select col_type_is('sex', 'sex_id', 'character varying(1)');
select col_not_null('sex', 'sex_id');
select col_hasnt_default('sex', 'sex_id');
select has_column('sex', 'name');
select col_type_is('sex', 'name', 'text');
select col_not_null('sex', 'name');
select col_hasnt_default('sex', 'name');
select *
from finish();
rollback;

44
test/sex_i18n.sql Normal file
View File

@ -0,0 +1,44 @@
-- Test sex_i18n
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(23);
set search_path to camper, public;
select has_table('sex_i18n');
select has_pk('sex_i18n');
select col_is_pk('sex_i18n', array['sex_id', 'lang_tag']);
select table_privs_are('sex_i18n', 'guest', array[]::text[]);
select table_privs_are('sex_i18n', 'employee', array['SELECT']);
select table_privs_are('sex_i18n', 'admin', array['SELECT']);
select table_privs_are('sex_i18n', 'authenticator', array[]::text[]);
select has_column('sex_i18n', 'sex_id');
select col_is_fk('sex_i18n', 'sex_id');
select fk_ok('sex_i18n', 'sex_id', 'sex', 'sex_id');
select col_type_is('sex_i18n', 'sex_id', 'character varying(1)');
select col_not_null('sex_i18n', 'sex_id');
select col_hasnt_default('sex_i18n', 'sex_id');
select has_column('sex_i18n', 'lang_tag');
select col_is_fk('sex_i18n', 'lang_tag');
select fk_ok('sex_i18n', 'lang_tag', 'language', 'lang_tag');
select col_type_is('sex_i18n', 'lang_tag', 'text');
select col_not_null('sex_i18n', 'lang_tag');
select col_hasnt_default('sex_i18n', 'lang_tag');
select has_column('sex_i18n', 'name');
select col_type_is('sex_i18n', 'name', 'text');
select col_not_null('sex_i18n', 'name');
select col_hasnt_default('sex_i18n', 'name');
select *
from finish();
rollback;

View File

@ -0,0 +1,35 @@
-- Verify camper:available_id_document_types on pg
begin;
set search_path to camper;
select 1 / count(*) from id_document_type where id_document_type_id = 'D' and name = 'DNI';
select 1 / count(*) from id_document_type where id_document_type_id = 'P' and name = 'Passport';
select 1 / count(*) from id_document_type where id_document_type_id = 'C' and name = 'Driving license';
select 1 / count(*) from id_document_type where id_document_type_id = 'I' and name = 'Identification document';
select 1 / count(*) from id_document_type where id_document_type_id = 'N' and name = 'Spanish residence permit';
select 1 / count(*) from id_document_type where id_document_type_id = 'X' and name = 'Residence permit from another Member State of the European Union';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'D' and lang_tag = 'ca' and name = 'DNI';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'P' and lang_tag = 'ca' and name = 'Passaport';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'C' and lang_tag = 'ca' and name = 'Permís de conduir';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'I' and lang_tag = 'ca' and name = 'Carta o document didentitat';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'N' and lang_tag = 'ca' and name = 'Permís de residència espanyol';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'X' and lang_tag = 'ca' and name = 'Permís de residència dun altre estat membre de la Unió Europea';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'D' and lang_tag = 'es' and name = 'DNI';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'P' and lang_tag = 'es' and name = 'Pasaporte';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'C' and lang_tag = 'es' and name = 'Permiso de conducir';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'I' and lang_tag = 'es' and name = 'Carta o documento de identidad';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'N' and lang_tag = 'es' and name = 'Permiso de residencia español';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'X' and lang_tag = 'es' and name = 'Permiso de residencia de otro Estado Miembro de la Unión Europea';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'D' and lang_tag = 'fr' and name = 'DNI';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'P' and lang_tag = 'fr' and name = 'Passeport';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'C' and lang_tag = 'fr' and name = 'Permis de conduire';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'I' and lang_tag = 'fr' and name = 'Carte didentité';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'N' and lang_tag = 'fr' and name = 'Permis de séjour espagnol';
select 1 / count(*) from id_document_type_i18n where id_document_type_id = 'X' and lang_tag = 'fr' and name = 'Titre de séjour dun autre État membre de lUnion européenne';
rollback;

View File

@ -0,0 +1,19 @@
-- Verify camper:available_sexes on pg
begin;
set search_path to camper;
select 1 / count(*) from sex where sex_id = 'F' and name = 'Female';
select 1 / count(*) from sex where sex_id = 'M' and name = 'Male';
select 1 / count(*) from sex_i18n where sex_id = 'F' and lang_tag = 'ca' and name = 'Femení';
select 1 / count(*) from sex_i18n where sex_id = 'M' and lang_tag = 'ca' and name = 'Masculí';
select 1 / count(*) from sex_i18n where sex_id = 'F' and lang_tag = 'es' and name = 'Femenino';
select 1 / count(*) from sex_i18n where sex_id = 'M' and lang_tag = 'es' and name = 'Masculino';
select 1 / count(*) from sex_i18n where sex_id = 'F' and lang_tag = 'fr' and name = 'Féminin';
select 1 / count(*) from sex_i18n where sex_id = 'M' and lang_tag = 'fr' and name = 'Masculin';
rollback;

23
verify/booking_guest.sql Normal file
View File

@ -0,0 +1,23 @@
-- Verify camper:booking_guest on pg
begin;
select booking_guest_id
, booking_id
, id_document_type_id
, id_document_number
, id_document_issue_date
, given_name
, first_surname
, second_surname
, sex_id
, birthdate
, country_code
, phone
, address
, created_at
, updated_at
from camper.booking_guest
where false;
rollback;

View File

@ -0,0 +1,7 @@
-- Verify camper:check_in_guests on pg
begin;
select has_function_privilege('camper.check_in_guests(integer, camper.checked_in_guest[])', 'execute');
rollback;

View File

@ -0,0 +1,7 @@
-- Verify camper:checked_in_guest on pg
begin;
select pg_catalog.has_type_privilege('camper.checked_in_guest', 'usage');
rollback;

View File

@ -0,0 +1,10 @@
-- Verify camper:id_document_type on pg
begin;
select id_document_type_id
, name
from camper.id_document_type
where false;
rollback;

View File

@ -0,0 +1,11 @@
-- Verify camper:id_document_type_i18n on pg
begin;
select id_document_type_id
, lang_tag
, name
from camper.id_document_type_i18n
where false;
rollback;

10
verify/sex.sql Normal file
View File

@ -0,0 +1,10 @@
-- Verify camper:sex on pg
begin;
select sex_id
, name
from camper.sex
where false;
rollback;

11
verify/sex_i18n.sql Normal file
View File

@ -0,0 +1,11 @@
-- Verify camper:sex_i18n on pg
begin;
select sex_id
, lang_tag
, name
from camper.sex_i18n
where false;
rollback;

View File

@ -919,3 +919,83 @@ label[x-show] > span, label[x-show] > br {
} }
/*</editor-fold>*/ /*</editor-fold>*/
/*<editor-fold desc="Check-in guests">*/
#checkin-guests {
display: flex;
flex-direction: column;
}
#checkin-guests :is(label, fieldset) {
margin-top: 0;
}
#checkin-guests br {
display: none;
}
#checkin-guests > fieldset {
counter-reset: guest-count;
}
#checkin-guests > fieldset > fieldset {
counter-increment: guest-count;
position: relative;
display: grid;
grid-template-columns: repeat(4, 1fr);
border-bottom: .5px solid;
padding: 2.25em 0 1em;
column-gap: 1ch;
row-gap: .75em;
}
#checkin-guests > fieldset > fieldset::before {
content: '#' counter(guest-count);
position: absolute;
}
#checkin-guests fieldset fieldset:first-of-type button {
display: none;
}
#checkin-guests fieldset button {
position: absolute;
right: 0;
width: min-content;
min-width: unset;
line-height: 1;
border: none;
cursor: pointer;
}
#checkin-guests > fieldset > fieldset::before,
#checkin-guests fieldset button {
top: .25em;
}
#checkin-guests fieldset button:hover {
background-color: var(--camper--color--light-gray);
}
#checkin-guests fieldset button::before {
content: '⌫';
}
#checkin-guests :is(input, select) {
width: 100%;
}
#checkin-guests label:nth-of-type(2), #checkin-guests label:nth-of-type(9) {
grid-column: span 2;
}
#checkin-guests label:last-of-type {
grid-column: 1 / -1;
}
#checkin-guests footer {
display: flex;
justify-content: space-between;
}
/*</editor-fold>*/

View File

@ -0,0 +1,34 @@
<!--
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
SPDX-License-Identifier: AGPL-3.0-only
-->
{{ define "title" -}}
{{( pgettext "Check-in Booking" "title" )}}
{{- end }}
{{ define "breadcrumb" -}}
<li><a href="./">{{( pgettext "Bookings" "title" )}}</a></li>
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/booking.checkinForm*/ -}}
<a href="/admin/bookings/{{ .Slug }}">{{( pgettext "Edit Booking" "action" )}}</a>
<h2>{{ template "title" .}}</h2>
<form method="post" action="/admin/bookings/{{ .Slug }}/check-in" id="checkin-guests">
{{ CSRFInput }}
<fieldset>
<legend>{{( pgettext "Guests" "title" )}}</legend>
{{ range .Guests -}}
{{ template "guest.gohtml" . }}
{{- end }}
</fieldset>
<footer>
<button type="submit">{{( pgettext "Check-in" "action" )}}</button>
<button type="button"
data-hx-get="/admin/bookings/{{ .Slug }}/guest"
data-hx-target="#checkin-guests > fieldset"
data-hx-swap="beforeend"
>{{( pgettext "Add another guest" "action" )}}</button>
</footer>
</form>
{{- end }}

View File

@ -21,6 +21,9 @@
{{ define "content" -}} {{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/booking.adminBookingForm*/ -}} {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/booking.adminBookingForm*/ -}}
{{ if .ID -}}
<a href="{{ .URL }}/check-in">{{( pgettext "Check-in Booking" "action" )}}</a>
{{- end }}
<h2>{{ template "title" .}}</h2> <h2>{{ template "title" .}}</h2>
<form id="booking-form" <form id="booking-form"
data-hx-ext="morph" data-hx-ext="morph"

View File

@ -0,0 +1,139 @@
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/booking.guestForm*/ -}}
<fieldset>
<button type="button"
onclick="this.closest('fieldset').remove(this);return false;"
><span class="sr-only">{{( pgettext "Remove" "action" )}}</span></button>
{{ with .IDDocumentNumber -}}
<label>
{{( pgettext "ID document number" "input" )}}<br>
<input type="text"
required
name="{{ .Name }}"
value="{{ .Val }}"
{{ template "error-attrs" . }}
><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .IDDocumentType -}}
<label>
{{( pgettext "ID document type" "input" )}}<br>
<select name="{{ .Name }}"
required
{{ template "error-attrs" . }}
>
<option value="">{{( gettext "Choose an ID document type" )}}</option>
{{ template "list-options" . }}
</select><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .IDDocumentDate -}}
<label>
{{( pgettext "ID document issue date (if any)" "input" )}}<br>
<input type="date"
max="{{ today }}"
name="{{ .Name }}"
value="{{ .Val }}"
{{ template "error-attrs" . }}
><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .FirstSurname -}}
<label>
{{( pgettext "First surname" "input" )}}<br>
<input type="text"
required
name="{{ .Name }}"
value="{{ .Val }}"
{{ template "error-attrs" . }}
><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .SecondSurname -}}
<label>
{{( pgettext "Second surname (if has one)" "input" )}}<br>
<input type="text"
name="{{ .Name }}"
value="{{ .Val }}"
{{ template "error-attrs" . }}
><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .GivenName -}}
<label>
{{( pgettext "Given name" "input" )}}<br>
<input type="text"
required
name="{{ .Name }}"
value="{{ .Val }}"
{{ template "error-attrs" . }}
><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .Sex -}}
<label>
{{( pgettext "Sex" "input" )}}<br>
<select name="{{ .Name }}"
required
{{ template "error-attrs" . }}
>
<option value="">{{( gettext "Choose a sex" )}}</option>
{{ template "list-options" . }}
</select><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .Birthdate -}}
<label>
{{( pgettext "Birthdate" "input" )}}<br>
<input type="date"
required
max="{{ today }}"
name="{{ .Name }}"
value="{{ .Val }}"
{{ template "error-attrs" . }}
><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .Country -}}
<label>
{{( pgettext "Nationality" "input" )}}<br>
<select name="{{ .Name }}"
required
{{ template "error-attrs" . }}
>
<option value="">{{( gettext "Choose a country" )}}</option>
{{ template "list-options" . }}
</select><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .Phone -}}
<label>
{{( pgettext "Phone (optional)" "input" )}}<br>
<input type="tel"
name="{{ .Name }}"
value="{{ .Val }}"
{{ template "error-attrs" . }}
><br>
{{ template "error-message" . }}
</label>
{{- end }}
{{ with .Address -}}
<label>
{{( pgettext "Address (optional)" "input" )}}<br>
<input type="text"
name="{{ .Name }}"
value="{{ .Val }}"
{{ template "error-attrs" . }}
><br>
{{ template "error-message" . }}
</label>
{{- end }}
</fieldset>