Add the admin page to see payments

Had to do a couple of changes to the database: add the currency_code to
the payment relation, to format the price according to the payment’s
currency instead of the company’s; and the reference SQL function, to
replace the equivalent golang function, so that i can use it to index
payments.

The rest is mostly the same as any other page, except that the
individual payment’s page is not a form, but a regular info dump.

I also moved the payment settings as a sub-route of payments, as i
believe this makes more sense than an additional user menu item.
This commit is contained in:
jordi fita mas 2024-02-14 04:54:42 +01:00
parent bd84df8169
commit f2143cd0e6
30 changed files with 1628 additions and 763 deletions

View File

@ -42,6 +42,7 @@ begin
, subtotal_dogs
, subtotal_tourist_tax
, total
, currency_code
, down_payment_percent
, zone_preferences
)
@ -61,6 +62,7 @@ begin
, sum(case when num_dogs > 0 then coalesce(pet.cost_per_night, 0) else 0 end)::integer
, sum(tourist_tax * num_adults)::integer
, 0
, currency_code
, case when arrival_date - current_date >= 7 then 0.3 else 1.0 end
, coalesce(zone_preferences, '')
from generate_series(arrival_date, departure_date - 1, interval '1 day') as date(day)
@ -73,6 +75,7 @@ begin
where campsite_type.slug = campsite_type_slug
group by company_id
, campsite_type_id
, currency_code
on conflict (slug) do update
set company_id = excluded.company_id
, campsite_type_id = excluded.campsite_type_id
@ -89,6 +92,7 @@ begin
, subtotal_dogs = excluded.subtotal_dogs
, subtotal_tourist_tax = excluded.subtotal_tourist_tax
, total = excluded.total
, currency_code = excluded.currency_code
, down_payment_percent = excluded.down_payment_percent
, zone_preferences = excluded.zone_preferences
, updated_at = current_timestamp

View File

@ -7,6 +7,8 @@
-- requires: positive_integer
-- requires: nonnegative_integer
-- requires: percentage
-- requires: currency_code
-- requires: currency
begin;
@ -30,6 +32,7 @@ create table payment (
subtotal_dogs nonnegative_integer not null,
subtotal_tourist_tax nonnegative_integer not null,
total nonnegative_integer not null,
currency_code currency_code not null references currency,
down_payment_percent percentage not null default 1.0,
zone_preferences text not null,
payment_status text not null default 'draft' references payment_status,

View File

@ -0,0 +1,23 @@
-- Deploy camper:order_code to pg
-- requires: roles
-- requires: schema_camper
-- requires: payment
begin;
set search_path to camper, public;
create or replace function reference(p payment) returns text as
$$
select lpad(p.payment_id::text, 8, '0') || substring(p.slug::text from 1 for 4);
$$
language sql
stable
;
revoke execute on function reference(payment) from public;
grant execute on function reference(payment) to guest;
grant execute on function reference(payment) to employee;
grant execute on function reference(payment) to admin;
commit;

View File

@ -19,6 +19,7 @@ import (
"dev.tandem.ws/tandem/camper/pkg/legal"
"dev.tandem.ws/tandem/camper/pkg/location"
"dev.tandem.ws/tandem/camper/pkg/media"
"dev.tandem.ws/tandem/camper/pkg/payment"
"dev.tandem.ws/tandem/camper/pkg/season"
"dev.tandem.ws/tandem/camper/pkg/services"
"dev.tandem.ws/tandem/camper/pkg/surroundings"
@ -35,6 +36,7 @@ type adminHandler struct {
legal *legal.AdminHandler
location *location.AdminHandler
media *media.AdminHandler
payment *payment.AdminHandler
season *season.AdminHandler
services *services.AdminHandler
surroundings *surroundings.AdminHandler
@ -51,6 +53,7 @@ func newAdminHandler(mediaDir string) *adminHandler {
legal: legal.NewAdminHandler(),
location: location.NewAdminHandler(),
media: media.NewAdminHandler(mediaDir),
payment: payment.NewAdminHandler(),
season: season.NewAdminHandler(),
services: services.NewAdminHandler(),
surroundings: surroundings.NewAdminHandler(),
@ -90,6 +93,8 @@ func (h *adminHandler) Handle(user *auth.User, company *auth.Company, conn *data
h.location.Handler(user, company, conn).ServeHTTP(w, r)
case "media":
h.media.Handler(user, company, conn).ServeHTTP(w, r)
case "payments":
h.payment.Handler(user, company, conn).ServeHTTP(w, r)
case "seasons":
h.season.Handler(user, company, conn).ServeHTTP(w, r)
case "services":

View File

@ -14,9 +14,7 @@ import (
"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"
)
@ -40,27 +38,6 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat
default:
httplib.MethodNotAllowed(w, r, http.MethodGet)
}
case "payment":
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
switch head {
case "":
switch r.Method {
case http.MethodGet:
f := newPaymentForm(user.Locale)
if err := f.FillFromDatabase(r.Context(), company, conn); err != nil {
if !database.ErrorIsNotFound(err) {
panic(err)
}
}
f.MustRender(w, r, user, company)
case http.MethodPut:
updatePaymentSettings(w, r, user, company, conn)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
default:
http.NotFound(w, r)
}
default:
http.NotFound(w, r)
}
@ -151,124 +128,3 @@ func (page bookingIndex) MustRender(w http.ResponseWriter, r *http.Request, user
template.MustRenderAdmin(w, r, user, company, "booking/index.gohtml", page)
}
}
type paymentForm struct {
MerchantCode *form.Input
TerminalNumber *form.Input
Environment *form.Select
Integration *form.Select
EncryptKey *form.Input
}
func newPaymentForm(l *locale.Locale) *paymentForm {
return &paymentForm{
MerchantCode: &form.Input{
Name: "merchant_code",
},
TerminalNumber: &form.Input{
Name: "terminal_number",
},
Environment: &form.Select{
Name: "environment",
Options: []*form.Option{
{
Value: "test",
Label: l.Pgettext("Test", "redsys environment"),
},
{
Value: "live",
Label: l.Pgettext("Live", "redsys environment"),
},
},
},
Integration: &form.Select{
Name: "integration",
Options: []*form.Option{
{
Value: "insite",
Label: l.Pgettext("InSite", "redsys integration"),
},
{
Value: "redirect",
Label: l.Pgettext("Redirect", "redsys integration"),
},
},
},
EncryptKey: &form.Input{
Name: "encrypt_key",
},
}
}
func (f *paymentForm) FillFromDatabase(ctx context.Context, company *auth.Company, conn *database.Conn) error {
return conn.QueryRow(ctx, `
select merchant_code
, terminal_number::text
, array[environment::text]
, array[integration::text]
from redsys
where company_id = $1`, company.ID).Scan(
&f.MerchantCode.Val,
&f.TerminalNumber.Val,
&f.Environment.Selected,
&f.Integration.Selected,
)
}
func (f *paymentForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "booking/payment.gohtml", f)
}
func (f *paymentForm) Parse(r *http.Request) error {
if err := r.ParseForm(); err != nil {
return err
}
f.MerchantCode.FillValue(r)
f.TerminalNumber.FillValue(r)
f.Environment.FillValue(r)
f.Integration.FillValue(r)
f.EncryptKey.FillValue(r)
return nil
}
func (f *paymentForm) Valid(l *locale.Locale) bool {
v := form.NewValidator(l)
if v.CheckRequired(f.MerchantCode, l.GettextNoop("Merchant code can not be empty.")) {
if v.CheckExactLength(f.MerchantCode, 9, l.GettextNoop("Merchant code must be exactly nine digits long.")) {
v.CheckValidInteger(f.MerchantCode, l.GettextNoop("Merchant code must be a number."))
}
}
if v.CheckRequired(f.TerminalNumber, l.GettextNoop("Terminal number can not be empty.")) {
message := l.GettextNoop("Terminal number must be a number between 1 and 999.")
if v.CheckValidInteger(f.TerminalNumber, message) {
if v.CheckMinInteger(f.TerminalNumber, 1, message) {
v.CheckMaxInteger(f.TerminalNumber, 999, message)
}
}
}
v.CheckSelectedOptions(f.Environment, l.GettextNoop("Selected environment is not valid."))
v.CheckSelectedOptions(f.Integration, l.GettextNoop("Selected integration is not valid."))
if f.EncryptKey.Val != "" {
v.CheckValidBase64(f.EncryptKey, l.GettextNoop("The merchant key is not valid."))
}
return v.AllOK
}
func updatePaymentSettings(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
f := newPaymentForm(user.Locale)
if ok, err := form.Handle(f, w, r, user); err != nil {
return
} else if !ok {
f.MustRender(w, r, user, company)
return
}
if err := conn.SetupRedsys(r.Context(), company.ID, f.MerchantCode.Val, f.TerminalNumber.Int(), f.Environment.Selected[0], f.Integration.Selected[0], f.EncryptKey.Val); err != nil {
panic(err)
}
httplib.Redirect(w, r, "/admin/booking/payment", http.StatusSeeOther)
}

View File

@ -96,7 +96,6 @@ func newBookingCart(ctx context.Context, conn *database.Conn, f *bookingForm, ca
, to_price(total, decimal_digits)
, to_price(payment.down_payment, decimal_digits)
from draft_payment($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) as payment
join company using (company_id)
join currency using (currency_code)
`,
database.ZeroNullUUID(f.PaymentSlug.Val),
@ -160,7 +159,6 @@ func newBookingCart(ctx context.Context, conn *database.Conn, f *bookingForm, ca
, to_price(subtotal, decimal_digits)
from payment_option
join payment using (payment_id)
join company using (company_id)
join currency using (currency_code)
where payment_id = $1
`, paymentID)

339
pkg/payment/admin.go Normal file
View File

@ -0,0 +1,339 @@
package payment
import (
"context"
"net/http"
"time"
"dev.tandem.ws/tandem/camper/pkg/auth"
"dev.tandem.ws/tandem/camper/pkg/database"
httplib "dev.tandem.ws/tandem/camper/pkg/http"
"dev.tandem.ws/tandem/camper/pkg/locale"
"dev.tandem.ws/tandem/camper/pkg/template"
"dev.tandem.ws/tandem/camper/pkg/uuid"
)
type AdminHandler struct {
}
func NewAdminHandler() *AdminHandler {
return &AdminHandler{}
}
func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var head string
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
switch head {
case "":
switch r.Method {
case http.MethodGet:
servePaymentIndex(w, r, user, company, conn)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet)
}
case "settings":
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
switch head {
case "":
switch r.Method {
case http.MethodGet:
f := newSettingsForm(user.Locale)
if err := f.FillFromDatabase(r.Context(), company, conn); err != nil {
if !database.ErrorIsNotFound(err) {
panic(err)
}
}
f.MustRender(w, r, user, company)
case http.MethodPut:
updatePaymentSettings(w, r, user, company, conn)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
default:
http.NotFound(w, r)
}
default:
if !uuid.Valid(head) {
http.NotFound(w, r)
return
}
payment, err := fetchPaymentDetails(r.Context(), conn, head, user.Locale)
if err != nil {
if database.ErrorIsNotFound(err) {
http.NotFound(w, r)
return
}
panic(err)
}
h.paymentHandler(user, company, payment).ServeHTTP(w, r)
}
})
}
func (h *AdminHandler) paymentHandler(user *auth.User, company *auth.Company, payment *paymentDetails) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var head string
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
switch head {
case "":
switch r.Method {
case http.MethodGet:
payment.MustRender(w, r, user, company)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet)
}
default:
http.NotFound(w, r)
}
})
}
func servePaymentIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
payments, err := collectPaymentEntries(r.Context(), company, conn, user.Locale)
if err != nil {
panic(err)
}
page := &paymentIndex{
Payments: payments,
}
page.MustRender(w, r, user, company)
}
type paymentEntry struct {
URL string
Reference string
DownPayment string
Total string
Status string
StatusLabel string
CreatedAt time.Time
}
func collectPaymentEntries(ctx context.Context, company *auth.Company, conn *database.Conn, locale *locale.Locale) ([]*paymentEntry, error) {
rows, err := conn.Query(ctx, `
select '/admin/payments/' || payment.slug
, payment.reference
, to_price(payment.down_payment, decimal_digits)
, to_price(total, decimal_digits)
, payment.payment_status
, coalesce(payment_status_i18n.name, payment_status.name)
, created_at
from payment
join currency using (currency_code)
join payment_status using (payment_status)
left join payment_status_i18n on payment_status_i18n.payment_status = payment.payment_status
and payment_status_i18n.lang_tag = $2
where company_id = $1
order by created_at desc
`, company.ID, locale.Language)
if err != nil {
return nil, err
}
defer rows.Close()
var payments []*paymentEntry
for rows.Next() {
entry := &paymentEntry{}
if err = rows.Scan(
&entry.URL,
&entry.Reference,
&entry.DownPayment,
&entry.Total,
&entry.Status,
&entry.StatusLabel,
&entry.CreatedAt,
); err != nil {
return nil, err
}
payments = append(payments, entry)
}
return payments, nil
}
type paymentIndex struct {
Payments []*paymentEntry
}
func (page *paymentIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "payment/index.gohtml", page)
}
type paymentDetails struct {
ID int
Reference string
CampsiteType string
ArrivalDate time.Time
DepartureDate time.Time
NumNights int
NumAdults int
NumTeenagers int
NumChildren int
NumDogs int
SubtotalTouristTax string
Total string
DownPaymentPercent int
DownPayment string
ZonePreferences string
Status string
StatusLabel string
CreatedAt time.Time
UpdatedAt time.Time
Options []*paymentOption
Customer *paymentCustomer
}
type paymentOption struct {
Label string
Units int
}
type paymentCustomer struct {
FullName string
Address string
PostalCode string
City string
Country string
Email string
Phone string
Language string
ACSICard bool
}
func fetchPaymentDetails(ctx context.Context, conn *database.Conn, slug string, locale *locale.Locale) (*paymentDetails, error) {
row := conn.QueryRow(ctx, `
select payment_id
, payment.reference
, coalesce(campsite_type_i18n.name, campsite_type.name)
, arrival_date
, departure_date
, departure_date - arrival_date
, number_adults
, number_teenagers
, number_children
, number_dogs
, to_price(subtotal_tourist_tax, decimal_digits)
, to_price(total, decimal_digits)
, (down_payment_percent * 100)::integer
, to_price(payment.down_payment, decimal_digits)
, zone_preferences
, payment.payment_status
, coalesce(payment_status_i18n.name, payment_status.name)
, created_at
, updated_at
from payment
join currency using (currency_code)
join campsite_type using (campsite_type_id)
join payment_status using (payment_status)
left join payment_status_i18n on payment_status_i18n.payment_status = payment.payment_status
and payment_status_i18n.lang_tag = $2
left join campsite_type_i18n on campsite_type_i18n.campsite_type_id = campsite_type.campsite_type_id
and campsite_type_i18n.lang_tag = $2
where payment.slug = $1
`, slug, locale.Language)
details := &paymentDetails{}
if err := row.Scan(
&details.ID,
&details.Reference,
&details.CampsiteType,
&details.ArrivalDate,
&details.DepartureDate,
&details.NumNights,
&details.NumAdults,
&details.NumTeenagers,
&details.NumChildren,
&details.NumDogs,
&details.SubtotalTouristTax,
&details.Total,
&details.DownPaymentPercent,
&details.DownPayment,
&details.ZonePreferences,
&details.Status,
&details.StatusLabel,
&details.CreatedAt,
&details.UpdatedAt,
); err != nil {
return nil, err
}
var err error
details.Options, err = fetchPaymentOptions(ctx, conn, details.ID, locale)
if err != nil && !database.ErrorIsNotFound(err) {
return nil, err
}
details.Customer, err = fetchPaymentCustomer(ctx, conn, details.ID, locale)
if err != nil && !database.ErrorIsNotFound(err) {
return nil, err
}
return details, nil
}
func fetchPaymentOptions(ctx context.Context, conn *database.Conn, paymentID int, locale *locale.Locale) ([]*paymentOption, error) {
rows, err := conn.Query(ctx, `
select coalesce(option_i18n.name, option.name)
, units
from payment_option
join campsite_type_option as option using (campsite_type_option_id)
left join campsite_type_option_i18n as option_i18n on option_i18n.campsite_type_option_id = option.campsite_type_option_id
and option_i18n.lang_tag = $2
where payment_id = $1
`, paymentID, locale.Language)
if err != nil {
return nil, err
}
defer rows.Close()
var options []*paymentOption
for rows.Next() {
option := &paymentOption{}
if err = rows.Scan(&option.Label, &option.Units); err != nil {
return nil, err
}
options = append(options, option)
}
return options, nil
}
func fetchPaymentCustomer(ctx context.Context, conn *database.Conn, paymentID int, locale *locale.Locale) (*paymentCustomer, error) {
row := conn.QueryRow(ctx, `
select full_name
, address
, postal_code
, city
, coalesce(country_i18n.name, country.name)
, email
, phone::text
, language.endonym
, acsi_card
from payment_customer
join country using (country_code)
left join country_i18n on country.country_code = country_i18n.country_code
and country_i18n.lang_tag = $2
join language on payment_customer.lang_tag = language.lang_tag
where payment_id = $1
`, paymentID, locale.Language)
customer := &paymentCustomer{}
if err := row.Scan(
&customer.FullName,
&customer.Address,
&customer.PostalCode,
&customer.City,
&customer.Country,
&customer.Email,
&customer.Phone,
&customer.Language,
&customer.ACSICard,
); err != nil {
return nil, err
}
return customer, nil
}
func (f *paymentDetails) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "payment/details.gohtml", f)
}

