Split the tax details “mega dialog” into separate pages
I needed to place the payment accounts section somewhere, and the most logical place seemed to be that dialog, where users can set up company parameters. However, that dialog was already saturated with related, but ultimately independent forms, and adding the account section would make things even worse, specially given that we need to be able to edit those accounts in a separate page. We agreed to separate that dialog into tabs, which means separate pages. When i had everything in a separated page, then i did not know how to actually share the code for the tabs, and decided that, for now, these “tabs” would be items from the profile menu. Same function, different presentation.
This commit is contained in:
parent
e626c7b4bd
commit
f95936c523
635
pkg/company.go
635
pkg/company.go
|
@ -85,24 +85,19 @@ type PaymentMethod struct {
|
|||
}
|
||||
|
||||
type taxDetailsForm struct {
|
||||
locale *Locale
|
||||
TradeName *InputField
|
||||
BusinessName *InputField
|
||||
VATIN *InputField
|
||||
Phone *InputField
|
||||
Email *InputField
|
||||
Web *InputField
|
||||
Address *InputField
|
||||
City *InputField
|
||||
Province *InputField
|
||||
PostalCode *InputField
|
||||
Country *SelectField
|
||||
Currency *SelectField
|
||||
InvoiceNumberFormat *InputField
|
||||
NextInvoiceNumber *InputField
|
||||
QuoteNumberFormat *InputField
|
||||
NextQuoteNumber *InputField
|
||||
LegalDisclaimer *InputField
|
||||
locale *Locale
|
||||
TradeName *InputField
|
||||
BusinessName *InputField
|
||||
VATIN *InputField
|
||||
Phone *InputField
|
||||
Email *InputField
|
||||
Web *InputField
|
||||
Address *InputField
|
||||
City *InputField
|
||||
Province *InputField
|
||||
PostalCode *InputField
|
||||
Country *SelectField
|
||||
Currency *SelectField
|
||||
}
|
||||
|
||||
func newTaxDetailsForm(ctx context.Context, conn *Conn, locale *Locale) *taxDetailsForm {
|
||||
|
@ -202,6 +197,206 @@ func newTaxDetailsForm(ctx context.Context, conn *Conn, locale *Locale) *taxDeta
|
|||
Required: true,
|
||||
Selected: []string{"EUR"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (form *taxDetailsForm) Parse(r *http.Request) error {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
form.TradeName.FillValue(r)
|
||||
form.BusinessName.FillValue(r)
|
||||
form.VATIN.FillValue(r)
|
||||
form.Phone.FillValue(r)
|
||||
form.Email.FillValue(r)
|
||||
form.Web.FillValue(r)
|
||||
form.Address.FillValue(r)
|
||||
form.City.FillValue(r)
|
||||
form.Province.FillValue(r)
|
||||
form.PostalCode.FillValue(r)
|
||||
form.Country.FillValue(r)
|
||||
form.Currency.FillValue(r)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (form *taxDetailsForm) Validate(ctx context.Context, conn *Conn) bool {
|
||||
validator := newFormValidator()
|
||||
|
||||
country := ""
|
||||
if validator.CheckValidSelectOption(form.Country, gettext("Selected country is not valid.", form.locale)) {
|
||||
country = form.Country.Selected[0]
|
||||
}
|
||||
|
||||
validator.CheckRequiredInput(form.BusinessName, gettext("Business name can not be empty.", form.locale))
|
||||
validator.CheckInputMinLength(form.BusinessName, 2, gettext("Business name must have at least two letters.", form.locale))
|
||||
if validator.CheckRequiredInput(form.VATIN, gettext("VAT number can not be empty.", form.locale)) {
|
||||
validator.CheckValidVATINInput(ctx, conn, form.VATIN, country, gettext("This value is not a valid VAT number.", form.locale))
|
||||
}
|
||||
if validator.CheckRequiredInput(form.Phone, gettext("Phone can not be empty.", form.locale)) {
|
||||
validator.CheckValidPhoneInput(ctx, conn, form.Phone, country, gettext("This value is not a valid phone number.", form.locale))
|
||||
}
|
||||
if validator.CheckRequiredInput(form.Email, gettext("Email can not be empty.", form.locale)) {
|
||||
validator.CheckValidEmailInput(form.Email, gettext("This value is not a valid email. It should be like name@domain.com.", form.locale))
|
||||
}
|
||||
if form.Web.Val != "" {
|
||||
validator.CheckValidURL(form.Web, gettext("This value is not a valid web address. It should be like https://domain.com/.", form.locale))
|
||||
}
|
||||
validator.CheckRequiredInput(form.Address, gettext("Address can not be empty.", form.locale))
|
||||
validator.CheckRequiredInput(form.City, gettext("City can not be empty.", form.locale))
|
||||
validator.CheckRequiredInput(form.Province, gettext("Province can not be empty.", form.locale))
|
||||
if validator.CheckRequiredInput(form.PostalCode, gettext("Postal code can not be empty.", form.locale)) {
|
||||
validator.CheckValidPostalCode(ctx, conn, form.PostalCode, country, gettext("This value is not a valid postal code.", form.locale))
|
||||
}
|
||||
validator.CheckValidSelectOption(form.Currency, gettext("Selected currency is not valid.", form.locale))
|
||||
|
||||
return validator.AllOK()
|
||||
}
|
||||
|
||||
func (form *taxDetailsForm) mustFillFromDatabase(ctx context.Context, conn *Conn, company *Company) *taxDetailsForm {
|
||||
err := conn.QueryRow(ctx, `
|
||||
select business_name
|
||||
, substr(vatin::text, 3)
|
||||
, trade_name
|
||||
, phone
|
||||
, email
|
||||
, web
|
||||
, address
|
||||
, city
|
||||
, province
|
||||
, postal_code
|
||||
, country_code
|
||||
, currency_code
|
||||
from company
|
||||
where company.company_id = $1`, company.Id).Scan(
|
||||
form.BusinessName,
|
||||
form.VATIN,
|
||||
form.TradeName,
|
||||
form.Phone,
|
||||
form.Email,
|
||||
form.Web,
|
||||
form.Address,
|
||||
form.City,
|
||||
form.Province,
|
||||
form.PostalCode,
|
||||
form.Country,
|
||||
form.Currency,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return form
|
||||
}
|
||||
|
||||
type TaxDetailsPage struct {
|
||||
DetailsForm *taxDetailsForm
|
||||
}
|
||||
|
||||
func (page *TaxDetailsPage) MustRender(w http.ResponseWriter, r *http.Request) {
|
||||
mustRenderMainTemplate(w, r, "company/tax-details.gohtml", page)
|
||||
}
|
||||
|
||||
func GetCompanyTaxDetailsForm(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
mustRenderTaxDetailsForm(w, r, newTaxDetailsFormFromDatabase(r))
|
||||
}
|
||||
|
||||
func newTaxDetailsFormFromDatabase(r *http.Request) *taxDetailsForm {
|
||||
locale := getLocale(r)
|
||||
conn := getConn(r)
|
||||
form := newTaxDetailsForm(r.Context(), conn, locale)
|
||||
|
||||
company := mustGetCompany(r)
|
||||
form.mustFillFromDatabase(r.Context(), conn, company)
|
||||
|
||||
return form
|
||||
}
|
||||
|
||||
func HandleCompanyTaxDetailsForm(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
locale := getLocale(r)
|
||||
conn := getConn(r)
|
||||
form := newTaxDetailsForm(r.Context(), conn, locale)
|
||||
if err := form.Parse(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := verifyCsrfTokenValid(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
if ok := form.Validate(r.Context(), conn); !ok {
|
||||
if !IsHTMxRequest(r) {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
}
|
||||
mustRenderTaxDetailsForm(w, r, form)
|
||||
return
|
||||
}
|
||||
company := mustGetCompany(r)
|
||||
conn.MustExec(r.Context(), `
|
||||
update company
|
||||
set business_name = $1
|
||||
, vatin = ($11 || $2)::vatin
|
||||
, trade_name = $3
|
||||
, phone = parse_packed_phone_number($4, $11)
|
||||
, email = $5
|
||||
, web = $6
|
||||
, address = $7
|
||||
, city = $8
|
||||
, province = $9
|
||||
, postal_code = $10
|
||||
, country_code = $11
|
||||
, currency_code = $12
|
||||
where company_id = $13
|
||||
`,
|
||||
form.BusinessName,
|
||||
form.VATIN,
|
||||
form.TradeName,
|
||||
form.Phone,
|
||||
form.Email,
|
||||
form.Web,
|
||||
form.Address,
|
||||
form.City,
|
||||
form.Province,
|
||||
form.PostalCode,
|
||||
form.Country,
|
||||
form.Currency,
|
||||
company.Id)
|
||||
htmxRedirect(w, r, companyURI(company, "/tax-details"))
|
||||
}
|
||||
|
||||
func mustRenderTaxDetailsForm(w http.ResponseWriter, r *http.Request, form *taxDetailsForm) {
|
||||
page := &TaxDetailsPage{
|
||||
DetailsForm: form,
|
||||
}
|
||||
page.MustRender(w, r)
|
||||
}
|
||||
|
||||
func mustGetCompany(r *http.Request) *Company {
|
||||
company := getCompany(r)
|
||||
if company == nil {
|
||||
panic(errors.New("company: required but not found"))
|
||||
}
|
||||
return company
|
||||
}
|
||||
|
||||
func serveCompanyInvoicingForm(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
conn := getConn(r)
|
||||
company := mustGetCompany(r)
|
||||
locale := getLocale(r)
|
||||
form := newInvoicingFormFromDatabase(r.Context(), conn, company, locale)
|
||||
form.MustRender(w, r)
|
||||
}
|
||||
|
||||
type InvoicingForm struct {
|
||||
locale *Locale
|
||||
InvoiceNumberFormat *InputField
|
||||
NextInvoiceNumber *InputField
|
||||
QuoteNumberFormat *InputField
|
||||
NextQuoteNumber *InputField
|
||||
LegalDisclaimer *InputField
|
||||
}
|
||||
|
||||
func newInvoicingForm(locale *Locale) *InvoicingForm {
|
||||
return &InvoicingForm{
|
||||
locale: locale,
|
||||
InvoiceNumberFormat: &InputField{
|
||||
Name: "invoice_number_format",
|
||||
Label: pgettext("input", "Invoice number format", locale),
|
||||
|
@ -240,82 +435,15 @@ func newTaxDetailsForm(ctx context.Context, conn *Conn, locale *Locale) *taxDeta
|
|||
}
|
||||
}
|
||||
|
||||
func (form *taxDetailsForm) Parse(r *http.Request) error {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
form.TradeName.FillValue(r)
|
||||
form.BusinessName.FillValue(r)
|
||||
form.VATIN.FillValue(r)
|
||||
form.Phone.FillValue(r)
|
||||
form.Email.FillValue(r)
|
||||
form.Web.FillValue(r)
|
||||
form.Address.FillValue(r)
|
||||
form.City.FillValue(r)
|
||||
form.Province.FillValue(r)
|
||||
form.PostalCode.FillValue(r)
|
||||
form.Country.FillValue(r)
|
||||
form.Currency.FillValue(r)
|
||||
form.InvoiceNumberFormat.FillValue(r)
|
||||
form.NextInvoiceNumber.FillValue(r)
|
||||
form.QuoteNumberFormat.FillValue(r)
|
||||
form.NextQuoteNumber.FillValue(r)
|
||||
form.LegalDisclaimer.FillValue(r)
|
||||
return nil
|
||||
func newInvoicingFormFromDatabase(ctx context.Context, conn *Conn, company *Company, locale *Locale) *InvoicingForm {
|
||||
form := newInvoicingForm(locale)
|
||||
form.mustFillFromDatabase(ctx, conn, company)
|
||||
return form
|
||||
}
|
||||
|
||||
func (form *taxDetailsForm) Validate(ctx context.Context, conn *Conn) bool {
|
||||
validator := newFormValidator()
|
||||
|
||||
country := ""
|
||||
if validator.CheckValidSelectOption(form.Country, gettext("Selected country is not valid.", form.locale)) {
|
||||
country = form.Country.Selected[0]
|
||||
}
|
||||
|
||||
validator.CheckRequiredInput(form.BusinessName, gettext("Business name can not be empty.", form.locale))
|
||||
validator.CheckInputMinLength(form.BusinessName, 2, gettext("Business name must have at least two letters.", form.locale))
|
||||
if validator.CheckRequiredInput(form.VATIN, gettext("VAT number can not be empty.", form.locale)) {
|
||||
validator.CheckValidVATINInput(ctx, conn, form.VATIN, country, gettext("This value is not a valid VAT number.", form.locale))
|
||||
}
|
||||
if validator.CheckRequiredInput(form.Phone, gettext("Phone can not be empty.", form.locale)) {
|
||||
validator.CheckValidPhoneInput(ctx, conn, form.Phone, country, gettext("This value is not a valid phone number.", form.locale))
|
||||
}
|
||||
if validator.CheckRequiredInput(form.Email, gettext("Email can not be empty.", form.locale)) {
|
||||
validator.CheckValidEmailInput(form.Email, gettext("This value is not a valid email. It should be like name@domain.com.", form.locale))
|
||||
}
|
||||
if form.Web.Val != "" {
|
||||
validator.CheckValidURL(form.Web, gettext("This value is not a valid web address. It should be like https://domain.com/.", form.locale))
|
||||
}
|
||||
validator.CheckRequiredInput(form.Address, gettext("Address can not be empty.", form.locale))
|
||||
validator.CheckRequiredInput(form.City, gettext("City can not be empty.", form.locale))
|
||||
validator.CheckRequiredInput(form.Province, gettext("Province can not be empty.", form.locale))
|
||||
if validator.CheckRequiredInput(form.PostalCode, gettext("Postal code can not be empty.", form.locale)) {
|
||||
validator.CheckValidPostalCode(ctx, conn, form.PostalCode, country, gettext("This value is not a valid postal code.", form.locale))
|
||||
}
|
||||
validator.CheckValidSelectOption(form.Currency, gettext("Selected currency is not valid.", form.locale))
|
||||
validator.CheckRequiredInput(form.InvoiceNumberFormat, gettext("Invoice number format can not be empty.", form.locale))
|
||||
validator.CheckValidInteger(form.NextInvoiceNumber, 1, math.MaxInt32, gettext("Next invoice number must be a number greater than zero.", form.locale))
|
||||
validator.CheckRequiredInput(form.QuoteNumberFormat, gettext("Quotation number format can not be empty.", form.locale))
|
||||
validator.CheckValidInteger(form.NextQuoteNumber, 1, math.MaxInt32, gettext("Next quotation number must be a number greater than zero.", form.locale))
|
||||
|
||||
return validator.AllOK()
|
||||
}
|
||||
|
||||
func (form *taxDetailsForm) mustFillFromDatabase(ctx context.Context, conn *Conn, company *Company) *taxDetailsForm {
|
||||
func (form *InvoicingForm) mustFillFromDatabase(ctx context.Context, conn *Conn, company *Company) {
|
||||
err := conn.QueryRow(ctx, `
|
||||
select business_name
|
||||
, substr(vatin::text, 3)
|
||||
, trade_name
|
||||
, phone
|
||||
, email
|
||||
, web
|
||||
, address
|
||||
, city
|
||||
, province
|
||||
, postal_code
|
||||
, country_code
|
||||
, currency_code
|
||||
, invoice_number_format
|
||||
select invoice_number_format
|
||||
, quote_number_format
|
||||
, legal_disclaimer
|
||||
, coalesce(invoice_number_counter.currval, 0) + 1
|
||||
|
@ -328,18 +456,6 @@ func (form *taxDetailsForm) mustFillFromDatabase(ctx context.Context, conn *Conn
|
|||
on quote_number_counter.company_id = company.company_id
|
||||
and quote_number_counter.year = date_part('year', current_date)
|
||||
where company.company_id = $1`, company.Id).Scan(
|
||||
form.BusinessName,
|
||||
form.VATIN,
|
||||
form.TradeName,
|
||||
form.Phone,
|
||||
form.Email,
|
||||
form.Web,
|
||||
form.Address,
|
||||
form.City,
|
||||
form.Province,
|
||||
form.PostalCode,
|
||||
form.Country,
|
||||
form.Currency,
|
||||
form.InvoiceNumberFormat,
|
||||
form.QuoteNumberFormat,
|
||||
form.LegalDisclaimer,
|
||||
|
@ -349,36 +465,39 @@ func (form *taxDetailsForm) mustFillFromDatabase(ctx context.Context, conn *Conn
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return form
|
||||
}
|
||||
|
||||
type TaxDetailsPage struct {
|
||||
DetailsForm *taxDetailsForm
|
||||
NewTaxForm *taxForm
|
||||
Taxes []*Tax
|
||||
NewPaymentMethodForm *paymentMethodForm
|
||||
PaymentMethods []*PaymentMethod
|
||||
func (form *InvoicingForm) MustRender(w http.ResponseWriter, r *http.Request) {
|
||||
mustRenderMainTemplate(w, r, "company/invoicing.gohtml", form)
|
||||
}
|
||||
|
||||
func GetCompanyTaxDetailsForm(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
mustRenderTaxDetailsForm(w, r, newTaxDetailsFormFromDatabase(r))
|
||||
func (form *InvoicingForm) Parse(r *http.Request) error {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
form.InvoiceNumberFormat.FillValue(r)
|
||||
form.NextInvoiceNumber.FillValue(r)
|
||||
form.QuoteNumberFormat.FillValue(r)
|
||||
form.NextQuoteNumber.FillValue(r)
|
||||
form.LegalDisclaimer.FillValue(r)
|
||||
return nil
|
||||
}
|
||||
|
||||
func newTaxDetailsFormFromDatabase(r *http.Request) *taxDetailsForm {
|
||||
func (form *InvoicingForm) Validate() bool {
|
||||
validator := newFormValidator()
|
||||
|
||||
validator.CheckRequiredInput(form.InvoiceNumberFormat, gettext("Invoice number format can not be empty.", form.locale))
|
||||
validator.CheckValidInteger(form.NextInvoiceNumber, 1, math.MaxInt32, gettext("Next invoice number must be a number greater than zero.", form.locale))
|
||||
validator.CheckRequiredInput(form.QuoteNumberFormat, gettext("Quotation number format can not be empty.", form.locale))
|
||||
validator.CheckValidInteger(form.NextQuoteNumber, 1, math.MaxInt32, gettext("Next quotation number must be a number greater than zero.", form.locale))
|
||||
|
||||
return validator.AllOK()
|
||||
}
|
||||
|
||||
func handleCompanyInvoicingForm(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
locale := getLocale(r)
|
||||
conn := getConn(r)
|
||||
form := newTaxDetailsForm(r.Context(), conn, locale)
|
||||
|
||||
company := mustGetCompany(r)
|
||||
form.mustFillFromDatabase(r.Context(), conn, company)
|
||||
|
||||
return form
|
||||
}
|
||||
|
||||
func HandleCompanyTaxDetailsForm(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
locale := getLocale(r)
|
||||
conn := getConn(r)
|
||||
form := newTaxDetailsForm(r.Context(), conn, locale)
|
||||
form := newInvoicingForm(locale)
|
||||
if err := form.Parse(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
|
@ -387,11 +506,11 @@ func HandleCompanyTaxDetailsForm(w http.ResponseWriter, r *http.Request, _ httpr
|
|||
http.Error(w, err.Error(), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
if ok := form.Validate(r.Context(), conn); !ok {
|
||||
if ok := form.Validate(); !ok {
|
||||
if !IsHTMxRequest(r) {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
}
|
||||
mustRenderTaxDetailsForm(w, r, form)
|
||||
form.MustRender(w, r)
|
||||
return
|
||||
}
|
||||
company := mustGetCompany(r)
|
||||
|
@ -399,35 +518,11 @@ func HandleCompanyTaxDetailsForm(w http.ResponseWriter, r *http.Request, _ httpr
|
|||
defer tx.MustRollback(r.Context())
|
||||
tx.MustExec(r.Context(), `
|
||||
update company
|
||||
set business_name = $1
|
||||
, vatin = ($11 || $2)::vatin
|
||||
, trade_name = $3
|
||||
, phone = parse_packed_phone_number($4, $11)
|
||||
, email = $5
|
||||
, web = $6
|
||||
, address = $7
|
||||
, city = $8
|
||||
, province = $9
|
||||
, postal_code = $10
|
||||
, country_code = $11
|
||||
, currency_code = $12
|
||||
, invoice_number_format = $13
|
||||
, quote_number_format = $14
|
||||
, legal_disclaimer = $15
|
||||
where company_id = $16
|
||||
set invoice_number_format = $1
|
||||
, quote_number_format = $2
|
||||
, legal_disclaimer = $3
|
||||
where company_id = $4
|
||||
`,
|
||||
form.BusinessName,
|
||||
form.VATIN,
|
||||
form.TradeName,
|
||||
form.Phone,
|
||||
form.Email,
|
||||
form.Web,
|
||||
form.Address,
|
||||
form.City,
|
||||
form.Province,
|
||||
form.PostalCode,
|
||||
form.Country,
|
||||
form.Currency,
|
||||
form.InvoiceNumberFormat,
|
||||
form.QuoteNumberFormat,
|
||||
form.LegalDisclaimer,
|
||||
|
@ -449,60 +544,39 @@ func HandleCompanyTaxDetailsForm(w http.ResponseWriter, r *http.Request, _ httpr
|
|||
company.Id,
|
||||
form.NextQuoteNumber.Integer()-1)
|
||||
tx.MustCommit(r.Context())
|
||||
if IsHTMxRequest(r) {
|
||||
w.Header().Set(HxTrigger, "closeModal")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
} else {
|
||||
http.Redirect(w, r, companyURI(company, "/tax-details"), http.StatusSeeOther)
|
||||
}
|
||||
htmxRedirect(w, r, companyURI(company, "/invoicing"))
|
||||
}
|
||||
|
||||
func mustRenderTaxDetailsForm(w http.ResponseWriter, r *http.Request, form *taxDetailsForm) {
|
||||
conn := getConn(r)
|
||||
locale := getLocale(r)
|
||||
page := &TaxDetailsPage{
|
||||
DetailsForm: form,
|
||||
NewTaxForm: newTaxForm(r.Context(), conn, mustGetCompany(r), locale),
|
||||
NewPaymentMethodForm: newPaymentMethodForm(locale),
|
||||
}
|
||||
mustRenderTexDetailsPage(w, r, page)
|
||||
}
|
||||
|
||||
func mustRenderTaxForm(w http.ResponseWriter, r *http.Request, form *taxForm) {
|
||||
page := &TaxDetailsPage{
|
||||
DetailsForm: newTaxDetailsFormFromDatabase(r),
|
||||
NewTaxForm: form,
|
||||
NewPaymentMethodForm: newPaymentMethodForm(getLocale(r)),
|
||||
}
|
||||
mustRenderTexDetailsPage(w, r, page)
|
||||
}
|
||||
|
||||
func mustRenderPaymentMethodForm(w http.ResponseWriter, r *http.Request, form *paymentMethodForm) {
|
||||
page := &TaxDetailsPage{
|
||||
DetailsForm: newTaxDetailsFormFromDatabase(r),
|
||||
NewTaxForm: newTaxForm(r.Context(), getConn(r), mustGetCompany(r), getLocale(r)),
|
||||
NewPaymentMethodForm: form,
|
||||
}
|
||||
mustRenderTexDetailsPage(w, r, page)
|
||||
}
|
||||
|
||||
func mustRenderTexDetailsPage(w http.ResponseWriter, r *http.Request, page *TaxDetailsPage) {
|
||||
func serveCompanyTaxes(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
conn := getConn(r)
|
||||
company := mustGetCompany(r)
|
||||
page.Taxes = mustGetTaxes(r.Context(), conn, company)
|
||||
page.PaymentMethods = mustCollectPaymentMethods(r.Context(), conn, company)
|
||||
mustRenderModalTemplate(w, r, "tax-details.gohtml", page)
|
||||
locale := getLocale(r)
|
||||
page := newTaxesPage(r.Context(), conn, company, locale)
|
||||
page.MustRender(w, r)
|
||||
}
|
||||
|
||||
func mustGetCompany(r *http.Request) *Company {
|
||||
company := getCompany(r)
|
||||
if company == nil {
|
||||
panic(errors.New("company: required but not found"))
|
||||
type TaxesPage struct {
|
||||
Taxes []*Tax
|
||||
Form *taxForm
|
||||
}
|
||||
|
||||
func newTaxesPage(ctx context.Context, conn *Conn, company *Company, locale *Locale) *TaxesPage {
|
||||
form := newTaxForm(ctx, conn, company, locale)
|
||||
return newTaxesPageWithForm(ctx, conn, company, form)
|
||||
}
|
||||
|
||||
func newTaxesPageWithForm(ctx context.Context, conn *Conn, company *Company, form *taxForm) *TaxesPage {
|
||||
return &TaxesPage{
|
||||
Taxes: mustCollectTaxes(ctx, conn, company),
|
||||
Form: form,
|
||||
}
|
||||
return company
|
||||
}
|
||||
|
||||
func mustGetTaxes(ctx context.Context, conn *Conn, company *Company) []*Tax {
|
||||
func (page *TaxesPage) MustRender(w http.ResponseWriter, r *http.Request) {
|
||||
mustRenderMainTemplate(w, r, "company/taxes.gohtml", page)
|
||||
}
|
||||
|
||||
func mustCollectTaxes(ctx context.Context, conn *Conn, company *Company) []*Tax {
|
||||
rows, err := conn.Query(ctx, "select tax_id, tax.name, tax_class.name, (rate * 100)::integer from tax join tax_class using (tax_class_id) where tax.company_id = $1 order by rate, tax.name", company.Id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -525,29 +599,6 @@ func mustGetTaxes(ctx context.Context, conn *Conn, company *Company) []*Tax {
|
|||
return taxes
|
||||
}
|
||||
|
||||
func mustCollectPaymentMethods(ctx context.Context, conn *Conn, company *Company) []*PaymentMethod {
|
||||
rows, err := conn.Query(ctx, "select payment_method_id, name, instructions from payment_method where company_id = $1 order by name", company.Id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var methods []*PaymentMethod
|
||||
for rows.Next() {
|
||||
method := &PaymentMethod{}
|
||||
err = rows.Scan(&method.Id, &method.Name, &method.Instructions)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
methods = append(methods, method)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
panic(rows.Err())
|
||||
}
|
||||
|
||||
return methods
|
||||
}
|
||||
|
||||
type taxForm struct {
|
||||
locale *Locale
|
||||
Name *InputField
|
||||
|
@ -604,25 +655,6 @@ func (form *taxForm) Validate() bool {
|
|||
return validator.AllOK()
|
||||
}
|
||||
|
||||
func HandleDeleteCompanyTax(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||
taxId, err := strconv.Atoi(params[0].Value)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if err := verifyCsrfTokenValid(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
conn := getConn(r)
|
||||
conn.MustExec(r.Context(), "delete from tax where tax_id = $1", taxId)
|
||||
if IsHTMxRequest(r) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
http.Redirect(w, r, companyURI(mustGetCompany(r), "/tax-details"), http.StatusSeeOther)
|
||||
}
|
||||
}
|
||||
|
||||
func HandleAddCompanyTax(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
locale := getLocale(r)
|
||||
conn := getConn(r)
|
||||
|
@ -640,15 +672,80 @@ func HandleAddCompanyTax(w http.ResponseWriter, r *http.Request, _ httprouter.Pa
|
|||
if !IsHTMxRequest(r) {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
}
|
||||
mustRenderTaxForm(w, r, form)
|
||||
page := newTaxesPageWithForm(r.Context(), conn, company, form)
|
||||
page.MustRender(w, r)
|
||||
return
|
||||
}
|
||||
conn.MustExec(r.Context(), "insert into tax (company_id, tax_class_id, name, rate) values ($1, $2, $3, $4 / 100::decimal)", company.Id, form.Class, form.Name, form.Rate.Integer())
|
||||
if IsHTMxRequest(r) {
|
||||
mustRenderTaxForm(w, r, newTaxForm(r.Context(), conn, company, locale))
|
||||
} else {
|
||||
http.Redirect(w, r, companyURI(company, "/tax-details"), http.StatusSeeOther)
|
||||
htmxRedirect(w, r, companyURI(company, "/taxes"))
|
||||
}
|
||||
|
||||
func HandleDeleteCompanyTax(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||
taxId, err := strconv.Atoi(params[0].Value)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if err := verifyCsrfTokenValid(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
conn := getConn(r)
|
||||
conn.MustExec(r.Context(), "delete from tax where tax_id = $1", taxId)
|
||||
company := mustGetCompany(r)
|
||||
htmxRedirect(w, r, companyURI(company, "/taxes"))
|
||||
}
|
||||
|
||||
func servePaymentMethods(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
conn := getConn(r)
|
||||
company := mustGetCompany(r)
|
||||
locale := getLocale(r)
|
||||
page := newPaymentMethodsPage(r.Context(), conn, company, locale)
|
||||
page.MustRender(w, r)
|
||||
}
|
||||
|
||||
type PaymentMethodsPage struct {
|
||||
PaymentMethods []*PaymentMethod
|
||||
Form *paymentMethodForm
|
||||
}
|
||||
|
||||
func newPaymentMethodsPage(ctx context.Context, conn *Conn, company *Company, locale *Locale) *PaymentMethodsPage {
|
||||
form := newPaymentMethodForm(locale)
|
||||
return newPaymentMethodsPageWithForm(ctx, conn, company, form)
|
||||
}
|
||||
|
||||
func newPaymentMethodsPageWithForm(ctx context.Context, conn *Conn, company *Company, form *paymentMethodForm) *PaymentMethodsPage {
|
||||
return &PaymentMethodsPage{
|
||||
PaymentMethods: mustCollectPaymentMethods(ctx, conn, company),
|
||||
Form: form,
|
||||
}
|
||||
}
|
||||
|
||||
func (page *PaymentMethodsPage) MustRender(w http.ResponseWriter, r *http.Request) {
|
||||
mustRenderMainTemplate(w, r, "company/payment_methods.gohtml", page)
|
||||
}
|
||||
|
||||
func mustCollectPaymentMethods(ctx context.Context, conn *Conn, company *Company) []*PaymentMethod {
|
||||
rows, err := conn.Query(ctx, "select payment_method_id, name, instructions from payment_method where company_id = $1 order by name", company.Id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var methods []*PaymentMethod
|
||||
for rows.Next() {
|
||||
method := &PaymentMethod{}
|
||||
err = rows.Scan(&method.Id, &method.Name, &method.Instructions)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
methods = append(methods, method)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
panic(rows.Err())
|
||||
}
|
||||
|
||||
return methods
|
||||
}
|
||||
|
||||
type paymentMethodForm struct {
|
||||
|
@ -691,25 +788,6 @@ func (form *paymentMethodForm) Validate() bool {
|
|||
return validator.AllOK()
|
||||
}
|
||||
|
||||
func HandleDeletePaymentMethod(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||
paymentMethodId, err := strconv.Atoi(params[0].Value)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if err := verifyCsrfTokenValid(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
conn := getConn(r)
|
||||
conn.MustExec(r.Context(), "delete from payment_method where payment_method_id = $1", paymentMethodId)
|
||||
if IsHTMxRequest(r) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
http.Redirect(w, r, companyURI(mustGetCompany(r), "/tax-details"), http.StatusSeeOther)
|
||||
}
|
||||
}
|
||||
|
||||
func HandleAddPaymentMethod(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
locale := getLocale(r)
|
||||
conn := getConn(r)
|
||||
|
@ -727,15 +805,28 @@ func HandleAddPaymentMethod(w http.ResponseWriter, r *http.Request, _ httprouter
|
|||
if !IsHTMxRequest(r) {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
}
|
||||
mustRenderPaymentMethodForm(w, r, form)
|
||||
page := newPaymentMethodsPageWithForm(r.Context(), conn, company, form)
|
||||
page.MustRender(w, r)
|
||||
return
|
||||
}
|
||||
conn.MustExec(r.Context(), "insert into payment_method (company_id, name, instructions) values ($1, $2, $3)", company.Id, form.Name, form.Instructions)
|
||||
if IsHTMxRequest(r) {
|
||||
mustRenderPaymentMethodForm(w, r, newPaymentMethodForm(locale))
|
||||
} else {
|
||||
http.Redirect(w, r, companyURI(company, "/tax-details"), http.StatusSeeOther)
|
||||
htmxRedirect(w, r, companyURI(company, "/payment-methods"))
|
||||
}
|
||||
|
||||
func HandleDeletePaymentMethod(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||
paymentMethodId, err := strconv.Atoi(params[0].Value)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if err := verifyCsrfTokenValid(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
conn := getConn(r)
|
||||
conn.MustExec(r.Context(), "delete from payment_method where payment_method_id = $1", paymentMethodId)
|
||||
company := mustGetCompany(r)
|
||||
htmxRedirect(w, r, companyURI(company, "/payment-methods"))
|
||||
}
|
||||
|
||||
func GetCompanySwitcher(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
|
@ -755,7 +846,7 @@ type UserCompany struct {
|
|||
}
|
||||
|
||||
func (page *CompanySwitchPage) MustRender(w http.ResponseWriter, r *http.Request) {
|
||||
mustRenderModalTemplate(w, r, "switch-company.gohtml", page)
|
||||
mustRenderModalTemplate(w, r, "company/switch.gohtml", page)
|
||||
}
|
||||
|
||||
func mustCollectUserCompanies(ctx context.Context, conn *Conn) []*UserCompany {
|
||||
|
|
|
@ -11,12 +11,16 @@ func NewRouter(db *Db, demo bool) http.Handler {
|
|||
companyRouter.GET("/profile", GetProfileForm)
|
||||
companyRouter.POST("/profile", HandleProfileForm)
|
||||
companyRouter.GET("/tax-details", GetCompanyTaxDetailsForm)
|
||||
companyRouter.GET("/switch-company", GetCompanySwitcher)
|
||||
companyRouter.POST("/tax-details", HandleCompanyTaxDetailsForm)
|
||||
companyRouter.POST("/tax", HandleAddCompanyTax)
|
||||
companyRouter.DELETE("/tax/:taxId", HandleDeleteCompanyTax)
|
||||
companyRouter.POST("/payment-method", HandleAddPaymentMethod)
|
||||
companyRouter.DELETE("/payment-method/:paymentMethodId", HandleDeletePaymentMethod)
|
||||
companyRouter.GET("/invoicing", serveCompanyInvoicingForm)
|
||||
companyRouter.POST("/invoicing", handleCompanyInvoicingForm)
|
||||
companyRouter.GET("/switch-company", GetCompanySwitcher)
|
||||
companyRouter.GET("/taxes", serveCompanyTaxes)
|
||||
companyRouter.POST("/taxes", HandleAddCompanyTax)
|
||||
companyRouter.DELETE("/taxes/:taxId", HandleDeleteCompanyTax)
|
||||
companyRouter.GET("/payment-methods", servePaymentMethods)
|
||||
companyRouter.POST("/payment-methods", HandleAddPaymentMethod)
|
||||
companyRouter.DELETE("/payment-methods/:paymentMethodId", HandleDeletePaymentMethod)
|
||||
companyRouter.GET("/contacts", IndexContacts)
|
||||
companyRouter.POST("/contacts", HandleAddContact)
|
||||
companyRouter.POST("/contacts/import", HandleImportContacts)
|
||||
|
|
359
po/ca.po
359
po/ca.po
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: numerus\n"
|
||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||
"POT-Creation-Date: 2024-08-13 02:06+0200\n"
|
||||
"POT-Creation-Date: 2024-08-14 04:02+0200\n"
|
||||
"PO-Revision-Date: 2023-01-18 17:08+0100\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||
|
@ -26,17 +26,20 @@ msgstr "Afegeix productes a la factura"
|
|||
#: web/template/invoices/products.gohtml:9 web/template/invoices/new.gohtml:9
|
||||
#: web/template/invoices/index.gohtml:9 web/template/invoices/view.gohtml:9
|
||||
#: web/template/invoices/edit.gohtml:9 web/template/home.gohtml:2
|
||||
#: web/template/switch-company.gohtml:9 web/template/quotes/products.gohtml:9
|
||||
#: web/template/quotes/new.gohtml:9 web/template/quotes/index.gohtml:9
|
||||
#: web/template/quotes/view.gohtml:9 web/template/quotes/edit.gohtml:9
|
||||
#: web/template/contacts/new.gohtml:9 web/template/contacts/index.gohtml:9
|
||||
#: web/template/contacts/edit.gohtml:10 web/template/contacts/import.gohtml:8
|
||||
#: web/template/profile.gohtml:9 web/template/expenses/new.gohtml:10
|
||||
#: web/template/expenses/index.gohtml:10 web/template/expenses/edit.gohtml:10
|
||||
#: web/template/tax-details.gohtml:9 web/template/products/new.gohtml:9
|
||||
#: web/template/products/index.gohtml:9 web/template/products/edit.gohtml:10
|
||||
#: web/template/payments/new.gohtml:10 web/template/payments/index.gohtml:10
|
||||
#: web/template/payments/edit.gohtml:10
|
||||
#: web/template/quotes/products.gohtml:9 web/template/quotes/new.gohtml:9
|
||||
#: web/template/quotes/index.gohtml:9 web/template/quotes/view.gohtml:9
|
||||
#: web/template/quotes/edit.gohtml:9 web/template/contacts/new.gohtml:9
|
||||
#: web/template/contacts/index.gohtml:9 web/template/contacts/edit.gohtml:10
|
||||
#: web/template/contacts/import.gohtml:8 web/template/profile.gohtml:9
|
||||
#: web/template/expenses/new.gohtml:10 web/template/expenses/index.gohtml:10
|
||||
#: web/template/expenses/edit.gohtml:10 web/template/company/taxes.gohtml:10
|
||||
#: web/template/company/switch.gohtml:9
|
||||
#: web/template/company/tax-details.gohtml:9
|
||||
#: web/template/company/invoicing.gohtml:10
|
||||
#: web/template/company/payment_methods.gohtml:10
|
||||
#: web/template/products/new.gohtml:9 web/template/products/index.gohtml:9
|
||||
#: web/template/products/edit.gohtml:10 web/template/payments/new.gohtml:10
|
||||
#: web/template/payments/index.gohtml:10 web/template/payments/edit.gohtml:10
|
||||
#: web/template/payments/accounts/new.gohtml:10
|
||||
#: web/template/payments/accounts/index.gohtml:10
|
||||
#: web/template/payments/accounts/edit.gohtml:10
|
||||
|
@ -64,7 +67,7 @@ msgid "All"
|
|||
msgstr "Tots"
|
||||
|
||||
#: web/template/invoices/products.gohtml:49
|
||||
#: web/template/switch-company.gohtml:22 web/template/quotes/products.gohtml:49
|
||||
#: web/template/quotes/products.gohtml:49 web/template/company/switch.gohtml:22
|
||||
#: web/template/products/index.gohtml:45
|
||||
#: web/template/payments/accounts/index.gohtml:25
|
||||
msgctxt "title"
|
||||
|
@ -214,9 +217,9 @@ msgctxt "title"
|
|||
msgid "Download"
|
||||
msgstr "Descàrrega"
|
||||
|
||||
#: web/template/invoices/index.gohtml:74 web/template/switch-company.gohtml:23
|
||||
#: web/template/quotes/index.gohtml:74 web/template/contacts/index.gohtml:51
|
||||
#: web/template/expenses/index.gohtml:76 web/template/products/index.gohtml:48
|
||||
#: web/template/invoices/index.gohtml:74 web/template/quotes/index.gohtml:74
|
||||
#: web/template/contacts/index.gohtml:51 web/template/expenses/index.gohtml:76
|
||||
#: web/template/company/switch.gohtml:23 web/template/products/index.gohtml:48
|
||||
#: web/template/payments/index.gohtml:31
|
||||
msgctxt "title"
|
||||
msgid "Actions"
|
||||
|
@ -342,17 +345,6 @@ msgctxt "action"
|
|||
msgid "Filters"
|
||||
msgstr "Filtra"
|
||||
|
||||
#: web/template/switch-company.gohtml:2 web/template/switch-company.gohtml:10
|
||||
#: web/template/switch-company.gohtml:18
|
||||
msgctxt "title"
|
||||
msgid "Company Switch"
|
||||
msgstr "Canvi d’empresa"
|
||||
|
||||
#: web/template/switch-company.gohtml:30
|
||||
msgctxt "action"
|
||||
msgid "Switch"
|
||||
msgstr "Canvia"
|
||||
|
||||
#: web/template/dashboard.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Dashboard"
|
||||
|
@ -468,52 +460,75 @@ msgctxt "menu"
|
|||
msgid "Tax Details"
|
||||
msgstr "Configuració fiscal"
|
||||
|
||||
#: web/template/app.gohtml:36
|
||||
#: web/template/app.gohtml:36 web/template/company/invoicing.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Invoicing and Quoting"
|
||||
msgstr "Facturació i pressuposts"
|
||||
|
||||
#: web/template/app.gohtml:42 web/template/company/taxes.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Taxes"
|
||||
msgstr "Imposts"
|
||||
|
||||
#: web/template/app.gohtml:48 web/template/company/payment_methods.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Payment Methods"
|
||||
msgstr "Mètodes de pagament"
|
||||
|
||||
#: web/template/app.gohtml:54 web/template/payments/accounts/new.gohtml:11
|
||||
#: web/template/payments/accounts/index.gohtml:3
|
||||
#: web/template/payments/accounts/index.gohtml:11
|
||||
#: web/template/payments/accounts/edit.gohtml:11
|
||||
msgctxt "title"
|
||||
msgid "Payment Accounts"
|
||||
msgstr "Comptes de pagament"
|
||||
|
||||
#: web/template/app.gohtml:60
|
||||
msgctxt "menu"
|
||||
msgid "Switch Company"
|
||||
msgstr "Canvi d’empresa"
|
||||
|
||||
#: web/template/app.gohtml:44
|
||||
#: web/template/app.gohtml:68
|
||||
msgctxt "action"
|
||||
msgid "Logout"
|
||||
msgstr "Surt"
|
||||
|
||||
#: web/template/app.gohtml:53
|
||||
#: web/template/app.gohtml:77
|
||||
msgctxt "nav"
|
||||
msgid "Dashboard"
|
||||
msgstr "Tauler"
|
||||
|
||||
#: web/template/app.gohtml:54
|
||||
#: web/template/app.gohtml:78
|
||||
msgctxt "nav"
|
||||
msgid "Quotations"
|
||||
msgstr "Pressuposts"
|
||||
|
||||
#: web/template/app.gohtml:55
|
||||
#: web/template/app.gohtml:79
|
||||
msgctxt "nav"
|
||||
msgid "Invoices"
|
||||
msgstr "Factures"
|
||||
|
||||
#: web/template/app.gohtml:56
|
||||
#: web/template/app.gohtml:80
|
||||
msgctxt "nav"
|
||||
msgid "Expenses"
|
||||
msgstr "Despeses"
|
||||
|
||||
#: web/template/app.gohtml:57
|
||||
#: web/template/app.gohtml:81
|
||||
msgctxt "nav"
|
||||
msgid "Payments"
|
||||
msgstr "Pagaments"
|
||||
|
||||
#: web/template/app.gohtml:58
|
||||
#: web/template/app.gohtml:82
|
||||
msgctxt "nav"
|
||||
msgid "Products"
|
||||
msgstr "Productes"
|
||||
|
||||
#: web/template/app.gohtml:59
|
||||
#: web/template/app.gohtml:83
|
||||
msgctxt "nav"
|
||||
msgid "Contacts"
|
||||
msgstr "Contactes"
|
||||
|
||||
#: web/template/app.gohtml:67
|
||||
#: web/template/app.gohtml:91
|
||||
msgid "<a href=\"https://numerus.cat/\">Numerus</a> Version: %s"
|
||||
msgstr "<a href=\"https://numerus.cat/\">Numerus</a> versió: %s"
|
||||
|
||||
|
@ -604,7 +619,8 @@ msgctxt "title"
|
|||
msgid "Language"
|
||||
msgstr "Idioma"
|
||||
|
||||
#: web/template/profile.gohtml:39 web/template/tax-details.gohtml:175
|
||||
#: web/template/profile.gohtml:39 web/template/company/tax-details.gohtml:36
|
||||
#: web/template/company/invoicing.gohtml:31
|
||||
msgctxt "action"
|
||||
msgid "Save changes"
|
||||
msgstr "Desa canvis"
|
||||
|
@ -649,70 +665,75 @@ msgctxt "title"
|
|||
msgid "Edit Expense “%s”"
|
||||
msgstr "Edició de la despesa «%s»"
|
||||
|
||||
#: web/template/tax-details.gohtml:2 web/template/tax-details.gohtml:10
|
||||
#: web/template/tax-details.gohtml:18
|
||||
msgctxt "title"
|
||||
msgid "Tax Details"
|
||||
msgstr "Configuració fiscal"
|
||||
|
||||
#: web/template/tax-details.gohtml:35
|
||||
msgctxt "title"
|
||||
msgid "Currency"
|
||||
msgstr "Moneda"
|
||||
|
||||
#: web/template/tax-details.gohtml:41
|
||||
msgctxt "title"
|
||||
msgid "Invoicing and Quoting"
|
||||
msgstr "Facturació i pressuposts"
|
||||
|
||||
#: web/template/tax-details.gohtml:56
|
||||
msgid "Are you sure?"
|
||||
msgstr "N’esteu segur?"
|
||||
|
||||
#: web/template/tax-details.gohtml:62
|
||||
#: web/template/company/taxes.gohtml:23
|
||||
msgctxt "title"
|
||||
msgid "Tax Name"
|
||||
msgstr "Nom impost"
|
||||
|
||||
#: web/template/tax-details.gohtml:63
|
||||
#: web/template/company/taxes.gohtml:24
|
||||
msgctxt "title"
|
||||
msgid "Rate (%)"
|
||||
msgstr "Percentatge"
|
||||
|
||||
#: web/template/tax-details.gohtml:64
|
||||
#: web/template/company/taxes.gohtml:25
|
||||
msgctxt "title"
|
||||
msgid "Class"
|
||||
msgstr "Classe"
|
||||
|
||||
#: web/template/tax-details.gohtml:88
|
||||
#: web/template/company/taxes.gohtml:29
|
||||
#: web/template/company/payment_methods.gohtml:28
|
||||
msgid "Are you sure?"
|
||||
msgstr "N’esteu segur?"
|
||||
|
||||
#: web/template/company/taxes.gohtml:49
|
||||
msgid "No taxes added yet."
|
||||
msgstr "No hi ha cap impost."
|
||||
|
||||
#: web/template/tax-details.gohtml:94 web/template/tax-details.gohtml:155
|
||||
#: web/template/company/taxes.gohtml:56
|
||||
msgctxt "title"
|
||||
msgid "New Line"
|
||||
msgstr "Nova línia"
|
||||
msgid "New Tax"
|
||||
msgstr "Nou impost"
|
||||
|
||||
#: web/template/tax-details.gohtml:108
|
||||
#: web/template/company/taxes.gohtml:66
|
||||
msgctxt "action"
|
||||
msgid "Add new tax"
|
||||
msgstr "Afegeix nou impost"
|
||||
|
||||
#: web/template/tax-details.gohtml:124
|
||||
#: web/template/company/switch.gohtml:2
|
||||
msgctxt "title"
|
||||
msgid "Company Switch"
|
||||
msgstr "Canvi d’empresa"
|
||||
|
||||
#: web/template/company/switch.gohtml:30
|
||||
msgctxt "action"
|
||||
msgid "Switch"
|
||||
msgstr "Canvia"
|
||||
|
||||
#: web/template/company/tax-details.gohtml:2
|
||||
msgctxt "title"
|
||||
msgid "Tax Details"
|
||||
msgstr "Configuració fiscal"
|
||||
|
||||
#: web/template/company/payment_methods.gohtml:23
|
||||
msgctxt "title"
|
||||
msgid "Payment Method"
|
||||
msgstr "Mètode de pagament"
|
||||
|
||||
#: web/template/tax-details.gohtml:125
|
||||
#: web/template/company/payment_methods.gohtml:24
|
||||
msgctxt "title"
|
||||
msgid "Instructions"
|
||||
msgstr "Instruccions"
|
||||
|
||||
#: web/template/tax-details.gohtml:149
|
||||
#: web/template/company/payment_methods.gohtml:48
|
||||
msgid "No payment methods added yet."
|
||||
msgstr "No hi ha cap mètode de pagament."
|
||||
|
||||
#: web/template/tax-details.gohtml:167
|
||||
#: web/template/company/payment_methods.gohtml:55
|
||||
msgctxt "title"
|
||||
msgid "New Payment Method"
|
||||
msgstr "Nou mètode de pagament"
|
||||
|
||||
#: web/template/company/payment_methods.gohtml:64
|
||||
msgctxt "action"
|
||||
msgid "Add new payment method"
|
||||
msgstr "Afegeix nou mètode de pagament"
|
||||
|
@ -801,14 +822,6 @@ msgctxt "title"
|
|||
msgid "New Payment Account"
|
||||
msgstr "Nou compte de pagament"
|
||||
|
||||
#: web/template/payments/accounts/new.gohtml:11
|
||||
#: web/template/payments/accounts/index.gohtml:3
|
||||
#: web/template/payments/accounts/index.gohtml:11
|
||||
#: web/template/payments/accounts/edit.gohtml:11
|
||||
msgctxt "title"
|
||||
msgid "Payment Accounts"
|
||||
msgstr "Comptes de pagament"
|
||||
|
||||
#: web/template/payments/accounts/index.gohtml:16
|
||||
msgctxt "action"
|
||||
msgid "New payment account"
|
||||
|
@ -843,7 +856,7 @@ msgctxt "title"
|
|||
msgid "VAT number"
|
||||
msgstr "DNI / NIF"
|
||||
|
||||
#: pkg/login.go:38 pkg/company.go:127 pkg/profile.go:40 pkg/contacts.go:276
|
||||
#: pkg/login.go:38 pkg/company.go:122 pkg/profile.go:40 pkg/contacts.go:276
|
||||
msgctxt "input"
|
||||
msgid "Email"
|
||||
msgstr "Correu-e"
|
||||
|
@ -853,11 +866,11 @@ msgctxt "input"
|
|||
msgid "Password"
|
||||
msgstr "Contrasenya"
|
||||
|
||||
#: pkg/login.go:76 pkg/company.go:283 pkg/profile.go:89
|
||||
#: pkg/login.go:76 pkg/company.go:238 pkg/profile.go:89
|
||||
msgid "Email can not be empty."
|
||||
msgstr "No podeu deixar el correu-e en blanc."
|
||||
|
||||
#: pkg/login.go:77 pkg/company.go:284 pkg/profile.go:90 pkg/contacts.go:420
|
||||
#: pkg/login.go:77 pkg/company.go:239 pkg/profile.go:90 pkg/contacts.go:420
|
||||
msgid "This value is not a valid email. It should be like name@domain.com."
|
||||
msgstr "Aquest valor no és un correu-e vàlid. Hauria de ser similar a nom@domini.cat."
|
||||
|
||||
|
@ -951,208 +964,208 @@ msgstr "Heu seleccionat un impost que no és vàlid."
|
|||
msgid "You can only select a tax of each class."
|
||||
msgstr "Només podeu seleccionar un impost de cada classe."
|
||||
|
||||
#: pkg/company.go:113
|
||||
#: pkg/company.go:108
|
||||
msgctxt "input"
|
||||
msgid "Trade name"
|
||||
msgstr "Nom comercial"
|
||||
|
||||
#: pkg/company.go:118 pkg/contacts.go:268
|
||||
#: pkg/company.go:113 pkg/contacts.go:268
|
||||
msgctxt "input"
|
||||
msgid "Phone"
|
||||
msgstr "Telèfon"
|
||||
|
||||
#: pkg/company.go:136 pkg/contacts.go:284
|
||||
#: pkg/company.go:131 pkg/contacts.go:284
|
||||
msgctxt "input"
|
||||
msgid "Web"
|
||||
msgstr "Web"
|
||||
|
||||
#: pkg/company.go:144 pkg/contacts.go:296
|
||||
#: pkg/company.go:139 pkg/contacts.go:296
|
||||
msgctxt "input"
|
||||
msgid "Business name"
|
||||
msgstr "Nom i cognoms"
|
||||
|
||||
#: pkg/company.go:154 pkg/contacts.go:306
|
||||
#: pkg/company.go:149 pkg/contacts.go:306
|
||||
msgctxt "input"
|
||||
msgid "VAT number"
|
||||
msgstr "DNI / NIF"
|
||||
|
||||
#: pkg/company.go:160 pkg/contacts.go:312
|
||||
#: pkg/company.go:155 pkg/contacts.go:312
|
||||
msgctxt "input"
|
||||
msgid "Address"
|
||||
msgstr "Adreça"
|
||||
|
||||
#: pkg/company.go:169 pkg/contacts.go:321
|
||||
#: pkg/company.go:164 pkg/contacts.go:321
|
||||
msgctxt "input"
|
||||
msgid "City"
|
||||
msgstr "Població"
|
||||
|
||||
#: pkg/company.go:175 pkg/contacts.go:327
|
||||
#: pkg/company.go:170 pkg/contacts.go:327
|
||||
msgctxt "input"
|
||||
msgid "Province"
|
||||
msgstr "Província"
|
||||
|
||||
#: pkg/company.go:181 pkg/contacts.go:333
|
||||
#: pkg/company.go:176 pkg/contacts.go:333
|
||||
msgctxt "input"
|
||||
msgid "Postal code"
|
||||
msgstr "Codi postal"
|
||||
|
||||
#: pkg/company.go:190 pkg/contacts.go:342
|
||||
#: pkg/company.go:185 pkg/contacts.go:342
|
||||
msgctxt "input"
|
||||
msgid "Country"
|
||||
msgstr "País"
|
||||
|
||||
#: pkg/company.go:200
|
||||
#: pkg/company.go:195
|
||||
msgctxt "input"
|
||||
msgid "Currency"
|
||||
msgstr "Moneda"
|
||||
|
||||
#: pkg/company.go:207
|
||||
#: pkg/company.go:226 pkg/contacts.go:394
|
||||
msgid "Selected country is not valid."
|
||||
msgstr "Heu seleccionat un país que no és vàlid."
|
||||
|
||||
#: pkg/company.go:230 pkg/contacts.go:397
|
||||
msgid "Business name can not be empty."
|
||||
msgstr "No podeu deixar el nom i els cognoms en blanc."
|
||||
|
||||
#: pkg/company.go:231 pkg/contacts.go:398
|
||||
msgid "Business name must have at least two letters."
|
||||
msgstr "Nom i cognoms han de tenir com a mínim dues lletres."
|
||||
|
||||
#: pkg/company.go:232 pkg/contacts.go:400
|
||||
msgid "VAT number can not be empty."
|
||||
msgstr "No podeu deixar el DNI o NIF en blanc."
|
||||
|
||||
#: pkg/company.go:233 pkg/contacts.go:401
|
||||
msgid "This value is not a valid VAT number."
|
||||
msgstr "Aquest valor no és un DNI o NIF vàlid."
|
||||
|
||||
#: pkg/company.go:235
|
||||
msgid "Phone can not be empty."
|
||||
msgstr "No podeu deixar el telèfon en blanc."
|
||||
|
||||
#: pkg/company.go:236 pkg/contacts.go:417
|
||||
msgid "This value is not a valid phone number."
|
||||
msgstr "Aquest valor no és un telèfon vàlid."
|
||||
|
||||
#: pkg/company.go:242 pkg/contacts.go:423
|
||||
msgid "This value is not a valid web address. It should be like https://domain.com/."
|
||||
msgstr "Aquest valor no és una adreça web vàlida. Hauria de ser similar a https://domini.cat/."
|
||||
|
||||
#: pkg/company.go:244 pkg/contacts.go:403
|
||||
msgid "Address can not be empty."
|
||||
msgstr "No podeu deixar l’adreça en blanc."
|
||||
|
||||
#: pkg/company.go:245 pkg/contacts.go:404
|
||||
msgid "City can not be empty."
|
||||
msgstr "No podeu deixar la població en blanc."
|
||||
|
||||
#: pkg/company.go:246 pkg/contacts.go:405
|
||||
msgid "Province can not be empty."
|
||||
msgstr "No podeu deixar la província en blanc."
|
||||
|
||||
#: pkg/company.go:247 pkg/contacts.go:407
|
||||
msgid "Postal code can not be empty."
|
||||
msgstr "No podeu deixar el codi postal en blanc."
|
||||
|
||||
#: pkg/company.go:248 pkg/contacts.go:408
|
||||
msgid "This value is not a valid postal code."
|
||||
msgstr "Aquest valor no és un codi postal vàlid."
|
||||
|
||||
#: pkg/company.go:250
|
||||
msgid "Selected currency is not valid."
|
||||
msgstr "Heu seleccionat una moneda que no és vàlida."
|
||||
|
||||
#: pkg/company.go:402
|
||||
msgctxt "input"
|
||||
msgid "Invoice number format"
|
||||
msgstr "Format del número de factura"
|
||||
|
||||
#: pkg/company.go:213
|
||||
#: pkg/company.go:408
|
||||
msgctxt "input"
|
||||
msgid "Next invoice number"
|
||||
msgstr "Següent número de factura"
|
||||
|
||||
#: pkg/company.go:222
|
||||
#: pkg/company.go:417
|
||||
msgctxt "input"
|
||||
msgid "Quotation number format"
|
||||
msgstr "Format del número de pressupost"
|
||||
|
||||
#: pkg/company.go:228
|
||||
#: pkg/company.go:423
|
||||
msgctxt "input"
|
||||
msgid "Next quotation number"
|
||||
msgstr "Següent número de pressupost"
|
||||
|
||||
#: pkg/company.go:237
|
||||
#: pkg/company.go:432
|
||||
msgctxt "input"
|
||||
msgid "Legal disclaimer"
|
||||
msgstr "Nota legal"
|
||||
|
||||
#: pkg/company.go:271 pkg/contacts.go:394
|
||||
msgid "Selected country is not valid."
|
||||
msgstr "Heu seleccionat un país que no és vàlid."
|
||||
|
||||
#: pkg/company.go:275 pkg/contacts.go:397
|
||||
msgid "Business name can not be empty."
|
||||
msgstr "No podeu deixar el nom i els cognoms en blanc."
|
||||
|
||||
#: pkg/company.go:276 pkg/contacts.go:398
|
||||
msgid "Business name must have at least two letters."
|
||||
msgstr "Nom i cognoms han de tenir com a mínim dues lletres."
|
||||
|
||||
#: pkg/company.go:277 pkg/contacts.go:400
|
||||
msgid "VAT number can not be empty."
|
||||
msgstr "No podeu deixar el DNI o NIF en blanc."
|
||||
|
||||
#: pkg/company.go:278 pkg/contacts.go:401
|
||||
msgid "This value is not a valid VAT number."
|
||||
msgstr "Aquest valor no és un DNI o NIF vàlid."
|
||||
|
||||
#: pkg/company.go:280
|
||||
msgid "Phone can not be empty."
|
||||
msgstr "No podeu deixar el telèfon en blanc."
|
||||
|
||||
#: pkg/company.go:281 pkg/contacts.go:417
|
||||
msgid "This value is not a valid phone number."
|
||||
msgstr "Aquest valor no és un telèfon vàlid."
|
||||
|
||||
#: pkg/company.go:287 pkg/contacts.go:423
|
||||
msgid "This value is not a valid web address. It should be like https://domain.com/."
|
||||
msgstr "Aquest valor no és una adreça web vàlida. Hauria de ser similar a https://domini.cat/."
|
||||
|
||||
#: pkg/company.go:289 pkg/contacts.go:403
|
||||
msgid "Address can not be empty."
|
||||
msgstr "No podeu deixar l’adreça en blanc."
|
||||
|
||||
#: pkg/company.go:290 pkg/contacts.go:404
|
||||
msgid "City can not be empty."
|
||||
msgstr "No podeu deixar la població en blanc."
|
||||
|
||||
#: pkg/company.go:291 pkg/contacts.go:405
|
||||
msgid "Province can not be empty."
|
||||
msgstr "No podeu deixar la província en blanc."
|
||||
|
||||
#: pkg/company.go:292 pkg/contacts.go:407
|
||||
msgid "Postal code can not be empty."
|
||||
msgstr "No podeu deixar el codi postal en blanc."
|
||||
|
||||
#: pkg/company.go:293 pkg/contacts.go:408
|
||||
msgid "This value is not a valid postal code."
|
||||
msgstr "Aquest valor no és un codi postal vàlid."
|
||||
|
||||
#: pkg/company.go:295
|
||||
msgid "Selected currency is not valid."
|
||||
msgstr "Heu seleccionat una moneda que no és vàlida."
|
||||
|
||||
#: pkg/company.go:296
|
||||
#: pkg/company.go:489
|
||||
msgid "Invoice number format can not be empty."
|
||||
msgstr "No podeu deixar el format del número de factura en blanc."
|
||||
|
||||
#: pkg/company.go:297
|
||||
#: pkg/company.go:490
|
||||
msgid "Next invoice number must be a number greater than zero."
|
||||
msgstr "El següent número de factura ha de ser un número major a zero."
|
||||
|
||||
#: pkg/company.go:298
|
||||
#: pkg/company.go:491
|
||||
msgid "Quotation number format can not be empty."
|
||||
msgstr "No podeu deixar el format del número de pressupost en blanc."
|
||||
|
||||
#: pkg/company.go:299
|
||||
#: pkg/company.go:492
|
||||
msgid "Next quotation number must be a number greater than zero."
|
||||
msgstr "El següent número de pressupost ha de ser un número major a zero."
|
||||
|
||||
#: pkg/company.go:563
|
||||
#: pkg/company.go:614
|
||||
msgctxt "input"
|
||||
msgid "Tax name"
|
||||
msgstr "Nom impost"
|
||||
|
||||
#: pkg/company.go:569
|
||||
#: pkg/company.go:620
|
||||
msgctxt "input"
|
||||
msgid "Tax Class"
|
||||
msgstr "Classe d’impost"
|
||||
|
||||
#: pkg/company.go:572
|
||||
#: pkg/company.go:623
|
||||
msgid "Select a tax class"
|
||||
msgstr "Escolliu una classe d’impost"
|
||||
|
||||
#: pkg/company.go:576
|
||||
#: pkg/company.go:627
|
||||
msgctxt "input"
|
||||
msgid "Rate (%)"
|
||||
msgstr "Percentatge"
|
||||
|
||||
#: pkg/company.go:599
|
||||
#: pkg/company.go:650
|
||||
msgid "Tax name can not be empty."
|
||||
msgstr "No podeu deixar el nom de l’impost en blanc."
|
||||
|
||||
#: pkg/company.go:600
|
||||
#: pkg/company.go:651
|
||||
msgid "Selected tax class is not valid."
|
||||
msgstr "Heu seleccionat una classe d’impost que no és vàlida."
|
||||
|
||||
#: pkg/company.go:601
|
||||
#: pkg/company.go:652
|
||||
msgid "Tax rate can not be empty."
|
||||
msgstr "No podeu deixar percentatge en blanc."
|
||||
|
||||
#: pkg/company.go:602
|
||||
#: pkg/company.go:653
|
||||
msgid "Tax rate must be an integer between -99 and 99."
|
||||
msgstr "El percentatge ha de ser entre -99 i 99."
|
||||
|
||||
#: pkg/company.go:665
|
||||
#: pkg/company.go:762
|
||||
msgctxt "input"
|
||||
msgid "Payment method name"
|
||||
msgstr "Nom del mètode de pagament"
|
||||
|
||||
#: pkg/company.go:671
|
||||
#: pkg/company.go:768
|
||||
msgctxt "input"
|
||||
msgid "Instructions"
|
||||
msgstr "Instruccions"
|
||||
|
||||
#: pkg/company.go:689
|
||||
#: pkg/company.go:786
|
||||
msgid "Payment method name can not be empty."
|
||||
msgstr "No podeu deixar el nom del mètode de pagament en blanc."
|
||||
|
||||
#: pkg/company.go:690
|
||||
#: pkg/company.go:787
|
||||
msgid "Payment instructions can not be empty."
|
||||
msgstr "No podeu deixar les instruccions de pagament en blanc."
|
||||
|
||||
|
@ -1567,6 +1580,14 @@ msgctxt "input"
|
|||
msgid "Holded Excel file"
|
||||
msgstr "Fitxer Excel del Holded"
|
||||
|
||||
#~ msgctxt "title"
|
||||
#~ msgid "Currency"
|
||||
#~ msgstr "Moneda"
|
||||
|
||||
#~ msgctxt "title"
|
||||
#~ msgid "New Line"
|
||||
#~ msgstr "Nova línia"
|
||||
|
||||
#~ msgid "Selected expense status is not valid."
|
||||
#~ msgstr "Heu seleccionat un estat de despesa que no és vàlid."
|
||||
|
||||
|
|
359
po/es.po
359
po/es.po
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: numerus\n"
|
||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||
"POT-Creation-Date: 2024-08-13 02:06+0200\n"
|
||||
"POT-Creation-Date: 2024-08-14 04:02+0200\n"
|
||||
"PO-Revision-Date: 2023-01-18 17:45+0100\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||
|
@ -26,17 +26,20 @@ msgstr "Añadir productos a la factura"
|
|||
#: web/template/invoices/products.gohtml:9 web/template/invoices/new.gohtml:9
|
||||
#: web/template/invoices/index.gohtml:9 web/template/invoices/view.gohtml:9
|
||||
#: web/template/invoices/edit.gohtml:9 web/template/home.gohtml:2
|
||||
#: web/template/switch-company.gohtml:9 web/template/quotes/products.gohtml:9
|
||||
#: web/template/quotes/new.gohtml:9 web/template/quotes/index.gohtml:9
|
||||
#: web/template/quotes/view.gohtml:9 web/template/quotes/edit.gohtml:9
|
||||
#: web/template/contacts/new.gohtml:9 web/template/contacts/index.gohtml:9
|
||||
#: web/template/contacts/edit.gohtml:10 web/template/contacts/import.gohtml:8
|
||||
#: web/template/profile.gohtml:9 web/template/expenses/new.gohtml:10
|
||||
#: web/template/expenses/index.gohtml:10 web/template/expenses/edit.gohtml:10
|
||||
#: web/template/tax-details.gohtml:9 web/template/products/new.gohtml:9
|
||||
#: web/template/products/index.gohtml:9 web/template/products/edit.gohtml:10
|
||||
#: web/template/payments/new.gohtml:10 web/template/payments/index.gohtml:10
|
||||
#: web/template/payments/edit.gohtml:10
|
||||
#: web/template/quotes/products.gohtml:9 web/template/quotes/new.gohtml:9
|
||||
#: web/template/quotes/index.gohtml:9 web/template/quotes/view.gohtml:9
|
||||
#: web/template/quotes/edit.gohtml:9 web/template/contacts/new.gohtml:9
|
||||
#: web/template/contacts/index.gohtml:9 web/template/contacts/edit.gohtml:10
|
||||
#: web/template/contacts/import.gohtml:8 web/template/profile.gohtml:9
|
||||
#: web/template/expenses/new.gohtml:10 web/template/expenses/index.gohtml:10
|
||||
#: web/template/expenses/edit.gohtml:10 web/template/company/taxes.gohtml:10
|
||||
#: web/template/company/switch.gohtml:9
|
||||
#: web/template/company/tax-details.gohtml:9
|
||||
#: web/template/company/invoicing.gohtml:10
|
||||
#: web/template/company/payment_methods.gohtml:10
|
||||
#: web/template/products/new.gohtml:9 web/template/products/index.gohtml:9
|
||||
#: web/template/products/edit.gohtml:10 web/template/payments/new.gohtml:10
|
||||
#: web/template/payments/index.gohtml:10 web/template/payments/edit.gohtml:10
|
||||
#: web/template/payments/accounts/new.gohtml:10
|
||||
#: web/template/payments/accounts/index.gohtml:10
|
||||
#: web/template/payments/accounts/edit.gohtml:10
|
||||
|
@ -64,7 +67,7 @@ msgid "All"
|
|||
msgstr "Todos"
|
||||
|
||||
#: web/template/invoices/products.gohtml:49
|
||||
#: web/template/switch-company.gohtml:22 web/template/quotes/products.gohtml:49
|
||||
#: web/template/quotes/products.gohtml:49 web/template/company/switch.gohtml:22
|
||||
#: web/template/products/index.gohtml:45
|
||||
#: web/template/payments/accounts/index.gohtml:25
|
||||
msgctxt "title"
|
||||
|
@ -214,9 +217,9 @@ msgctxt "title"
|
|||
msgid "Download"
|
||||
msgstr "Descargar"
|
||||
|
||||
#: web/template/invoices/index.gohtml:74 web/template/switch-company.gohtml:23
|
||||
#: web/template/quotes/index.gohtml:74 web/template/contacts/index.gohtml:51
|
||||
#: web/template/expenses/index.gohtml:76 web/template/products/index.gohtml:48
|
||||
#: web/template/invoices/index.gohtml:74 web/template/quotes/index.gohtml:74
|
||||
#: web/template/contacts/index.gohtml:51 web/template/expenses/index.gohtml:76
|
||||
#: web/template/company/switch.gohtml:23 web/template/products/index.gohtml:48
|
||||
#: web/template/payments/index.gohtml:31
|
||||
msgctxt "title"
|
||||
msgid "Actions"
|
||||
|
@ -342,17 +345,6 @@ msgctxt "action"
|
|||
msgid "Filters"
|
||||
msgstr "Filtrar"
|
||||
|
||||
#: web/template/switch-company.gohtml:2 web/template/switch-company.gohtml:10
|
||||
#: web/template/switch-company.gohtml:18
|
||||
msgctxt "title"
|
||||
msgid "Company Switch"
|
||||
msgstr "Cambio de empresa"
|
||||
|
||||
#: web/template/switch-company.gohtml:30
|
||||
msgctxt "action"
|
||||
msgid "Switch"
|
||||
msgstr "Cambiar"
|
||||
|
||||
#: web/template/dashboard.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Dashboard"
|
||||
|
@ -468,52 +460,75 @@ msgctxt "menu"
|
|||
msgid "Tax Details"
|
||||
msgstr "Configuración fiscal"
|
||||
|
||||
#: web/template/app.gohtml:36
|
||||
#: web/template/app.gohtml:36 web/template/company/invoicing.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Invoicing and Quoting"
|
||||
msgstr "Facturación y presupuestos"
|
||||
|
||||
#: web/template/app.gohtml:42 web/template/company/taxes.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Taxes"
|
||||
msgstr "Impuestos"
|
||||
|
||||
#: web/template/app.gohtml:48 web/template/company/payment_methods.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Payment Methods"
|
||||
msgstr "Métodos de pago"
|
||||
|
||||
#: web/template/app.gohtml:54 web/template/payments/accounts/new.gohtml:11
|
||||
#: web/template/payments/accounts/index.gohtml:3
|
||||
#: web/template/payments/accounts/index.gohtml:11
|
||||
#: web/template/payments/accounts/edit.gohtml:11
|
||||
msgctxt "title"
|
||||
msgid "Payment Accounts"
|
||||
msgstr "Cuenta de pago"
|
||||
|
||||
#: web/template/app.gohtml:60
|
||||
msgctxt "menu"
|
||||
msgid "Switch Company"
|
||||
msgstr "Cambio de empresa"
|
||||
|
||||
#: web/template/app.gohtml:44
|
||||
#: web/template/app.gohtml:68
|
||||
msgctxt "action"
|
||||
msgid "Logout"
|
||||
msgstr "Salir"
|
||||
|
||||
#: web/template/app.gohtml:53
|
||||
#: web/template/app.gohtml:77
|
||||
msgctxt "nav"
|
||||
msgid "Dashboard"
|
||||
msgstr "Panel"
|
||||
|
||||
#: web/template/app.gohtml:54
|
||||
#: web/template/app.gohtml:78
|
||||
msgctxt "nav"
|
||||
msgid "Quotations"
|
||||
msgstr "Presupuestos"
|
||||
|
||||
#: web/template/app.gohtml:55
|
||||
#: web/template/app.gohtml:79
|
||||
msgctxt "nav"
|
||||
msgid "Invoices"
|
||||
msgstr "Facturas"
|
||||
|
||||
#: web/template/app.gohtml:56
|
||||
#: web/template/app.gohtml:80
|
||||
msgctxt "nav"
|
||||
msgid "Expenses"
|
||||
msgstr "Gastos"
|
||||
|
||||
#: web/template/app.gohtml:57
|
||||
#: web/template/app.gohtml:81
|
||||
msgctxt "nav"
|
||||
msgid "Payments"
|
||||
msgstr "Pagos"
|
||||
|
||||
#: web/template/app.gohtml:58
|
||||
#: web/template/app.gohtml:82
|
||||
msgctxt "nav"
|
||||
msgid "Products"
|
||||
msgstr "Productos"
|
||||
|
||||
#: web/template/app.gohtml:59
|
||||
#: web/template/app.gohtml:83
|
||||
msgctxt "nav"
|
||||
msgid "Contacts"
|
||||
msgstr "Contactos"
|
||||
|
||||
#: web/template/app.gohtml:67
|
||||
#: web/template/app.gohtml:91
|
||||
msgid "<a href=\"https://numerus.cat/\">Numerus</a> Version: %s"
|
||||
msgstr "<a href=\"https://numerus.cat/\">Numerus</a> versión: %s"
|
||||
|
||||
|
@ -604,7 +619,8 @@ msgctxt "title"
|
|||
msgid "Language"
|
||||
msgstr "Idioma"
|
||||
|
||||
#: web/template/profile.gohtml:39 web/template/tax-details.gohtml:175
|
||||
#: web/template/profile.gohtml:39 web/template/company/tax-details.gohtml:36
|
||||
#: web/template/company/invoicing.gohtml:31
|
||||
msgctxt "action"
|
||||
msgid "Save changes"
|
||||
msgstr "Guardar cambios"
|
||||
|
@ -649,70 +665,75 @@ msgctxt "title"
|
|||
msgid "Edit Expense “%s”"
|
||||
msgstr "Edición del gasto «%s»"
|
||||
|
||||
#: web/template/tax-details.gohtml:2 web/template/tax-details.gohtml:10
|
||||
#: web/template/tax-details.gohtml:18
|
||||
msgctxt "title"
|
||||
msgid "Tax Details"
|
||||
msgstr "Configuración fiscal"
|
||||
|
||||
#: web/template/tax-details.gohtml:35
|
||||
msgctxt "title"
|
||||
msgid "Currency"
|
||||
msgstr "Moneda"
|
||||
|
||||
#: web/template/tax-details.gohtml:41
|
||||
msgctxt "title"
|
||||
msgid "Invoicing and Quoting"
|
||||
msgstr "Facturación y presupuestos"
|
||||
|
||||
#: web/template/tax-details.gohtml:56
|
||||
msgid "Are you sure?"
|
||||
msgstr "¿Estáis seguro?"
|
||||
|
||||
#: web/template/tax-details.gohtml:62
|
||||
#: web/template/company/taxes.gohtml:23
|
||||
msgctxt "title"
|
||||
msgid "Tax Name"
|
||||
msgstr "Nombre impuesto"
|
||||
|
||||
#: web/template/tax-details.gohtml:63
|
||||
#: web/template/company/taxes.gohtml:24
|
||||
msgctxt "title"
|
||||
msgid "Rate (%)"
|
||||
msgstr "Porcentaje"
|
||||
|
||||
#: web/template/tax-details.gohtml:64
|
||||
#: web/template/company/taxes.gohtml:25
|
||||
msgctxt "title"
|
||||
msgid "Class"
|
||||
msgstr "Clase"
|
||||
|
||||
#: web/template/tax-details.gohtml:88
|
||||
#: web/template/company/taxes.gohtml:29
|
||||
#: web/template/company/payment_methods.gohtml:28
|
||||
msgid "Are you sure?"
|
||||
msgstr "¿Estáis seguro?"
|
||||
|
||||
#: web/template/company/taxes.gohtml:49
|
||||
msgid "No taxes added yet."
|
||||
msgstr "No hay impuestos."
|
||||
|
||||
#: web/template/tax-details.gohtml:94 web/template/tax-details.gohtml:155
|
||||
#: web/template/company/taxes.gohtml:56
|
||||
msgctxt "title"
|
||||
msgid "New Line"
|
||||
msgstr "Nueva línea"
|
||||
msgid "New Tax"
|
||||
msgstr "Nuevo impuesto"
|
||||
|
||||
#: web/template/tax-details.gohtml:108
|
||||
#: web/template/company/taxes.gohtml:66
|
||||
msgctxt "action"
|
||||
msgid "Add new tax"
|
||||
msgstr "Añadir nuevo impuesto"
|
||||
|
||||
#: web/template/tax-details.gohtml:124
|
||||
#: web/template/company/switch.gohtml:2
|
||||
msgctxt "title"
|
||||
msgid "Company Switch"
|
||||
msgstr "Cambio de empresa"
|
||||
|
||||
#: web/template/company/switch.gohtml:30
|
||||
msgctxt "action"
|
||||
msgid "Switch"
|
||||
msgstr "Cambiar"
|
||||
|
||||
#: web/template/company/tax-details.gohtml:2
|
||||
msgctxt "title"
|
||||
msgid "Tax Details"
|
||||
msgstr "Configuración fiscal"
|
||||
|
||||
#: web/template/company/payment_methods.gohtml:23
|
||||
msgctxt "title"
|
||||
msgid "Payment Method"
|
||||
msgstr "Método de pago"
|
||||
|
||||
#: web/template/tax-details.gohtml:125
|
||||
#: web/template/company/payment_methods.gohtml:24
|
||||
msgctxt "title"
|
||||
msgid "Instructions"
|
||||
msgstr "Instrucciones"
|
||||
|
||||
#: web/template/tax-details.gohtml:149
|
||||
#: web/template/company/payment_methods.gohtml:48
|
||||
msgid "No payment methods added yet."
|
||||
msgstr "No hay métodos de pago."
|
||||
|
||||
#: web/template/tax-details.gohtml:167
|
||||
#: web/template/company/payment_methods.gohtml:55
|
||||
msgctxt "title"
|
||||
msgid "New Payment Method"
|
||||
msgstr "Nuevo método de pago"
|
||||
|
||||
#: web/template/company/payment_methods.gohtml:64
|
||||
msgctxt "action"
|
||||
msgid "Add new payment method"
|
||||
msgstr "Añadir nuevo método de pago"
|
||||
|
@ -801,14 +822,6 @@ msgctxt "title"
|
|||
msgid "New Payment Account"
|
||||
msgstr "Nueva cuenta de pago"
|
||||
|
||||
#: web/template/payments/accounts/new.gohtml:11
|
||||
#: web/template/payments/accounts/index.gohtml:3
|
||||
#: web/template/payments/accounts/index.gohtml:11
|
||||
#: web/template/payments/accounts/edit.gohtml:11
|
||||
msgctxt "title"
|
||||
msgid "Payment Accounts"
|
||||
msgstr "Cuenta de pago"
|
||||
|
||||
#: web/template/payments/accounts/index.gohtml:16
|
||||
msgctxt "action"
|
||||
msgid "New payment account"
|
||||
|
@ -843,7 +856,7 @@ msgctxt "title"
|
|||
msgid "VAT number"
|
||||
msgstr "DNI / NIF"
|
||||
|
||||
#: pkg/login.go:38 pkg/company.go:127 pkg/profile.go:40 pkg/contacts.go:276
|
||||
#: pkg/login.go:38 pkg/company.go:122 pkg/profile.go:40 pkg/contacts.go:276
|
||||
msgctxt "input"
|
||||
msgid "Email"
|
||||
msgstr "Correo-e"
|
||||
|
@ -853,11 +866,11 @@ msgctxt "input"
|
|||
msgid "Password"
|
||||
msgstr "Contraseña"
|
||||
|
||||
#: pkg/login.go:76 pkg/company.go:283 pkg/profile.go:89
|
||||
#: pkg/login.go:76 pkg/company.go:238 pkg/profile.go:89
|
||||
msgid "Email can not be empty."
|
||||
msgstr "No podéis dejar el correo-e en blanco."
|
||||
|
||||
#: pkg/login.go:77 pkg/company.go:284 pkg/profile.go:90 pkg/contacts.go:420
|
||||
#: pkg/login.go:77 pkg/company.go:239 pkg/profile.go:90 pkg/contacts.go:420
|
||||
msgid "This value is not a valid email. It should be like name@domain.com."
|
||||
msgstr "Este valor no es un correo-e válido. Tiene que ser parecido a nombre@dominio.es."
|
||||
|
||||
|
@ -951,208 +964,208 @@ msgstr "Habéis escogido un impuesto que no es válido."
|
|||
msgid "You can only select a tax of each class."
|
||||
msgstr "Solo podéis escoger un impuesto de cada clase."
|
||||
|
||||
#: pkg/company.go:113
|
||||
#: pkg/company.go:108
|
||||
msgctxt "input"
|
||||
msgid "Trade name"
|
||||
msgstr "Nombre comercial"
|
||||
|
||||
#: pkg/company.go:118 pkg/contacts.go:268
|
||||
#: pkg/company.go:113 pkg/contacts.go:268
|
||||
msgctxt "input"
|
||||
msgid "Phone"
|
||||
msgstr "Teléfono"
|
||||
|
||||
#: pkg/company.go:136 pkg/contacts.go:284
|
||||
#: pkg/company.go:131 pkg/contacts.go:284
|
||||
msgctxt "input"
|
||||
msgid "Web"
|
||||
msgstr "Web"
|
||||
|
||||
#: pkg/company.go:144 pkg/contacts.go:296
|
||||
#: pkg/company.go:139 pkg/contacts.go:296
|
||||
msgctxt "input"
|
||||
msgid "Business name"
|
||||
msgstr "Nombre y apellidos"
|
||||
|
||||
#: pkg/company.go:154 pkg/contacts.go:306
|
||||
#: pkg/company.go:149 pkg/contacts.go:306
|
||||
msgctxt "input"
|
||||
msgid "VAT number"
|
||||
msgstr "DNI / NIF"
|
||||
|
||||
#: pkg/company.go:160 pkg/contacts.go:312
|
||||
#: pkg/company.go:155 pkg/contacts.go:312
|
||||
msgctxt "input"
|
||||
msgid "Address"
|
||||
msgstr "Dirección"
|
||||
|
||||
#: pkg/company.go:169 pkg/contacts.go:321
|
||||
#: pkg/company.go:164 pkg/contacts.go:321
|
||||
msgctxt "input"
|
||||
msgid "City"
|
||||
msgstr "Población"
|
||||
|
||||
#: pkg/company.go:175 pkg/contacts.go:327
|
||||
#: pkg/company.go:170 pkg/contacts.go:327
|
||||
msgctxt "input"
|
||||
msgid "Province"
|
||||
msgstr "Provincia"
|
||||
|
||||
#: pkg/company.go:181 pkg/contacts.go:333
|
||||
#: pkg/company.go:176 pkg/contacts.go:333
|
||||
msgctxt "input"
|
||||
msgid "Postal code"
|
||||
msgstr "Código postal"
|
||||
|
||||
#: pkg/company.go:190 pkg/contacts.go:342
|
||||
#: pkg/company.go:185 pkg/contacts.go:342
|
||||
msgctxt "input"
|
||||
msgid "Country"
|
||||
msgstr "País"
|
||||
|
||||
#: pkg/company.go:200
|
||||
#: pkg/company.go:195
|
||||
msgctxt "input"
|
||||
msgid "Currency"
|
||||
msgstr "Moneda"
|
||||
|
||||
#: pkg/company.go:207
|
||||
#: pkg/company.go:226 pkg/contacts.go:394
|
||||
msgid "Selected country is not valid."
|
||||
msgstr "Habéis escogido un país que no es válido."
|
||||
|
||||
#: pkg/company.go:230 pkg/contacts.go:397
|
||||
msgid "Business name can not be empty."
|
||||
msgstr "No podéis dejar el nombre y los apellidos en blanco."
|
||||
|
||||
#: pkg/company.go:231 pkg/contacts.go:398
|
||||
msgid "Business name must have at least two letters."
|
||||
msgstr "El nombre y los apellidos deben contener como mínimo dos letras."
|
||||
|
||||
#: pkg/company.go:232 pkg/contacts.go:400
|
||||
msgid "VAT number can not be empty."
|
||||
msgstr "No podéis dejar el DNI o NIF en blanco."
|
||||
|
||||
#: pkg/company.go:233 pkg/contacts.go:401
|
||||
msgid "This value is not a valid VAT number."
|
||||
msgstr "Este valor no es un DNI o NIF válido."
|
||||
|
||||
#: pkg/company.go:235
|
||||
msgid "Phone can not be empty."
|
||||
msgstr "No podéis dejar el teléfono en blanco."
|
||||
|
||||
#: pkg/company.go:236 pkg/contacts.go:417
|
||||
msgid "This value is not a valid phone number."
|
||||
msgstr "Este valor no es un teléfono válido."
|
||||
|
||||
#: pkg/company.go:242 pkg/contacts.go:423
|
||||
msgid "This value is not a valid web address. It should be like https://domain.com/."
|
||||
msgstr "Este valor no es una dirección web válida. Tiene que ser parecida a https://dominio.es/."
|
||||
|
||||
#: pkg/company.go:244 pkg/contacts.go:403
|
||||
msgid "Address can not be empty."
|
||||
msgstr "No podéis dejar la dirección en blanco."
|
||||
|
||||
#: pkg/company.go:245 pkg/contacts.go:404
|
||||
msgid "City can not be empty."
|
||||
msgstr "No podéis dejar la población en blanco."
|
||||
|
||||
#: pkg/company.go:246 pkg/contacts.go:405
|
||||
msgid "Province can not be empty."
|
||||
msgstr "No podéis dejar la provincia en blanco."
|
||||
|
||||
#: pkg/company.go:247 pkg/contacts.go:407
|
||||
msgid "Postal code can not be empty."
|
||||
msgstr "No podéis dejar el código postal en blanco."
|
||||
|
||||
#: pkg/company.go:248 pkg/contacts.go:408
|
||||
msgid "This value is not a valid postal code."
|
||||
msgstr "Este valor no es un código postal válido válido."
|
||||
|
||||
#: pkg/company.go:250
|
||||
msgid "Selected currency is not valid."
|
||||
msgstr "Habéis escogido una moneda que no es válida."
|
||||
|
||||
#: pkg/company.go:402
|
||||
msgctxt "input"
|
||||
msgid "Invoice number format"
|
||||
msgstr "Formato del número de factura"
|
||||
|
||||
#: pkg/company.go:213
|
||||
#: pkg/company.go:408
|
||||
msgctxt "input"
|
||||
msgid "Next invoice number"
|
||||
msgstr "Siguiente número de factura"
|
||||
|
||||
#: pkg/company.go:222
|
||||
#: pkg/company.go:417
|
||||
msgctxt "input"
|
||||
msgid "Quotation number format"
|
||||
msgstr "Formato del número de presupuesto"
|
||||
|
||||
#: pkg/company.go:228
|
||||
#: pkg/company.go:423
|
||||
msgctxt "input"
|
||||
msgid "Next quotation number"
|
||||
msgstr "Siguiente número de presupuesto"
|
||||
|
||||
#: pkg/company.go:237
|
||||
#: pkg/company.go:432
|
||||
msgctxt "input"
|
||||
msgid "Legal disclaimer"
|
||||
msgstr "Nota legal"
|
||||
|
||||
#: pkg/company.go:271 pkg/contacts.go:394
|
||||
msgid "Selected country is not valid."
|
||||
msgstr "Habéis escogido un país que no es válido."
|
||||
|
||||
#: pkg/company.go:275 pkg/contacts.go:397
|
||||
msgid "Business name can not be empty."
|
||||
msgstr "No podéis dejar el nombre y los apellidos en blanco."
|
||||
|
||||
#: pkg/company.go:276 pkg/contacts.go:398
|
||||
msgid "Business name must have at least two letters."
|
||||
msgstr "El nombre y los apellidos deben contener como mínimo dos letras."
|
||||
|
||||
#: pkg/company.go:277 pkg/contacts.go:400
|
||||
msgid "VAT number can not be empty."
|
||||
msgstr "No podéis dejar el DNI o NIF en blanco."
|
||||
|
||||
#: pkg/company.go:278 pkg/contacts.go:401
|
||||
msgid "This value is not a valid VAT number."
|
||||
msgstr "Este valor no es un DNI o NIF válido."
|
||||
|
||||
#: pkg/company.go:280
|
||||
msgid "Phone can not be empty."
|
||||
msgstr "No podéis dejar el teléfono en blanco."
|
||||
|
||||
#: pkg/company.go:281 pkg/contacts.go:417
|
||||
msgid "This value is not a valid phone number."
|
||||
msgstr "Este valor no es un teléfono válido."
|
||||
|
||||
#: pkg/company.go:287 pkg/contacts.go:423
|
||||
msgid "This value is not a valid web address. It should be like https://domain.com/."
|
||||
msgstr "Este valor no es una dirección web válida. Tiene que ser parecida a https://dominio.es/."
|
||||
|
||||
#: pkg/company.go:289 pkg/contacts.go:403
|
||||
msgid "Address can not be empty."
|
||||
msgstr "No podéis dejar la dirección en blanco."
|
||||
|
||||
#: pkg/company.go:290 pkg/contacts.go:404
|
||||
msgid "City can not be empty."
|
||||
msgstr "No podéis dejar la población en blanco."
|
||||
|
||||
#: pkg/company.go:291 pkg/contacts.go:405
|
||||
msgid "Province can not be empty."
|
||||
msgstr "No podéis dejar la provincia en blanco."
|
||||
|
||||
#: pkg/company.go:292 pkg/contacts.go:407
|
||||
msgid "Postal code can not be empty."
|
||||
msgstr "No podéis dejar el código postal en blanco."
|
||||
|
||||
#: pkg/company.go:293 pkg/contacts.go:408
|
||||
msgid "This value is not a valid postal code."
|
||||
msgstr "Este valor no es un código postal válido válido."
|
||||
|
||||
#: pkg/company.go:295
|
||||
msgid "Selected currency is not valid."
|
||||
msgstr "Habéis escogido una moneda que no es válida."
|
||||
|
||||
#: pkg/company.go:296
|
||||
#: pkg/company.go:489
|
||||
msgid "Invoice number format can not be empty."
|
||||
msgstr "No podéis dejar el formato del número de factura en blanco."
|
||||
|
||||
#: pkg/company.go:297
|
||||
#: pkg/company.go:490
|
||||
msgid "Next invoice number must be a number greater than zero."
|
||||
msgstr "El siguiente número de factura tiene que ser un número mayor a cero."
|
||||
|
||||
#: pkg/company.go:298
|
||||
#: pkg/company.go:491
|
||||
msgid "Quotation number format can not be empty."
|
||||
msgstr "No podéis dejar el formato del número de presupuesto en blanco."
|
||||
|
||||
#: pkg/company.go:299
|
||||
#: pkg/company.go:492
|
||||
msgid "Next quotation number must be a number greater than zero."
|
||||
msgstr "El siguiente número de presupuesto tiene que ser un número mayor a cero."
|
||||
|
||||
#: pkg/company.go:563
|
||||
#: pkg/company.go:614
|
||||
msgctxt "input"
|
||||
msgid "Tax name"
|
||||
msgstr "Nombre impuesto"
|
||||
|
||||
#: pkg/company.go:569
|
||||
#: pkg/company.go:620
|
||||
msgctxt "input"
|
||||
msgid "Tax Class"
|
||||
msgstr "Clase de impuesto"
|
||||
|
||||
#: pkg/company.go:572
|
||||
#: pkg/company.go:623
|
||||
msgid "Select a tax class"
|
||||
msgstr "Escoged una clase de impuesto"
|
||||
|
||||
#: pkg/company.go:576
|
||||
#: pkg/company.go:627
|
||||
msgctxt "input"
|
||||
msgid "Rate (%)"
|
||||
msgstr "Porcentaje"
|
||||
|
||||
#: pkg/company.go:599
|
||||
#: pkg/company.go:650
|
||||
msgid "Tax name can not be empty."
|
||||
msgstr "No podéis dejar el nombre del impuesto en blanco."
|
||||
|
||||
#: pkg/company.go:600
|
||||
#: pkg/company.go:651
|
||||
msgid "Selected tax class is not valid."
|
||||
msgstr "Habéis escogido una clase impuesto que no es válida."
|
||||
|
||||
#: pkg/company.go:601
|
||||
#: pkg/company.go:652
|
||||
msgid "Tax rate can not be empty."
|
||||
msgstr "No podéis dejar el porcentaje en blanco."
|
||||
|
||||
#: pkg/company.go:602
|
||||
#: pkg/company.go:653
|
||||
msgid "Tax rate must be an integer between -99 and 99."
|
||||
msgstr "El porcentaje tiene que estar entre -99 y 99."
|
||||
|
||||
#: pkg/company.go:665
|
||||
#: pkg/company.go:762
|
||||
msgctxt "input"
|
||||
msgid "Payment method name"
|
||||
msgstr "Nombre del método de pago"
|
||||
|
||||
#: pkg/company.go:671
|
||||
#: pkg/company.go:768
|
||||
msgctxt "input"
|
||||
msgid "Instructions"
|
||||
msgstr "Instrucciones"
|
||||
|
||||
#: pkg/company.go:689
|
||||
#: pkg/company.go:786
|
||||
msgid "Payment method name can not be empty."
|
||||
msgstr "No podéis dejar el nombre del método de pago en blanco."
|
||||
|
||||
#: pkg/company.go:690
|
||||
#: pkg/company.go:787
|
||||
msgid "Payment instructions can not be empty."
|
||||
msgstr "No podéis dejar las instrucciones de pago en blanco."
|
||||
|
||||
|
@ -1567,6 +1580,14 @@ msgctxt "input"
|
|||
msgid "Holded Excel file"
|
||||
msgstr "Archivo Excel de Holded"
|
||||
|
||||
#~ msgctxt "title"
|
||||
#~ msgid "Currency"
|
||||
#~ msgstr "Moneda"
|
||||
|
||||
#~ msgctxt "title"
|
||||
#~ msgid "New Line"
|
||||
#~ msgstr "Nueva línea"
|
||||
|
||||
#~ msgid "Selected expense status is not valid."
|
||||
#~ msgstr "Habéis escogido un estado de gasto que no es válido."
|
||||
|
||||
|
|
|
@ -25,11 +25,35 @@
|
|||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" href="{{ companyURI "/tax-details" }}" data-hx-boost="true">
|
||||
<a role="menuitem" href="{{ companyURI "/tax-details" }}">
|
||||
<i class="ri-vip-diamond-line"></i>
|
||||
{{( pgettext "Tax Details" "menu" )}}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" href="{{ companyURI "/invoicing"}}">
|
||||
<i class="ri-file-paper-2-line"></i>
|
||||
{{( pgettext "Invoicing and Quoting" "title" )}}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" href="{{ companyURI "/taxes"}}">
|
||||
<i class="ri-government-line"></i>
|
||||
{{( pgettext "Taxes" "title" )}}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" href="{{ companyURI "/payment-methods"}}">
|
||||
<i class="ri-money-euro-circle-line"></i>
|
||||
{{( pgettext "Payment Methods" "title" )}}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" href="{{ companyURI "/payment-accounts"}}">
|
||||
<i class="ri-bank-card-2-line"></i>
|
||||
{{( pgettext "Payment Accounts" "title" )}}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" href="{{ companyURI "/switch-company" }}" data-hx-boost="true">
|
||||
<i class="ri-briefcase-line"></i>
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
{{ define "title" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InvoicingForm*/ -}}
|
||||
{{( pgettext "Invoicing and Quoting" "title" )}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "breadcrumbs" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InvoicingForm*/ -}}
|
||||
<nav data-hx-target="main" data-hx-boost="true">
|
||||
<p>
|
||||
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
|
||||
<a>{{ template "title" . }}</a>
|
||||
</p>
|
||||
</nav>
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" }}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InvoicingForm*/ -}}
|
||||
<section data-hx-target="main" data-hx-swap="innerHTML show:false">
|
||||
<h2>{{ template "title" . }}</h2>
|
||||
<form method="POST" action="{{ companyURI "/invoicing" }}" data-hx-boost="true">
|
||||
<fieldset id="invoicing">
|
||||
{{ csrfToken }}
|
||||
|
||||
{{ template "input-field" .InvoiceNumberFormat }}
|
||||
{{ template "input-field" .NextInvoiceNumber }}
|
||||
{{ template "input-field" .QuoteNumberFormat }}
|
||||
{{ template "input-field" .NextQuoteNumber }}
|
||||
{{ template "input-field" .LegalDisclaimer }}
|
||||
</fieldset>
|
||||
<footer>
|
||||
<button form="details" type="submit">{{( pgettext "Save changes" "action" )}}</button>
|
||||
</footer>
|
||||
</form>
|
||||
</section>
|
||||
{{- end }}
|
|
@ -0,0 +1,68 @@
|
|||
{{ define "title" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.PaymentMethodsPage*/ -}}
|
||||
{{( pgettext "Payment Methods" "title" )}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "breadcrumbs" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.PaymentMethodsPage*/ -}}
|
||||
<nav data-hx-target="main" data-hx-boost="true">
|
||||
<p>
|
||||
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
|
||||
<a>{{ template "title" . }}</a>
|
||||
</p>
|
||||
</nav>
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" }}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.PaymentMethodsPage*/ -}}
|
||||
<section data-hx-target="main" data-hx-swap="innerHTML show:false">
|
||||
<h2>{{ template "title" . }}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{( pgettext "Payment Method" "title" )}}</th>
|
||||
<th>{{( pgettext "Instructions" "title" )}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
{{ $confirm := ( gettext "Are you sure?" )}}
|
||||
<tbody data-hx-confirm="{{ $confirm }}" data-hx-target="closest tr" data-hx-swap="outerHTML swap:1s">
|
||||
{{ with .PaymentMethods }}
|
||||
{{- range $method := . }}
|
||||
<tr>
|
||||
<td>{{ .Name }}</td>
|
||||
<td>{{ .Instructions }}</td>
|
||||
<td>
|
||||
<form method="POST" action="{{ companyURI "/payment-methods"}}/{{ .Id }}"
|
||||
data-hx-boost="true">
|
||||
{{ csrfToken }}
|
||||
{{ deleteMethod }}
|
||||
<button class="icon" aria-label="{{( gettext "Delete payment method" )}}"
|
||||
><i class="ri-delete-back-2-line"></i></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{- end }}
|
||||
{{ else }}
|
||||
<tr>
|
||||
<td colspan="3">{{( gettext "No payment methods added yet." )}}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<form method="POST" action="{{ companyURI "/payment-methods" }}" data-hx-boost="true">
|
||||
<h3>{{( pgettext "New Payment Method" "title")}}</h3>
|
||||
<fieldset>
|
||||
{{ csrfToken }}
|
||||
{{ with .Form -}}
|
||||
{{ template "input-field" .Name }}
|
||||
{{ template "input-field" .Instructions }}
|
||||
{{- end }}
|
||||
</fieldset>
|
||||
<footer>
|
||||
<button>{{( pgettext "Add new payment method" "action" )}}</button>
|
||||
</footer>
|
||||
</form>
|
||||
</section>
|
||||
{{- end }}
|
|
@ -7,7 +7,7 @@
|
|||
<nav data-hx-target="main" data-hx-boost="true">
|
||||
<p>
|
||||
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
|
||||
<a>{{( pgettext "Company Switch" "title" )}}</a>
|
||||
<a>{{ template "title" . }}</a>
|
||||
</p>
|
||||
</nav>
|
||||
{{- end }}
|
||||
|
@ -15,7 +15,7 @@
|
|||
{{ define "content" }}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.CompanySwitchPage*/ -}}
|
||||
<section class="dialog-content" id="switch-company-dialog-content" data-hx-target="this">
|
||||
<h2>{{(pgettext "Company Switch" "title")}}</h2>
|
||||
<h2>{{ template "title" . }}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
|
@ -0,0 +1,41 @@
|
|||
{{ define "title" -}}
|
||||
{{( pgettext "Tax Details" "title" )}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "breadcrumbs" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.TaxDetailsPage*/ -}}
|
||||
<nav data-hx-target="main" data-hx-boost="true">
|
||||
<p>
|
||||
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
|
||||
<a>{{ template "title" . }}</a>
|
||||
</p>
|
||||
</nav>
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" }}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.TaxDetailsPage*/ -}}
|
||||
<section data-hx-target="main" data-hx-swap="innerHTML show:false">
|
||||
<h2>{{ template "title" . }}</h2>
|
||||
{{ with .DetailsForm }}
|
||||
<form method="POST" action="{{ companyURI "/tax-details" }}" data-hx-boost="true">
|
||||
{{ csrfToken }}
|
||||
{{ template "input-field" .BusinessName }}
|
||||
{{ template "input-field" .VATIN }}
|
||||
{{ template "input-field" .TradeName }}
|
||||
{{ template "input-field" .Phone }}
|
||||
{{ template "input-field" .Email }}
|
||||
{{ template "input-field" .Web }}
|
||||
{{ template "input-field" .Address | addInputAttr `class="width-2x"` }}
|
||||
{{ template "input-field" .City }}
|
||||
{{ template "input-field" .Province }}
|
||||
{{ template "input-field" .PostalCode }}
|
||||
{{ template "select-field" .Country | addSelectAttr `class="width-fixed"` }}
|
||||
{{ template "select-field" .Currency }}
|
||||
|
||||
<fieldset>
|
||||
<button type="submit">{{( pgettext "Save changes" "action" )}}</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
{{ end }}
|
||||
</section>
|
||||
{{- end }}
|
|
@ -0,0 +1,70 @@
|
|||
{{ define "title" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.TaxesPage*/ -}}
|
||||
{{( pgettext "Taxes" "title" )}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "breadcrumbs" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.TaxesPage*/ -}}
|
||||
<nav data-hx-target="main" data-hx-boost="true">
|
||||
<p>
|
||||
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
|
||||
<a>{{ template "title" . }}</a>
|
||||
</p>
|
||||
</nav>
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" }}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.TaxesPage*/ -}}
|
||||
<section data-hx-target="main" data-hx-swap="innerHTML show:false">
|
||||
<h2>{{ template "title" . }}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{( pgettext "Tax Name" "title" )}}</th>
|
||||
<th class="numeric">{{( pgettext "Rate (%)" "title" )}}</th>
|
||||
<th>{{( pgettext "Class" "title" )}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
{{ $confirm := ( gettext "Are you sure?" )}}
|
||||
<tbody data-hx-confirm="{{ $confirm }}" data-hx-target="closest tr" data-hx-swap="outerHTML swap:1s">
|
||||
{{ with .Taxes }}
|
||||
{{- range $tax := . }}
|
||||
<tr>
|
||||
<td>{{ .Name }}</td>
|
||||
<td class="numeric">{{ .Rate }}</td>
|
||||
<td>{{ .Class }}</td>
|
||||
<td>
|
||||
<form method="POST" action="{{ companyURI "/taxes"}}/{{ .Id }}" data-hx-boost="true">
|
||||
{{ csrfToken }}
|
||||
{{ deleteMethod }}
|
||||
<button class="icon" aria-label="{{( gettext "Delete tax" )}}"
|
||||
><i class="ri-delete-back-2-line"></i></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{- end }}
|
||||
{{ else }}
|
||||
<tr>
|
||||
<td colspan="4">{{( gettext "No taxes added yet." )}}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<form method="POST" action="{{ companyURI "/taxes" }}" data-hx-boost="true">
|
||||
<h3>{{( pgettext "New Tax" "title")}}</h3>
|
||||
<fieldset>
|
||||
{{ csrfToken }}
|
||||
{{ with .Form -}}
|
||||
{{ template "input-field" .Name }}
|
||||
{{ template "input-field" .Rate }}
|
||||
{{ template "select-field" .Class }}
|
||||
{{- end }}
|
||||
</fieldset>
|
||||
<footer>
|
||||
<button>{{( pgettext "Add new tax" "action" )}}</button>
|
||||
</footer>
|
||||
</form>
|
||||
</section>
|
||||
{{- end }}
|
|
@ -1,178 +0,0 @@
|
|||
{{ define "title" -}}
|
||||
{{( pgettext "Tax Details" "title" )}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "breadcrumbs" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.TaxDetailsPage*/ -}}
|
||||
<nav data-hx-target="main" data-hx-boost="true">
|
||||
<p>
|
||||
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
|
||||
<a>{{( pgettext "Tax Details" "title" )}}</a>
|
||||
</p>
|
||||
</nav>
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" }}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.TaxDetailsPage*/ -}}
|
||||
<section class="dialog-content" id="tax-details-dialog-content" data-hx-target="this">
|
||||
<h2>{{(pgettext "Tax Details" "title")}}</h2>
|
||||
{{ with .DetailsForm }}
|
||||
<form id="details" method="POST" action="{{ companyURI "/tax-details" }}" data-hx-boost="true" data-hx-select="#tax-details-dialog-content">
|
||||
{{ csrfToken }}
|
||||
{{ template "input-field" .BusinessName }}
|
||||
{{ template "input-field" .VATIN }}
|
||||
{{ template "input-field" .TradeName }}
|
||||
{{ template "input-field" .Phone }}
|
||||
{{ template "input-field" .Email }}
|
||||
{{ template "input-field" .Web }}
|
||||
{{ template "input-field" .Address | addInputAttr `class="width-2x"` }}
|
||||
{{ template "input-field" .City }}
|
||||
{{ template "input-field" .Province }}
|
||||
{{ template "input-field" .PostalCode }}
|
||||
{{ template "select-field" .Country | addSelectAttr `class="width-fixed"` }}
|
||||
|
||||
<fieldset>
|
||||
<legend id="currency-legend">{{( pgettext "Currency" "title" )}}</legend>
|
||||
|
||||
{{ template "select-field" .Currency }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset id="invoicing">
|
||||
<legend>{{( pgettext "Invoicing and Quoting" "title" )}}</legend>
|
||||
|
||||
{{ template "input-field" .InvoiceNumberFormat }}
|
||||
{{ template "input-field" .NextInvoiceNumber }}
|
||||
{{ template "input-field" .QuoteNumberFormat }}
|
||||
{{ template "input-field" .NextQuoteNumber }}
|
||||
{{ template "input-field" .LegalDisclaimer }}
|
||||
</fieldset>
|
||||
</form>
|
||||
{{ end }}
|
||||
|
||||
<form id="newtax" method="POST" action="{{ companyURI "/tax" }}" data-hx-boost="true" data-hx-select="#tax-details-dialog-content">
|
||||
{{ csrfToken }}
|
||||
</form>
|
||||
|
||||
{{ $confirm := ( gettext "Are you sure?" )}}
|
||||
<fieldset>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%"></th>
|
||||
<th>{{( pgettext "Tax Name" "title" )}}</th>
|
||||
<th>{{( pgettext "Rate (%)" "title" )}}</th>
|
||||
<th>{{( pgettext "Class" "title" )}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-hx-confirm="{{ $confirm }}" data-hx-target="closest tr" data-hx-swap="outerHTML swap:1s">
|
||||
{{ with .Taxes }}
|
||||
{{- range $tax := . }}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>{{ .Name }}</td>
|
||||
<td>{{ .Rate }}</td>
|
||||
<td>{{ .Class }}</td>
|
||||
<td>
|
||||
<form method="POST" action="{{ companyURI "/tax"}}/{{ .Id }}" data-hx-boost="true">
|
||||
{{ csrfToken }}
|
||||
{{ deleteMethod }}
|
||||
<button class="icon" aria-label="{{( gettext "Delete tax" )}}" type="submit"><i
|
||||
class="ri-delete-back-2-line"></i></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{- end }}
|
||||
{{ else }}
|
||||
<tr>
|
||||
<td colspan="4">{{( gettext "No taxes added yet." )}}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th scope="row">{{( pgettext "New Line" "title")}}</th>
|
||||
<td>
|
||||
{{ template "input-field" .NewTaxForm.Name | addInputAttr `form="newtax"` }}
|
||||
</td>
|
||||
<td>
|
||||
{{ template "input-field" .NewTaxForm.Rate | addInputAttr `form="newtax"` }}
|
||||
</td>
|
||||
<td>
|
||||
{{ template "select-field" .NewTaxForm.Class | addSelectAttr `form="newtax"` }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"></td>
|
||||
<td colspan="2">
|
||||
<button form="newtax" type="submit">{{( pgettext "Add new tax" "action" )}}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<form id="new-payment-method" method="POST" action="{{ companyURI "/payment-method" }}" data-hx-boost="true" data-hx-select="#tax-details-dialog-content">
|
||||
{{ csrfToken }}
|
||||
</form>
|
||||
|
||||
<fieldset>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%"></th>
|
||||
<th>{{( pgettext "Payment Method" "title" )}}</th>
|
||||
<th>{{( pgettext "Instructions" "title" )}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-hx-confirm="{{ $confirm }}" data-hx-target="closest tr" data-hx-swap="outerHTML swap:1s">
|
||||
{{ with .PaymentMethods }}
|
||||
{{- range $method := . }}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>{{ .Name }}</td>
|
||||
<td>{{ .Instructions }}</td>
|
||||
<td>
|
||||
<form method="POST" action="{{ companyURI "/payment-method"}}/{{ .Id }}" data-hx-boost="true">
|
||||
{{ csrfToken }}
|
||||
{{ deleteMethod }}
|
||||
<button class="icon" aria-label="{{( gettext "Delete payment method" )}}"
|
||||
type="submit"><i
|
||||
class="ri-delete-back-2-line"></i></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{- end }}
|
||||
{{ else }}
|
||||
<tr>
|
||||
<td colspan="4">{{( gettext "No payment methods added yet." )}}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th scope="row">{{( pgettext "New Line" "title")}}</th>
|
||||
<td>
|
||||
{{ template "input-field" .NewPaymentMethodForm.Name | addInputAttr `form="new-payment-method"` }}
|
||||
</td>
|
||||
<td>
|
||||
{{ template "input-field" .NewPaymentMethodForm.Instructions | addInputAttr `form="new-payment-method"` }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"></td>
|
||||
<td colspan="2">
|
||||
<button form="new-payment-method"
|
||||
type="submit">{{( pgettext "Add new payment method" "action" )}}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<button form="details" type="submit">{{( pgettext "Save changes" "action" )}}</button>
|
||||
</fieldset>
|
||||
</section>
|
||||
{{- end }}
|
Loading…
Reference in New Issue