Add total amount for quotes, invoices, and expenses tables
We have shown the application to a potential user, and they told us that it would be very useful to have a total in the table’s footer, so that they can verify the amount with the bank’s extracts.
This commit is contained in:
parent
8a4f80783d
commit
07c1071975
|
@ -23,8 +23,9 @@ type ExpenseEntry struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type expensesIndexPage struct {
|
type expensesIndexPage struct {
|
||||||
Expenses []*ExpenseEntry
|
Expenses []*ExpenseEntry
|
||||||
Filters *expenseFilterForm
|
TotalAmount string
|
||||||
|
Filters *expenseFilterForm
|
||||||
}
|
}
|
||||||
|
|
||||||
func IndexExpenses(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
func IndexExpenses(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
@ -37,42 +38,15 @@ func IndexExpenses(w http.ResponseWriter, r *http.Request, _ httprouter.Params)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
page := &expensesIndexPage{
|
page := &expensesIndexPage{
|
||||||
Expenses: mustCollectExpenseEntries(r.Context(), conn, company, filters),
|
Expenses: mustCollectExpenseEntries(r.Context(), conn, company, filters),
|
||||||
Filters: filters,
|
TotalAmount: mustComputeExpensesTotalAmount(r.Context(), conn, filters),
|
||||||
|
Filters: filters,
|
||||||
}
|
}
|
||||||
mustRenderMainTemplate(w, r, "expenses/index.gohtml", page)
|
mustRenderMainTemplate(w, r, "expenses/index.gohtml", page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustCollectExpenseEntries(ctx context.Context, conn *Conn, company *Company, filters *expenseFilterForm) []*ExpenseEntry {
|
func mustCollectExpenseEntries(ctx context.Context, conn *Conn, company *Company, filters *expenseFilterForm) []*ExpenseEntry {
|
||||||
args := []interface{}{company.Id}
|
where, args := filters.BuildQuery(nil)
|
||||||
where := []string{"expense.company_id = $1"}
|
|
||||||
appendWhere := func(expression string, value interface{}) {
|
|
||||||
args = append(args, value)
|
|
||||||
where = append(where, fmt.Sprintf(expression, len(args)))
|
|
||||||
}
|
|
||||||
maybeAppendWhere := func(expression string, value string, conv func(string) interface{}) {
|
|
||||||
if value != "" {
|
|
||||||
if conv == nil {
|
|
||||||
appendWhere(expression, value)
|
|
||||||
} else {
|
|
||||||
appendWhere(expression, conv(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
maybeAppendWhere("contact_id = $%d", filters.Contact.String(), func(v string) interface{} {
|
|
||||||
customerId, _ := strconv.Atoi(filters.Contact.Selected[0])
|
|
||||||
return customerId
|
|
||||||
})
|
|
||||||
maybeAppendWhere("invoice_number = $%d", filters.InvoiceNumber.String(), nil)
|
|
||||||
maybeAppendWhere("invoice_date >= $%d", filters.FromDate.String(), nil)
|
|
||||||
maybeAppendWhere("invoice_date <= $%d", filters.ToDate.String(), nil)
|
|
||||||
if len(filters.Tags.Tags) > 0 {
|
|
||||||
if filters.TagsCondition.Selected == "and" {
|
|
||||||
appendWhere("expense.tags @> $%d", filters.Tags)
|
|
||||||
} else {
|
|
||||||
appendWhere("expense.tags && $%d", filters.Tags)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rows := conn.MustQuery(ctx, fmt.Sprintf(`
|
rows := conn.MustQuery(ctx, fmt.Sprintf(`
|
||||||
select expense.slug
|
select expense.slug
|
||||||
, invoice_date
|
, invoice_date
|
||||||
|
@ -87,7 +61,7 @@ func mustCollectExpenseEntries(ctx context.Context, conn *Conn, company *Company
|
||||||
join currency using (currency_code)
|
join currency using (currency_code)
|
||||||
where (%s)
|
where (%s)
|
||||||
order by invoice_date
|
order by invoice_date
|
||||||
`, strings.Join(where, ") AND (")), args...)
|
`, where), args...)
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var entries []*ExpenseEntry
|
var entries []*ExpenseEntry
|
||||||
|
@ -104,6 +78,18 @@ func mustCollectExpenseEntries(ctx context.Context, conn *Conn, company *Company
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustComputeExpensesTotalAmount(ctx context.Context, conn *Conn, filters *expenseFilterForm) string {
|
||||||
|
where, args := filters.BuildQuery(nil)
|
||||||
|
return conn.MustGetText(ctx, "0", fmt.Sprintf(`
|
||||||
|
select to_price(sum(amount)::integer, decimal_digits)
|
||||||
|
from expense
|
||||||
|
join currency using (currency_code)
|
||||||
|
where (%s)
|
||||||
|
group by decimal_digits
|
||||||
|
`, where), args...)
|
||||||
|
}
|
||||||
|
|
||||||
func ServeExpenseForm(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
func ServeExpenseForm(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||||
locale := getLocale(r)
|
locale := getLocale(r)
|
||||||
conn := getConn(r)
|
conn := getConn(r)
|
||||||
|
@ -391,6 +377,41 @@ func (form *expenseFilterForm) Parse(r *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (form *expenseFilterForm) BuildQuery(args []interface{}) (string, []interface{}) {
|
||||||
|
var where []string
|
||||||
|
appendWhere := func(expression string, value interface{}) {
|
||||||
|
args = append(args, value)
|
||||||
|
where = append(where, fmt.Sprintf(expression, len(args)))
|
||||||
|
}
|
||||||
|
maybeAppendWhere := func(expression string, value string, conv func(string) interface{}) {
|
||||||
|
if value != "" {
|
||||||
|
if conv == nil {
|
||||||
|
appendWhere(expression, value)
|
||||||
|
} else {
|
||||||
|
appendWhere(expression, conv(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appendWhere("expense.company_id = $%d", form.company.Id)
|
||||||
|
maybeAppendWhere("contact_id = $%d", form.Contact.String(), func(v string) interface{} {
|
||||||
|
customerId, _ := strconv.Atoi(form.Contact.Selected[0])
|
||||||
|
return customerId
|
||||||
|
})
|
||||||
|
maybeAppendWhere("invoice_number = $%d", form.InvoiceNumber.String(), nil)
|
||||||
|
maybeAppendWhere("invoice_date >= $%d", form.FromDate.String(), nil)
|
||||||
|
maybeAppendWhere("invoice_date <= $%d", form.ToDate.String(), nil)
|
||||||
|
if len(form.Tags.Tags) > 0 {
|
||||||
|
if form.TagsCondition.Selected == "and" {
|
||||||
|
appendWhere("expense.tags @> $%d", form.Tags)
|
||||||
|
} else {
|
||||||
|
appendWhere("expense.tags && $%d", form.Tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(where, ") AND ("), args
|
||||||
|
}
|
||||||
|
|
||||||
func ServeEditExpenseTags(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
func ServeEditExpenseTags(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||||
conn := getConn(r)
|
conn := getConn(r)
|
||||||
locale := getLocale(r)
|
locale := getLocale(r)
|
||||||
|
|
|
@ -35,6 +35,7 @@ type InvoiceEntry struct {
|
||||||
|
|
||||||
type InvoicesIndexPage struct {
|
type InvoicesIndexPage struct {
|
||||||
Invoices []*InvoiceEntry
|
Invoices []*InvoiceEntry
|
||||||
|
TotalAmount string
|
||||||
Filters *invoiceFilterForm
|
Filters *invoiceFilterForm
|
||||||
InvoiceStatuses map[string]string
|
InvoiceStatuses map[string]string
|
||||||
}
|
}
|
||||||
|
@ -49,44 +50,16 @@ func IndexInvoices(w http.ResponseWriter, r *http.Request, _ httprouter.Params)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
page := &InvoicesIndexPage{
|
page := &InvoicesIndexPage{
|
||||||
Invoices: mustCollectInvoiceEntries(r.Context(), conn, company, locale, filters),
|
Invoices: mustCollectInvoiceEntries(r.Context(), conn, locale, filters),
|
||||||
|
TotalAmount: mustComputeInvoicesTotalAmount(r.Context(), conn, filters),
|
||||||
Filters: filters,
|
Filters: filters,
|
||||||
InvoiceStatuses: mustCollectInvoiceStatuses(r.Context(), conn, locale),
|
InvoiceStatuses: mustCollectInvoiceStatuses(r.Context(), conn, locale),
|
||||||
}
|
}
|
||||||
mustRenderMainTemplate(w, r, "invoices/index.gohtml", page)
|
mustRenderMainTemplate(w, r, "invoices/index.gohtml", page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustCollectInvoiceEntries(ctx context.Context, conn *Conn, company *Company, locale *Locale, filters *invoiceFilterForm) []*InvoiceEntry {
|
func mustCollectInvoiceEntries(ctx context.Context, conn *Conn, locale *Locale, filters *invoiceFilterForm) []*InvoiceEntry {
|
||||||
args := []interface{}{locale.Language.String(), company.Id}
|
where, args := filters.BuildQuery([]interface{}{locale.Language.String()})
|
||||||
where := []string{"invoice.company_id = $2"}
|
|
||||||
appendWhere := func(expression string, value interface{}) {
|
|
||||||
args = append(args, value)
|
|
||||||
where = append(where, fmt.Sprintf(expression, len(args)))
|
|
||||||
}
|
|
||||||
maybeAppendWhere := func(expression string, value string, conv func(string) interface{}) {
|
|
||||||
if value != "" {
|
|
||||||
if conv == nil {
|
|
||||||
appendWhere(expression, value)
|
|
||||||
} else {
|
|
||||||
appendWhere(expression, conv(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
maybeAppendWhere("contact_id = $%d", filters.Customer.String(), func(v string) interface{} {
|
|
||||||
customerId, _ := strconv.Atoi(filters.Customer.Selected[0])
|
|
||||||
return customerId
|
|
||||||
})
|
|
||||||
maybeAppendWhere("invoice.invoice_status = $%d", filters.InvoiceStatus.String(), nil)
|
|
||||||
maybeAppendWhere("invoice_number = $%d", filters.InvoiceNumber.String(), nil)
|
|
||||||
maybeAppendWhere("invoice_date >= $%d", filters.FromDate.String(), nil)
|
|
||||||
maybeAppendWhere("invoice_date <= $%d", filters.ToDate.String(), nil)
|
|
||||||
if len(filters.Tags.Tags) > 0 {
|
|
||||||
if filters.TagsCondition.Selected == "and" {
|
|
||||||
appendWhere("invoice.tags @> $%d", filters.Tags)
|
|
||||||
} else {
|
|
||||||
appendWhere("invoice.tags && $%d", filters.Tags)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rows := conn.MustQuery(ctx, fmt.Sprintf(`
|
rows := conn.MustQuery(ctx, fmt.Sprintf(`
|
||||||
select invoice.slug
|
select invoice.slug
|
||||||
, invoice_date
|
, invoice_date
|
||||||
|
@ -104,7 +77,7 @@ func mustCollectInvoiceEntries(ctx context.Context, conn *Conn, company *Company
|
||||||
where (%s)
|
where (%s)
|
||||||
order by invoice_date desc
|
order by invoice_date desc
|
||||||
, invoice_number desc
|
, invoice_number desc
|
||||||
`, strings.Join(where, ") AND (")), args...)
|
`, where), args...)
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var entries []*InvoiceEntry
|
var entries []*InvoiceEntry
|
||||||
|
@ -122,6 +95,18 @@ func mustCollectInvoiceEntries(ctx context.Context, conn *Conn, company *Company
|
||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustComputeInvoicesTotalAmount(ctx context.Context, conn *Conn, filters *invoiceFilterForm) string {
|
||||||
|
where, args := filters.BuildQuery(nil)
|
||||||
|
return conn.MustGetText(ctx, "0", fmt.Sprintf(`
|
||||||
|
select to_price(sum(total)::integer, decimal_digits)
|
||||||
|
from invoice
|
||||||
|
join invoice_amount using (invoice_id)
|
||||||
|
join currency using (currency_code)
|
||||||
|
where (%s)
|
||||||
|
group by decimal_digits
|
||||||
|
`, where), args...)
|
||||||
|
}
|
||||||
|
|
||||||
func mustCollectInvoiceStatuses(ctx context.Context, conn *Conn, locale *Locale) map[string]string {
|
func mustCollectInvoiceStatuses(ctx context.Context, conn *Conn, locale *Locale) map[string]string {
|
||||||
rows := conn.MustQuery(ctx, "select invoice_status.invoice_status, isi18n.name from invoice_status join invoice_status_i18n isi18n using(invoice_status) where isi18n.lang_tag = $1 order by invoice_status", locale.Language.String())
|
rows := conn.MustQuery(ctx, "select invoice_status.invoice_status, isi18n.name from invoice_status join invoice_status_i18n isi18n using(invoice_status) where isi18n.lang_tag = $1 order by invoice_status", locale.Language.String())
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
@ -159,7 +144,7 @@ func newInvoiceFilterForm(ctx context.Context, conn *Conn, locale *Locale, compa
|
||||||
company: company,
|
company: company,
|
||||||
Customer: &SelectField{
|
Customer: &SelectField{
|
||||||
Name: "customer",
|
Name: "customer",
|
||||||
Label: pgettext("input", "Customer", locale),
|
Label: pgettext("input", "Contact", locale),
|
||||||
EmptyLabel: gettext("All customers", locale),
|
EmptyLabel: gettext("All customers", locale),
|
||||||
Options: mustGetContactOptions(ctx, conn, company),
|
Options: mustGetContactOptions(ctx, conn, company),
|
||||||
},
|
},
|
||||||
|
@ -220,6 +205,41 @@ func (form *invoiceFilterForm) Parse(r *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (form *invoiceFilterForm) BuildQuery(args []interface{}) (string, []interface{}) {
|
||||||
|
var where []string
|
||||||
|
appendWhere := func(expression string, value interface{}) {
|
||||||
|
args = append(args, value)
|
||||||
|
where = append(where, fmt.Sprintf(expression, len(args)))
|
||||||
|
}
|
||||||
|
maybeAppendWhere := func(expression string, value string, conv func(string) interface{}) {
|
||||||
|
if value != "" {
|
||||||
|
if conv == nil {
|
||||||
|
appendWhere(expression, value)
|
||||||
|
} else {
|
||||||
|
appendWhere(expression, conv(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appendWhere("invoice.company_id = $%d", form.company.Id)
|
||||||
|
maybeAppendWhere("contact_id = $%d", form.Customer.String(), func(v string) interface{} {
|
||||||
|
customerId, _ := strconv.Atoi(form.Customer.Selected[0])
|
||||||
|
return customerId
|
||||||
|
})
|
||||||
|
maybeAppendWhere("invoice.invoice_status = $%d", form.InvoiceStatus.String(), nil)
|
||||||
|
maybeAppendWhere("invoice_number = $%d", form.InvoiceNumber.String(), nil)
|
||||||
|
maybeAppendWhere("invoice_date >= $%d", form.FromDate.String(), nil)
|
||||||
|
maybeAppendWhere("invoice_date <= $%d", form.ToDate.String(), nil)
|
||||||
|
if len(form.Tags.Tags) > 0 {
|
||||||
|
if form.TagsCondition.Selected == "and" {
|
||||||
|
appendWhere("invoice.tags @> $%d", form.Tags)
|
||||||
|
} else {
|
||||||
|
appendWhere("invoice.tags && $%d", form.Tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(where, ") AND ("), args
|
||||||
|
}
|
||||||
|
|
||||||
func ServeInvoice(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
func ServeInvoice(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||||
conn := getConn(r)
|
conn := getConn(r)
|
||||||
company := mustGetCompany(r)
|
company := mustGetCompany(r)
|
||||||
|
@ -583,7 +603,7 @@ func newInvoiceForm(ctx context.Context, conn *Conn, locale *Locale, company *Co
|
||||||
},
|
},
|
||||||
Customer: &SelectField{
|
Customer: &SelectField{
|
||||||
Name: "customer",
|
Name: "customer",
|
||||||
Label: pgettext("input", "Customer", locale),
|
Label: pgettext("input", "Contact", locale),
|
||||||
Required: true,
|
Required: true,
|
||||||
Options: mustGetContactOptions(ctx, conn, company),
|
Options: mustGetContactOptions(ctx, conn, company),
|
||||||
},
|
},
|
||||||
|
|
92
pkg/quote.go
92
pkg/quote.go
|
@ -33,6 +33,7 @@ type QuoteEntry struct {
|
||||||
|
|
||||||
type QuotesIndexPage struct {
|
type QuotesIndexPage struct {
|
||||||
Quotes []*QuoteEntry
|
Quotes []*QuoteEntry
|
||||||
|
TotalAmount string
|
||||||
Filters *quoteFilterForm
|
Filters *quoteFilterForm
|
||||||
QuoteStatuses map[string]string
|
QuoteStatuses map[string]string
|
||||||
}
|
}
|
||||||
|
@ -47,44 +48,16 @@ func IndexQuotes(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
page := &QuotesIndexPage{
|
page := &QuotesIndexPage{
|
||||||
Quotes: mustCollectQuoteEntries(r.Context(), conn, company, locale, filters),
|
Quotes: mustCollectQuoteEntries(r.Context(), conn, locale, filters),
|
||||||
|
TotalAmount: mustComputeQuotesTotalAmount(r.Context(), conn, filters),
|
||||||
Filters: filters,
|
Filters: filters,
|
||||||
QuoteStatuses: mustCollectQuoteStatuses(r.Context(), conn, locale),
|
QuoteStatuses: mustCollectQuoteStatuses(r.Context(), conn, locale),
|
||||||
}
|
}
|
||||||
mustRenderMainTemplate(w, r, "quotes/index.gohtml", page)
|
mustRenderMainTemplate(w, r, "quotes/index.gohtml", page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustCollectQuoteEntries(ctx context.Context, conn *Conn, company *Company, locale *Locale, filters *quoteFilterForm) []*QuoteEntry {
|
func mustCollectQuoteEntries(ctx context.Context, conn *Conn, locale *Locale, filters *quoteFilterForm) []*QuoteEntry {
|
||||||
args := []interface{}{locale.Language.String(), company.Id}
|
where, args := filters.BuildQuery([]interface{}{locale.Language.String()})
|
||||||
where := []string{"quote.company_id = $2"}
|
|
||||||
appendWhere := func(expression string, value interface{}) {
|
|
||||||
args = append(args, value)
|
|
||||||
where = append(where, fmt.Sprintf(expression, len(args)))
|
|
||||||
}
|
|
||||||
maybeAppendWhere := func(expression string, value string, conv func(string) interface{}) {
|
|
||||||
if value != "" {
|
|
||||||
if conv == nil {
|
|
||||||
appendWhere(expression, value)
|
|
||||||
} else {
|
|
||||||
appendWhere(expression, conv(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
maybeAppendWhere("contact_id = $%d", filters.Customer.String(), func(v string) interface{} {
|
|
||||||
customerId, _ := strconv.Atoi(filters.Customer.Selected[0])
|
|
||||||
return customerId
|
|
||||||
})
|
|
||||||
maybeAppendWhere("quote.quote_status = $%d", filters.QuoteStatus.String(), nil)
|
|
||||||
maybeAppendWhere("quote_number = $%d", filters.QuoteNumber.String(), nil)
|
|
||||||
maybeAppendWhere("quote_date >= $%d", filters.FromDate.String(), nil)
|
|
||||||
maybeAppendWhere("quote_date <= $%d", filters.ToDate.String(), nil)
|
|
||||||
if len(filters.Tags.Tags) > 0 {
|
|
||||||
if filters.TagsCondition.Selected == "and" {
|
|
||||||
appendWhere("quote.tags @> $%d", filters.Tags)
|
|
||||||
} else {
|
|
||||||
appendWhere("quote.tags && $%d", filters.Tags)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rows := conn.MustQuery(ctx, fmt.Sprintf(`
|
rows := conn.MustQuery(ctx, fmt.Sprintf(`
|
||||||
select quote.slug
|
select quote.slug
|
||||||
, quote_date
|
, quote_date
|
||||||
|
@ -103,7 +76,7 @@ func mustCollectQuoteEntries(ctx context.Context, conn *Conn, company *Company,
|
||||||
where (%s)
|
where (%s)
|
||||||
order by quote_date desc
|
order by quote_date desc
|
||||||
, quote_number desc
|
, quote_number desc
|
||||||
`, strings.Join(where, ") AND (")), args...)
|
`, where), args...)
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var entries []*QuoteEntry
|
var entries []*QuoteEntry
|
||||||
|
@ -121,6 +94,19 @@ func mustCollectQuoteEntries(ctx context.Context, conn *Conn, company *Company,
|
||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustComputeQuotesTotalAmount(ctx context.Context, conn *Conn, filters *quoteFilterForm) string {
|
||||||
|
where, args := filters.BuildQuery(nil)
|
||||||
|
return conn.MustGetText(ctx, "0", fmt.Sprintf(`
|
||||||
|
select to_price(sum(total)::integer, decimal_digits)
|
||||||
|
from quote
|
||||||
|
left join quote_contact using (quote_id)
|
||||||
|
join quote_amount using (quote_id)
|
||||||
|
join currency using (currency_code)
|
||||||
|
where (%s)
|
||||||
|
group by decimal_digits
|
||||||
|
`, where), args...)
|
||||||
|
}
|
||||||
|
|
||||||
func mustCollectQuoteStatuses(ctx context.Context, conn *Conn, locale *Locale) map[string]string {
|
func mustCollectQuoteStatuses(ctx context.Context, conn *Conn, locale *Locale) map[string]string {
|
||||||
rows := conn.MustQuery(ctx, "select quote_status.quote_status, isi18n.name from quote_status join quote_status_i18n isi18n using(quote_status) where isi18n.lang_tag = $1 order by quote_status", locale.Language.String())
|
rows := conn.MustQuery(ctx, "select quote_status.quote_status, isi18n.name from quote_status join quote_status_i18n isi18n using(quote_status) where isi18n.lang_tag = $1 order by quote_status", locale.Language.String())
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
@ -158,7 +144,7 @@ func newQuoteFilterForm(ctx context.Context, conn *Conn, locale *Locale, company
|
||||||
company: company,
|
company: company,
|
||||||
Customer: &SelectField{
|
Customer: &SelectField{
|
||||||
Name: "customer",
|
Name: "customer",
|
||||||
Label: pgettext("input", "Customer", locale),
|
Label: pgettext("input", "Contact", locale),
|
||||||
EmptyLabel: gettext("All customers", locale),
|
EmptyLabel: gettext("All customers", locale),
|
||||||
Options: mustGetContactOptions(ctx, conn, company),
|
Options: mustGetContactOptions(ctx, conn, company),
|
||||||
},
|
},
|
||||||
|
@ -219,6 +205,42 @@ func (form *quoteFilterForm) Parse(r *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (form *quoteFilterForm) BuildQuery(args []interface{}) (string, []interface{}) {
|
||||||
|
var where []string
|
||||||
|
appendWhere := func(expression string, value interface{}) {
|
||||||
|
args = append(args, value)
|
||||||
|
where = append(where, fmt.Sprintf(expression, len(args)))
|
||||||
|
}
|
||||||
|
maybeAppendWhere := func(expression string, value string, conv func(string) interface{}) {
|
||||||
|
if value != "" {
|
||||||
|
if conv == nil {
|
||||||
|
appendWhere(expression, value)
|
||||||
|
} else {
|
||||||
|
appendWhere(expression, conv(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appendWhere("quote.company_id = $%d", form.company.Id)
|
||||||
|
maybeAppendWhere("contact_id = $%d", form.Customer.String(), func(v string) interface{} {
|
||||||
|
customerId, _ := strconv.Atoi(form.Customer.Selected[0])
|
||||||
|
return customerId
|
||||||
|
})
|
||||||
|
maybeAppendWhere("quote.quote_status = $%d", form.QuoteStatus.String(), nil)
|
||||||
|
maybeAppendWhere("quote_number = $%d", form.QuoteNumber.String(), nil)
|
||||||
|
maybeAppendWhere("quote_date >= $%d", form.FromDate.String(), nil)
|
||||||
|
maybeAppendWhere("quote_date <= $%d", form.ToDate.String(), nil)
|
||||||
|
if len(form.Tags.Tags) > 0 {
|
||||||
|
if form.TagsCondition.Selected == "and" {
|
||||||
|
appendWhere("quote.tags @> $%d", form.Tags)
|
||||||
|
} else {
|
||||||
|
appendWhere("quote.tags && $%d", form.Tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(where, ") AND ("), args
|
||||||
|
}
|
||||||
|
|
||||||
func ServeQuote(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
func ServeQuote(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||||
conn := getConn(r)
|
conn := getConn(r)
|
||||||
company := mustGetCompany(r)
|
company := mustGetCompany(r)
|
||||||
|
@ -583,7 +605,7 @@ func newQuoteForm(ctx context.Context, conn *Conn, locale *Locale, company *Comp
|
||||||
},
|
},
|
||||||
Customer: &SelectField{
|
Customer: &SelectField{
|
||||||
Name: "customer",
|
Name: "customer",
|
||||||
Label: pgettext("input", "Customer", locale),
|
Label: pgettext("input", "Contact", locale),
|
||||||
EmptyLabel: gettext("Select a customer to quote.", locale),
|
EmptyLabel: gettext("Select a customer to quote.", locale),
|
||||||
Options: mustGetContactOptions(ctx, conn, company),
|
Options: mustGetContactOptions(ctx, conn, company),
|
||||||
},
|
},
|
||||||
|
|
161
po/ca.po
161
po/ca.po
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: numerus\n"
|
"Project-Id-Version: numerus\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2023-06-20 10:48+0200\n"
|
"POT-Creation-Date: 2023-06-20 11:29+0200\n"
|
||||||
"PO-Revision-Date: 2023-01-18 17:08+0100\n"
|
"PO-Revision-Date: 2023-01-18 17:08+0100\n"
|
||||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||||
|
@ -157,10 +157,9 @@ msgid "Invoice Num."
|
||||||
msgstr "Núm. factura"
|
msgstr "Núm. factura"
|
||||||
|
|
||||||
#: web/template/invoices/index.gohtml:52 web/template/quotes/index.gohtml:52
|
#: web/template/invoices/index.gohtml:52 web/template/quotes/index.gohtml:52
|
||||||
#: web/template/contacts/index.gohtml:40 web/template/expenses/index.gohtml:43
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Contact"
|
msgid "Customer"
|
||||||
msgstr "Contacte"
|
msgstr "Client"
|
||||||
|
|
||||||
#: web/template/invoices/index.gohtml:53 web/template/quotes/index.gohtml:53
|
#: web/template/invoices/index.gohtml:53 web/template/quotes/index.gohtml:53
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
|
@ -216,6 +215,11 @@ msgstr "Duplica"
|
||||||
msgid "No invoices added yet."
|
msgid "No invoices added yet."
|
||||||
msgstr "No hi ha cap factura."
|
msgstr "No hi ha cap factura."
|
||||||
|
|
||||||
|
#: web/template/invoices/index.gohtml:144 web/template/quotes/index.gohtml:152
|
||||||
|
#: web/template/expenses/index.gohtml:105
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Total"
|
||||||
|
|
||||||
#: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:33
|
#: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:33
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Invoice %s"
|
msgid "Invoice %s"
|
||||||
|
@ -449,6 +453,11 @@ msgctxt "action"
|
||||||
msgid "New contact"
|
msgid "New contact"
|
||||||
msgstr "Nou contacte"
|
msgstr "Nou contacte"
|
||||||
|
|
||||||
|
#: web/template/contacts/index.gohtml:40 web/template/expenses/index.gohtml:43
|
||||||
|
msgctxt "title"
|
||||||
|
msgid "Contact"
|
||||||
|
msgstr "Contacte"
|
||||||
|
|
||||||
#: web/template/contacts/index.gohtml:41
|
#: web/template/contacts/index.gohtml:41
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
|
@ -665,82 +674,82 @@ msgstr "No podeu deixar la contrasenya en blanc."
|
||||||
msgid "Invalid user or password."
|
msgid "Invalid user or password."
|
||||||
msgstr "Nom d’usuari o contrasenya incorrectes."
|
msgstr "Nom d’usuari o contrasenya incorrectes."
|
||||||
|
|
||||||
#: pkg/products.go:164 pkg/products.go:263 pkg/quote.go:801 pkg/invoices.go:851
|
#: pkg/products.go:164 pkg/products.go:263 pkg/quote.go:823 pkg/invoices.go:871
|
||||||
#: pkg/contacts.go:135
|
#: pkg/contacts.go:135
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Nom"
|
msgstr "Nom"
|
||||||
|
|
||||||
#: pkg/products.go:169 pkg/products.go:290 pkg/quote.go:188 pkg/quote.go:608
|
#: pkg/products.go:169 pkg/products.go:290 pkg/quote.go:174 pkg/quote.go:630
|
||||||
#: pkg/expenses.go:202 pkg/expenses.go:361 pkg/invoices.go:189
|
#: pkg/expenses.go:188 pkg/expenses.go:347 pkg/invoices.go:174
|
||||||
#: pkg/invoices.go:603 pkg/invoices.go:1150 pkg/contacts.go:140
|
#: pkg/invoices.go:623 pkg/invoices.go:1170 pkg/contacts.go:140
|
||||||
#: pkg/contacts.go:325
|
#: pkg/contacts.go:325
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Tags"
|
msgid "Tags"
|
||||||
msgstr "Etiquetes"
|
msgstr "Etiquetes"
|
||||||
|
|
||||||
#: pkg/products.go:173 pkg/quote.go:192 pkg/expenses.go:365 pkg/invoices.go:193
|
#: pkg/products.go:173 pkg/quote.go:178 pkg/expenses.go:351 pkg/invoices.go:178
|
||||||
#: pkg/contacts.go:144
|
#: pkg/contacts.go:144
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Tags Condition"
|
msgid "Tags Condition"
|
||||||
msgstr "Condició de les etiquetes"
|
msgstr "Condició de les etiquetes"
|
||||||
|
|
||||||
#: pkg/products.go:177 pkg/quote.go:196 pkg/expenses.go:369 pkg/invoices.go:197
|
#: pkg/products.go:177 pkg/quote.go:182 pkg/expenses.go:355 pkg/invoices.go:182
|
||||||
#: pkg/contacts.go:148
|
#: pkg/contacts.go:148
|
||||||
msgctxt "tag condition"
|
msgctxt "tag condition"
|
||||||
msgid "All"
|
msgid "All"
|
||||||
msgstr "Totes"
|
msgstr "Totes"
|
||||||
|
|
||||||
#: pkg/products.go:178 pkg/expenses.go:370 pkg/invoices.go:198
|
#: pkg/products.go:178 pkg/expenses.go:356 pkg/invoices.go:183
|
||||||
#: pkg/contacts.go:149
|
#: pkg/contacts.go:149
|
||||||
msgid "Invoices must have all the specified labels."
|
msgid "Invoices must have all the specified labels."
|
||||||
msgstr "Les factures han de tenir totes les etiquetes."
|
msgstr "Les factures han de tenir totes les etiquetes."
|
||||||
|
|
||||||
#: pkg/products.go:182 pkg/quote.go:201 pkg/expenses.go:374 pkg/invoices.go:202
|
#: pkg/products.go:182 pkg/quote.go:187 pkg/expenses.go:360 pkg/invoices.go:187
|
||||||
#: pkg/contacts.go:153
|
#: pkg/contacts.go:153
|
||||||
msgctxt "tag condition"
|
msgctxt "tag condition"
|
||||||
msgid "Any"
|
msgid "Any"
|
||||||
msgstr "Qualsevol"
|
msgstr "Qualsevol"
|
||||||
|
|
||||||
#: pkg/products.go:183 pkg/expenses.go:375 pkg/invoices.go:203
|
#: pkg/products.go:183 pkg/expenses.go:361 pkg/invoices.go:188
|
||||||
#: pkg/contacts.go:154
|
#: pkg/contacts.go:154
|
||||||
msgid "Invoices must have at least one of the specified labels."
|
msgid "Invoices must have at least one of the specified labels."
|
||||||
msgstr "Les factures han de tenir com a mínim una de les etiquetes."
|
msgstr "Les factures han de tenir com a mínim una de les etiquetes."
|
||||||
|
|
||||||
#: pkg/products.go:269 pkg/quote.go:815 pkg/invoices.go:865
|
#: pkg/products.go:269 pkg/quote.go:837 pkg/invoices.go:885
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripció"
|
msgstr "Descripció"
|
||||||
|
|
||||||
#: pkg/products.go:274 pkg/quote.go:819 pkg/invoices.go:869
|
#: pkg/products.go:274 pkg/quote.go:841 pkg/invoices.go:889
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Price"
|
msgid "Price"
|
||||||
msgstr "Preu"
|
msgstr "Preu"
|
||||||
|
|
||||||
#: pkg/products.go:284 pkg/quote.go:848 pkg/expenses.go:181 pkg/invoices.go:898
|
#: pkg/products.go:284 pkg/quote.go:870 pkg/expenses.go:167 pkg/invoices.go:918
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Taxes"
|
msgid "Taxes"
|
||||||
msgstr "Imposts"
|
msgstr "Imposts"
|
||||||
|
|
||||||
#: pkg/products.go:309 pkg/quote.go:897 pkg/profile.go:92 pkg/invoices.go:947
|
#: pkg/products.go:309 pkg/quote.go:919 pkg/profile.go:92 pkg/invoices.go:967
|
||||||
msgid "Name can not be empty."
|
msgid "Name can not be empty."
|
||||||
msgstr "No podeu deixar el nom en blanc."
|
msgstr "No podeu deixar el nom en blanc."
|
||||||
|
|
||||||
#: pkg/products.go:310 pkg/quote.go:898 pkg/invoices.go:948
|
#: pkg/products.go:310 pkg/quote.go:920 pkg/invoices.go:968
|
||||||
msgid "Price can not be empty."
|
msgid "Price can not be empty."
|
||||||
msgstr "No podeu deixar el preu en blanc."
|
msgstr "No podeu deixar el preu en blanc."
|
||||||
|
|
||||||
#: pkg/products.go:311 pkg/quote.go:899 pkg/invoices.go:949
|
#: pkg/products.go:311 pkg/quote.go:921 pkg/invoices.go:969
|
||||||
msgid "Price must be a number greater than zero."
|
msgid "Price must be a number greater than zero."
|
||||||
msgstr "El preu ha de ser un número major a zero."
|
msgstr "El preu ha de ser un número major a zero."
|
||||||
|
|
||||||
#: pkg/products.go:313 pkg/quote.go:907 pkg/expenses.go:227 pkg/expenses.go:232
|
#: pkg/products.go:313 pkg/quote.go:929 pkg/expenses.go:213 pkg/expenses.go:218
|
||||||
#: pkg/invoices.go:957
|
#: pkg/invoices.go:977
|
||||||
msgid "Selected tax is not valid."
|
msgid "Selected tax is not valid."
|
||||||
msgstr "Heu seleccionat un impost que no és vàlid."
|
msgstr "Heu seleccionat un impost que no és vàlid."
|
||||||
|
|
||||||
#: pkg/products.go:314 pkg/quote.go:908 pkg/expenses.go:228 pkg/expenses.go:233
|
#: pkg/products.go:314 pkg/quote.go:930 pkg/expenses.go:214 pkg/expenses.go:219
|
||||||
#: pkg/invoices.go:958
|
#: pkg/invoices.go:978
|
||||||
msgid "You can only select a tax of each class."
|
msgid "You can only select a tax of each class."
|
||||||
msgstr "Només podeu seleccionar un impost de cada classe."
|
msgstr "Només podeu seleccionar un impost de cada classe."
|
||||||
|
|
||||||
|
@ -847,141 +856,141 @@ msgstr "No podeu deixar el nom del mètode de pagament en blanc."
|
||||||
msgid "Payment instructions can not be empty."
|
msgid "Payment instructions can not be empty."
|
||||||
msgstr "No podeu deixar les instruccions de pagament en blanc."
|
msgstr "No podeu deixar les instruccions de pagament en blanc."
|
||||||
|
|
||||||
#: pkg/quote.go:148 pkg/quote.go:609 pkg/expenses.go:164 pkg/expenses.go:340
|
#: pkg/quote.go:147 pkg/quote.go:608 pkg/expenses.go:150 pkg/expenses.go:326
|
||||||
#: pkg/invoices.go:147 pkg/invoices.go:606
|
#: pkg/invoices.go:147 pkg/invoices.go:606
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Contact"
|
msgid "Contact"
|
||||||
msgstr "Contacte"
|
msgstr "Contacte"
|
||||||
|
|
||||||
#: pkg/quote.go:162 pkg/expenses.go:341 pkg/invoices.go:163
|
#: pkg/quote.go:148 pkg/invoices.go:148
|
||||||
msgid "All customers"
|
msgid "All customers"
|
||||||
msgstr "Tots els clients"
|
msgstr "Tots els clients"
|
||||||
|
|
||||||
#: pkg/quote.go:167 pkg/quote.go:580
|
#: pkg/quote.go:153 pkg/quote.go:602
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Quotation Status"
|
msgid "Quotation Status"
|
||||||
msgstr "Estat del pressupost"
|
msgstr "Estat del pressupost"
|
||||||
|
|
||||||
#: pkg/quote.go:168 pkg/invoices.go:169
|
#: pkg/quote.go:154 pkg/invoices.go:154
|
||||||
msgid "All status"
|
msgid "All status"
|
||||||
msgstr "Tots els estats"
|
msgstr "Tots els estats"
|
||||||
|
|
||||||
#: pkg/quote.go:173
|
#: pkg/quote.go:159
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Quotation Number"
|
msgid "Quotation Number"
|
||||||
msgstr "Número de pressupost"
|
msgstr "Número de pressupost"
|
||||||
|
|
||||||
#: pkg/quote.go:178 pkg/expenses.go:351 pkg/invoices.go:179
|
#: pkg/quote.go:164 pkg/expenses.go:337 pkg/invoices.go:164
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "From Date"
|
msgid "From Date"
|
||||||
msgstr "A partir de la data"
|
msgstr "A partir de la data"
|
||||||
|
|
||||||
#: pkg/quote.go:183 pkg/expenses.go:356 pkg/invoices.go:184
|
#: pkg/quote.go:169 pkg/expenses.go:342 pkg/invoices.go:169
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "To Date"
|
msgid "To Date"
|
||||||
msgstr "Fins la data"
|
msgstr "Fins la data"
|
||||||
|
|
||||||
#: pkg/quote.go:197
|
#: pkg/quote.go:183
|
||||||
msgid "Quotations must have all the specified labels."
|
msgid "Quotations must have all the specified labels."
|
||||||
msgstr "Els pressuposts han de tenir totes les etiquetes."
|
msgstr "Els pressuposts han de tenir totes les etiquetes."
|
||||||
|
|
||||||
#: pkg/quote.go:202
|
#: pkg/quote.go:188
|
||||||
msgid "Quotations must have at least one of the specified labels."
|
msgid "Quotations must have at least one of the specified labels."
|
||||||
msgstr "Els pressuposts han de tenir com a mínim una de les etiquetes."
|
msgstr "Els pressuposts han de tenir com a mínim una de les etiquetes."
|
||||||
|
|
||||||
#: pkg/quote.go:528
|
#: pkg/quote.go:550
|
||||||
msgid "quotations.zip"
|
msgid "quotations.zip"
|
||||||
msgstr "pressuposts.zip"
|
msgstr "pressuposts.zip"
|
||||||
|
|
||||||
#: pkg/quote.go:534 pkg/quote.go:1063 pkg/quote.go:1071 pkg/invoices.go:535
|
#: pkg/quote.go:556 pkg/quote.go:1085 pkg/quote.go:1093 pkg/invoices.go:555
|
||||||
#: pkg/invoices.go:1125 pkg/invoices.go:1133
|
#: pkg/invoices.go:1145 pkg/invoices.go:1153
|
||||||
msgid "Invalid action"
|
msgid "Invalid action"
|
||||||
msgstr "Acció invàlida."
|
msgstr "Acció invàlida."
|
||||||
|
|
||||||
#: pkg/quote.go:587
|
#: pkg/quote.go:609
|
||||||
msgid "Select a customer to quote."
|
msgid "Select a customer to quote."
|
||||||
msgstr "Escolliu un client a pressupostar."
|
msgstr "Escolliu un client a pressupostar."
|
||||||
|
|
||||||
#: pkg/quote.go:592
|
#: pkg/quote.go:614
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Quotation Date"
|
msgid "Quotation Date"
|
||||||
msgstr "Data del pressupost"
|
msgstr "Data del pressupost"
|
||||||
|
|
||||||
#: pkg/quote.go:598
|
#: pkg/quote.go:620
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Terms and conditions"
|
msgid "Terms and conditions"
|
||||||
msgstr "Condicions d’acceptació"
|
msgstr "Condicions d’acceptació"
|
||||||
|
|
||||||
#: pkg/quote.go:603 pkg/invoices.go:598
|
#: pkg/quote.go:625 pkg/invoices.go:618
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Notes"
|
msgid "Notes"
|
||||||
msgstr "Notes"
|
msgstr "Notes"
|
||||||
|
|
||||||
#: pkg/quote.go:612 pkg/invoices.go:608
|
#: pkg/quote.go:634 pkg/invoices.go:628
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Payment Method"
|
msgid "Payment Method"
|
||||||
msgstr "Mètode de pagament"
|
msgstr "Mètode de pagament"
|
||||||
|
|
||||||
#: pkg/quote.go:613
|
#: pkg/quote.go:635
|
||||||
msgid "Select a payment method."
|
msgid "Select a payment method."
|
||||||
msgstr "Escolliu un mètode de pagament."
|
msgstr "Escolliu un mètode de pagament."
|
||||||
|
|
||||||
#: pkg/quote.go:649
|
#: pkg/quote.go:671
|
||||||
msgid "Selected quotation status is not valid."
|
msgid "Selected quotation status is not valid."
|
||||||
msgstr "Heu seleccionat un estat de pressupost que no és vàlid."
|
msgstr "Heu seleccionat un estat de pressupost que no és vàlid."
|
||||||
|
|
||||||
#: pkg/quote.go:651 pkg/invoices.go:645
|
#: pkg/quote.go:673 pkg/invoices.go:665
|
||||||
msgid "Selected customer is not valid."
|
msgid "Selected customer is not valid."
|
||||||
msgstr "Heu seleccionat un client que no és vàlid."
|
msgstr "Heu seleccionat un client que no és vàlid."
|
||||||
|
|
||||||
#: pkg/quote.go:653
|
#: pkg/quote.go:675
|
||||||
msgid "Quotation date can not be empty."
|
msgid "Quotation date can not be empty."
|
||||||
msgstr "No podeu deixar la data del pressupost en blanc."
|
msgstr "No podeu deixar la data del pressupost en blanc."
|
||||||
|
|
||||||
#: pkg/quote.go:654
|
#: pkg/quote.go:676
|
||||||
msgid "Quotation date must be a valid date."
|
msgid "Quotation date must be a valid date."
|
||||||
msgstr "La data del pressupost ha de ser vàlida."
|
msgstr "La data del pressupost ha de ser vàlida."
|
||||||
|
|
||||||
#: pkg/quote.go:657 pkg/invoices.go:649
|
#: pkg/quote.go:679 pkg/invoices.go:669
|
||||||
msgid "Selected payment method is not valid."
|
msgid "Selected payment method is not valid."
|
||||||
msgstr "Heu seleccionat un mètode de pagament que no és vàlid."
|
msgstr "Heu seleccionat un mètode de pagament que no és vàlid."
|
||||||
|
|
||||||
#: pkg/quote.go:791 pkg/quote.go:796 pkg/invoices.go:841 pkg/invoices.go:846
|
#: pkg/quote.go:813 pkg/quote.go:818 pkg/invoices.go:861 pkg/invoices.go:866
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr "Identificador"
|
msgstr "Identificador"
|
||||||
|
|
||||||
#: pkg/quote.go:829 pkg/invoices.go:879
|
#: pkg/quote.go:851 pkg/invoices.go:899
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Quantity"
|
msgid "Quantity"
|
||||||
msgstr "Quantitat"
|
msgstr "Quantitat"
|
||||||
|
|
||||||
#: pkg/quote.go:838 pkg/invoices.go:888
|
#: pkg/quote.go:860 pkg/invoices.go:908
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Discount (%)"
|
msgid "Discount (%)"
|
||||||
msgstr "Descompte (%)"
|
msgstr "Descompte (%)"
|
||||||
|
|
||||||
#: pkg/quote.go:892
|
#: pkg/quote.go:914
|
||||||
msgid "Quotation product ID must be a number greater than zero."
|
msgid "Quotation product ID must be a number greater than zero."
|
||||||
msgstr "L’ID del producte de pressupost ha de ser un número major a zero."
|
msgstr "L’ID del producte de pressupost ha de ser un número major a zero."
|
||||||
|
|
||||||
#: pkg/quote.go:895 pkg/invoices.go:945
|
#: pkg/quote.go:917 pkg/invoices.go:965
|
||||||
msgid "Product ID must be a positive number or zero."
|
msgid "Product ID must be a positive number or zero."
|
||||||
msgstr "L’ID del producte ha de ser un número positiu o zero."
|
msgstr "L’ID del producte ha de ser un número positiu o zero."
|
||||||
|
|
||||||
#: pkg/quote.go:901 pkg/invoices.go:951
|
#: pkg/quote.go:923 pkg/invoices.go:971
|
||||||
msgid "Quantity can not be empty."
|
msgid "Quantity can not be empty."
|
||||||
msgstr "No podeu deixar la quantitat en blanc."
|
msgstr "No podeu deixar la quantitat en blanc."
|
||||||
|
|
||||||
#: pkg/quote.go:902 pkg/invoices.go:952
|
#: pkg/quote.go:924 pkg/invoices.go:972
|
||||||
msgid "Quantity must be a number greater than zero."
|
msgid "Quantity must be a number greater than zero."
|
||||||
msgstr "La quantitat ha de ser un número major a zero."
|
msgstr "La quantitat ha de ser un número major a zero."
|
||||||
|
|
||||||
#: pkg/quote.go:904 pkg/invoices.go:954
|
#: pkg/quote.go:926 pkg/invoices.go:974
|
||||||
msgid "Discount can not be empty."
|
msgid "Discount can not be empty."
|
||||||
msgstr "No podeu deixar el descompte en blanc."
|
msgstr "No podeu deixar el descompte en blanc."
|
||||||
|
|
||||||
#: pkg/quote.go:905 pkg/invoices.go:955
|
#: pkg/quote.go:927 pkg/invoices.go:975
|
||||||
msgid "Discount must be a percentage between 0 and 100."
|
msgid "Discount must be a percentage between 0 and 100."
|
||||||
msgstr "El descompte ha de ser un percentatge entre 0 i 100."
|
msgstr "El descompte ha de ser un percentatge entre 0 i 100."
|
||||||
|
|
||||||
|
@ -1048,87 +1057,87 @@ msgctxt "period option"
|
||||||
msgid "Previous year"
|
msgid "Previous year"
|
||||||
msgstr "Any anterior"
|
msgstr "Any anterior"
|
||||||
|
|
||||||
#: pkg/expenses.go:129
|
#: pkg/expenses.go:115
|
||||||
msgid "Select a contact."
|
msgid "Select a contact."
|
||||||
msgstr "Escolliu un contacte."
|
msgstr "Escolliu un contacte."
|
||||||
|
|
||||||
#: pkg/expenses.go:170
|
#: pkg/expenses.go:156
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Invoice number"
|
msgid "Invoice number"
|
||||||
msgstr "Número de factura"
|
msgstr "Número de factura"
|
||||||
|
|
||||||
#: pkg/expenses.go:175 pkg/invoices.go:592
|
#: pkg/expenses.go:161 pkg/invoices.go:612
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Invoice Date"
|
msgid "Invoice Date"
|
||||||
msgstr "Data de factura"
|
msgstr "Data de factura"
|
||||||
|
|
||||||
#: pkg/expenses.go:187
|
#: pkg/expenses.go:173
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Amount"
|
msgid "Amount"
|
||||||
msgstr "Import"
|
msgstr "Import"
|
||||||
|
|
||||||
#: pkg/expenses.go:197
|
#: pkg/expenses.go:183
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "File"
|
msgid "File"
|
||||||
msgstr "Fitxer"
|
msgstr "Fitxer"
|
||||||
|
|
||||||
#: pkg/expenses.go:225
|
#: pkg/expenses.go:211
|
||||||
msgid "Selected contact is not valid."
|
msgid "Selected contact is not valid."
|
||||||
msgstr "Heu seleccionat un contacte que no és vàlid."
|
msgstr "Heu seleccionat un contacte que no és vàlid."
|
||||||
|
|
||||||
#: pkg/expenses.go:226 pkg/invoices.go:647
|
#: pkg/expenses.go:212 pkg/invoices.go:667
|
||||||
msgid "Invoice date must be a valid date."
|
msgid "Invoice date must be a valid date."
|
||||||
msgstr "La data de facturació ha de ser vàlida."
|
msgstr "La data de facturació ha de ser vàlida."
|
||||||
|
|
||||||
#: pkg/expenses.go:229
|
#: pkg/expenses.go:215
|
||||||
msgid "Amount can not be empty."
|
msgid "Amount can not be empty."
|
||||||
msgstr "No podeu deixar l’import en blanc."
|
msgstr "No podeu deixar l’import en blanc."
|
||||||
|
|
||||||
#: pkg/expenses.go:230
|
#: pkg/expenses.go:216
|
||||||
msgid "Amount must be a number greater than zero."
|
msgid "Amount must be a number greater than zero."
|
||||||
msgstr "L’import ha de ser un número major a zero."
|
msgstr "L’import ha de ser un número major a zero."
|
||||||
|
|
||||||
#: pkg/expenses.go:341
|
#: pkg/expenses.go:327
|
||||||
msgid "All contacts"
|
msgid "All contacts"
|
||||||
msgstr "Tots els contactes"
|
msgstr "Tots els contactes"
|
||||||
|
|
||||||
#: pkg/expenses.go:346 pkg/invoices.go:159
|
#: pkg/expenses.go:332 pkg/invoices.go:159
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Invoice Number"
|
msgid "Invoice Number"
|
||||||
msgstr "Número de factura"
|
msgstr "Número de factura"
|
||||||
|
|
||||||
#: pkg/invoices.go:168 pkg/invoices.go:580
|
#: pkg/invoices.go:153 pkg/invoices.go:600
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Invoice Status"
|
msgid "Invoice Status"
|
||||||
msgstr "Estat de la factura"
|
msgstr "Estat de la factura"
|
||||||
|
|
||||||
#: pkg/invoices.go:428
|
#: pkg/invoices.go:448
|
||||||
msgid "Select a customer to bill."
|
msgid "Select a customer to bill."
|
||||||
msgstr "Escolliu un client a facturar."
|
msgstr "Escolliu un client a facturar."
|
||||||
|
|
||||||
#: pkg/invoices.go:529
|
#: pkg/invoices.go:549
|
||||||
msgid "invoices.zip"
|
msgid "invoices.zip"
|
||||||
msgstr "factures.zip"
|
msgstr "factures.zip"
|
||||||
|
|
||||||
#: pkg/invoices.go:644
|
#: pkg/invoices.go:664
|
||||||
msgid "Selected invoice status is not valid."
|
msgid "Selected invoice status is not valid."
|
||||||
msgstr "Heu seleccionat un estat de factura que no és vàlid."
|
msgstr "Heu seleccionat un estat de factura que no és vàlid."
|
||||||
|
|
||||||
#: pkg/invoices.go:646
|
#: pkg/invoices.go:666
|
||||||
msgid "Invoice date can not be empty."
|
msgid "Invoice date can not be empty."
|
||||||
msgstr "No podeu deixar la data de la factura en blanc."
|
msgstr "No podeu deixar la data de la factura en blanc."
|
||||||
|
|
||||||
#: pkg/invoices.go:782
|
#: pkg/invoices.go:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Re: quotation #%s of %s"
|
msgid "Re: quotation #%s of %s"
|
||||||
msgstr "Ref: pressupost núm. %s del %s"
|
msgstr "Ref: pressupost núm. %s del %s"
|
||||||
|
|
||||||
#: pkg/invoices.go:783
|
#: pkg/invoices.go:803
|
||||||
msgctxt "to_char"
|
msgctxt "to_char"
|
||||||
msgid "MM/DD/YYYY"
|
msgid "MM/DD/YYYY"
|
||||||
msgstr "DD/MM/YYYY"
|
msgstr "DD/MM/YYYY"
|
||||||
|
|
||||||
#: pkg/invoices.go:942
|
#: pkg/invoices.go:962
|
||||||
msgid "Invoice product ID must be a number greater than zero."
|
msgid "Invoice product ID must be a number greater than zero."
|
||||||
msgstr "L’ID del producte de factura ha de ser un número major a zero."
|
msgstr "L’ID del producte de factura ha de ser un número major a zero."
|
||||||
|
|
||||||
|
@ -1234,10 +1243,6 @@ msgstr "No podeu deixar el codi postal en blanc."
|
||||||
msgid "This value is not a valid postal code."
|
msgid "This value is not a valid postal code."
|
||||||
msgstr "Aquest valor no és un codi postal vàlid."
|
msgstr "Aquest valor no és un codi postal vàlid."
|
||||||
|
|
||||||
#~ msgctxt "title"
|
|
||||||
#~ msgid "Customer"
|
|
||||||
#~ msgstr "Client"
|
|
||||||
|
|
||||||
#~ msgctxt "input"
|
#~ msgctxt "input"
|
||||||
#~ msgid "Customer"
|
#~ msgid "Customer"
|
||||||
#~ msgstr "Client"
|
#~ msgstr "Client"
|
||||||
|
|
161
po/es.po
161
po/es.po
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: numerus\n"
|
"Project-Id-Version: numerus\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2023-06-20 10:48+0200\n"
|
"POT-Creation-Date: 2023-06-20 11:29+0200\n"
|
||||||
"PO-Revision-Date: 2023-01-18 17:45+0100\n"
|
"PO-Revision-Date: 2023-01-18 17:45+0100\n"
|
||||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||||
|
@ -157,10 +157,9 @@ msgid "Invoice Num."
|
||||||
msgstr "N.º factura"
|
msgstr "N.º factura"
|
||||||
|
|
||||||
#: web/template/invoices/index.gohtml:52 web/template/quotes/index.gohtml:52
|
#: web/template/invoices/index.gohtml:52 web/template/quotes/index.gohtml:52
|
||||||
#: web/template/contacts/index.gohtml:40 web/template/expenses/index.gohtml:43
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Contact"
|
msgid "Customer"
|
||||||
msgstr "Contacto"
|
msgstr "Cliente"
|
||||||
|
|
||||||
#: web/template/invoices/index.gohtml:53 web/template/quotes/index.gohtml:53
|
#: web/template/invoices/index.gohtml:53 web/template/quotes/index.gohtml:53
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
|
@ -216,6 +215,11 @@ msgstr "Duplicar"
|
||||||
msgid "No invoices added yet."
|
msgid "No invoices added yet."
|
||||||
msgstr "No hay facturas."
|
msgstr "No hay facturas."
|
||||||
|
|
||||||
|
#: web/template/invoices/index.gohtml:144 web/template/quotes/index.gohtml:152
|
||||||
|
#: web/template/expenses/index.gohtml:105
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Total"
|
||||||
|
|
||||||
#: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:33
|
#: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:33
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Invoice %s"
|
msgid "Invoice %s"
|
||||||
|
@ -449,6 +453,11 @@ msgctxt "action"
|
||||||
msgid "New contact"
|
msgid "New contact"
|
||||||
msgstr "Nuevo contacto"
|
msgstr "Nuevo contacto"
|
||||||
|
|
||||||
|
#: web/template/contacts/index.gohtml:40 web/template/expenses/index.gohtml:43
|
||||||
|
msgctxt "title"
|
||||||
|
msgid "Contact"
|
||||||
|
msgstr "Contacto"
|
||||||
|
|
||||||
#: web/template/contacts/index.gohtml:41
|
#: web/template/contacts/index.gohtml:41
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
|
@ -665,82 +674,82 @@ msgstr "No podéis dejar la contraseña en blanco."
|
||||||
msgid "Invalid user or password."
|
msgid "Invalid user or password."
|
||||||
msgstr "Nombre de usuario o contraseña inválido."
|
msgstr "Nombre de usuario o contraseña inválido."
|
||||||
|
|
||||||
#: pkg/products.go:164 pkg/products.go:263 pkg/quote.go:801 pkg/invoices.go:851
|
#: pkg/products.go:164 pkg/products.go:263 pkg/quote.go:823 pkg/invoices.go:871
|
||||||
#: pkg/contacts.go:135
|
#: pkg/contacts.go:135
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Nombre"
|
msgstr "Nombre"
|
||||||
|
|
||||||
#: pkg/products.go:169 pkg/products.go:290 pkg/quote.go:188 pkg/quote.go:608
|
#: pkg/products.go:169 pkg/products.go:290 pkg/quote.go:174 pkg/quote.go:630
|
||||||
#: pkg/expenses.go:202 pkg/expenses.go:361 pkg/invoices.go:189
|
#: pkg/expenses.go:188 pkg/expenses.go:347 pkg/invoices.go:174
|
||||||
#: pkg/invoices.go:603 pkg/invoices.go:1150 pkg/contacts.go:140
|
#: pkg/invoices.go:623 pkg/invoices.go:1170 pkg/contacts.go:140
|
||||||
#: pkg/contacts.go:325
|
#: pkg/contacts.go:325
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Tags"
|
msgid "Tags"
|
||||||
msgstr "Etiquetes"
|
msgstr "Etiquetes"
|
||||||
|
|
||||||
#: pkg/products.go:173 pkg/quote.go:192 pkg/expenses.go:365 pkg/invoices.go:193
|
#: pkg/products.go:173 pkg/quote.go:178 pkg/expenses.go:351 pkg/invoices.go:178
|
||||||
#: pkg/contacts.go:144
|
#: pkg/contacts.go:144
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Tags Condition"
|
msgid "Tags Condition"
|
||||||
msgstr "Condición de las etiquetas"
|
msgstr "Condición de las etiquetas"
|
||||||
|
|
||||||
#: pkg/products.go:177 pkg/quote.go:196 pkg/expenses.go:369 pkg/invoices.go:197
|
#: pkg/products.go:177 pkg/quote.go:182 pkg/expenses.go:355 pkg/invoices.go:182
|
||||||
#: pkg/contacts.go:148
|
#: pkg/contacts.go:148
|
||||||
msgctxt "tag condition"
|
msgctxt "tag condition"
|
||||||
msgid "All"
|
msgid "All"
|
||||||
msgstr "Todas"
|
msgstr "Todas"
|
||||||
|
|
||||||
#: pkg/products.go:178 pkg/expenses.go:370 pkg/invoices.go:198
|
#: pkg/products.go:178 pkg/expenses.go:356 pkg/invoices.go:183
|
||||||
#: pkg/contacts.go:149
|
#: pkg/contacts.go:149
|
||||||
msgid "Invoices must have all the specified labels."
|
msgid "Invoices must have all the specified labels."
|
||||||
msgstr "Las facturas deben tener todas las etiquetas."
|
msgstr "Las facturas deben tener todas las etiquetas."
|
||||||
|
|
||||||
#: pkg/products.go:182 pkg/quote.go:201 pkg/expenses.go:374 pkg/invoices.go:202
|
#: pkg/products.go:182 pkg/quote.go:187 pkg/expenses.go:360 pkg/invoices.go:187
|
||||||
#: pkg/contacts.go:153
|
#: pkg/contacts.go:153
|
||||||
msgctxt "tag condition"
|
msgctxt "tag condition"
|
||||||
msgid "Any"
|
msgid "Any"
|
||||||
msgstr "Cualquiera"
|
msgstr "Cualquiera"
|
||||||
|
|
||||||
#: pkg/products.go:183 pkg/expenses.go:375 pkg/invoices.go:203
|
#: pkg/products.go:183 pkg/expenses.go:361 pkg/invoices.go:188
|
||||||
#: pkg/contacts.go:154
|
#: pkg/contacts.go:154
|
||||||
msgid "Invoices must have at least one of the specified labels."
|
msgid "Invoices must have at least one of the specified labels."
|
||||||
msgstr "Las facturas deben tener como mínimo una de las etiquetas."
|
msgstr "Las facturas deben tener como mínimo una de las etiquetas."
|
||||||
|
|
||||||
#: pkg/products.go:269 pkg/quote.go:815 pkg/invoices.go:865
|
#: pkg/products.go:269 pkg/quote.go:837 pkg/invoices.go:885
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripción"
|
msgstr "Descripción"
|
||||||
|
|
||||||
#: pkg/products.go:274 pkg/quote.go:819 pkg/invoices.go:869
|
#: pkg/products.go:274 pkg/quote.go:841 pkg/invoices.go:889
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Price"
|
msgid "Price"
|
||||||
msgstr "Precio"
|
msgstr "Precio"
|
||||||
|
|
||||||
#: pkg/products.go:284 pkg/quote.go:848 pkg/expenses.go:181 pkg/invoices.go:898
|
#: pkg/products.go:284 pkg/quote.go:870 pkg/expenses.go:167 pkg/invoices.go:918
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Taxes"
|
msgid "Taxes"
|
||||||
msgstr "Impuestos"
|
msgstr "Impuestos"
|
||||||
|
|
||||||
#: pkg/products.go:309 pkg/quote.go:897 pkg/profile.go:92 pkg/invoices.go:947
|
#: pkg/products.go:309 pkg/quote.go:919 pkg/profile.go:92 pkg/invoices.go:967
|
||||||
msgid "Name can not be empty."
|
msgid "Name can not be empty."
|
||||||
msgstr "No podéis dejar el nombre en blanco."
|
msgstr "No podéis dejar el nombre en blanco."
|
||||||
|
|
||||||
#: pkg/products.go:310 pkg/quote.go:898 pkg/invoices.go:948
|
#: pkg/products.go:310 pkg/quote.go:920 pkg/invoices.go:968
|
||||||
msgid "Price can not be empty."
|
msgid "Price can not be empty."
|
||||||
msgstr "No podéis dejar el precio en blanco."
|
msgstr "No podéis dejar el precio en blanco."
|
||||||
|
|
||||||
#: pkg/products.go:311 pkg/quote.go:899 pkg/invoices.go:949
|
#: pkg/products.go:311 pkg/quote.go:921 pkg/invoices.go:969
|
||||||
msgid "Price must be a number greater than zero."
|
msgid "Price must be a number greater than zero."
|
||||||
msgstr "El precio tiene que ser un número mayor a cero."
|
msgstr "El precio tiene que ser un número mayor a cero."
|
||||||
|
|
||||||
#: pkg/products.go:313 pkg/quote.go:907 pkg/expenses.go:227 pkg/expenses.go:232
|
#: pkg/products.go:313 pkg/quote.go:929 pkg/expenses.go:213 pkg/expenses.go:218
|
||||||
#: pkg/invoices.go:957
|
#: pkg/invoices.go:977
|
||||||
msgid "Selected tax is not valid."
|
msgid "Selected tax is not valid."
|
||||||
msgstr "Habéis escogido un impuesto que no es válido."
|
msgstr "Habéis escogido un impuesto que no es válido."
|
||||||
|
|
||||||
#: pkg/products.go:314 pkg/quote.go:908 pkg/expenses.go:228 pkg/expenses.go:233
|
#: pkg/products.go:314 pkg/quote.go:930 pkg/expenses.go:214 pkg/expenses.go:219
|
||||||
#: pkg/invoices.go:958
|
#: pkg/invoices.go:978
|
||||||
msgid "You can only select a tax of each class."
|
msgid "You can only select a tax of each class."
|
||||||
msgstr "Solo podéis escoger un impuesto de cada clase."
|
msgstr "Solo podéis escoger un impuesto de cada clase."
|
||||||
|
|
||||||
|
@ -847,141 +856,141 @@ msgstr "No podéis dejar el nombre del método de pago en blanco."
|
||||||
msgid "Payment instructions can not be empty."
|
msgid "Payment instructions can not be empty."
|
||||||
msgstr "No podéis dejar las instrucciones de pago en blanco."
|
msgstr "No podéis dejar las instrucciones de pago en blanco."
|
||||||
|
|
||||||
#: pkg/quote.go:148 pkg/quote.go:609 pkg/expenses.go:164 pkg/expenses.go:340
|
#: pkg/quote.go:147 pkg/quote.go:608 pkg/expenses.go:150 pkg/expenses.go:326
|
||||||
#: pkg/invoices.go:147 pkg/invoices.go:606
|
#: pkg/invoices.go:147 pkg/invoices.go:606
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Contact"
|
msgid "Contact"
|
||||||
msgstr "Contacto"
|
msgstr "Contacto"
|
||||||
|
|
||||||
#: pkg/quote.go:162 pkg/expenses.go:341 pkg/invoices.go:163
|
#: pkg/quote.go:148 pkg/invoices.go:148
|
||||||
msgid "All customers"
|
msgid "All customers"
|
||||||
msgstr "Todos los clientes"
|
msgstr "Todos los clientes"
|
||||||
|
|
||||||
#: pkg/quote.go:167 pkg/quote.go:580
|
#: pkg/quote.go:153 pkg/quote.go:602
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Quotation Status"
|
msgid "Quotation Status"
|
||||||
msgstr "Estado del presupuesto"
|
msgstr "Estado del presupuesto"
|
||||||
|
|
||||||
#: pkg/quote.go:168 pkg/invoices.go:169
|
#: pkg/quote.go:154 pkg/invoices.go:154
|
||||||
msgid "All status"
|
msgid "All status"
|
||||||
msgstr "Todos los estados"
|
msgstr "Todos los estados"
|
||||||
|
|
||||||
#: pkg/quote.go:173
|
#: pkg/quote.go:159
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Quotation Number"
|
msgid "Quotation Number"
|
||||||
msgstr "Número de presupuesto"
|
msgstr "Número de presupuesto"
|
||||||
|
|
||||||
#: pkg/quote.go:178 pkg/expenses.go:351 pkg/invoices.go:179
|
#: pkg/quote.go:164 pkg/expenses.go:337 pkg/invoices.go:164
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "From Date"
|
msgid "From Date"
|
||||||
msgstr "A partir de la fecha"
|
msgstr "A partir de la fecha"
|
||||||
|
|
||||||
#: pkg/quote.go:183 pkg/expenses.go:356 pkg/invoices.go:184
|
#: pkg/quote.go:169 pkg/expenses.go:342 pkg/invoices.go:169
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "To Date"
|
msgid "To Date"
|
||||||
msgstr "Hasta la fecha"
|
msgstr "Hasta la fecha"
|
||||||
|
|
||||||
#: pkg/quote.go:197
|
#: pkg/quote.go:183
|
||||||
msgid "Quotations must have all the specified labels."
|
msgid "Quotations must have all the specified labels."
|
||||||
msgstr "Los presupuestos deben tener todas las etiquetas."
|
msgstr "Los presupuestos deben tener todas las etiquetas."
|
||||||
|
|
||||||
#: pkg/quote.go:202
|
#: pkg/quote.go:188
|
||||||
msgid "Quotations must have at least one of the specified labels."
|
msgid "Quotations must have at least one of the specified labels."
|
||||||
msgstr "Los presupuestos deben tener como mínimo una de las etiquetas."
|
msgstr "Los presupuestos deben tener como mínimo una de las etiquetas."
|
||||||
|
|
||||||
#: pkg/quote.go:528
|
#: pkg/quote.go:550
|
||||||
msgid "quotations.zip"
|
msgid "quotations.zip"
|
||||||
msgstr "presupuestos.zip"
|
msgstr "presupuestos.zip"
|
||||||
|
|
||||||
#: pkg/quote.go:534 pkg/quote.go:1063 pkg/quote.go:1071 pkg/invoices.go:535
|
#: pkg/quote.go:556 pkg/quote.go:1085 pkg/quote.go:1093 pkg/invoices.go:555
|
||||||
#: pkg/invoices.go:1125 pkg/invoices.go:1133
|
#: pkg/invoices.go:1145 pkg/invoices.go:1153
|
||||||
msgid "Invalid action"
|
msgid "Invalid action"
|
||||||
msgstr "Acción inválida."
|
msgstr "Acción inválida."
|
||||||
|
|
||||||
#: pkg/quote.go:587
|
#: pkg/quote.go:609
|
||||||
msgid "Select a customer to quote."
|
msgid "Select a customer to quote."
|
||||||
msgstr "Escoged un cliente a presupuestar."
|
msgstr "Escoged un cliente a presupuestar."
|
||||||
|
|
||||||
#: pkg/quote.go:592
|
#: pkg/quote.go:614
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Quotation Date"
|
msgid "Quotation Date"
|
||||||
msgstr "Fecha del presupuesto"
|
msgstr "Fecha del presupuesto"
|
||||||
|
|
||||||
#: pkg/quote.go:598
|
#: pkg/quote.go:620
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Terms and conditions"
|
msgid "Terms and conditions"
|
||||||
msgstr "Condiciones de aceptación"
|
msgstr "Condiciones de aceptación"
|
||||||
|
|
||||||
#: pkg/quote.go:603 pkg/invoices.go:598
|
#: pkg/quote.go:625 pkg/invoices.go:618
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Notes"
|
msgid "Notes"
|
||||||
msgstr "Notas"
|
msgstr "Notas"
|
||||||
|
|
||||||
#: pkg/quote.go:612 pkg/invoices.go:608
|
#: pkg/quote.go:634 pkg/invoices.go:628
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Payment Method"
|
msgid "Payment Method"
|
||||||
msgstr "Método de pago"
|
msgstr "Método de pago"
|
||||||
|
|
||||||
#: pkg/quote.go:613
|
#: pkg/quote.go:635
|
||||||
msgid "Select a payment method."
|
msgid "Select a payment method."
|
||||||
msgstr "Escoged un método e pago."
|
msgstr "Escoged un método e pago."
|
||||||
|
|
||||||
#: pkg/quote.go:649
|
#: pkg/quote.go:671
|
||||||
msgid "Selected quotation status is not valid."
|
msgid "Selected quotation status is not valid."
|
||||||
msgstr "Habéis escogido un estado de presupuesto que no es válido."
|
msgstr "Habéis escogido un estado de presupuesto que no es válido."
|
||||||
|
|
||||||
#: pkg/quote.go:651 pkg/invoices.go:645
|
#: pkg/quote.go:673 pkg/invoices.go:665
|
||||||
msgid "Selected customer is not valid."
|
msgid "Selected customer is not valid."
|
||||||
msgstr "Habéis escogido un cliente que no es válido."
|
msgstr "Habéis escogido un cliente que no es válido."
|
||||||
|
|
||||||
#: pkg/quote.go:653
|
#: pkg/quote.go:675
|
||||||
msgid "Quotation date can not be empty."
|
msgid "Quotation date can not be empty."
|
||||||
msgstr "No podéis dejar la fecha del presupuesto en blanco."
|
msgstr "No podéis dejar la fecha del presupuesto en blanco."
|
||||||
|
|
||||||
#: pkg/quote.go:654
|
#: pkg/quote.go:676
|
||||||
msgid "Quotation date must be a valid date."
|
msgid "Quotation date must be a valid date."
|
||||||
msgstr "La fecha de presupuesto debe ser válida."
|
msgstr "La fecha de presupuesto debe ser válida."
|
||||||
|
|
||||||
#: pkg/quote.go:657 pkg/invoices.go:649
|
#: pkg/quote.go:679 pkg/invoices.go:669
|
||||||
msgid "Selected payment method is not valid."
|
msgid "Selected payment method is not valid."
|
||||||
msgstr "Habéis escogido un método de pago que no es válido."
|
msgstr "Habéis escogido un método de pago que no es válido."
|
||||||
|
|
||||||
#: pkg/quote.go:791 pkg/quote.go:796 pkg/invoices.go:841 pkg/invoices.go:846
|
#: pkg/quote.go:813 pkg/quote.go:818 pkg/invoices.go:861 pkg/invoices.go:866
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr "Identificador"
|
msgstr "Identificador"
|
||||||
|
|
||||||
#: pkg/quote.go:829 pkg/invoices.go:879
|
#: pkg/quote.go:851 pkg/invoices.go:899
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Quantity"
|
msgid "Quantity"
|
||||||
msgstr "Cantidad"
|
msgstr "Cantidad"
|
||||||
|
|
||||||
#: pkg/quote.go:838 pkg/invoices.go:888
|
#: pkg/quote.go:860 pkg/invoices.go:908
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Discount (%)"
|
msgid "Discount (%)"
|
||||||
msgstr "Descuento (%)"
|
msgstr "Descuento (%)"
|
||||||
|
|
||||||
#: pkg/quote.go:892
|
#: pkg/quote.go:914
|
||||||
msgid "Quotation product ID must be a number greater than zero."
|
msgid "Quotation product ID must be a number greater than zero."
|
||||||
msgstr "El ID de producto de presupuesto tiene que ser un número mayor a cero."
|
msgstr "El ID de producto de presupuesto tiene que ser un número mayor a cero."
|
||||||
|
|
||||||
#: pkg/quote.go:895 pkg/invoices.go:945
|
#: pkg/quote.go:917 pkg/invoices.go:965
|
||||||
msgid "Product ID must be a positive number or zero."
|
msgid "Product ID must be a positive number or zero."
|
||||||
msgstr "El ID de producto tiene que ser un número positivo o cero."
|
msgstr "El ID de producto tiene que ser un número positivo o cero."
|
||||||
|
|
||||||
#: pkg/quote.go:901 pkg/invoices.go:951
|
#: pkg/quote.go:923 pkg/invoices.go:971
|
||||||
msgid "Quantity can not be empty."
|
msgid "Quantity can not be empty."
|
||||||
msgstr "No podéis dejar la cantidad en blanco."
|
msgstr "No podéis dejar la cantidad en blanco."
|
||||||
|
|
||||||
#: pkg/quote.go:902 pkg/invoices.go:952
|
#: pkg/quote.go:924 pkg/invoices.go:972
|
||||||
msgid "Quantity must be a number greater than zero."
|
msgid "Quantity must be a number greater than zero."
|
||||||
msgstr "La cantidad tiene que ser un número mayor a cero."
|
msgstr "La cantidad tiene que ser un número mayor a cero."
|
||||||
|
|
||||||
#: pkg/quote.go:904 pkg/invoices.go:954
|
#: pkg/quote.go:926 pkg/invoices.go:974
|
||||||
msgid "Discount can not be empty."
|
msgid "Discount can not be empty."
|
||||||
msgstr "No podéis dejar el descuento en blanco."
|
msgstr "No podéis dejar el descuento en blanco."
|
||||||
|
|
||||||
#: pkg/quote.go:905 pkg/invoices.go:955
|
#: pkg/quote.go:927 pkg/invoices.go:975
|
||||||
msgid "Discount must be a percentage between 0 and 100."
|
msgid "Discount must be a percentage between 0 and 100."
|
||||||
msgstr "El descuento tiene que ser un porcentaje entre 0 y 100."
|
msgstr "El descuento tiene que ser un porcentaje entre 0 y 100."
|
||||||
|
|
||||||
|
@ -1048,87 +1057,87 @@ msgctxt "period option"
|
||||||
msgid "Previous year"
|
msgid "Previous year"
|
||||||
msgstr "Año anterior"
|
msgstr "Año anterior"
|
||||||
|
|
||||||
#: pkg/expenses.go:129
|
#: pkg/expenses.go:115
|
||||||
msgid "Select a contact."
|
msgid "Select a contact."
|
||||||
msgstr "Escoged un contacto"
|
msgstr "Escoged un contacto"
|
||||||
|
|
||||||
#: pkg/expenses.go:170
|
#: pkg/expenses.go:156
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Invoice number"
|
msgid "Invoice number"
|
||||||
msgstr "Número de factura"
|
msgstr "Número de factura"
|
||||||
|
|
||||||
#: pkg/expenses.go:175 pkg/invoices.go:592
|
#: pkg/expenses.go:161 pkg/invoices.go:612
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Invoice Date"
|
msgid "Invoice Date"
|
||||||
msgstr "Fecha de factura"
|
msgstr "Fecha de factura"
|
||||||
|
|
||||||
#: pkg/expenses.go:187
|
#: pkg/expenses.go:173
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Amount"
|
msgid "Amount"
|
||||||
msgstr "Importe"
|
msgstr "Importe"
|
||||||
|
|
||||||
#: pkg/expenses.go:197
|
#: pkg/expenses.go:183
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "File"
|
msgid "File"
|
||||||
msgstr "Archivo"
|
msgstr "Archivo"
|
||||||
|
|
||||||
#: pkg/expenses.go:225
|
#: pkg/expenses.go:211
|
||||||
msgid "Selected contact is not valid."
|
msgid "Selected contact is not valid."
|
||||||
msgstr "Habéis escogido un contacto que no es válido."
|
msgstr "Habéis escogido un contacto que no es válido."
|
||||||
|
|
||||||
#: pkg/expenses.go:226 pkg/invoices.go:647
|
#: pkg/expenses.go:212 pkg/invoices.go:667
|
||||||
msgid "Invoice date must be a valid date."
|
msgid "Invoice date must be a valid date."
|
||||||
msgstr "La fecha de factura debe ser válida."
|
msgstr "La fecha de factura debe ser válida."
|
||||||
|
|
||||||
#: pkg/expenses.go:229
|
#: pkg/expenses.go:215
|
||||||
msgid "Amount can not be empty."
|
msgid "Amount can not be empty."
|
||||||
msgstr "No podéis dejar el importe en blanco."
|
msgstr "No podéis dejar el importe en blanco."
|
||||||
|
|
||||||
#: pkg/expenses.go:230
|
#: pkg/expenses.go:216
|
||||||
msgid "Amount must be a number greater than zero."
|
msgid "Amount must be a number greater than zero."
|
||||||
msgstr "El importe tiene que ser un número mayor a cero."
|
msgstr "El importe tiene que ser un número mayor a cero."
|
||||||
|
|
||||||
#: pkg/expenses.go:341
|
#: pkg/expenses.go:327
|
||||||
msgid "All contacts"
|
msgid "All contacts"
|
||||||
msgstr "Todos los contactos"
|
msgstr "Todos los contactos"
|
||||||
|
|
||||||
#: pkg/expenses.go:346 pkg/invoices.go:159
|
#: pkg/expenses.go:332 pkg/invoices.go:159
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Invoice Number"
|
msgid "Invoice Number"
|
||||||
msgstr "Número de factura"
|
msgstr "Número de factura"
|
||||||
|
|
||||||
#: pkg/invoices.go:168 pkg/invoices.go:580
|
#: pkg/invoices.go:153 pkg/invoices.go:600
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Invoice Status"
|
msgid "Invoice Status"
|
||||||
msgstr "Estado de la factura"
|
msgstr "Estado de la factura"
|
||||||
|
|
||||||
#: pkg/invoices.go:428
|
#: pkg/invoices.go:448
|
||||||
msgid "Select a customer to bill."
|
msgid "Select a customer to bill."
|
||||||
msgstr "Escoged un cliente a facturar."
|
msgstr "Escoged un cliente a facturar."
|
||||||
|
|
||||||
#: pkg/invoices.go:529
|
#: pkg/invoices.go:549
|
||||||
msgid "invoices.zip"
|
msgid "invoices.zip"
|
||||||
msgstr "facturas.zip"
|
msgstr "facturas.zip"
|
||||||
|
|
||||||
#: pkg/invoices.go:644
|
#: pkg/invoices.go:664
|
||||||
msgid "Selected invoice status is not valid."
|
msgid "Selected invoice status is not valid."
|
||||||
msgstr "Habéis escogido un estado de factura que no es válido."
|
msgstr "Habéis escogido un estado de factura que no es válido."
|
||||||
|
|
||||||
#: pkg/invoices.go:646
|
#: pkg/invoices.go:666
|
||||||
msgid "Invoice date can not be empty."
|
msgid "Invoice date can not be empty."
|
||||||
msgstr "No podéis dejar la fecha de la factura en blanco."
|
msgstr "No podéis dejar la fecha de la factura en blanco."
|
||||||
|
|
||||||
#: pkg/invoices.go:782
|
#: pkg/invoices.go:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Re: quotation #%s of %s"
|
msgid "Re: quotation #%s of %s"
|
||||||
msgstr "Ref: presupuesto n.º %s del %s"
|
msgstr "Ref: presupuesto n.º %s del %s"
|
||||||
|
|
||||||
#: pkg/invoices.go:783
|
#: pkg/invoices.go:803
|
||||||
msgctxt "to_char"
|
msgctxt "to_char"
|
||||||
msgid "MM/DD/YYYY"
|
msgid "MM/DD/YYYY"
|
||||||
msgstr "DD/MM/YYYY"
|
msgstr "DD/MM/YYYY"
|
||||||
|
|
||||||
#: pkg/invoices.go:942
|
#: pkg/invoices.go:962
|
||||||
msgid "Invoice product ID must be a number greater than zero."
|
msgid "Invoice product ID must be a number greater than zero."
|
||||||
msgstr "El ID de producto de factura tiene que ser un número mayor a cero."
|
msgstr "El ID de producto de factura tiene que ser un número mayor a cero."
|
||||||
|
|
||||||
|
@ -1234,10 +1243,6 @@ msgstr "No podéis dejar el código postal en blanco."
|
||||||
msgid "This value is not a valid postal code."
|
msgid "This value is not a valid postal code."
|
||||||
msgstr "Este valor no es un código postal válido válido."
|
msgstr "Este valor no es un código postal válido válido."
|
||||||
|
|
||||||
#~ msgctxt "title"
|
|
||||||
#~ msgid "Customer"
|
|
||||||
#~ msgstr "Cliente"
|
|
||||||
|
|
||||||
#~ msgctxt "input"
|
#~ msgctxt "input"
|
||||||
#~ msgid "Customer"
|
#~ msgid "Customer"
|
||||||
#~ msgstr "Cliente"
|
#~ msgstr "Cliente"
|
||||||
|
|
|
@ -263,6 +263,10 @@ tbody tr:nth-child(even) {
|
||||||
background-color: var(--numerus--header--background-color);
|
background-color: var(--numerus--header--background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tfoot th {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
div[role="alert"].error {
|
div[role="alert"].error {
|
||||||
padding: 1.25em;
|
padding: 1.25em;
|
||||||
background-color: var(--numerus--color--red);
|
background-color: var(--numerus--color--red);
|
||||||
|
|
|
@ -99,5 +99,14 @@
|
||||||
</tr>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
{{ if .Expenses }}
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th scope="row" colspan="5">{{( gettext "Total" )}}</th>
|
||||||
|
<td class="numeric">{{ .TotalAmount|formatPrice }}</td>
|
||||||
|
<td colspan="2"></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
{{ end }}
|
||||||
</table>
|
</table>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
@ -138,5 +138,14 @@
|
||||||
</tr>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
{{ if .Invoices }}
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th scope="row" colspan="6">{{( gettext "Total" )}}</th>
|
||||||
|
<td class="numeric">{{ .TotalAmount|formatPrice }}</td>
|
||||||
|
<td colspan="2"></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
{{ end }}
|
||||||
</table>
|
</table>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
@ -103,9 +103,9 @@
|
||||||
</td>
|
</td>
|
||||||
<td class="numeric">{{ .Total|formatPrice }}</td>
|
<td class="numeric">{{ .Total|formatPrice }}</td>
|
||||||
<td class="quote-download"><a href="{{ companyURI "/quotes/"}}{{ .Slug }}.pdf"
|
<td class="quote-download"><a href="{{ companyURI "/quotes/"}}{{ .Slug }}.pdf"
|
||||||
download="{{ .Number}}.pdf"
|
download="{{ .Number}}.pdf"
|
||||||
title="{{( pgettext "Download quotation" "action" )}}"
|
title="{{( pgettext "Download quotation" "action" )}}"
|
||||||
aria-label="{{( pgettext "Download quotation" "action" )}}"><i
|
aria-label="{{( pgettext "Download quotation" "action" )}}"><i
|
||||||
class="ri-download-line"></i></a></td>
|
class="ri-download-line"></i></a></td>
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
<details class="menu">
|
<details class="menu">
|
||||||
|
@ -146,5 +146,14 @@
|
||||||
</tr>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
{{ if .Quotes }}
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th scope="row" colspan="6">{{( gettext "Total" )}}</th>
|
||||||
|
<td class="numeric">{{ .TotalAmount|formatPrice }}</td>
|
||||||
|
<td colspan="2"></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
{{ end }}
|
||||||
</table>
|
</table>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
Loading…
Reference in New Issue