View File

@ -74,17 +74,17 @@ func fetchPayment(ctx context.Context, conn *database.Conn, paymentSlug string)
row := conn.QueryRow(ctx, `
select payment_id
, payment.slug::text
, payment.reference
, payment.created_at
, to_price(total, decimal_digits)
, to_price(payment.down_payment, decimal_digits)
from payment
join company using (company_id)
join currency using (currency_code)
where payment.slug = $1
and payment_status <> 'draft'
`, paymentSlug)
payment := &Payment{}
if err := row.Scan(&payment.ID, &payment.Slug, &payment.CreateTime, &payment.Total, &payment.DownPayment); err != nil {
if err := row.Scan(&payment.ID, &payment.Slug, &payment.Reference, &payment.CreateTime, &payment.Total, &payment.DownPayment); err != nil {
return nil, err
}
return payment, nil
@ -93,6 +93,7 @@ func fetchPayment(ctx context.Context, conn *database.Conn, paymentSlug string)
type Payment struct {
ID int
Slug string
Reference string
Total string
DownPayment string
CreateTime time.Time
@ -105,7 +106,7 @@ func (payment *Payment) createRequest(r *http.Request, user *auth.User, company
request := redsys.Request{
TransactionType: redsys.TransactionTypeCharge,
Amount: payment.DownPayment,
OrderNumber: payment.OrderNumber(),
OrderNumber: payment.Reference,
Product: user.Locale.Pgettext("Campsite Booking", "order product name"),
SuccessURL: fmt.Sprintf("%s/success", baseURL),
FailureURL: fmt.Sprintf("%s/failure", baseURL),
@ -115,10 +116,6 @@ func (payment *Payment) createRequest(r *http.Request, user *auth.User, company
return request.Sign(r.Context(), conn, company)
}
func (payment *Payment) OrderNumber() string {
return fmt.Sprintf("%08d%s", payment.ID, payment.Slug[:4])
}
type paymentPage struct {
*template.PublicPage
Environment string
@ -240,7 +237,7 @@ func handleNotification(w http.ResponseWriter, r *http.Request, user *auth.User,
http.Error(w, "Invalid response", http.StatusBadRequest)
return
}
if response.OrderNumber != payment.OrderNumber() {
if response.OrderNumber != payment.Reference {
http.Error(w, "Response for a different payment", http.StatusBadRequest)
return
}
@ -287,7 +284,7 @@ type address struct {
func sendEmail(ctx context.Context, conn *database.Conn, payment *Payment, company *auth.Company, locale *locale.Locale) error {
email := &CompletedEmail{
CurrentLocale: locale.Language.String(),
PaymentReference: payment.OrderNumber(),
PaymentReference: payment.Reference,
Total: template.FormatPrice(payment.Total, locale.Language, locale.CurrencyPattern, company.DecimalDigits, company.CurrencySymbol),
DownPayment: template.FormatPrice(payment.DownPayment, locale.Language, locale.CurrencyPattern, company.DecimalDigits, company.CurrencySymbol),
CompanyAddress: &address{},

135
pkg/payment/settings.go Normal file
View File

@ -0,0 +1,135 @@
package payment
import (
"context"
"net/http"
"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"
)
type settingsForm struct {
MerchantCode *form.Input
TerminalNumber *form.Input
Environment *form.Select
Integration *form.Select
EncryptKey *form.Input
}
func newSettingsForm(l *locale.Locale) *settingsForm {
return &settingsForm{
MerchantCode: &form.Input{
Name: "merchant_code",
},
TerminalNumber: &form.Input{
Name: "terminal_number",
},
Environment: &form.Select{
Name: "environment",
Options: []*form.Option{
{
Value: "test",
Label: l.Pgettext("Test", "redsys environment"),
},
{
Value: "live",
Label: l.Pgettext("Live", "redsys environment"),
},
},
},
Integration: &form.Select{
Name: "integration",
Options: []*form.Option{
{
Value: "insite",
Label: l.Pgettext("InSite", "redsys integration"),
},
{
Value: "redirect",
Label: l.Pgettext("Redirect", "redsys integration"),
},
},
},
EncryptKey: &form.Input{
Name: "encrypt_key",
},
}
}
func (f *settingsForm) FillFromDatabase(ctx context.Context, company *auth.Company, conn *database.Conn) error {
return conn.QueryRow(ctx, `
select merchant_code
, terminal_number::text
, array[environment::text]
, array[integration::text]
from redsys
where company_id = $1`, company.ID).Scan(
&f.MerchantCode.Val,
&f.TerminalNumber.Val,
&f.Environment.Selected,
&f.Integration.Selected,
)
}
func (f *settingsForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "payment/settings.gohtml", f)
}
func (f *settingsForm) Parse(r *http.Request) error {
if err := r.ParseForm(); err != nil {
return err
}
f.MerchantCode.FillValue(r)
f.TerminalNumber.FillValue(r)
f.Environment.FillValue(r)
f.Integration.FillValue(r)
f.EncryptKey.FillValue(r)
return nil
}
func (f *settingsForm) Valid(l *locale.Locale) bool {
v := form.NewValidator(l)
if v.CheckRequired(f.MerchantCode, l.GettextNoop("Merchant code can not be empty.")) {
if v.CheckExactLength(f.MerchantCode, 9, l.GettextNoop("Merchant code must be exactly nine digits long.")) {
v.CheckValidInteger(f.MerchantCode, l.GettextNoop("Merchant code must be a number."))
}
}
if v.CheckRequired(f.TerminalNumber, l.GettextNoop("Terminal number can not be empty.")) {
message := l.GettextNoop("Terminal number must be a number between 1 and 999.")
if v.CheckValidInteger(f.TerminalNumber, message) {
if v.CheckMinInteger(f.TerminalNumber, 1, message) {
v.CheckMaxInteger(f.TerminalNumber, 999, message)
}
}
}
v.CheckSelectedOptions(f.Environment, l.GettextNoop("Selected environment is not valid."))
v.CheckSelectedOptions(f.Integration, l.GettextNoop("Selected integration is not valid."))
if f.EncryptKey.Val != "" {
v.CheckValidBase64(f.EncryptKey, l.GettextNoop("The merchant key is not valid."))
}
return v.AllOK
}
func updatePaymentSettings(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
f := newSettingsForm(user.Locale)
if ok, err := form.Handle(f, w, r, user); err != nil {
return
} else if !ok {
f.MustRender(w, r, user, company)
return
}
if err := conn.SetupRedsys(r.Context(), company.ID, f.MerchantCode.Val, f.TerminalNumber.Int(), f.Environment.Selected[0], f.Integration.Selected[0], f.EncryptKey.Val); err != nil {
panic(err)
}
httplib.Redirect(w, r, "/admin/payments", http.StatusSeeOther)
}

View File

@ -107,6 +107,9 @@ func mustRenderLayout(w io.Writer, user *auth.User, company *auth.Company, templ
"formatDate": func(time time.Time) template.HTML {
return template.HTML(`<time datetime="` + time.Format(database.ISODateFormat) + `">` + time.Format("02/01/2006") + "</time>")
},
"formatDateTime": func(time time.Time) template.HTML {
return template.HTML(`<time datetime="` + time.Format(database.ISODateFormat) + `">` + time.Format("02/01/2006 15:04:05") + "</time>")
},
"formatDateAttr": func(time time.Time) string {
return time.Format(database.ISODateFormat)
},

428
po/ca.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-02-13 23:38+0100\n"
"POT-Creation-Date: 2024-02-14 04:43+0100\n"
"PO-Revision-Date: 2024-02-06 10:04+0100\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Catalan <ca@dodds.net>\n"
@ -380,12 +380,14 @@ msgstr "dg"
#: web/templates/public/campsite/dates.gohtml:4
#: web/templates/public/booking/fields.gohtml:29
#: web/templates/admin/payment/details.gohtml:52
msgctxt "input"
msgid "Arrival date"
msgstr "Data darribada"
#: web/templates/public/campsite/dates.gohtml:15
#: web/templates/public/booking/fields.gohtml:40
#: web/templates/admin/payment/details.gohtml:56
msgctxt "input"
msgid "Departure date"
msgstr "Data de sortida"
@ -624,6 +626,7 @@ msgstr "Allotjaments"
#: web/templates/public/layout.gohtml:70
#: web/templates/public/booking/page.gohtml:7
#: web/templates/admin/payment/details.gohtml:41
msgctxt "title"
msgid "Booking"
msgstr "Reserva"
@ -643,9 +646,10 @@ msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Numbe
msgstr "<abbr title=\"Número\">Núm.</abbr> <abbr title=\"Registre de Turisme de Catalunya\">RTC</abbr> %s"
#: web/templates/public/booking/fields.gohtml:14
#: web/templates/admin/payment/details.gohtml:44
msgctxt "title"
msgid "Accommodation"
msgstr "Allotjaments"
msgstr "Allotjament"
#: web/templates/public/booking/fields.gohtml:26
msgctxt "title"
@ -658,25 +662,29 @@ msgid "Guests"
msgstr "Hostes"
#: web/templates/public/booking/fields.gohtml:59
#: web/templates/admin/payment/details.gohtml:64
msgctxt "input"
msgid "Adults aged 17 or older"
msgstr "Adults de 17 anys o més"
#: web/templates/public/booking/fields.gohtml:70
#: web/templates/admin/payment/details.gohtml:68
msgctxt "input"
msgid "Teenagers from 11 to 16 years old"
msgstr "Adolescents dentre 11 i 16 anys"
#: web/templates/public/booking/fields.gohtml:81
#: web/templates/admin/payment/details.gohtml:72
msgctxt "input"
msgid "Children from 2 to 10 years old"
msgstr "Nens dentre 2 i 10 anys)"
msgstr "Nens dentre 2 i 10 anys"
#: web/templates/public/booking/fields.gohtml:91
msgid "Note: Due to guest capacity, we have added more accomodations to the booking, but we <strong>cannot</strong> guarantee that they will be next to each other."
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:99
#: web/templates/admin/payment/details.gohtml:76
msgctxt "input"
msgid "Dogs"
msgstr "Gossos"
@ -695,11 +703,13 @@ msgid "Campground map"
msgstr "Mapa del càmping"
#: web/templates/public/booking/fields.gohtml:145
#: web/templates/admin/payment/details.gohtml:106
msgctxt "title"
msgid "Customer Details"
msgstr "Detalls del client"
#: web/templates/public/booking/fields.gohtml:148
#: web/templates/admin/payment/details.gohtml:109
msgctxt "input"
msgid "Full name"
msgstr "Nom i cognoms"
@ -720,6 +730,7 @@ msgid "Town or village (optional)"
msgstr "Població (opcional)"
#: web/templates/public/booking/fields.gohtml:184
#: web/templates/admin/payment/details.gohtml:125
#: web/templates/admin/taxDetails.gohtml:101
msgctxt "input"
msgid "Country"
@ -730,6 +741,7 @@ msgid "Choose a country"
msgstr "Esculli un país"
#: web/templates/public/booking/fields.gohtml:195
#: web/templates/admin/payment/details.gohtml:129
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
#: web/templates/admin/taxDetails.gohtml:53
msgctxt "input"
@ -737,6 +749,7 @@ msgid "Email"
msgstr "Correu-e"
#: web/templates/public/booking/fields.gohtml:204
#: web/templates/admin/payment/details.gohtml:133
#: web/templates/admin/taxDetails.gohtml:45
msgctxt "input"
msgid "Phone"
@ -758,10 +771,186 @@ msgid "Total"
msgstr "Total"
#: web/templates/public/booking/fields.gohtml:244
#: web/templates/admin/payment/details.gohtml:84
msgctxt "cart"
msgid "Down payment"
msgstr "A compte"
#: web/templates/admin/payment/settings.gohtml:6
#: web/templates/admin/payment/index.gohtml:14
msgctxt "title"
msgid "Payment Settings"
msgstr "Paràmetres de pagament"
#: web/templates/admin/payment/settings.gohtml:10
#: web/templates/admin/payment/index.gohtml:6
#: web/templates/admin/payment/details.gohtml:11
#: web/templates/admin/layout.gohtml:40
msgctxt "title"
msgid "Payments"
msgstr "Pagaments"
#: web/templates/admin/payment/settings.gohtml:21
msgctxt "input"
msgid "Merchant Code"
msgstr "Codi del comerç"
#: web/templates/admin/payment/settings.gohtml:30
msgctxt "input"
msgid "Terminal Number"
msgstr "Número de terminal"
#: web/templates/admin/payment/settings.gohtml:40
msgctxt "input"
msgid "Merchant Key (only if must change it)"
msgstr "Clau del comerç (només si sha de canviar)"
#: web/templates/admin/payment/settings.gohtml:42
msgctxt "input"
msgid "Merchant Key"
msgstr "Clau del comerç"
#: web/templates/admin/payment/settings.gohtml:52
msgctxt "title"
msgid "Environment"
msgstr "Entorn"
#: web/templates/admin/payment/settings.gohtml:59
msgctxt "title"
msgid "Integration"
msgstr "Integració"
#: web/templates/admin/payment/settings.gohtml:66
#: web/templates/admin/location.gohtml:53 web/templates/admin/profile.gohtml:78
#: web/templates/admin/taxDetails.gohtml:170
msgctxt "action"
msgid "Save changes"
msgstr "Desa els canvis"
#: web/templates/admin/payment/index.gohtml:20
#: web/templates/admin/user/login-attempts.gohtml:19
msgctxt "header"
msgid "Date"
msgstr "Data"
#: web/templates/admin/payment/index.gohtml:21
#: web/templates/admin/payment/details.gohtml:22
#: web/templates/admin/booking/index.gohtml:21
msgctxt "header"
msgid "Reference"
msgstr "Referència"
#: web/templates/admin/payment/index.gohtml:22
#: web/templates/admin/payment/details.gohtml:26
#: web/templates/admin/booking/index.gohtml:25
msgctxt "header"
msgid "Status"
msgstr "Estat"
#: web/templates/admin/payment/index.gohtml:23
msgctxt "header"
msgid "Down payment"
msgstr "A compte"
#: web/templates/admin/payment/index.gohtml:24
msgctxt "header"
msgid "Total"
msgstr "Total"
#: web/templates/admin/payment/index.gohtml:40
msgid "No payments found."
msgstr "No sha trobat cap pagament."
#: web/templates/admin/payment/details.gohtml:7
msgctxt "title"
msgid "Payment %s"
msgstr "Pagament %s"
#: web/templates/admin/payment/details.gohtml:19
msgctxt "title"
msgid "Payment"
msgstr "Pagament"
#: web/templates/admin/payment/details.gohtml:30
msgctxt "payment header"
msgid "Created at"
msgstr "Creat el"
#: web/templates/admin/payment/details.gohtml:34
msgctxt "payment header"
msgid "Last updated at"
msgstr "Actualitzat per darrera vegada el"
#: web/templates/admin/payment/details.gohtml:48
msgctxt "header"
msgid "Area preferences"
msgstr "Preferències dàrea"
#: web/templates/admin/payment/details.gohtml:60
msgctxt "cart"
msgid "Nights"
msgstr "Nits"
#: web/templates/admin/payment/details.gohtml:80 pkg/booking/cart.go:188
msgctxt "cart"
msgid "Tourist tax"
msgstr "Impost turístic"
#: web/templates/admin/payment/details.gohtml:92
#: web/templates/admin/campsite/type/option/form.gohtml:18
#: web/templates/admin/campsite/type/option/index.gohtml:6
#: web/templates/admin/campsite/type/option/index.gohtml:17
msgctxt "title"
msgid "Campsite Type Options"
msgstr "Opcions del tipus dallotjament"
#: web/templates/admin/payment/details.gohtml:113
#: web/templates/admin/taxDetails.gohtml:69
msgctxt "input"
msgid "Address"
msgstr "Adreça"
#: web/templates/admin/payment/details.gohtml:117
#: web/templates/admin/taxDetails.gohtml:93
msgctxt "input"
msgid "Postcode"
msgstr "Codi postal"
#: web/templates/admin/payment/details.gohtml:121
#: web/templates/admin/taxDetails.gohtml:77
msgctxt "input"
msgid "City"
msgstr "Població"
#: web/templates/admin/payment/details.gohtml:137
#: web/templates/admin/profile.gohtml:68
msgctxt "input"
msgid "Language"
msgstr "Idioma"
#: web/templates/admin/payment/details.gohtml:141
msgctxt "input"
msgid "ACSI card?"
msgstr "Targeta ACSI?"
#: web/templates/admin/payment/details.gohtml:142
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "Yes"
msgstr "Sí"
#: web/templates/admin/payment/details.gohtml:142
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "No"
msgstr "No"
#: web/templates/admin/legal/form.gohtml:8
#: web/templates/admin/legal/form.gohtml:29
msgctxt "title"
@ -911,13 +1100,6 @@ msgctxt "input"
msgid "Map Embed"
msgstr "Incrustació del mapa"
#: web/templates/admin/location.gohtml:53 web/templates/admin/profile.gohtml:78
#: web/templates/admin/taxDetails.gohtml:170
#: web/templates/admin/booking/payment.gohtml:65
msgctxt "action"
msgid "Save changes"
msgstr "Desa els canvis"
#: web/templates/admin/campsite/feature/form.gohtml:8
msgctxt "title"
msgid "Edit Campsite Feature"
@ -1145,22 +1327,6 @@ msgctxt "action"
msgid "Edit Carousel"
msgstr "Edita el carrusel"
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "Yes"
msgstr "Sí"
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "No"
msgstr "No"
#: web/templates/admin/campsite/index.gohtml:47
msgid "No campsites added yet."
msgstr "No sha afegit cap allotjament encara."
@ -1368,13 +1534,6 @@ msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nova opció del tipus dallotjament"
#: web/templates/admin/campsite/type/option/form.gohtml:18
#: web/templates/admin/campsite/type/option/index.gohtml:6
#: web/templates/admin/campsite/type/option/index.gohtml:17
msgctxt "title"
msgid "Campsite Type Options"
msgstr "Opcions del tipus dallotjament"
#: web/templates/admin/campsite/type/option/form.gohtml:54
msgctxt "input"
msgid "Minimum"
@ -1568,11 +1727,6 @@ msgctxt "input"
msgid "Password Confirmation"
msgstr "Confirmació de la contrasenya"
#: web/templates/admin/profile.gohtml:68
msgctxt "input"
msgid "Language"
msgstr "Idioma"
#: web/templates/admin/user/login-attempts.gohtml:6
#: web/templates/admin/user/login-attempts.gohtml:15
msgctxt "title"
@ -1587,11 +1741,6 @@ msgctxt "title"
msgid "Users"
msgstr "Usuaris"
#: web/templates/admin/user/login-attempts.gohtml:19
msgctxt "header"
msgid "Date"
msgstr "Data"
#: web/templates/admin/user/login-attempts.gohtml:20
#: web/templates/admin/user/index.gohtml:21
msgctxt "header"
@ -1649,26 +1798,11 @@ msgctxt "input"
msgid "Trade Name"
msgstr "Nom comercial"
#: web/templates/admin/taxDetails.gohtml:69
msgctxt "input"
msgid "Address"
msgstr "Adreça"
#: web/templates/admin/taxDetails.gohtml:77
msgctxt "input"
msgid "City"
msgstr "Població"
#: web/templates/admin/taxDetails.gohtml:85
msgctxt "input"
msgid "Province"
msgstr "Província"
#: web/templates/admin/taxDetails.gohtml:93
msgctxt "input"
msgid "Postcode"
msgstr "Codi postal"
#: web/templates/admin/taxDetails.gohtml:111
msgctxt "input"
msgid "Currency"
@ -1854,13 +1988,6 @@ msgctxt "title"
msgid "Company Settings"
msgstr "Paràmetres de lempresa"
#: web/templates/admin/layout.gohtml:40
#: web/templates/admin/booking/payment.gohtml:6
#: web/templates/admin/booking/payment.gohtml:15
msgctxt "title"
msgid "Payment Settings"
msgstr "Paràmetres de pagament"
#: web/templates/admin/layout.gohtml:55
#: web/templates/admin/media/form.gohtml:10
#: web/templates/admin/media/index.gohtml:6
@ -1988,36 +2115,6 @@ msgctxt "title"
msgid "Upload Media"
msgstr "Pujada de mèdia"
#: web/templates/admin/booking/payment.gohtml:20
msgctxt "input"
msgid "Merchant Code"
msgstr "Codi del comerç"
#: web/templates/admin/booking/payment.gohtml:29
msgctxt "input"
msgid "Terminal Number"
msgstr "Número de terminal"
#: web/templates/admin/booking/payment.gohtml:39
msgctxt "input"
msgid "Merchant Key (only if must change it)"
msgstr "Clau del comerç (només si sha de canviar)"
#: web/templates/admin/booking/payment.gohtml:41
msgctxt "input"
msgid "Merchant Key"
msgstr "Clau del comerç"
#: web/templates/admin/booking/payment.gohtml:51
msgctxt "title"
msgid "Environment"
msgstr "Entorn"
#: web/templates/admin/booking/payment.gohtml:58
msgctxt "title"
msgid "Integration"
msgstr "Integració"
#: web/templates/admin/booking/index.gohtml:14
msgctxt "action"
msgid "Add Booking"
@ -2028,11 +2125,6 @@ msgctxt "action"
msgid "Export Bookings"
msgstr "Exporta reserves"
#: web/templates/admin/booking/index.gohtml:21
msgctxt "header"
msgid "Reference"
msgstr "Referència"
#: web/templates/admin/booking/index.gohtml:22
msgctxt "header"
msgid "Arrival Date"
@ -2048,21 +2140,68 @@ msgctxt "header"
msgid "Holder Name"
msgstr "Nom del titular"
#: web/templates/admin/booking/index.gohtml:25
msgctxt "header"
msgid "Status"
msgstr "Estat"
#: web/templates/admin/booking/index.gohtml:41
msgid "No booking found."
msgstr "No sha trobat cap reserva."
#: pkg/payment/public.go:109
#: pkg/payment/settings.go:37
msgctxt "redsys environment"
msgid "Test"
msgstr "Proves"
#: pkg/payment/settings.go:41
msgctxt "redsys environment"
msgid "Live"
msgstr "Real"
#: pkg/payment/settings.go:50
msgctxt "redsys integration"
msgid "InSite"
msgstr "InSite"
#: pkg/payment/settings.go:54
msgctxt "redsys integration"
msgid "Redirect"
msgstr "Redirecció"
#: pkg/payment/settings.go:98
msgid "Merchant code can not be empty."
msgstr "No podeu deixar el codi del comerç en blanc."
#: pkg/payment/settings.go:99
msgid "Merchant code must be exactly nine digits long."
msgstr "El codi del comerç ha de ser de nou dígits."
#: pkg/payment/settings.go:100
msgid "Merchant code must be a number."
msgstr "El codi del comerç."
#: pkg/payment/settings.go:104
msgid "Terminal number can not be empty."
msgstr "No podeu deixar el número del terminal en blanc."
#: pkg/payment/settings.go:105
msgid "Terminal number must be a number between 1 and 999."
msgstr "El número del terminal ha de ser entre 1 i 999"
#: pkg/payment/settings.go:113
msgid "Selected environment is not valid."
msgstr "Lentorn escollit no és vàlid."
#: pkg/payment/settings.go:114
msgid "Selected integration is not valid."
msgstr "La integració escollida no és vàlida."
#: pkg/payment/settings.go:117
msgid "The merchant key is not valid."
msgstr "Aquesta clau del comerç no és vàlid."
#: pkg/payment/public.go:110
msgctxt "order product name"
msgid "Campsite Booking"
msgstr "Reserva de càmping"
#: pkg/payment/public.go:346
#: pkg/payment/public.go:342
msgctxt "subject"
msgid "Booking payment successfully received"
msgstr "Rebut amb èxit el pagament de la reserva"
@ -2140,7 +2279,7 @@ msgstr "Lidioma escollit no és vàlid."
msgid "File must be a valid PNG or JPEG image."
msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida."
#: pkg/app/admin.go:70
#: pkg/app/admin.go:73
msgid "Access forbidden"
msgstr "Accés prohibit"
@ -2563,93 +2702,36 @@ msgstr "No podeu deixar el fitxer del mèdia en blanc."
msgid "Filename can not be empty."
msgstr "No podeu deixar el nom del fitxer en blanc."
#: pkg/booking/cart.go:151
#: pkg/booking/cart.go:150
msgctxt "cart"
msgid "Night"
msgstr "Nit"
#: pkg/booking/cart.go:152
#: pkg/booking/cart.go:151
msgctxt "cart"
msgid "Adult"
msgstr "Adult"
#: pkg/booking/cart.go:153
#: pkg/booking/cart.go:152
msgctxt "cart"
msgid "Teenager"
msgstr "Adolescent"
#: pkg/booking/cart.go:154
#: pkg/booking/cart.go:153
msgctxt "cart"
msgid "Child"
msgstr "Nen"
#: pkg/booking/cart.go:155
#: pkg/booking/cart.go:154
msgctxt "cart"
msgid "Dog"
msgstr "Gos"
#: pkg/booking/cart.go:190
msgctxt "cart"
msgid "Tourist tax"
msgstr "Impost turístic"
#: pkg/booking/admin.go:149
#: pkg/booking/admin.go:126
msgctxt "filename"
msgid "bookings.ods"
msgstr "reserves.ods"
#: pkg/booking/admin.go:177
msgctxt "redsys environment"
msgid "Test"
msgstr "Proves"
#: pkg/booking/admin.go:181
msgctxt "redsys environment"
msgid "Live"
msgstr "Real"
#: pkg/booking/admin.go:190
msgctxt "redsys integration"
msgid "InSite"
msgstr "InSite"
#: pkg/booking/admin.go:194
msgctxt "redsys integration"
msgid "Redirect"
msgstr "Redirecció"
#: pkg/booking/admin.go:238
msgid "Merchant code can not be empty."
msgstr "No podeu deixar el codi del comerç en blanc."
#: pkg/booking/admin.go:239
msgid "Merchant code must be exactly nine digits long."
msgstr "El codi del comerç ha de ser de nou dígits."
#: pkg/booking/admin.go:240
msgid "Merchant code must be a number."
msgstr "El codi del comerç."
#: pkg/booking/admin.go:244
msgid "Terminal number can not be empty."
msgstr "No podeu deixar el número del terminal en blanc."
#: pkg/booking/admin.go:245
msgid "Terminal number must be a number between 1 and 999."
msgstr "El número del terminal ha de ser entre 1 i 999"
#: pkg/booking/admin.go:253
msgid "Selected environment is not valid."
msgstr "Lentorn escollit no és vàlid."
#: pkg/booking/admin.go:254
msgid "Selected integration is not valid."
msgstr "La integració escollida no és vàlida."
#: pkg/booking/admin.go:257
msgid "The merchant key is not valid."
msgstr "Aquesta clau del comerç no és vàlid."
#: pkg/booking/public.go:275 pkg/booking/public.go:304
msgid "Arrival date must be a valid date."
msgstr "La data darribada ha de ser una data vàlida."
@ -2771,10 +2853,6 @@ msgstr "El nom i els cognoms han de tenir com a mínim una lletra."
msgid "It is mandatory to agree to the reservation conditions."
msgstr "És obligatori acceptar les condicions de reserves."
#~ msgctxt "title"
#~ msgid "Payment"
#~ msgstr "Pagament"
#~ msgctxt "action"
#~ msgid "Pay"
#~ msgstr "Paga"

426
po/es.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-02-13 23:38+0100\n"
"POT-Creation-Date: 2024-02-14 04:47+0100\n"
"PO-Revision-Date: 2024-02-06 10:04+0100\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Spanish <es@tp.org.es>\n"
@ -380,12 +380,14 @@ msgstr "do"
#: web/templates/public/campsite/dates.gohtml:4
#: web/templates/public/booking/fields.gohtml:29
#: web/templates/admin/payment/details.gohtml:52
msgctxt "input"
msgid "Arrival date"
msgstr "Fecha de llegada"
#: web/templates/public/campsite/dates.gohtml:15
#: web/templates/public/booking/fields.gohtml:40
#: web/templates/admin/payment/details.gohtml:56
msgctxt "input"
msgid "Departure date"
msgstr "Fecha de salida"
@ -624,6 +626,7 @@ msgstr "Alojamientos"
#: web/templates/public/layout.gohtml:70
#: web/templates/public/booking/page.gohtml:7
#: web/templates/admin/payment/details.gohtml:41
msgctxt "title"
msgid "Booking"
msgstr "Reserva"
@ -643,6 +646,7 @@ msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Numbe
msgstr "<abbr title=\"Número\">Nº</abbr> <abbr title=\"Registro de Turismo de Cataluña\">RTC</abbr> %s"
#: web/templates/public/booking/fields.gohtml:14
#: web/templates/admin/payment/details.gohtml:44
msgctxt "title"
msgid "Accommodation"
msgstr "Alojamientos"
@ -658,16 +662,19 @@ msgid "Guests"
msgstr "Huéspedes"
#: web/templates/public/booking/fields.gohtml:59
#: web/templates/admin/payment/details.gohtml:64
msgctxt "input"
msgid "Adults aged 17 or older"
msgstr "Adultos de 17 años o más"
#: web/templates/public/booking/fields.gohtml:70
#: web/templates/admin/payment/details.gohtml:68
msgctxt "input"
msgid "Teenagers from 11 to 16 years old"
msgstr "Adolescentes de 11 a 16 años"
#: web/templates/public/booking/fields.gohtml:81
#: web/templates/admin/payment/details.gohtml:72
msgctxt "input"
msgid "Children from 2 to 10 years old"
msgstr "Niños de 2 a 10 años"
@ -677,6 +684,7 @@ msgid "Note: Due to guest capacity, we have added more accomodations to the book
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:99
#: web/templates/admin/payment/details.gohtml:76
msgctxt "input"
msgid "Dogs"
msgstr "Perros"
@ -695,11 +703,13 @@ msgid "Campground map"
msgstr "Mapa del camping"
#: web/templates/public/booking/fields.gohtml:145
#: web/templates/admin/payment/details.gohtml:106
msgctxt "title"
msgid "Customer Details"
msgstr "Detalles del cliente"
#: web/templates/public/booking/fields.gohtml:148
#: web/templates/admin/payment/details.gohtml:109
msgctxt "input"
msgid "Full name"
msgstr "Nombre y apellidos"
@ -720,6 +730,7 @@ msgid "Town or village (optional)"
msgstr "Población (opcional)"
#: web/templates/public/booking/fields.gohtml:184
#: web/templates/admin/payment/details.gohtml:125
#: web/templates/admin/taxDetails.gohtml:101
msgctxt "input"
msgid "Country"
@ -730,6 +741,7 @@ msgid "Choose a country"
msgstr "Escoja un país"
#: web/templates/public/booking/fields.gohtml:195
#: web/templates/admin/payment/details.gohtml:129
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
#: web/templates/admin/taxDetails.gohtml:53
msgctxt "input"
@ -737,6 +749,7 @@ msgid "Email"
msgstr "Correo-e"
#: web/templates/public/booking/fields.gohtml:204
#: web/templates/admin/payment/details.gohtml:133
#: web/templates/admin/taxDetails.gohtml:45
msgctxt "input"
msgid "Phone"
@ -758,10 +771,188 @@ msgid "Total"
msgstr "Total"
#: web/templates/public/booking/fields.gohtml:244
#: web/templates/admin/payment/details.gohtml:84
msgctxt "cart"
msgid "Down payment"
msgstr "A cuenta"
#: web/templates/admin/payment/settings.gohtml:6
#: web/templates/admin/payment/index.gohtml:14
msgctxt "title"
msgid "Payment Settings"
msgstr "Parámetros de pago"
#: web/templates/admin/payment/settings.gohtml:10
#: web/templates/admin/payment/index.gohtml:6
#: web/templates/admin/payment/details.gohtml:11
#: web/templates/admin/layout.gohtml:40
msgctxt "title"
msgid "Payments"
msgstr "Pagos"
#: web/templates/admin/payment/settings.gohtml:21
msgctxt "input"
msgid "Merchant Code"
msgstr "Código del comercio"
#: web/templates/admin/payment/settings.gohtml:30
msgctxt "input"
msgid "Terminal Number"
msgstr "Número de terminal"
#: web/templates/admin/payment/settings.gohtml:40
msgctxt "input"
msgid "Merchant Key (only if must change it)"
msgstr "Clave del comercio (sólo si se debe cambiar)"
#: web/templates/admin/payment/settings.gohtml:42
msgctxt "input"
msgid "Merchant Key"
msgstr "Clave del comercio"
#: web/templates/admin/payment/settings.gohtml:52
msgctxt "title"
msgid "Environment"
msgstr "Entorno"
#: web/templates/admin/payment/settings.gohtml:59
msgctxt "title"
msgid "Integration"
msgstr "Integración"
#: web/templates/admin/payment/settings.gohtml:66
#: web/templates/admin/location.gohtml:53 web/templates/admin/profile.gohtml:78
#: web/templates/admin/taxDetails.gohtml:170
msgctxt "action"
msgid "Save changes"
msgstr "Guardar los cambios"
#: web/templates/admin/payment/index.gohtml:20
#: web/templates/admin/user/login-attempts.gohtml:19
msgctxt "header"
msgid "Date"
msgstr "Fecha"
#: web/templates/admin/payment/index.gohtml:21
#: web/templates/admin/payment/details.gohtml:22
#: web/templates/admin/booking/index.gohtml:21
msgctxt "header"
msgid "Reference"
msgstr "Referencia"
#: web/templates/admin/payment/index.gohtml:22
#: web/templates/admin/payment/details.gohtml:26
#: web/templates/admin/booking/index.gohtml:25
msgctxt "header"
msgid "Status"
msgstr "Estado"
#: web/templates/admin/payment/index.gohtml:23
msgctxt "header"
msgid "Down payment"
msgstr "A cuenta"
#: web/templates/admin/payment/index.gohtml:24
msgctxt "header"
msgid "Total"
msgstr "Total"
#: web/templates/admin/payment/index.gohtml:40
msgid "No payments found."
msgstr "No se ha encontrado ningún pago."
#: web/templates/admin/payment/details.gohtml:7
msgctxt "title"
msgid "Payment %s"
msgstr "Pago %s"
#: web/templates/admin/payment/details.gohtml:19
msgctxt "title"
msgid "Payment"
msgstr "Pago"
#: web/templates/admin/payment/details.gohtml:30
#, fuzzy
msgctxt "payment header"
msgid "Created at"
msgstr "Creado el"
#: web/templates/admin/payment/details.gohtml:34
#, fuzzy
msgctxt "payment header"
msgid "Last updated at"
msgstr "Actualizado por última vez el"
#: web/templates/admin/payment/details.gohtml:48
msgctxt "header"
msgid "Area preferences"
msgstr "Preferencias de área"
#: web/templates/admin/payment/details.gohtml:60
msgctxt "cart"
msgid "Nights"
msgstr "Noches"
#: web/templates/admin/payment/details.gohtml:80 pkg/booking/cart.go:188
msgctxt "cart"
msgid "Tourist tax"
msgstr "Impuesto turístico"
#: web/templates/admin/payment/details.gohtml:92
#: web/templates/admin/campsite/type/option/form.gohtml:18
#: web/templates/admin/campsite/type/option/index.gohtml:6
#: web/templates/admin/campsite/type/option/index.gohtml:17
msgctxt "title"
msgid "Campsite Type Options"
msgstr "Opciones del tipo de alojamiento"
#: web/templates/admin/payment/details.gohtml:113
#: web/templates/admin/taxDetails.gohtml:69
msgctxt "input"
msgid "Address"
msgstr "Dirección"
#: web/templates/admin/payment/details.gohtml:117
#: web/templates/admin/taxDetails.gohtml:93
msgctxt "input"
msgid "Postcode"
msgstr "Código postal"
#: web/templates/admin/payment/details.gohtml:121
#: web/templates/admin/taxDetails.gohtml:77
msgctxt "input"
msgid "City"
msgstr "Población"
#: web/templates/admin/payment/details.gohtml:137
#: web/templates/admin/profile.gohtml:68
msgctxt "input"
msgid "Language"
msgstr "Idioma"
#: web/templates/admin/payment/details.gohtml:141
msgctxt "input"
msgid "ACSI card?"
msgstr "¿Tarjeta ACSI?"
#: web/templates/admin/payment/details.gohtml:142
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "Yes"
msgstr "Sí"
#: web/templates/admin/payment/details.gohtml:142
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "No"
msgstr "No"
#: web/templates/admin/legal/form.gohtml:8
#: web/templates/admin/legal/form.gohtml:29
msgctxt "title"
@ -911,13 +1102,6 @@ msgctxt "input"
msgid "Map Embed"
msgstr "Incrustación del mapa"
#: web/templates/admin/location.gohtml:53 web/templates/admin/profile.gohtml:78
#: web/templates/admin/taxDetails.gohtml:170
#: web/templates/admin/booking/payment.gohtml:65
msgctxt "action"
msgid "Save changes"
msgstr "Guardar los cambios"
#: web/templates/admin/campsite/feature/form.gohtml:8
msgctxt "title"
msgid "Edit Campsite Feature"
@ -1145,22 +1329,6 @@ msgctxt "action"
msgid "Edit Carousel"
msgstr "Editar el carrusel"
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "Yes"
msgstr "Sí"
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "No"
msgstr "No"
#: web/templates/admin/campsite/index.gohtml:47
msgid "No campsites added yet."
msgstr "No se ha añadido ningún alojamiento todavía."
@ -1368,13 +1536,6 @@ msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nueva opción del tipo de alojamiento"
#: web/templates/admin/campsite/type/option/form.gohtml:18
#: web/templates/admin/campsite/type/option/index.gohtml:6
#: web/templates/admin/campsite/type/option/index.gohtml:17
msgctxt "title"
msgid "Campsite Type Options"
msgstr "Opciones del tipo de alojamiento"
#: web/templates/admin/campsite/type/option/form.gohtml:54
msgctxt "input"
msgid "Minimum"
@ -1568,11 +1729,6 @@ msgctxt "input"
msgid "Password Confirmation"
msgstr "Confirmación de la contraseña"
#: web/templates/admin/profile.gohtml:68
msgctxt "input"
msgid "Language"
msgstr "Idioma"
#: web/templates/admin/user/login-attempts.gohtml:6
#: web/templates/admin/user/login-attempts.gohtml:15
msgctxt "title"
@ -1587,11 +1743,6 @@ msgctxt "title"
msgid "Users"
msgstr "Usuarios"
#: web/templates/admin/user/login-attempts.gohtml:19
msgctxt "header"
msgid "Date"
msgstr "Fecha"
#: web/templates/admin/user/login-attempts.gohtml:20
#: web/templates/admin/user/index.gohtml:21
msgctxt "header"
@ -1649,26 +1800,11 @@ msgctxt "input"
msgid "Trade Name"
msgstr "Nombre comercial"
#: web/templates/admin/taxDetails.gohtml:69
msgctxt "input"
msgid "Address"
msgstr "Dirección"
#: web/templates/admin/taxDetails.gohtml:77
msgctxt "input"
msgid "City"
msgstr "Población"
#: web/templates/admin/taxDetails.gohtml:85
msgctxt "input"
msgid "Province"
msgstr "Provincia"
#: web/templates/admin/taxDetails.gohtml:93
msgctxt "input"
msgid "Postcode"
msgstr "Código postal"
#: web/templates/admin/taxDetails.gohtml:111
msgctxt "input"
msgid "Currency"
@ -1854,13 +1990,6 @@ msgctxt "title"
msgid "Company Settings"
msgstr "Parámetros de la empresa"
#: web/templates/admin/layout.gohtml:40
#: web/templates/admin/booking/payment.gohtml:6
#: web/templates/admin/booking/payment.gohtml:15
msgctxt "title"
msgid "Payment Settings"
msgstr "Parámetros de pago"
#: web/templates/admin/layout.gohtml:55
#: web/templates/admin/media/form.gohtml:10
#: web/templates/admin/media/index.gohtml:6
@ -1988,36 +2117,6 @@ msgctxt "title"
msgid "Upload Media"
msgstr "Subida de medio"
#: web/templates/admin/booking/payment.gohtml:20
msgctxt "input"
msgid "Merchant Code"
msgstr "Código del comercio"
#: web/templates/admin/booking/payment.gohtml:29
msgctxt "input"
msgid "Terminal Number"
msgstr "Número de terminal"
#: web/templates/admin/booking/payment.gohtml:39
msgctxt "input"
msgid "Merchant Key (only if must change it)"
msgstr "Clave del comercio (sólo si se debe cambiar)"
#: web/templates/admin/booking/payment.gohtml:41
msgctxt "input"
msgid "Merchant Key"
msgstr "Clave del comercio"
#: web/templates/admin/booking/payment.gohtml:51
msgctxt "title"
msgid "Environment"
msgstr "Entorno"
#: web/templates/admin/booking/payment.gohtml:58
msgctxt "title"
msgid "Integration"
msgstr "Integración"
#: web/templates/admin/booking/index.gohtml:14
msgctxt "action"
msgid "Add Booking"
@ -2028,11 +2127,6 @@ msgctxt "action"
msgid "Export Bookings"
msgstr "Exportar eservas"
#: web/templates/admin/booking/index.gohtml:21
msgctxt "header"
msgid "Reference"
msgstr "Referencia"
#: web/templates/admin/booking/index.gohtml:22
msgctxt "header"
msgid "Arrival Date"
@ -2048,21 +2142,68 @@ msgctxt "header"
msgid "Holder Name"
msgstr "Nombre del titular"
#: web/templates/admin/booking/index.gohtml:25
msgctxt "header"
msgid "Status"
msgstr "Estado"
#: web/templates/admin/booking/index.gohtml:41
msgid "No booking found."
msgstr "No se ha encontrado ninguna reserva."
#: pkg/payment/public.go:109
#: pkg/payment/settings.go:37
msgctxt "redsys environment"
msgid "Test"
msgstr "Pruebas"
#: pkg/payment/settings.go:41
msgctxt "redsys environment"
msgid "Live"
msgstr "Real"
#: pkg/payment/settings.go:50
msgctxt "redsys integration"
msgid "InSite"
msgstr "InSite"
#: pkg/payment/settings.go:54
msgctxt "redsys integration"
msgid "Redirect"
msgstr "Redirección"
#: pkg/payment/settings.go:98
msgid "Merchant code can not be empty."
msgstr "No podéis dejar el código del comercio en blanco."
#: pkg/payment/settings.go:99
msgid "Merchant code must be exactly nine digits long."
msgstr "El código del comercio tiene que ser de nueve dígitos."
#: pkg/payment/settings.go:100
msgid "Merchant code must be a number."
msgstr "El código del comercio tiene que ser un número."
#: pkg/payment/settings.go:104
msgid "Terminal number can not be empty."
msgstr "No podéis dejar el número de terminal en blanco."
#: pkg/payment/settings.go:105
msgid "Terminal number must be a number between 1 and 999."
msgstr "El número de terminal tiene que ser entre 1 y 999."
#: pkg/payment/settings.go:113
msgid "Selected environment is not valid."
msgstr "El entorno escogido no es válido."
#: pkg/payment/settings.go:114
msgid "Selected integration is not valid."
msgstr "La integración escogida no es válida."
#: pkg/payment/settings.go:117
msgid "The merchant key is not valid."
msgstr "Esta clave del comercio no es válida."
#: pkg/payment/public.go:110
msgctxt "order product name"
msgid "Campsite Booking"
msgstr "Reserva de camping"
#: pkg/payment/public.go:346
#: pkg/payment/public.go:342
msgctxt "subject"
msgid "Booking payment successfully received"
msgstr "Se ha recibido correctamente el pago de la reserva"
@ -2140,7 +2281,7 @@ msgstr "El idioma escogido no es válido."
msgid "File must be a valid PNG or JPEG image."
msgstr "El archivo tiene que ser una imagen PNG o JPEG válida."
#: pkg/app/admin.go:70
#: pkg/app/admin.go:73
msgid "Access forbidden"
msgstr "Acceso prohibido"
@ -2563,93 +2704,36 @@ msgstr "No podéis dejar el archivo del medio en blanco."
msgid "Filename can not be empty."
msgstr "No podéis dejar el nombre del archivo en blanco."
#: pkg/booking/cart.go:151
#: pkg/booking/cart.go:150
msgctxt "cart"
msgid "Night"
msgstr "Noche"
#: pkg/booking/cart.go:152
#: pkg/booking/cart.go:151
msgctxt "cart"
msgid "Adult"
msgstr "Adulto"
#: pkg/booking/cart.go:153
#: pkg/booking/cart.go:152
msgctxt "cart"
msgid "Teenager"
msgstr "Adolescente"
#: pkg/booking/cart.go:154
#: pkg/booking/cart.go:153
msgctxt "cart"
msgid "Child"
msgstr "Niño"
#: pkg/booking/cart.go:155
#: pkg/booking/cart.go:154
msgctxt "cart"
msgid "Dog"
msgstr "Perro"
#: pkg/booking/cart.go:190
msgctxt "cart"
msgid "Tourist tax"
msgstr "Impuesto turístico"
#: pkg/booking/admin.go:149
#: pkg/booking/admin.go:126
msgctxt "filename"
msgid "bookings.ods"
msgstr "reservas.ods"
#: pkg/booking/admin.go:177
msgctxt "redsys environment"
msgid "Test"
msgstr "Pruebas"
#: pkg/booking/admin.go:181
msgctxt "redsys environment"
msgid "Live"
msgstr "Real"
#: pkg/booking/admin.go:190
msgctxt "redsys integration"
msgid "InSite"
msgstr "InSite"
#: pkg/booking/admin.go:194
msgctxt "redsys integration"
msgid "Redirect"
msgstr "Redirección"
#: pkg/booking/admin.go:238
msgid "Merchant code can not be empty."
msgstr "No podéis dejar el código del comercio en blanco."
#: pkg/booking/admin.go:239
msgid "Merchant code must be exactly nine digits long."
msgstr "El código del comercio tiene que ser de nueve dígitos."
#: pkg/booking/admin.go:240
msgid "Merchant code must be a number."
msgstr "El código del comercio tiene que ser un número."
#: pkg/booking/admin.go:244
msgid "Terminal number can not be empty."
msgstr "No podéis dejar el número de terminal en blanco."
#: pkg/booking/admin.go:245
msgid "Terminal number must be a number between 1 and 999."
msgstr "El número de terminal tiene que ser entre 1 y 999."
#: pkg/booking/admin.go:253
msgid "Selected environment is not valid."
msgstr "El entorno escogido no es válido."
#: pkg/booking/admin.go:254
msgid "Selected integration is not valid."
msgstr "La integración escogida no es válida."
#: pkg/booking/admin.go:257
msgid "The merchant key is not valid."
msgstr "Esta clave del comercio no es válida."
#: pkg/booking/public.go:275 pkg/booking/public.go:304
msgid "Arrival date must be a valid date."
msgstr "La fecha de llegada tiene que ser una fecha válida."
@ -2771,10 +2855,6 @@ msgstr "El nombre y los apellidos tienen que tener como mínimo una letra."
msgid "It is mandatory to agree to the reservation conditions."
msgstr "Es obligatorio aceptar las condiciones de reserva."
#~ msgctxt "title"
#~ msgid "Payment"
#~ msgstr "Pago"
#~ msgctxt "action"
#~ msgid "Pay"
#~ msgstr "Pagar"

444
po/fr.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-02-13 23:38+0100\n"
"POT-Creation-Date: 2024-02-14 04:47+0100\n"
"PO-Revision-Date: 2024-02-06 10:05+0100\n"
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
"Language-Team: French <traduc@traduc.org>\n"
@ -380,12 +380,14 @@ msgstr "Dim."
#: web/templates/public/campsite/dates.gohtml:4
#: web/templates/public/booking/fields.gohtml:29
#: web/templates/admin/payment/details.gohtml:52
msgctxt "input"
msgid "Arrival date"
msgstr "Date darrivée"
#: web/templates/public/campsite/dates.gohtml:15
#: web/templates/public/booking/fields.gohtml:40
#: web/templates/admin/payment/details.gohtml:56
msgctxt "input"
msgid "Departure date"
msgstr "Date de depart"
@ -393,7 +395,7 @@ msgstr "Date de depart"
#: web/templates/public/surroundings.gohtml:30
msgctxt "title"
msgid "What to Do Outside the Campsite?"
msgstr "Que faire à lextérieur du camping ?"
msgstr "Que faire à lextérieur du camping ?"
#: web/templates/public/surroundings.gohtml:50
msgctxt "title"
@ -624,6 +626,7 @@ msgstr "Locatifs"
#: web/templates/public/layout.gohtml:70
#: web/templates/public/booking/page.gohtml:7
#: web/templates/admin/payment/details.gohtml:41
msgctxt "title"
msgid "Booking"
msgstr "Réservation"
@ -643,6 +646,7 @@ msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Numbe
msgstr "<abbr title=\"Registre du tourisme de Catalogne\"># RTC</abbr> %s"
#: web/templates/public/booking/fields.gohtml:14
#: web/templates/admin/payment/details.gohtml:44
msgctxt "title"
msgid "Accommodation"
msgstr "Hébergement"
@ -658,16 +662,19 @@ msgid "Guests"
msgstr "Personnes logeant"
#: web/templates/public/booking/fields.gohtml:59
#: web/templates/admin/payment/details.gohtml:64
msgctxt "input"
msgid "Adults aged 17 or older"
msgstr "Adultes âgés 17 ans ou plus"
#: web/templates/public/booking/fields.gohtml:70
#: web/templates/admin/payment/details.gohtml:68
msgctxt "input"
msgid "Teenagers from 11 to 16 years old"
msgstr "Adolescents de 11 à 16 ans"
#: web/templates/public/booking/fields.gohtml:81
#: web/templates/admin/payment/details.gohtml:72
msgctxt "input"
msgid "Children from 2 to 10 years old"
msgstr "Enfants de 2 à 10 ans"
@ -677,6 +684,7 @@ msgid "Note: Due to guest capacity, we have added more accomodations to the book
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:99
#: web/templates/admin/payment/details.gohtml:76
msgctxt "input"
msgid "Dogs"
msgstr "Chiens"
@ -695,11 +703,13 @@ msgid "Campground map"
msgstr "Plan du camping"
#: web/templates/public/booking/fields.gohtml:145
#: web/templates/admin/payment/details.gohtml:106
msgctxt "title"
msgid "Customer Details"
msgstr "Détails du client"
#: web/templates/public/booking/fields.gohtml:148
#: web/templates/admin/payment/details.gohtml:109
msgctxt "input"
msgid "Full name"
msgstr "Nom et prénom"
@ -720,6 +730,7 @@ msgid "Town or village (optional)"
msgstr "Ville (Facultatif)"
#: web/templates/public/booking/fields.gohtml:184
#: web/templates/admin/payment/details.gohtml:125
#: web/templates/admin/taxDetails.gohtml:101
msgctxt "input"
msgid "Country"
@ -730,6 +741,7 @@ msgid "Choose a country"
msgstr "Choisissez un pays"
#: web/templates/public/booking/fields.gohtml:195
#: web/templates/admin/payment/details.gohtml:129
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
#: web/templates/admin/taxDetails.gohtml:53
msgctxt "input"
@ -737,6 +749,7 @@ msgid "Email"
msgstr "E-mail"
#: web/templates/public/booking/fields.gohtml:204
#: web/templates/admin/payment/details.gohtml:133
#: web/templates/admin/taxDetails.gohtml:45
msgctxt "input"
msgid "Phone"
@ -745,7 +758,7 @@ msgstr "Téléphone"
#: web/templates/public/booking/fields.gohtml:215
msgctxt "input"
msgid "ACSI card? (optional)"
msgstr "Carte ACSI ? (Facultatif)"
msgstr "Carte ACSI ? (Facultatif)"
#: web/templates/public/booking/fields.gohtml:222
msgctxt "input"
@ -758,10 +771,188 @@ msgid "Total"
msgstr "Totale"
#: web/templates/public/booking/fields.gohtml:244
#: web/templates/admin/payment/details.gohtml:84
msgctxt "cart"
msgid "Down payment"
msgstr "Acompte"
#: web/templates/admin/payment/settings.gohtml:6
#: web/templates/admin/payment/index.gohtml:14
msgctxt "title"
msgid "Payment Settings"
msgstr "Paramètres de paiement"
#: web/templates/admin/payment/settings.gohtml:10
#: web/templates/admin/payment/index.gohtml:6
#: web/templates/admin/payment/details.gohtml:11
#: web/templates/admin/layout.gohtml:40
msgctxt "title"
msgid "Payments"
msgstr "Paiements"
#: web/templates/admin/payment/settings.gohtml:21
msgctxt "input"
msgid "Merchant Code"
msgstr "Code Marchant"
#: web/templates/admin/payment/settings.gohtml:30
msgctxt "input"
msgid "Terminal Number"
msgstr "Numéro de terminal"
#: web/templates/admin/payment/settings.gohtml:40
msgctxt "input"
msgid "Merchant Key (only if must change it)"
msgstr "Clé marchande (uniquement si vous devez la changer)"
#: web/templates/admin/payment/settings.gohtml:42
msgctxt "input"
msgid "Merchant Key"
msgstr "Clé Marchant"
#: web/templates/admin/payment/settings.gohtml:52
msgctxt "title"
msgid "Environment"
msgstr "Environnement"
#: web/templates/admin/payment/settings.gohtml:59
msgctxt "title"
msgid "Integration"
msgstr "Intégration"
#: web/templates/admin/payment/settings.gohtml:66
#: web/templates/admin/location.gohtml:53 web/templates/admin/profile.gohtml:78
#: web/templates/admin/taxDetails.gohtml:170
msgctxt "action"
msgid "Save changes"
msgstr "Enregistrer les changements"
#: web/templates/admin/payment/index.gohtml:20
#: web/templates/admin/user/login-attempts.gohtml:19
msgctxt "header"
msgid "Date"
msgstr "Date"
#: web/templates/admin/payment/index.gohtml:21
#: web/templates/admin/payment/details.gohtml:22
#: web/templates/admin/booking/index.gohtml:21
msgctxt "header"
msgid "Reference"
msgstr "Référence"
#: web/templates/admin/payment/index.gohtml:22
#: web/templates/admin/payment/details.gohtml:26
#: web/templates/admin/booking/index.gohtml:25
msgctxt "header"
msgid "Status"
msgstr "Statut"
#: web/templates/admin/payment/index.gohtml:23
msgctxt "header"
msgid "Down payment"
msgstr "Acompte"
#: web/templates/admin/payment/index.gohtml:24
msgctxt "header"
msgid "Total"
msgstr "Totale"
#: web/templates/admin/payment/index.gohtml:40
msgid "No payments found."
msgstr "Aucun paiement trouvée."
#: web/templates/admin/payment/details.gohtml:7
msgctxt "title"
msgid "Payment %s"
msgstr "Paiement %s"
#: web/templates/admin/payment/details.gohtml:19
msgctxt "title"
msgid "Payment"
msgstr "Paiement"
#: web/templates/admin/payment/details.gohtml:30
#, fuzzy
msgctxt "payment header"
msgid "Created at"
msgstr "Créé à"
#: web/templates/admin/payment/details.gohtml:34
#, fuzzy
msgctxt "payment header"
msgid "Last updated at"
msgstr "Dernière mise à jour à"
#: web/templates/admin/payment/details.gohtml:48
msgctxt "header"
msgid "Area preferences"
msgstr "Préférences de zone"
#: web/templates/admin/payment/details.gohtml:60
msgctxt "cart"
msgid "Nights"
msgstr "Nuits"
#: web/templates/admin/payment/details.gohtml:80 pkg/booking/cart.go:188
msgctxt "cart"
msgid "Tourist tax"
msgstr "Taxe touristique"
#: web/templates/admin/payment/details.gohtml:92
#: web/templates/admin/campsite/type/option/form.gohtml:18
#: web/templates/admin/campsite/type/option/index.gohtml:6
#: web/templates/admin/campsite/type/option/index.gohtml:17
msgctxt "title"
msgid "Campsite Type Options"
msgstr "Options de type demplacement de camping"
#: web/templates/admin/payment/details.gohtml:113
#: web/templates/admin/taxDetails.gohtml:69
msgctxt "input"
msgid "Address"
msgstr "Adresse"
#: web/templates/admin/payment/details.gohtml:117
#: web/templates/admin/taxDetails.gohtml:93
msgctxt "input"
msgid "Postcode"
msgstr "Code Postal"
#: web/templates/admin/payment/details.gohtml:121
#: web/templates/admin/taxDetails.gohtml:77
msgctxt "input"
msgid "City"
msgstr "Ville"
#: web/templates/admin/payment/details.gohtml:137
#: web/templates/admin/profile.gohtml:68
msgctxt "input"
msgid "Language"
msgstr "Langue"
#: web/templates/admin/payment/details.gohtml:141
msgctxt "input"
msgid "ACSI card?"
msgstr "Carte ACSI ?"
#: web/templates/admin/payment/details.gohtml:142
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "Yes"
msgstr "Oui"
#: web/templates/admin/payment/details.gohtml:142
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "No"
msgstr "Non"
#: web/templates/admin/legal/form.gohtml:8
#: web/templates/admin/legal/form.gohtml:29
msgctxt "title"
@ -911,13 +1102,6 @@ msgctxt "input"
msgid "Map Embed"
msgstr "Carte intégrée"
#: web/templates/admin/location.gohtml:53 web/templates/admin/profile.gohtml:78
#: web/templates/admin/taxDetails.gohtml:170
#: web/templates/admin/booking/payment.gohtml:65
msgctxt "action"
msgid "Save changes"
msgstr "Enregistrer les changements"
#: web/templates/admin/campsite/feature/form.gohtml:8
msgctxt "title"
msgid "Edit Campsite Feature"
@ -971,7 +1155,7 @@ msgstr "Actions"
#: web/templates/admin/campsite/type/feature/index.gohtml:36
#: web/templates/admin/amenity/feature/index.gohtml:35
msgid "Are you sure you wish to delete this feature?"
msgstr "Êtes-vous sûr de vouloir supprimer cette caractéristique ?"
msgstr "Êtes-vous sûr de vouloir supprimer cette caractéristique ?"
#: web/templates/admin/campsite/feature/index.gohtml:47
#: web/templates/admin/campsite/carousel/index.gohtml:49
@ -1048,7 +1232,7 @@ msgstr "Légende"
#: web/templates/admin/amenity/carousel/index.gohtml:35
#: web/templates/admin/home/index.gohtml:103
msgid "Are you sure you wish to delete this slide?"
msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?"
msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?"
#: web/templates/admin/campsite/carousel/index.gohtml:58
#: web/templates/admin/campsite/type/carousel/index.gohtml:59
@ -1145,22 +1329,6 @@ msgctxt "action"
msgid "Edit Carousel"
msgstr "Modifier le carrousel"
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "Yes"
msgstr "Oui"
#: web/templates/admin/campsite/index.gohtml:41
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "No"
msgstr "Non"
#: web/templates/admin/campsite/index.gohtml:47
msgid "No campsites added yet."
msgstr "Aucun camping na encore été ajouté."
@ -1368,13 +1536,6 @@ msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nouvelle option de type demplacement de camping"
#: web/templates/admin/campsite/type/option/form.gohtml:18
#: web/templates/admin/campsite/type/option/index.gohtml:6
#: web/templates/admin/campsite/type/option/index.gohtml:17
msgctxt "title"
msgid "Campsite Type Options"
msgstr "Options de type demplacement de camping"
#: web/templates/admin/campsite/type/option/form.gohtml:54
msgctxt "input"
msgid "Minimum"
@ -1402,7 +1563,7 @@ msgstr "Ajouter une option"
#: web/templates/admin/campsite/type/option/index.gohtml:35
msgid "Are you sure you wish to delete this option?"
msgstr "Êtes-vous sûr de vouloir supprimer cette option ?"
msgstr "Êtes-vous sûr de vouloir supprimer cette option ?"
#: web/templates/admin/campsite/type/option/index.gohtml:56
msgid "No campsite type options added yet."
@ -1541,7 +1702,7 @@ msgstr "Service"
#: web/templates/admin/services/index.gohtml:79
msgid "Are you sure you wish to delete this service?"
msgstr "Êtes-vous sûr de vouloir supprimer ce service ?"
msgstr "Êtes-vous sûr de vouloir supprimer ce service ?"
#: web/templates/admin/services/index.gohtml:100
msgid "No services added yet."
@ -1568,11 +1729,6 @@ msgctxt "input"
msgid "Password Confirmation"
msgstr "Confirmation du mot de passe"
#: web/templates/admin/profile.gohtml:68
msgctxt "input"
msgid "Language"
msgstr "Langue"
#: web/templates/admin/user/login-attempts.gohtml:6
#: web/templates/admin/user/login-attempts.gohtml:15
msgctxt "title"
@ -1587,11 +1743,6 @@ msgctxt "title"
msgid "Users"
msgstr "Utilisateurs"
#: web/templates/admin/user/login-attempts.gohtml:19
msgctxt "header"
msgid "Date"
msgstr "Date"
#: web/templates/admin/user/login-attempts.gohtml:20
#: web/templates/admin/user/index.gohtml:21
msgctxt "header"
@ -1625,7 +1776,7 @@ msgstr "Rôle"
#: web/templates/admin/user/index.gohtml:27
msgid "Are you sure you wish to delete this user?"
msgstr "Êtes-vous sûr de vouloir supprimer ce utilisateur ?"
msgstr "Êtes-vous sûr de vouloir supprimer ce utilisateur ?"
#: web/templates/admin/taxDetails.gohtml:6
#: web/templates/admin/taxDetails.gohtml:15
@ -1649,26 +1800,11 @@ msgctxt "input"
msgid "Trade Name"
msgstr "Nom commercial"
#: web/templates/admin/taxDetails.gohtml:69
msgctxt "input"
msgid "Address"
msgstr "Adresse"
#: web/templates/admin/taxDetails.gohtml:77
msgctxt "input"
msgid "City"
msgstr "Ville"
#: web/templates/admin/taxDetails.gohtml:85
msgctxt "input"
msgid "Province"
msgstr "Province"
#: web/templates/admin/taxDetails.gohtml:93
msgctxt "input"
msgid "Postcode"
msgstr "Code Postal"
#: web/templates/admin/taxDetails.gohtml:111
msgctxt "input"
msgid "Currency"
@ -1762,7 +1898,7 @@ msgstr "Ajouter un point dintérêt"
#: web/templates/admin/surroundings/index.gohtml:88
msgid "Are you sure you wish to delete this highlight?"
msgstr "Êtes-vous sûr de vouloir supprimer cette point dintérêt ?"
msgstr "Êtes-vous sûr de vouloir supprimer cette point dintérêt ?"
#: web/templates/admin/surroundings/index.gohtml:110
msgid "No highlights added yet."
@ -1838,7 +1974,7 @@ msgstr "Ajouter un installation"
#: web/templates/admin/amenity/index.gohtml:29
msgid "Are you sure you wish to delete this amenity?"
msgstr "Êtes-vous sûr de vouloir supprimer ce installation ?"
msgstr "Êtes-vous sûr de vouloir supprimer ce installation ?"
#: web/templates/admin/amenity/index.gohtml:53
msgid "No amenities added yet."
@ -1854,13 +1990,6 @@ msgctxt "title"
msgid "Company Settings"
msgstr "Paramètres de lentreprise"
#: web/templates/admin/layout.gohtml:40
#: web/templates/admin/booking/payment.gohtml:6
#: web/templates/admin/booking/payment.gohtml:15
msgctxt "title"
msgid "Payment Settings"
msgstr "Paramètres de paiement"
#: web/templates/admin/layout.gohtml:55
#: web/templates/admin/media/form.gohtml:10
#: web/templates/admin/media/index.gohtml:6
@ -1988,36 +2117,6 @@ msgctxt "title"
msgid "Upload Media"
msgstr "Envoyer un fichier"
#: web/templates/admin/booking/payment.gohtml:20
msgctxt "input"
msgid "Merchant Code"
msgstr "Code Marchant"
#: web/templates/admin/booking/payment.gohtml:29
msgctxt "input"
msgid "Terminal Number"
msgstr "Numéro de terminal"
#: web/templates/admin/booking/payment.gohtml:39
msgctxt "input"
msgid "Merchant Key (only if must change it)"
msgstr "Clé marchande (uniquement si vous devez la changer)"
#: web/templates/admin/booking/payment.gohtml:41
msgctxt "input"
msgid "Merchant Key"
msgstr "Clé Marchant"
#: web/templates/admin/booking/payment.gohtml:51
msgctxt "title"
msgid "Environment"
msgstr "Environnement"
#: web/templates/admin/booking/payment.gohtml:58
msgctxt "title"
msgid "Integration"
msgstr "Intégration"
#: web/templates/admin/booking/index.gohtml:14
msgctxt "action"
msgid "Add Booking"
@ -2028,11 +2127,6 @@ msgctxt "action"
msgid "Export Bookings"
msgstr "Exporter les réservations"
#: web/templates/admin/booking/index.gohtml:21
msgctxt "header"
msgid "Reference"
msgstr "Référence"
#: web/templates/admin/booking/index.gohtml:22
msgctxt "header"
msgid "Arrival Date"
@ -2048,21 +2142,68 @@ msgctxt "header"
msgid "Holder Name"
msgstr "Nom du titulaire"
#: web/templates/admin/booking/index.gohtml:25
msgctxt "header"
msgid "Status"
msgstr "Statut"
#: web/templates/admin/booking/index.gohtml:41
msgid "No booking found."
msgstr "Aucune réservation trouvée."
#: pkg/payment/public.go:109
#: pkg/payment/settings.go:37
msgctxt "redsys environment"
msgid "Test"
msgstr "Test"
#: pkg/payment/settings.go:41
msgctxt "redsys environment"
msgid "Live"
msgstr "Live"
#: pkg/payment/settings.go:50
msgctxt "redsys integration"
msgid "InSite"
msgstr "Insite"
#: pkg/payment/settings.go:54
msgctxt "redsys integration"
msgid "Redirect"
msgstr "Redirection"
#: pkg/payment/settings.go:98
msgid "Merchant code can not be empty."
msgstr "Le code marchand ne peut pas être vide."
#: pkg/payment/settings.go:99
msgid "Merchant code must be exactly nine digits long."
msgstr "Le code marchand doit comporter exactement neuf chiffres."
#: pkg/payment/settings.go:100
msgid "Merchant code must be a number."
msgstr "Le code du commerçant doit être un chiffre."
#: pkg/payment/settings.go:104
msgid "Terminal number can not be empty."
msgstr "Le numéro de terminal ne peut pas être vide."
#: pkg/payment/settings.go:105
msgid "Terminal number must be a number between 1 and 999."
msgstr "Le numéro de terminal doit être compris entre 1 et 999."
#: pkg/payment/settings.go:113
msgid "Selected environment is not valid."
msgstr "Lenvironnement sélectionné nest pas valide."
#: pkg/payment/settings.go:114
msgid "Selected integration is not valid."
msgstr "Lintégration sélectionnée nest pas valide."
#: pkg/payment/settings.go:117
msgid "The merchant key is not valid."
msgstr "La clé marchand nest pas valide."
#: pkg/payment/public.go:110
msgctxt "order product name"
msgid "Campsite Booking"
msgstr "Réservation camping"
#: pkg/payment/public.go:346
#: pkg/payment/public.go:342
msgctxt "subject"
msgid "Booking payment successfully received"
msgstr "Paiement de réservation reçu avec succès"
@ -2140,7 +2281,7 @@ msgstr "La langue sélectionnée nest pas valide."
msgid "File must be a valid PNG or JPEG image."
msgstr "Le fichier doit être une image PNG ou JPEG valide."
#: pkg/app/admin.go:70
#: pkg/app/admin.go:73
msgid "Access forbidden"
msgstr "Accès interdit"
@ -2563,93 +2704,36 @@ msgstr "Le fichier téléchargé ne peut pas être vide."
msgid "Filename can not be empty."
msgstr "Le nom de fichier ne peut pas être vide."
#: pkg/booking/cart.go:151
#: pkg/booking/cart.go:150
msgctxt "cart"
msgid "Night"
msgstr "Nuit"
#: pkg/booking/cart.go:152
#: pkg/booking/cart.go:151
msgctxt "cart"
msgid "Adult"
msgstr "Adulte"
#: pkg/booking/cart.go:153
#: pkg/booking/cart.go:152
msgctxt "cart"
msgid "Teenager"
msgstr "Adolescent"
#: pkg/booking/cart.go:154
#: pkg/booking/cart.go:153
msgctxt "cart"
msgid "Child"
msgstr "Enfant"
#: pkg/booking/cart.go:155
#: pkg/booking/cart.go:154
msgctxt "cart"
msgid "Dog"
msgstr "Chien"
#: pkg/booking/cart.go:190
msgctxt "cart"
msgid "Tourist tax"
msgstr "Taxe touristique"
#: pkg/booking/admin.go:149
#: pkg/booking/admin.go:126
msgctxt "filename"
msgid "bookings.ods"
msgstr "reservations.ods"
#: pkg/booking/admin.go:177
msgctxt "redsys environment"
msgid "Test"
msgstr "Test"
#: pkg/booking/admin.go:181
msgctxt "redsys environment"
msgid "Live"
msgstr "Live"
#: pkg/booking/admin.go:190
msgctxt "redsys integration"
msgid "InSite"
msgstr "Insite"
#: pkg/booking/admin.go:194
msgctxt "redsys integration"
msgid "Redirect"
msgstr "Redirection"
#: pkg/booking/admin.go:238
msgid "Merchant code can not be empty."
msgstr "Le code marchand ne peut pas être vide."
#: pkg/booking/admin.go:239
msgid "Merchant code must be exactly nine digits long."
msgstr "Le code marchand doit comporter exactement neuf chiffres."
#: pkg/booking/admin.go:240
msgid "Merchant code must be a number."
msgstr "Le code du commerçant doit être un chiffre."
#: pkg/booking/admin.go:244
msgid "Terminal number can not be empty."
msgstr "Le numéro de terminal ne peut pas être vide."
#: pkg/booking/admin.go:245
msgid "Terminal number must be a number between 1 and 999."
msgstr "Le numéro de terminal doit être compris entre 1 et 999."
#: pkg/booking/admin.go:253
msgid "Selected environment is not valid."
msgstr "Lenvironnement sélectionné nest pas valide."
#: pkg/booking/admin.go:254
msgid "Selected integration is not valid."
msgstr "Lintégration sélectionnée nest pas valide."
#: pkg/booking/admin.go:257
msgid "The merchant key is not valid."
msgstr "La clé marchand nest pas valide."
#: pkg/booking/public.go:275 pkg/booking/public.go:304
msgid "Arrival date must be a valid date."
msgstr "La date darrivée doit être une date valide."
@ -2771,10 +2855,6 @@ msgstr "Le nom complet doit comporter au moins une lettre."
msgid "It is mandatory to agree to the reservation conditions."
msgstr "Il est obligatoire daccepter les conditions de réservation."
#~ msgctxt "title"
#~ msgid "Payment"
#~ msgstr "Paiement"
#~ msgctxt "action"
#~ msgid "Pay"
#~ msgstr "Payer"

View File

@ -0,0 +1,7 @@
-- Revert camper:order_code from pg
begin;
drop function if exists camper.reference(camper.payment);
commit;

View File

@ -246,7 +246,7 @@ payment_status_i18n [roles schema_camper payment_status language] 2024-02-11T21:
available_payment_status [payment_status payment_status_i18n] 2024-02-11T21:22:38Z jordi fita mas <jordi@tandem.blog> # Add available payment statuses
positive_integer [schema_camper] 2024-02-13T20:24:09Z jordi fita mas <jordi@tandem.blog> # Add positive integer domain
percentage [schema_camper] 2024-02-13T20:09:10Z jordi fita mas <jordi@tandem.blog> # Add percentage domain
payment [roles schema_camper company campsite_type payment_status positive_integer nonnegative_integer percentage] 2024-02-11T21:54:13Z jordi fita mas <jordi@tandem.blog> # Add relation for payments
payment [roles schema_camper company campsite_type payment_status positive_integer nonnegative_integer percentage currency_code currency] 2024-02-11T21:54:13Z jordi fita mas <jordi@tandem.blog> # Add relation for payments
payment_customer [roles schema_camper payment country country_code extension_pg_libphonenumber] 2024-02-12T00:10:20Z jordi fita mas <jordi@tandem.blog> # Add relation of payment customer
payment_option [roles schema_camper payment campsite_type_option positive_integer nonnegative_integer] 2024-02-12T00:58:07Z jordi fita mas <jordi@tandem.blog> # Add relation of payment for campsite type options
draft_payment [roles schema_camper season_calendar season campsite_type campsite_type_pet_cost campsite_type_cost campsite_type_option_cost campsite_type_option payment payment_option] 2024-02-12T01:31:52Z jordi fita mas <jordi@tandem.blog> # Add function to create a payment draft
@ -257,3 +257,4 @@ redsys_decode_response [roles schema_camper extension_pgcrypto decode_base64url
payment_redsys_response [roles schema_camper payment currency_code] 2024-02-12T21:32:23Z jordi fita mas <jordi@tandem.blog> # Add relation for Redsys responses to payments
process_payment_response [roles schema_camper redsys_response payment payment_redsys_response parse_price currency] 2024-02-12T22:04:48Z jordi fita mas <jordi@tandem.blog> # Add function to process Redsys response of a payment
down_payment [roles schema_camper payment] 2024-02-13T21:53:44Z jordi fita mas <jordi@tandem.blog> # Add function to compute payment down payment from its percentage
payment_reference [roles schema_camper payment] 2024-02-14T01:45:37Z jordi fita mas <jordi@tandem.blog> # Add function to generate a payment reference

View File

@ -46,14 +46,14 @@ insert into campsite_type (campsite_type_id, slug, company_id, name, media_id, m
values (12, 'c1b6f4fc-32c1-4cd5-b796-0c5059152a52', 2, 'Plots', 10, 6, '[1, 7]', true)
;
insert into payment (payment_id, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, down_payment_percent, zone_preferences)
values (22, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, '')
, (23, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, '')
, (24, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2500, 0.75, '')
, (25, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1234, 0.99, '')
, (26, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, '')
, (27, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 987654, 0.33, '')
, (28, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 987654, 0.19, '')
insert into payment (payment_id, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, currency_code, down_payment_percent, zone_preferences)
values (22, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', 1.0, '')
, (23, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', 0.5, '')
, (24, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2500, 'EUR', 0.75, '')
, (25, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1234, 'EUR', 0.99, '')
, (26, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 'EUR', 0.5, '')
, (27, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 987654, 'EUR', 0.33, '')
, (28, 2, 12, '2024-08-28', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 987654, 'EUR', 0.19, '')
;
select bag_eq(

View File

@ -95,9 +95,9 @@ values (16, 4, 800)
, (20, 8, 590)
;
insert into payment (payment_id, slug, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences, payment_status, created_at, updated_at)
values (22, '7cccfe16-695e-486d-a6a5-1162fb85cafb', 2, 12, current_date + 60, current_date + 62, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 'draft', '2024-01-01 01:01:01', '2024-01-01 01:01:01')
, (24, '6eeae04c-2fea-4d67-97dc-a4b8a83df99f', 2, 12, current_date + 61, current_date + 62, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 'pending', '2024-01-01 02:02:02', '2024-01-01 02:02:02')
insert into payment (payment_id, slug, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, currency_code, zone_preferences, payment_status, created_at, updated_at)
values (22, '7cccfe16-695e-486d-a6a5-1162fb85cafb', 2, 12, current_date + 60, current_date + 62, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'USD', '', 'draft', '2024-01-01 01:01:01', '2024-01-01 01:01:01')
, (24, '6eeae04c-2fea-4d67-97dc-a4b8a83df99f', 2, 12, current_date + 61, current_date + 62, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'USD', '', 'pending', '2024-01-01 02:02:02', '2024-01-01 02:02:02')
;
insert into payment_option (payment_id, campsite_type_option_id, units, subtotal)
@ -128,12 +128,12 @@ select results_ne(
);
select bag_eq(
$$ select company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, down_payment_percent, zone_preferences, payment_status, created_at, updated_at from payment $$,
$$ values (2, 12, current_date + 58, current_date + 65, 3200, 2, 10420, 4, 20840, 6, 25080, 3, 2450, 4900, 79160, 0.3, 'pref I before E', 'draft', '2024-01-01 01:01:01', current_timestamp)
, (2, 14, current_date + 59, current_date + 64, 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, 0.3, '', 'draft', current_timestamp, current_timestamp)
, (2, 14, current_date + 6, current_date + 11, 85000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 86750, 1.0, '', 'draft', current_timestamp, current_timestamp)
, (2, 12, current_date + 61, current_date + 62, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, '', 'pending', '2024-01-01 02:02:02', '2024-01-01 02:02:02')
, (2, 14, current_date + 31, current_date + 36, 85000, 2, 0, 1, 0, 1, 0, 1, 0, 3500, 96000, 0.3, 'under a tree', 'draft', current_timestamp, current_timestamp)
$$ select company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, currency_code, down_payment_percent, zone_preferences, payment_status, created_at, updated_at from payment $$,
$$ values (2, 12, current_date + 58, current_date + 65, 3200, 2, 10420, 4, 20840, 6, 25080, 3, 2450, 4900, 79160, 'EUR', 0.3, 'pref I before E', 'draft', '2024-01-01 01:01:01', current_timestamp)
, (2, 14, current_date + 59, current_date + 64, 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, 'EUR', 0.3, '', 'draft', current_timestamp, current_timestamp)
, (2, 14, current_date + 6, current_date + 11, 85000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 86750, 'EUR', 1.0, '', 'draft', current_timestamp, current_timestamp)
, (2, 12, current_date + 61, current_date + 62, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'USD', 1.0, '', 'pending', '2024-01-01 02:02:02', '2024-01-01 02:02:02')
, (2, 14, current_date + 31, current_date + 36, 85000, 2, 0, 1, 0, 1, 0, 1, 0, 3500, 96000, 'EUR', 0.3, 'under a tree', 'draft', current_timestamp, current_timestamp)
$$,
'Should have added and updated payments'
);

View File

@ -5,7 +5,7 @@ reset client_min_messages;
begin;
select plan(108);
select plan(114);
set search_path to camper, public;
@ -108,6 +108,13 @@ select col_type_is('payment', 'total', 'nonnegative_integer');
select col_not_null('payment', 'total');
select col_hasnt_default('payment', 'total');
select has_column('payment', 'currency_code');
select col_is_fk('payment', 'currency_code');
select fk_ok('payment', 'currency_code', 'currency', 'currency_code');
select col_type_is('payment', 'currency_code', 'currency_code');
select col_not_null('payment', 'currency_code');
select col_hasnt_default('payment', 'currency_code');
select has_column('payment', 'down_payment_percent');
select col_type_is('payment', 'down_payment_percent', 'percentage');
select col_not_null('payment', 'down_payment_percent');
@ -166,7 +173,7 @@ values (10, 1, 2, 'Type A', '<p>A</p>', 5, '[1, 7]', true)
;
select throws_ok(
$$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences) values (1, 10, '2024-07-07', '2024-07-07', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, '') $$,
$$ insert into payment (company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, currency_code, zone_preferences) values (1, 10, '2024-07-07', '2024-07-07', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', '') $$,
'23514', 'new row for relation "payment" violates check constraint "departure_after_arrival"',
'Should not be able to insert a payment with a departure date equal or before the arrival date (i.e., at least one night)'
);

View File

@ -42,42 +42,6 @@ select col_not_null('payment_option', 'subtotal');
select col_hasnt_default('payment_option', 'subtotal');
set client_min_messages to warning;
truncate payment_option cascade;
truncate payment cascade;
truncate campsite_type_option cascade;
truncate campsite_type cascade;
truncate media cascade;
truncate media_content cascade;
truncate company cascade;
reset client_min_messages;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag)
values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca')
;
insert into media_content (media_type, bytes)
values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};')
;
insert into media (media_id, company_id, original_filename, content_hash)
values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};'))
;
insert into campsite_type (campsite_type_id, company_id, media_id, name, description, max_campers, bookable_nights, active)
values (10, 1, 2, 'Type A', '<p>A</p>', 5, '[1, 7]', true)
;
insert into campsite_type_option (campsite_type_option_id, campsite_type_id, name, range, per_night)
values (11, 10, 'Option 1', '[2, 2]', true)
, (12, 10, 'Option 2', '[4, 8]', true)
;
insert into payment (payment_id, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences)
values (15, 1, 10, '2024-07-07', '2024-07-08', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, '')
;
select *
from finish();

View File

@ -0,0 +1,74 @@
-- Test reference
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(10);
set search_path to camper, public;
select has_function('camper', 'reference', array['payment']);
select function_lang_is('camper', 'reference', array['payment'], 'sql');
select function_returns('camper', 'reference', array['payment'], 'text');
select isnt_definer('camper', 'reference', array['payment']);
select volatility_is('camper', 'reference', array['payment'], 'stable');
select function_privs_are('camper', 'reference', array['payment'], 'guest', array['EXECUTE']);
select function_privs_are('camper', 'reference', array['payment'], 'employee', array['EXECUTE']);
select function_privs_are('camper', 'reference', array['payment'], 'admin', array['EXECUTE']);
select function_privs_are('camper', 'reference', array['payment'], 'authenticator', array[]::text[]);
set client_min_messages to warning;
truncate payment cascade;
truncate campsite_type cascade;
truncate media cascade;
truncate media_content cascade;
truncate company cascade;
reset client_min_messages;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 350, '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 (10, 2, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};'))
;
insert into campsite_type (campsite_type_id, slug, company_id, name, media_id, max_campers, bookable_nights, overflow_allowed)
values (12, 'c1b6f4fc-32c1-4cd5-b796-0c5059152a52', 2, 'Plots', 10, 6, '[1, 7]', true)
;
insert into payment (payment_id, slug, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, currency_code, zone_preferences)
values (22, '4ef35e2f-ef98-42d6-a724-913bd761ca8c', 2, 12, '2024-08-29', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', '')
, (23, '6d1b8e4c-c3c6-4fe4-92c1-2cbf94526693', 2, 12, '2024-08-29', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', '')
, (24, '8d38a482-8a25-4d85-9929-e5f425fcac04', 2, 12, '2024-08-29', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', '')
, (25, 'b770f8b7-f148-4ab4-a786-aa070af598e5', 2, 12, '2024-08-29', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', '')
, (26, '31910d73-d343-44b7-8a29-f7e075b64933', 2, 12, '2024-08-29', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', '')
, (27, 'c9488490-ac09-4402-90cd-f6f0546f04c0', 2, 12, '2024-08-29', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', '')
, (28, '5819823e-c0ac-4baa-a3ae-515fbb70e909', 2, 12, '2024-08-29', '2024-09-03', 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'EUR', '')
;
select bag_eq(
$$ select payment_id, payment.reference from payment $$,
$$ values (22, '000000224ef3')
, (23, '000000236d1b')
, (24, '000000248d38')
, (25, '00000025b770')
, (26, '000000263191')
, (27, '00000027c948')
, (28, '000000285819')
$$,
'Should give out the order code for each payment'
);
select *
from finish();
rollback;

View File

@ -44,14 +44,14 @@ insert into campsite_type (campsite_type_id, slug, company_id, name, media_id, m
values (12, 'c1b6f4fc-32c1-4cd5-b796-0c5059152a52', 2, 'Plots', 10, 6, '[1, 7]', true)
;
insert into payment (payment_id, slug, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences, payment_status, created_at, updated_at)
values (22, '4ef35e2f-ef98-42d6-a724-913bd761ca8c', 2, 12, '2024-08-28', '2024-09-04', 3200, 2, 10420, 4, 20840, 6, 25080, 3, 2450, 4900, 79160, 'pref I before E', 'draft', '2024-01-01 01:01:01', '2024-01-01 01:01:01')
, (24, '6d1b8e4c-c3c6-4fe4-92c1-2cbf94526693', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, '', 'pending', '2024-01-02 02:02:02', '2024-01-02 02:02:02')
, (26, '8d38a482-8a25-4d85-9929-e5f425fcac04', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, '', 'completed', '2024-01-03 03:03:03', '2024-01-03 03:03:03')
, (28, 'b770f8b7-f148-4ab4-a786-aa070af598e5', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, '', 'failed', '2024-01-04 04:04:04', '2024-01-04 04:04:04')
, (30, '31910d73-d343-44b7-8a29-f7e075b64933', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, '', 'refunded', '2024-01-05 05:05:05', '2024-01-05 05:05:05')
, (32, 'c9488490-ac09-4402-90cd-f6f0546f04c0', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, '', 'pending', '2024-01-05 05:05:05', '2024-01-05 05:05:05')
, (34, '5819823e-c0ac-4baa-a3ae-515fbb70e909', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, '', 'pending', '2024-01-05 05:05:05', '2024-01-06 06:06:06')
insert into payment (payment_id, slug, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, currency_code, zone_preferences, payment_status, created_at, updated_at)
values (22, '4ef35e2f-ef98-42d6-a724-913bd761ca8c', 2, 12, '2024-08-28', '2024-09-04', 3200, 2, 10420, 4, 20840, 6, 25080, 3, 2450, 4900, 79160, 'EUR', 'pref I before E', 'draft', '2024-01-01 01:01:01', '2024-01-01 01:01:01')
, (24, '6d1b8e4c-c3c6-4fe4-92c1-2cbf94526693', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, 'EUR', '', 'pending', '2024-01-02 02:02:02', '2024-01-02 02:02:02')
, (26, '8d38a482-8a25-4d85-9929-e5f425fcac04', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, 'EUR', '', 'completed', '2024-01-03 03:03:03', '2024-01-03 03:03:03')
, (28, 'b770f8b7-f148-4ab4-a786-aa070af598e5', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, 'EUR', '', 'failed', '2024-01-04 04:04:04', '2024-01-04 04:04:04')
, (30, '31910d73-d343-44b7-8a29-f7e075b64933', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, 'EUR', '', 'refunded', '2024-01-05 05:05:05', '2024-01-05 05:05:05')
, (32, 'c9488490-ac09-4402-90cd-f6f0546f04c0', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, 'EUR', '', 'pending', '2024-01-05 05:05:05', '2024-01-05 05:05:05')
, (34, '5819823e-c0ac-4baa-a3ae-515fbb70e909', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, 'EUR', '', 'pending', '2024-01-05 05:05:05', '2024-01-06 06:06:06')
;
insert into payment_redsys_response (payment_id, response_code, date_time, secure_payment, transaction_type, amount, currency_code, order_number, authorization_code, merchant_code, terminal_number, error_code)

View File

@ -45,9 +45,9 @@ insert into campsite_type (campsite_type_id, slug, company_id, name, media_id, m
values (12, 'c1b6f4fc-32c1-4cd5-b796-0c5059152a52', 2, 'Plots', 10, 6, '[1, 7]', true)
;
insert into payment (payment_id, slug, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, zone_preferences, payment_status, created_at, updated_at)
values (22, '4ef35e2f-ef98-42d6-a724-913bd761ca8c', 2, 12, '2024-08-28', '2024-09-04', 3200, 2, 10420, 4, 20840, 6, 25080, 3, 2450, 4900, 79160, 'pref I before E', 'draft', '2024-01-01 01:01:01', '2024-01-01')
, (24, '6d1b8e4c-c3c6-4fe4-92c1-2cbf94526693', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, '', 'draft', current_timestamp, current_timestamp)
insert into payment (payment_id, slug, company_id, campsite_type_id, arrival_date, departure_date, subtotal_nights, number_adults, subtotal_adults, number_teenagers, subtotal_teenagers, number_children, subtotal_children, number_dogs, subtotal_dogs, subtotal_tourist_tax, total, currency_code, zone_preferences, payment_status, created_at, updated_at)
values (22, '4ef35e2f-ef98-42d6-a724-913bd761ca8c', 2, 12, '2024-08-28', '2024-09-04', 3200, 2, 10420, 4, 20840, 6, 25080, 3, 2450, 4900, 79160, 'EUR', 'pref I before E', 'draft', '2024-01-01 01:01:01', '2024-01-01')
, (24, '6d1b8e4c-c3c6-4fe4-92c1-2cbf94526693', 2, 12, '2024-08-29', '2024-09-03', 71000, 1, 0, 2, 0, 3, 0, 0, 0, 1750, 72750, 'EUR', '', 'draft', current_timestamp, current_timestamp)
;
insert into payment_customer (payment_id, full_name, address, postal_code, city, country_code, email, phone, acsi_card, lang_tag)

View File

@ -19,6 +19,7 @@ select payment_id
, subtotal_dogs
, subtotal_tourist_tax
, total
, currency_code
, down_payment_percent
, zone_preferences
, payment_status

View File

@ -0,0 +1,7 @@
-- Verify camper:order_code on pg
begin;
select has_function_privilege('camper.reference(camper.payment)', 'execute');
rollback;

View File

@ -289,6 +289,8 @@ main {
padding: 2rem 3rem;
}
/*<editor-fold desc="table">*/
table:not(.month) {
width: 100%;
border-collapse: collapse;
@ -304,6 +306,11 @@ table:not(.month) th {
text-align: start;
}
table:not(.month) .numeric, .numeric {
text-align: end;
}
/*</editor-fold>*/
/* user menu */
nav details {
position: relative;
@ -719,25 +726,30 @@ label[x-show] > span, label[x-show] > br {
}
/*</editor-fold>*/
/*<editor-fold desc="booking">*/
/*<editor-fold desc="statuses">*/
.booking-created .booking-status {
.booking-created .booking-status,
.payment-draft .payment-status {
background-color: var(--camper--color--light-blue);
}
.booking-cancelled .booking-status {
.booking-cancelled .booking-status,
.payment-failed .payment-status {
background-color: var(--camper--color--rosy);
}
.booking-confirmed .booking-status {
.booking-confirmed .booking-status,
.payment-pending .payment-status {
background-color: var(--camper--color--hay);
}
.booking-checked-in .booking-status {
.booking-checked-in .booking-status,
.payment-complete .payment-status {
background-color: var(--camper--color--light-green);
}
.booking-invoiced .booking-status {
.booking-invoiced .booking-status,
.payment-refunded .payment-status {
background-color: var(--camper--color--light-gray);
}

View File

@ -37,7 +37,7 @@
<a href="/admin/company">{{( pgettext "Company Settings" "title" )}}</a>
</li>
<li>
<a href="/admin/bookings/payment">{{( pgettext "Payment Settings" "title" )}}</a>
<a href="/admin/payments">{{( pgettext "Payments" "title" )}}</a>
</li>
<li>
<a href="/admin/campsites/types">{{( pgettext "Campsite Types" "title" )}}</a>

View File

@ -0,0 +1,148 @@
<!--
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
SPDX-License-Identifier: AGPL-3.0-only
-->
{{ define "title" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/payment.paymentDetails*/ -}}
{{ printf ( pgettext "Payment %s" "title" ) .Reference }}
{{- end }}
{{ define "breadcrumb" -}}
<li><a href="./">{{( pgettext "Payments" "title" )}}</a></li>
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/payment.paymentDetails*/ -}}
<h2>{{ template "title" . }}</h2>
<table class="payment-{{ .Status}}">
<caption>{{( pgettext "Payment" "title" )}}</caption>
<tbody>
<tr>
<th scope="row">{{( pgettext "Reference" "header" )}}</th>
<td>{{ .Reference }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Status" "header" )}}</th>
<td class="payment-status">{{ .StatusLabel }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Created at" "payment header" )}}</th>
<td>{{ .CreatedAt | formatDateTime }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Last updated at" "payment header" )}}</th>
<td>{{ .UpdatedAt | formatDateTime }}</td>
</tr>
</tbody>
</table>
<table>
<caption>{{( pgettext "Booking" "title" )}}</caption>
<tbody>
<tr>
<th scope="row">{{( pgettext "Accommodation" "title" )}}</th>
<td>{{ .CampsiteType }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Area preferences" "header" )}}</th>
<td>{{ .ZonePreferences }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Arrival date" "input" )}}</th>
<td>{{ .ArrivalDate | formatDate }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Departure date" "input" )}}</th>
<td>{{ .DepartureDate | formatDate }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Nights" "cart" )}}</th>
<td class="numeric">{{ .NumNights }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Adults aged 17 or older" "input" )}}</th>
<td class="numeric">{{ .NumAdults }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Teenagers from 11 to 16 years old" "input" )}}</th>
<td class="numeric">{{ .NumTeenagers }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Children from 2 to 10 years old" "input" )}}</th>
<td class="numeric">{{ .NumChildren }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Dogs" "input" )}}</th>
<td class="numeric">{{ .NumDogs }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Tourist tax" "cart" )}}</th>
<td class="numeric">{{ .SubtotalTouristTax | formatPrice }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Down payment" "cart" )}}</th>
<td class="numeric">{{ .DownPaymentPercent }} %, {{ .DownPayment | formatPrice }}</td>
</tr>
</tbody>
</table>
{{ with .Options -}}
<table>
<caption>{{( pgettext "Campsite Type Options" "title" )}}</caption>
<tbody>
{{ range . -}}
<tr>
<th scope="row">{{ .Label }}</th>
<td class="numeric">{{ .Units }}</td>
</tr>
{{- end }}
</tbody>
</table>
{{- end }}
{{ with .Customer -}}
<table>
<caption>{{( pgettext "Customer Details" "title" )}}</caption>
<tbody>
<tr>
<th scope="row">{{( pgettext "Full name" "input" )}}</th>
<td>{{ .FullName }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Address" "input" )}}</th>
<td>{{ .Address }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Postcode" "input" )}}</th>
<td>{{ .PostalCode }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "City" "input" )}}</th>
<td>{{ .City }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Country" "input" )}}</th>
<td>{{ .Country }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "Email" "input" )}}</th>
<td><a href="mailto:{{ .Email}}">{{ .Email }}</a></td>
</tr>
<tr>
<th scope="row">{{( pgettext "Phone" "input" )}}</th>
<td><a href="tel:{{ replaceAll .Phone " " "" }}">{{ .Phone }}</a></td>
</tr>
<tr>
<th scope="row">{{( pgettext "Language" "input" )}}</th>
<td>{{ .Language }}</td>
</tr>
<tr>
<th scope="row">{{( pgettext "ACSI card?" "input" )}}</th>
<td>{{if .ACSICard}}{{( gettext "Yes" )}}{{ else }}{{( gettext "No" )}}{{ end }}</td>
</tr>
</tbody>
</table>
{{- end }}
{{- end }}

View File

@ -0,0 +1,42 @@
<!--
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
SPDX-License-Identifier: AGPL-3.0-only
-->
{{ define "title" -}}
{{( pgettext "Payments" "title" )}}
{{- end }}
{{ define "breadcrumb" -}}
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/payment.paymentIndex*/ -}}
<a href="/admin/payments/settings">{{( pgettext "Payment Settings" "title" )}}</a>
<h2>{{ template "title" . }}</h2>
{{ if .Payments -}}
<table>
<thead>
<tr>
<th scope="col">{{( pgettext "Date" "header" )}}</th>
<th scope="col">{{( pgettext "Reference" "header" )}}</th>
<th scope="col">{{( pgettext "Status" "header" )}}</th>
<th class="numeric" scope="col">{{( pgettext "Down payment" "header" )}}</th>
<th class="numeric" scope="col">{{( pgettext "Total" "header" )}}</th>
</tr>
</thead>
<tbody>
{{ range .Payments -}}
<tr class="payment-{{ .Status }}">
<td>{{ .CreatedAt | formatDate }}</td>
<td><a href="{{ .URL }}">{{ .Reference }}</a></td>
<td class="payment-status">{{ .StatusLabel }}</td>
<td class="numeric">{{ .DownPayment | formatPrice }}</td>
<td class="numeric">{{ .Total | formatPrice }}</td>
</tr>
{{- end }}
</tbody>
</table>
{{ else -}}
<p>{{( gettext "No payments found." )}}</p>
{{- end }}
{{- end }}

View File

@ -7,12 +7,13 @@
{{- end }}
{{ define "breadcrumb" -}}
<li><a href="./">{{( pgettext "Payments" "title" )}}</a></li>
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/booking.paymentForm*/ -}}
<form data-hx-put="/admin/booking/payment">
<h2>{{( pgettext "Payment Settings" "title" )}}</h2>
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/payment.settingsForm*/ -}}
<form data-hx-put="/admin/payments/settings">
<h2>{{ template "title" . }}</h2>
{{ CSRFInput }}
<fieldset>
{{ with .MerchantCode -}}

View File

@ -2,7 +2,7 @@
<dl class="payment-details">
<div>
<dt>{{( pgettext "Order Number" "title" )}}</dt>
<dd>{{ .OrderNumber }}</dd>
<dd>{{ .Reference }}</dd>
</div>
<div>
<dt>{{( pgettext "Date" "title" )}}</dt>