Add option to export the list of quotes, invoices, and expenses to ODS

This was requested by a potential user, as they want to be able to do
whatever they want to do to these lists with a spreadsheet.

In fact, they requested to be able to export to CSV, but, as always,
using CSV is a minefield because of Microsoft: since their Excel product
is fucking unable to write and read CSV from different locales, even if
using the same exact Excel product, i can not also create a CSV file
that is guaranteed to work on all locales.  If i used the non-standard
sep=; thing to tell Excel that it is a fucking stupid application, then
proper applications would show that line as a row, which is the correct
albeit undesirable behaviour.

The solution is to use a spreadsheet file format that does not have this
issue.  As far as I know, by default Excel is able to read XLSX and ODS
files, but i refuse to use the artificially complex, not the actually
used in Excel, and lobbied standard that Microsoft somehow convinced ISO
to publish, as i am using a different format because of the mess they
made, and i do not want to bend over in front of them, so ODS it is.

ODS is neither an elegant or good format by any means, but at least i
can write them using simple strings, because there is no ODS library
in Debian and i am not going to write yet another DEB package for an
overengineered package to write a simple table—all i want is to say
“here are these n columns, and these m columns; have a good day!”.

Part of #51.
This commit is contained in:
jordi fita mas 2023-07-18 13:29:36 +02:00
parent 835e52dbcb
commit 0c4ef97dff
10 changed files with 683 additions and 336 deletions

View File

@ -593,6 +593,10 @@ func ServeExpenseAttachment(w http.ResponseWriter, r *http.Request, params httpr
func HandleEditExpenseAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) { func HandleEditExpenseAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
slug := params[0].Value slug := params[0].Value
switch slug {
case "batch":
HandleBatchExpenseAction(w, r, params)
default:
if !ValidUuid(slug) { if !ValidUuid(slug) {
http.NotFound(w, r) http.NotFound(w, r)
return return
@ -601,6 +605,7 @@ func HandleEditExpenseAction(w http.ResponseWriter, r *http.Request, params http
handleExpenseAction(w, r, actionUri, func(w http.ResponseWriter, r *http.Request, form *expenseForm) { handleExpenseAction(w, r, actionUri, func(w http.ResponseWriter, r *http.Request, form *expenseForm) {
mustRenderEditExpenseForm(w, r, slug, form) mustRenderEditExpenseForm(w, r, slug, form)
}) })
}
} }
func HandleNewExpenseAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) { func HandleNewExpenseAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
@ -646,3 +651,29 @@ func handleExpenseAction(w http.ResponseWriter, r *http.Request, action string,
http.Error(w, gettext("Invalid action", locale), http.StatusBadRequest) http.Error(w, gettext("Invalid action", locale), http.StatusBadRequest)
} }
} }
func HandleBatchExpenseAction(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if err := verifyCsrfTokenValid(r); err != nil {
http.Error(w, err.Error(), http.StatusForbidden)
return
}
locale := getLocale(r)
switch r.Form.Get("action") {
case "export":
conn := getConn(r)
company := getCompany(r)
filters := newExpenseFilterForm(r.Context(), conn, locale, company)
if err := filters.Parse(r); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ods := mustWriteExpensesOds(mustCollectExpenseEntries(r.Context(), conn, locale, filters), locale, company)
writeOdsResponse(w, ods, gettext("expenses.ods", locale))
default:
http.Error(w, gettext("Invalid action", locale), http.StatusBadRequest)
}
}

View File

@ -428,6 +428,10 @@ func (field *ToggleField) FillValue(r *http.Request) {
} }
} }
func (field *ToggleField) String() string {
return field.Selected
}
type FormValidator struct { type FormValidator struct {
Valid bool Valid bool
} }

View File

@ -648,14 +648,14 @@ func HandleBatchInvoiceAction(w http.ResponseWriter, r *http.Request, _ httprout
http.Error(w, err.Error(), http.StatusForbidden) http.Error(w, err.Error(), http.StatusForbidden)
return return
} }
locale := getLocale(r)
switch r.Form.Get("action") {
case "download":
slugs := r.Form["invoice"] slugs := r.Form["invoice"]
if len(slugs) == 0 { if len(slugs) == 0 {
http.Redirect(w, r, companyURI(mustGetCompany(r), "/invoices"), http.StatusSeeOther) http.Redirect(w, r, companyURI(mustGetCompany(r), "/invoices"), http.StatusSeeOther)
return return
} }
locale := getLocale(r)
switch r.Form.Get("action") {
case "download":
invoices := mustWriteInvoicesPdf(r, slugs) invoices := mustWriteInvoicesPdf(r, slugs)
w.Header().Set("Content-Type", "application/zip") w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", gettext("invoices.zip", locale))) w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", gettext("invoices.zip", locale)))
@ -663,6 +663,16 @@ func HandleBatchInvoiceAction(w http.ResponseWriter, r *http.Request, _ httprout
if _, err := w.Write(invoices); err != nil { if _, err := w.Write(invoices); err != nil {
panic(err) panic(err)
} }
case "export":
conn := getConn(r)
company := getCompany(r)
filters := newInvoiceFilterForm(r.Context(), conn, locale, company)
if err := filters.Parse(r); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ods := mustWriteInvoicesOds(mustCollectInvoiceEntries(r.Context(), conn, locale, filters), locale, company)
writeOdsResponse(w, ods, gettext("invoices.ods", locale))
default: default:
http.Error(w, gettext("Invalid action", locale), http.StatusBadRequest) http.Error(w, gettext("Invalid action", locale), http.StatusBadRequest)
} }

213
pkg/ods.go Normal file
View File

@ -0,0 +1,213 @@
package pkg
import (
"archive/zip"
"bytes"
"encoding/xml"
"fmt"
"net/http"
"strings"
"time"
)
const (
mimetype = "application/vnd.oasis.opendocument.spreadsheet"
metaDashInfManifestXml = `<?xml version="1.0" encoding="UTF-8"?>
<manifest:manifest
xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"
manifest:version="1.3">
<manifest:file-entry manifest:full-path="/" manifest:version="1.3" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>
<manifest:file-entry manifest:full-path="meta.xml" manifest:media-type="text/xml"/>
<manifest:file-entry manifest:full-path="styles.xml" manifest:media-type="text/xml"/>
<manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/>
</manifest:manifest>
`
metaXml = `<?xml version="1.0" encoding="UTF-8"?>
<office:document-meta
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
office:version="1.3">
<office:meta>
<meta:creation-date></meta:creation-date>
<meta:generator>Numerus</meta:generator>
</office:meta>
</office:document-meta>
`
stylesXml = `<?xml version="1.0" encoding="UTF-8"?>
<office:document-styles
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
office:version="1.3">
</office:document-styles>
`
)
func mustWriteInvoicesOds(invoices []*InvoiceEntry, locale *Locale, company *Company) []byte {
columns := []string{
"Date",
"Invoice Num.",
"Customer",
"Status",
"Tags",
"Amount",
}
return mustWriteTableOds(invoices, columns, locale, func(sb *strings.Builder, invoice *InvoiceEntry) {
writeCellDate(sb, invoice.Date)
writeCellString(sb, invoice.Number)
writeCellString(sb, invoice.CustomerName)
writeCellString(sb, invoice.StatusLabel)
writeCellString(sb, strings.Join(invoice.Tags, ","))
writeCellFloat(sb, invoice.Total, locale, company)
})
}
func mustWriteQuotesOds(quotes []*QuoteEntry, locale *Locale, company *Company) []byte {
columns := []string{
"Date",
"Quotation Num.",
"Customer",
"Status",
"Tags",
"Amount",
}
return mustWriteTableOds(quotes, columns, locale, func(sb *strings.Builder, quote *QuoteEntry) {
writeCellDate(sb, quote.Date)
writeCellString(sb, quote.Number)
writeCellString(sb, quote.CustomerName)
writeCellString(sb, quote.StatusLabel)
writeCellString(sb, strings.Join(quote.Tags, ","))
writeCellFloat(sb, quote.Total, locale, company)
})
}
func mustWriteExpensesOds(expenses []*ExpenseEntry, locale *Locale, company *Company) []byte {
columns := []string{
"Contact",
"Invoice Date",
"Invoice Number",
"Status",
"Tags",
"Amount",
}
return mustWriteTableOds(expenses, columns, locale, func(sb *strings.Builder, expense *ExpenseEntry) {
writeCellString(sb, expense.InvoicerName)
writeCellDate(sb, expense.InvoiceDate)
writeCellString(sb, expense.InvoiceNumber)
writeCellString(sb, expense.StatusLabel)
writeCellString(sb, strings.Join(expense.Tags, ","))
writeCellFloat(sb, expense.Amount, locale, company)
})
}
func mustWriteTableOds[K interface{}](rows []*K, columns []string, locale *Locale, writeRow func(*strings.Builder, *K)) []byte {
var sb strings.Builder
sb.WriteString(`<?xml version="1.0" encoding="UTF-8"?>
<office:document-content
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
office:version="1.3">
<office:scripts/>
<office:font-face-decls>
<style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/>
</office:font-face-decls>
<office:automatic-styles>
<style:style style:name="co1" style:family="table-column">
<style:table-column-properties fo:break-before="auto" style:column-width="0.889in"/>
</style:style>
<style:style style:name="ro1" style:family="table-row">
<style:table-row-properties style:row-height="0.178in" fo:break-before="auto" style:use-optimal-row-height="true"/>
</style:style>
<style:style style:name="ta1" style:family="table" style:master-page-name="Default">
<style:table-properties table:display="true" style:writing-mode="lr-tb"/>
</style:style>
<number:date-style style:name="N37" number:automatic-order="true">
<number:day number:style="long"/>
<number:text>/</number:text>
<number:month number:style="long"/>
<number:text>/</number:text>
<number:year/>
</number:date-style>
<style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>
</office:automatic-styles>
<office:body>
<office:spreadsheet>
<table:calculation-settings table:automatic-find-labels="false" table:use-regular-expressions="false" table:use-wildcards="true"/>
<table:table table:name="Sheet1" table:style-name="ta1">
`)
sb.WriteString(fmt.Sprintf(" <table:table-column table:style-name=\"co1\" table:number-columns-repeated=\"%d\" table:default-cell-style-name=\"Default\"/>\n", len(columns)))
sb.WriteString(` <table:table-row table:style-name="ro1">
`)
for _, t := range columns {
writeCellString(&sb, locale.GetC(t, "title"))
}
sb.WriteString(" </table:table-row>\n")
for _, row := range rows {
sb.WriteString(" <table:table-row table:style-name=\"ro1\">\n")
writeRow(&sb, row)
sb.WriteString(" </table:table-row>\n")
}
sb.WriteString(` </table:table>
<table:named-expressions/>
</office:spreadsheet>
</office:body>
</office:document-content>
`)
return mustWriteOds(sb.String())
}
func mustWriteOds(content string) []byte {
buf := new(bytes.Buffer)
ods := zip.NewWriter(buf)
mustWriteOdsFile(ods, "mimetype", mimetype, zip.Store)
mustWriteOdsFile(ods, "META-INF/manifest.xml", metaDashInfManifestXml, zip.Deflate)
mustWriteOdsFile(ods, "meta.xml", metaXml, zip.Deflate)
mustWriteOdsFile(ods, "styles.xml", stylesXml, zip.Deflate)
mustWriteOdsFile(ods, "content.xml", content, zip.Deflate)
mustClose(ods)
return buf.Bytes()
}
func mustWriteOdsFile(ods *zip.Writer, name string, content string, method uint16) {
f, err := ods.CreateHeader(&zip.FileHeader{
Name: name,
Method: method,
Modified: time.Now(),
})
if err != nil {
panic(err)
}
if _, err = f.Write([]byte(content)); err != nil {
panic(err)
}
}
func writeCellString(sb *strings.Builder, s string) {
sb.WriteString(` <table:table-cell office:value-type="string" calcext:value-type="string"><text:p>`)
if err := xml.EscapeText(sb, []byte(s)); err != nil {
panic(err)
}
sb.WriteString("</text:p></table:table-cell>\n")
}
func writeCellDate(sb *strings.Builder, t time.Time) {
sb.WriteString(fmt.Sprintf(" <table:table-cell table:style-name=\"ce1\" office:value-type=\"date\" office:date-value=\"%s\" calcext:value-type=\"date\"><text:p>%s</text:p></table:table-cell>\n", t.Format("2006-01-02"), t.Format("02/01/06")))
}
func writeCellFloat(sb *strings.Builder, s string, locale *Locale, company *Company) {
sb.WriteString(fmt.Sprintf(" <table:table-cell office:value-type=\"float\" office:value=\"%s\" calcext:value-type=\"float\"><text:p>%s</text:p></table:table-cell>\n", s, formatPrice(s, locale.Language, "%.[1]*[2]f", company.DecimalDigits, "")))
}
func writeOdsResponse(w http.ResponseWriter, ods []byte, filename string) {
w.Header().Set("Content-Type", "application/vnd.oasis.opendocument.spreadsheet")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
w.WriteHeader(http.StatusOK)
if _, err := w.Write(ods); err != nil {
panic(err)
}
}

View File

@ -605,14 +605,14 @@ func HandleBatchQuoteAction(w http.ResponseWriter, r *http.Request, _ httprouter
http.Error(w, err.Error(), http.StatusForbidden) http.Error(w, err.Error(), http.StatusForbidden)
return return
} }
locale := getLocale(r)
switch r.Form.Get("action") {
case "download":
slugs := r.Form["quote"] slugs := r.Form["quote"]
if len(slugs) == 0 { if len(slugs) == 0 {
http.Redirect(w, r, companyURI(mustGetCompany(r), "/quotes"), http.StatusSeeOther) http.Redirect(w, r, companyURI(mustGetCompany(r), "/quotes"), http.StatusSeeOther)
return return
} }
locale := getLocale(r)
switch r.Form.Get("action") {
case "download":
quotes := mustWriteQuotesPdf(r, slugs) quotes := mustWriteQuotesPdf(r, slugs)
w.Header().Set("Content-Type", "application/zip") w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", gettext("quotations.zip", locale))) w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", gettext("quotations.zip", locale)))
@ -620,6 +620,16 @@ func HandleBatchQuoteAction(w http.ResponseWriter, r *http.Request, _ httprouter
if _, err := w.Write(quotes); err != nil { if _, err := w.Write(quotes); err != nil {
panic(err) panic(err)
} }
case "export":
conn := getConn(r)
company := getCompany(r)
filters := newQuoteFilterForm(r.Context(), conn, locale, company)
if err := filters.Parse(r); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ods := mustWriteQuotesOds(mustCollectQuoteEntries(r.Context(), conn, locale, filters), locale, company)
writeOdsResponse(w, ods, gettext("quotations.ods", locale))
default: default:
http.Error(w, gettext("Invalid action", locale), http.StatusBadRequest) http.Error(w, gettext("Invalid action", locale), http.StatusBadRequest)
} }

331
po/ca.po
View File

@ -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-07-16 20:50+0200\n" "POT-Creation-Date: 2023-07-18 13:12+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"
@ -126,117 +126,123 @@ msgctxt "action"
msgid "Save" msgid "Save"
msgstr "Desa" msgstr "Desa"
#: web/template/invoices/index.gohtml:19 #: web/template/invoices/index.gohtml:28
msgctxt "action" msgctxt "action"
msgid "Download invoices" msgid "Download invoices"
msgstr "Descarrega factures" msgstr "Descarrega factures"
#: web/template/invoices/index.gohtml:21 #: web/template/invoices/index.gohtml:31 web/template/quotes/index.gohtml:31
#: web/template/expenses/index.gohtml:29
msgctxt "action"
msgid "Export list"
msgstr "Exporta llistat"
#: web/template/invoices/index.gohtml:33
msgctxt "action" msgctxt "action"
msgid "New invoice" msgid "New invoice"
msgstr "Nova factura" msgstr "Nova factura"
#: web/template/invoices/index.gohtml:45 web/template/dashboard.gohtml:23 #: web/template/invoices/index.gohtml:57 web/template/dashboard.gohtml:23
#: web/template/quotes/index.gohtml:45 web/template/contacts/index.gohtml:38 #: web/template/quotes/index.gohtml:57 web/template/contacts/index.gohtml:38
#: web/template/expenses/index.gohtml:39 web/template/products/index.gohtml:36 #: web/template/expenses/index.gohtml:56 web/template/products/index.gohtml:36
msgctxt "action" msgctxt "action"
msgid "Filter" msgid "Filter"
msgstr "Filtra" msgstr "Filtra"
#: web/template/invoices/index.gohtml:48 web/template/quotes/index.gohtml:48 #: web/template/invoices/index.gohtml:60 web/template/quotes/index.gohtml:60
#: web/template/contacts/index.gohtml:41 web/template/expenses/index.gohtml:42 #: web/template/contacts/index.gohtml:41 web/template/expenses/index.gohtml:59
#: web/template/products/index.gohtml:39 #: web/template/products/index.gohtml:39
msgctxt "action" msgctxt "action"
msgid "Reset" msgid "Reset"
msgstr "Restableix" msgstr "Restableix"
#: web/template/invoices/index.gohtml:54 #: web/template/invoices/index.gohtml:66
msgctxt "invoice" msgctxt "invoice"
msgid "All" msgid "All"
msgstr "Totes" msgstr "Totes"
#: web/template/invoices/index.gohtml:55 web/template/invoices/view.gohtml:38 #: web/template/invoices/index.gohtml:67 web/template/invoices/view.gohtml:38
#: web/template/quotes/index.gohtml:55 web/template/quotes/view.gohtml:37 #: web/template/quotes/index.gohtml:67 web/template/quotes/view.gohtml:37
msgctxt "title" msgctxt "title"
msgid "Date" msgid "Date"
msgstr "Data" msgstr "Data"
#: web/template/invoices/index.gohtml:56 #: web/template/invoices/index.gohtml:68
msgctxt "title" msgctxt "title"
msgid "Invoice Num." msgid "Invoice Num."
msgstr "Núm. factura" msgstr "Núm. factura"
#: web/template/invoices/index.gohtml:57 web/template/quotes/index.gohtml:57 #: web/template/invoices/index.gohtml:69 web/template/quotes/index.gohtml:69
msgctxt "title" msgctxt "title"
msgid "Customer" msgid "Customer"
msgstr "Client" msgstr "Client"
#: web/template/invoices/index.gohtml:58 web/template/quotes/index.gohtml:58 #: web/template/invoices/index.gohtml:70 web/template/quotes/index.gohtml:70
#: web/template/expenses/index.gohtml:51 #: web/template/expenses/index.gohtml:68
msgctxt "title" msgctxt "title"
msgid "Status" msgid "Status"
msgstr "Estat" msgstr "Estat"
#: web/template/invoices/index.gohtml:59 web/template/quotes/index.gohtml:59 #: web/template/invoices/index.gohtml:71 web/template/quotes/index.gohtml:71
#: web/template/contacts/index.gohtml:50 web/template/expenses/index.gohtml:52 #: web/template/contacts/index.gohtml:50 web/template/expenses/index.gohtml:69
#: web/template/products/index.gohtml:46 #: web/template/products/index.gohtml:46
msgctxt "title" msgctxt "title"
msgid "Tags" msgid "Tags"
msgstr "Etiquetes" msgstr "Etiquetes"
#: web/template/invoices/index.gohtml:60 web/template/quotes/index.gohtml:60 #: web/template/invoices/index.gohtml:72 web/template/quotes/index.gohtml:72
#: web/template/expenses/index.gohtml:53 #: web/template/expenses/index.gohtml:70
msgctxt "title" msgctxt "title"
msgid "Amount" msgid "Amount"
msgstr "Import" msgstr "Import"
#: web/template/invoices/index.gohtml:61 web/template/quotes/index.gohtml:61 #: web/template/invoices/index.gohtml:73 web/template/quotes/index.gohtml:73
#: web/template/expenses/index.gohtml:54 #: web/template/expenses/index.gohtml:71
msgctxt "title" msgctxt "title"
msgid "Download" msgid "Download"
msgstr "Descàrrega" msgstr "Descàrrega"
#: web/template/invoices/index.gohtml:62 web/template/quotes/index.gohtml:62 #: web/template/invoices/index.gohtml:74 web/template/quotes/index.gohtml:74
#: web/template/contacts/index.gohtml:51 web/template/expenses/index.gohtml:55 #: web/template/contacts/index.gohtml:51 web/template/expenses/index.gohtml:72
#: web/template/products/index.gohtml:48 #: web/template/products/index.gohtml:48
msgctxt "title" msgctxt "title"
msgid "Actions" msgid "Actions"
msgstr "Accions" msgstr "Accions"
#: web/template/invoices/index.gohtml:69 #: web/template/invoices/index.gohtml:81
msgctxt "action" msgctxt "action"
msgid "Select invoice %v" msgid "Select invoice %v"
msgstr "Selecciona factura %v" msgstr "Selecciona factura %v"
#: web/template/invoices/index.gohtml:110 #: web/template/invoices/index.gohtml:122
msgctxt "action" msgctxt "action"
msgid "Download invoice %s" msgid "Download invoice %s"
msgstr "Descarrega factura %s" msgstr "Descarrega factura %s"
#: web/template/invoices/index.gohtml:118 #: web/template/invoices/index.gohtml:130
msgid "Actions for invoice %s" msgid "Actions for invoice %s"
msgstr "Accions per la factura %s" msgstr "Accions per la factura %s"
#: web/template/invoices/index.gohtml:126 web/template/invoices/view.gohtml:19 #: web/template/invoices/index.gohtml:138 web/template/invoices/view.gohtml:19
#: web/template/quotes/index.gohtml:125 web/template/quotes/view.gohtml:22 #: web/template/quotes/index.gohtml:137 web/template/quotes/view.gohtml:22
#: web/template/contacts/index.gohtml:82 web/template/expenses/index.gohtml:117 #: web/template/contacts/index.gohtml:82 web/template/expenses/index.gohtml:134
#: web/template/products/index.gohtml:78 #: web/template/products/index.gohtml:78
msgctxt "action" msgctxt "action"
msgid "Edit" msgid "Edit"
msgstr "Edita" msgstr "Edita"
#: web/template/invoices/index.gohtml:134 web/template/invoices/view.gohtml:16 #: web/template/invoices/index.gohtml:146 web/template/invoices/view.gohtml:16
#: web/template/quotes/index.gohtml:133 web/template/quotes/view.gohtml:19 #: web/template/quotes/index.gohtml:145 web/template/quotes/view.gohtml:19
msgctxt "action" msgctxt "action"
msgid "Duplicate" msgid "Duplicate"
msgstr "Duplica" msgstr "Duplica"
#: web/template/invoices/index.gohtml:144 #: web/template/invoices/index.gohtml:156
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:151 web/template/quotes/index.gohtml:158 #: web/template/invoices/index.gohtml:163 web/template/quotes/index.gohtml:170
#: web/template/expenses/index.gohtml:134 #: web/template/expenses/index.gohtml:151
msgid "Total" msgid "Total"
msgstr "Total" msgstr "Total"
@ -363,41 +369,41 @@ msgctxt "title"
msgid "New Quotation" msgid "New Quotation"
msgstr "Nou pressupost" msgstr "Nou pressupost"
#: web/template/quotes/index.gohtml:19 #: web/template/quotes/index.gohtml:28
msgctxt "action" msgctxt "action"
msgid "Download quotations" msgid "Download quotations"
msgstr "Descarrega pressuposts" msgstr "Descarrega pressuposts"
#: web/template/quotes/index.gohtml:21 #: web/template/quotes/index.gohtml:33
msgctxt "action" msgctxt "action"
msgid "New quotation" msgid "New quotation"
msgstr "Nou pressupost" msgstr "Nou pressupost"
#: web/template/quotes/index.gohtml:54 #: web/template/quotes/index.gohtml:66
msgctxt "quote" msgctxt "quote"
msgid "All" msgid "All"
msgstr "Tots" msgstr "Tots"
#: web/template/quotes/index.gohtml:56 #: web/template/quotes/index.gohtml:68
msgctxt "title" msgctxt "title"
msgid "Quotation Num." msgid "Quotation Num."
msgstr "Núm. pressupost" msgstr "Núm. pressupost"
#: web/template/quotes/index.gohtml:69 #: web/template/quotes/index.gohtml:81
msgctxt "action" msgctxt "action"
msgid "Select quotation %v" msgid "Select quotation %v"
msgstr "Selecciona pressupost %v" msgstr "Selecciona pressupost %v"
#: web/template/quotes/index.gohtml:117 #: web/template/quotes/index.gohtml:129
msgid "Actions for quote %s" msgid "Actions for quote %s"
msgstr "Accions pel pressupost %s" msgstr "Accions pel pressupost %s"
#: web/template/quotes/index.gohtml:141 web/template/quotes/view.gohtml:16 #: web/template/quotes/index.gohtml:153 web/template/quotes/view.gohtml:16
msgctxt "action" msgctxt "action"
msgid "Create invoice" msgid "Create invoice"
msgstr "Crea factura" msgstr "Crea factura"
#: web/template/quotes/index.gohtml:151 #: web/template/quotes/index.gohtml:163
msgid "No quotations added yet." msgid "No quotations added yet."
msgstr "No hi ha cap pressupost." msgstr "No hi ha cap pressupost."
@ -488,7 +494,7 @@ msgctxt "action"
msgid "New contact" msgid "New contact"
msgstr "Nou contacte" msgstr "Nou contacte"
#: web/template/contacts/index.gohtml:47 web/template/expenses/index.gohtml:48 #: web/template/contacts/index.gohtml:47 web/template/expenses/index.gohtml:65
msgctxt "title" msgctxt "title"
msgid "Contact" msgid "Contact"
msgstr "Contacte" msgstr "Contacte"
@ -569,26 +575,26 @@ msgctxt "title"
msgid "Expenses" msgid "Expenses"
msgstr "Despeses" msgstr "Despeses"
#: web/template/expenses/index.gohtml:16 #: web/template/expenses/index.gohtml:32
msgctxt "action" msgctxt "action"
msgid "New expense" msgid "New expense"
msgstr "Nova despesa" msgstr "Nova despesa"
#: web/template/expenses/index.gohtml:49 #: web/template/expenses/index.gohtml:66
msgctxt "title" msgctxt "title"
msgid "Invoice Date" msgid "Invoice Date"
msgstr "Data de factura" msgstr "Data de factura"
#: web/template/expenses/index.gohtml:50 #: web/template/expenses/index.gohtml:67
msgctxt "title" msgctxt "title"
msgid "Invoice Number" msgid "Invoice Number"
msgstr "Número de factura" msgstr "Número de factura"
#: web/template/expenses/index.gohtml:109 #: web/template/expenses/index.gohtml:126
msgid "Actions for expense %s" msgid "Actions for expense %s"
msgstr "Accions per la despesa %s" msgstr "Accions per la despesa %s"
#: web/template/expenses/index.gohtml:127 #: web/template/expenses/index.gohtml:144
msgid "No expenses added yet." msgid "No expenses added yet."
msgstr "No hi ha cap despesa." msgstr "No hi ha cap despesa."
@ -695,7 +701,7 @@ msgctxt "title"
msgid "Edit Product “%s”" msgid "Edit Product “%s”"
msgstr "Edició del producte «%s»" msgstr "Edició del producte «%s»"
#: pkg/login.go:37 pkg/company.go:127 pkg/profile.go:40 pkg/contacts.go:267 #: pkg/login.go:37 pkg/company.go:127 pkg/profile.go:40 pkg/contacts.go:276
msgctxt "input" msgctxt "input"
msgid "Email" msgid "Email"
msgstr "Correu-e" msgstr "Correu-e"
@ -709,7 +715,7 @@ msgstr "Contrasenya"
msgid "Email can not be empty." msgid "Email can not be empty."
msgstr "No podeu deixar el correu-e en blanc." msgstr "No podeu deixar el correu-e en blanc."
#: pkg/login.go:71 pkg/company.go:284 pkg/profile.go:90 pkg/contacts.go:411 #: pkg/login.go:71 pkg/company.go:284 pkg/profile.go:90 pkg/contacts.go:420
msgid "This value is not a valid email. It should be like name@domain.com." 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." msgstr "Aquest valor no és un correu-e vàlid. Hauria de ser similar a nom@domini.cat."
@ -721,84 +727,84 @@ msgstr "No podeu deixar la contrasenya en blanc."
msgid "Invalid user or password." msgid "Invalid user or password."
msgstr "Nom dusuari o contrasenya incorrectes." msgstr "Nom dusuari o contrasenya incorrectes."
#: pkg/products.go:164 pkg/products.go:268 pkg/quote.go:887 #: pkg/products.go:172 pkg/products.go:276 pkg/quote.go:901
#: pkg/invoices.go:1002 pkg/contacts.go:140 pkg/contacts.go:253 #: pkg/invoices.go:1016 pkg/contacts.go:149 pkg/contacts.go:262
msgctxt "input" msgctxt "input"
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
#: pkg/products.go:169 pkg/products.go:295 pkg/quote.go:174 pkg/quote.go:694 #: pkg/products.go:177 pkg/products.go:303 pkg/quote.go:174 pkg/quote.go:708
#: pkg/expenses.go:274 pkg/expenses.go:433 pkg/invoices.go:174 #: pkg/expenses.go:278 pkg/expenses.go:442 pkg/invoices.go:174
#: pkg/invoices.go:732 pkg/invoices.go:1304 pkg/contacts.go:145 #: pkg/invoices.go:746 pkg/invoices.go:1331 pkg/contacts.go:154
#: pkg/contacts.go:353 #: pkg/contacts.go:362
msgctxt "input" msgctxt "input"
msgid "Tags" msgid "Tags"
msgstr "Etiquetes" msgstr "Etiquetes"
#: pkg/products.go:173 pkg/quote.go:178 pkg/expenses.go:443 pkg/invoices.go:178 #: pkg/products.go:181 pkg/quote.go:178 pkg/expenses.go:452 pkg/invoices.go:178
#: pkg/contacts.go:149 #: pkg/contacts.go:158
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:182 pkg/expenses.go:447 pkg/invoices.go:182 #: pkg/products.go:185 pkg/quote.go:182 pkg/expenses.go:456 pkg/invoices.go:182
#: pkg/contacts.go:153 #: pkg/contacts.go:162
msgctxt "tag condition" msgctxt "tag condition"
msgid "All" msgid "All"
msgstr "Totes" msgstr "Totes"
#: pkg/products.go:178 pkg/expenses.go:448 pkg/invoices.go:183 #: pkg/products.go:186 pkg/expenses.go:457 pkg/invoices.go:183
#: pkg/contacts.go:154 #: pkg/contacts.go:163
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:187 pkg/expenses.go:452 pkg/invoices.go:187 #: pkg/products.go:190 pkg/quote.go:187 pkg/expenses.go:461 pkg/invoices.go:187
#: pkg/contacts.go:158 #: pkg/contacts.go:167
msgctxt "tag condition" msgctxt "tag condition"
msgid "Any" msgid "Any"
msgstr "Qualsevol" msgstr "Qualsevol"
#: pkg/products.go:183 pkg/expenses.go:453 pkg/invoices.go:188 #: pkg/products.go:191 pkg/expenses.go:462 pkg/invoices.go:188
#: pkg/contacts.go:159 #: pkg/contacts.go:168
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:274 pkg/quote.go:901 pkg/invoices.go:1016 #: pkg/products.go:282 pkg/quote.go:915 pkg/invoices.go:1030
msgctxt "input" msgctxt "input"
msgid "Description" msgid "Description"
msgstr "Descripció" msgstr "Descripció"
#: pkg/products.go:279 pkg/quote.go:905 pkg/invoices.go:1020 #: pkg/products.go:287 pkg/quote.go:919 pkg/invoices.go:1034
msgctxt "input" msgctxt "input"
msgid "Price" msgid "Price"
msgstr "Preu" msgstr "Preu"
#: pkg/products.go:289 pkg/quote.go:934 pkg/expenses.go:242 #: pkg/products.go:297 pkg/quote.go:948 pkg/expenses.go:246
#: pkg/invoices.go:1049 #: pkg/invoices.go:1063
msgctxt "input" msgctxt "input"
msgid "Taxes" msgid "Taxes"
msgstr "Imposts" msgstr "Imposts"
#: pkg/products.go:314 pkg/quote.go:983 pkg/profile.go:92 pkg/invoices.go:1098 #: pkg/products.go:322 pkg/quote.go:997 pkg/profile.go:92 pkg/invoices.go:1112
#: pkg/contacts.go:403 #: pkg/contacts.go:412
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:315 pkg/quote.go:984 pkg/invoices.go:1099 #: pkg/products.go:323 pkg/quote.go:998 pkg/invoices.go:1113
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:316 pkg/quote.go:985 pkg/invoices.go:1100 #: pkg/products.go:324 pkg/quote.go:999 pkg/invoices.go:1114
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:318 pkg/quote.go:993 pkg/expenses.go:310 #: pkg/products.go:326 pkg/quote.go:1007 pkg/expenses.go:314
#: pkg/invoices.go:1108 #: pkg/invoices.go:1122
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:319 pkg/quote.go:994 pkg/expenses.go:311 #: pkg/products.go:327 pkg/quote.go:1008 pkg/expenses.go:315
#: pkg/invoices.go:1109 #: pkg/invoices.go:1123
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."
@ -807,47 +813,47 @@ msgctxt "input"
msgid "Trade name" msgid "Trade name"
msgstr "Nom comercial" msgstr "Nom comercial"
#: pkg/company.go:118 pkg/contacts.go:259 #: pkg/company.go:118 pkg/contacts.go:268
msgctxt "input" msgctxt "input"
msgid "Phone" msgid "Phone"
msgstr "Telèfon" msgstr "Telèfon"
#: pkg/company.go:136 pkg/contacts.go:275 #: pkg/company.go:136 pkg/contacts.go:284
msgctxt "input" msgctxt "input"
msgid "Web" msgid "Web"
msgstr "Web" msgstr "Web"
#: pkg/company.go:144 pkg/contacts.go:287 #: pkg/company.go:144 pkg/contacts.go:296
msgctxt "input" msgctxt "input"
msgid "Business name" msgid "Business name"
msgstr "Nom i cognoms" msgstr "Nom i cognoms"
#: pkg/company.go:154 pkg/contacts.go:297 #: pkg/company.go:154 pkg/contacts.go:306
msgctxt "input" msgctxt "input"
msgid "VAT number" msgid "VAT number"
msgstr "DNI / NIF" msgstr "DNI / NIF"
#: pkg/company.go:160 pkg/contacts.go:303 #: pkg/company.go:160 pkg/contacts.go:312
msgctxt "input" msgctxt "input"
msgid "Address" msgid "Address"
msgstr "Adreça" msgstr "Adreça"
#: pkg/company.go:169 pkg/contacts.go:312 #: pkg/company.go:169 pkg/contacts.go:321
msgctxt "input" msgctxt "input"
msgid "City" msgid "City"
msgstr "Població" msgstr "Població"
#: pkg/company.go:175 pkg/contacts.go:318 #: pkg/company.go:175 pkg/contacts.go:327
msgctxt "input" msgctxt "input"
msgid "Province" msgid "Province"
msgstr "Província" msgstr "Província"
#: pkg/company.go:181 pkg/contacts.go:324 #: pkg/company.go:181 pkg/contacts.go:333
msgctxt "input" msgctxt "input"
msgid "Postal code" msgid "Postal code"
msgstr "Codi postal" msgstr "Codi postal"
#: pkg/company.go:190 pkg/contacts.go:333 #: pkg/company.go:190 pkg/contacts.go:342
msgctxt "input" msgctxt "input"
msgid "Country" msgid "Country"
msgstr "País" msgstr "País"
@ -882,23 +888,23 @@ msgctxt "input"
msgid "Legal disclaimer" msgid "Legal disclaimer"
msgstr "Nota legal" msgstr "Nota legal"
#: pkg/company.go:271 pkg/contacts.go:385 #: pkg/company.go:271 pkg/contacts.go:394
msgid "Selected country is not valid." msgid "Selected country is not valid."
msgstr "Heu seleccionat un país que no és vàlid." msgstr "Heu seleccionat un país que no és vàlid."
#: pkg/company.go:275 pkg/contacts.go:388 #: pkg/company.go:275 pkg/contacts.go:397
msgid "Business name can not be empty." msgid "Business name can not be empty."
msgstr "No podeu deixar el nom i els cognoms en blanc." msgstr "No podeu deixar el nom i els cognoms en blanc."
#: pkg/company.go:276 pkg/contacts.go:389 #: pkg/company.go:276 pkg/contacts.go:398
msgid "Business name must have at least two letters." msgid "Business name must have at least two letters."
msgstr "Nom i cognoms han de tenir com a mínim dues lletres." msgstr "Nom i cognoms han de tenir com a mínim dues lletres."
#: pkg/company.go:277 pkg/contacts.go:391 #: pkg/company.go:277 pkg/contacts.go:400
msgid "VAT number can not be empty." msgid "VAT number can not be empty."
msgstr "No podeu deixar el DNI o NIF en blanc." msgstr "No podeu deixar el DNI o NIF en blanc."
#: pkg/company.go:278 pkg/contacts.go:392 #: pkg/company.go:278 pkg/contacts.go:401
msgid "This value is not a valid VAT number." msgid "This value is not a valid VAT number."
msgstr "Aquest valor no és un DNI o NIF vàlid." msgstr "Aquest valor no és un DNI o NIF vàlid."
@ -906,31 +912,31 @@ msgstr "Aquest valor no és un DNI o NIF vàlid."
msgid "Phone can not be empty." msgid "Phone can not be empty."
msgstr "No podeu deixar el telèfon en blanc." msgstr "No podeu deixar el telèfon en blanc."
#: pkg/company.go:281 pkg/contacts.go:408 #: pkg/company.go:281 pkg/contacts.go:417
msgid "This value is not a valid phone number." msgid "This value is not a valid phone number."
msgstr "Aquest valor no és un telèfon vàlid." msgstr "Aquest valor no és un telèfon vàlid."
#: pkg/company.go:287 pkg/contacts.go:414 #: pkg/company.go:287 pkg/contacts.go:423
msgid "This value is not a valid web address. It should be like https://domain.com/." 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/." 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:394 #: pkg/company.go:289 pkg/contacts.go:403
msgid "Address can not be empty." msgid "Address can not be empty."
msgstr "No podeu deixar ladreça en blanc." msgstr "No podeu deixar ladreça en blanc."
#: pkg/company.go:290 pkg/contacts.go:395 #: pkg/company.go:290 pkg/contacts.go:404
msgid "City can not be empty." msgid "City can not be empty."
msgstr "No podeu deixar la població en blanc." msgstr "No podeu deixar la població en blanc."
#: pkg/company.go:291 pkg/contacts.go:396 #: pkg/company.go:291 pkg/contacts.go:405
msgid "Province can not be empty." msgid "Province can not be empty."
msgstr "No podeu deixar la província en blanc." msgstr "No podeu deixar la província en blanc."
#: pkg/company.go:292 pkg/contacts.go:398 #: pkg/company.go:292 pkg/contacts.go:407
msgid "Postal code can not be empty." msgid "Postal code can not be empty."
msgstr "No podeu deixar el codi postal en blanc." msgstr "No podeu deixar el codi postal en blanc."
#: pkg/company.go:293 pkg/contacts.go:399 #: pkg/company.go:293 pkg/contacts.go:408
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."
@ -1007,7 +1013,7 @@ 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:147 pkg/quote.go:672 pkg/invoices.go:147 pkg/invoices.go:715 #: pkg/quote.go:147 pkg/quote.go:686 pkg/invoices.go:147 pkg/invoices.go:729
msgctxt "input" msgctxt "input"
msgid "Customer" msgid "Customer"
msgstr "Client" msgstr "Client"
@ -1016,12 +1022,12 @@ msgstr "Client"
msgid "All customers" msgid "All customers"
msgstr "Tots els clients" msgstr "Tots els clients"
#: pkg/quote.go:153 pkg/quote.go:666 #: pkg/quote.go:153 pkg/quote.go:680
msgctxt "input" msgctxt "input"
msgid "Quotation Status" msgid "Quotation Status"
msgstr "Estat del pressupost" msgstr "Estat del pressupost"
#: pkg/quote.go:154 pkg/expenses.go:438 pkg/invoices.go:154 #: pkg/quote.go:154 pkg/expenses.go:447 pkg/invoices.go:154
msgid "All status" msgid "All status"
msgstr "Tots els estats" msgstr "Tots els estats"
@ -1030,12 +1036,12 @@ msgctxt "input"
msgid "Quotation Number" msgid "Quotation Number"
msgstr "Número de pressupost" msgstr "Número de pressupost"
#: pkg/quote.go:164 pkg/expenses.go:423 pkg/invoices.go:164 #: pkg/quote.go:164 pkg/expenses.go:432 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:169 pkg/expenses.go:428 pkg/invoices.go:169 #: pkg/quote.go:169 pkg/expenses.go:437 pkg/invoices.go:169
msgctxt "input" msgctxt "input"
msgid "To Date" msgid "To Date"
msgstr "Fins la data" msgstr "Fins la data"
@ -1048,99 +1054,104 @@ msgstr "Els pressuposts han de tenir totes les etiquetes."
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:614 #: pkg/quote.go:618
msgid "quotations.zip" msgid "quotations.zip"
msgstr "pressuposts.zip" msgstr "pressuposts.zip"
#: pkg/quote.go:620 pkg/quote.go:1149 pkg/quote.go:1157 pkg/expenses.go:620 #: pkg/quote.go:632
#: pkg/invoices.go:663 pkg/invoices.go:1279 pkg/invoices.go:1287 msgid "quotations.ods"
msgstr "pressuposts.ods"
#: pkg/quote.go:634 pkg/quote.go:1176 pkg/quote.go:1184 pkg/expenses.go:651
#: pkg/expenses.go:677 pkg/invoices.go:677 pkg/invoices.go:1306
#: pkg/invoices.go:1314
msgid "Invalid action" msgid "Invalid action"
msgstr "Acció invàlida." msgstr "Acció invàlida."
#: pkg/quote.go:673 #: pkg/quote.go:687
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:678 #: pkg/quote.go:692
msgctxt "input" msgctxt "input"
msgid "Quotation Date" msgid "Quotation Date"
msgstr "Data del pressupost" msgstr "Data del pressupost"
#: pkg/quote.go:684 #: pkg/quote.go:698
msgctxt "input" msgctxt "input"
msgid "Terms and conditions" msgid "Terms and conditions"
msgstr "Condicions dacceptació" msgstr "Condicions dacceptació"
#: pkg/quote.go:689 pkg/invoices.go:727 #: pkg/quote.go:703 pkg/invoices.go:741
msgctxt "input" msgctxt "input"
msgid "Notes" msgid "Notes"
msgstr "Notes" msgstr "Notes"
#: pkg/quote.go:698 pkg/invoices.go:737 #: pkg/quote.go:712 pkg/invoices.go:751
msgctxt "input" msgctxt "input"
msgid "Payment Method" msgid "Payment Method"
msgstr "Mètode de pagament" msgstr "Mètode de pagament"
#: pkg/quote.go:699 #: pkg/quote.go:713
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:735 #: pkg/quote.go:749
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:737 pkg/invoices.go:792 #: pkg/quote.go:751 pkg/invoices.go:806
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:739 #: pkg/quote.go:753
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:740 #: pkg/quote.go:754
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:743 pkg/invoices.go:796 #: pkg/quote.go:757 pkg/invoices.go:810
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:877 pkg/quote.go:882 pkg/invoices.go:992 pkg/invoices.go:997 #: pkg/quote.go:891 pkg/quote.go:896 pkg/invoices.go:1006 pkg/invoices.go:1011
msgctxt "input" msgctxt "input"
msgid "Id" msgid "Id"
msgstr "Identificador" msgstr "Identificador"
#: pkg/quote.go:915 pkg/invoices.go:1030 #: pkg/quote.go:929 pkg/invoices.go:1044
msgctxt "input" msgctxt "input"
msgid "Quantity" msgid "Quantity"
msgstr "Quantitat" msgstr "Quantitat"
#: pkg/quote.go:924 pkg/invoices.go:1039 #: pkg/quote.go:938 pkg/invoices.go:1053
msgctxt "input" msgctxt "input"
msgid "Discount (%)" msgid "Discount (%)"
msgstr "Descompte (%)" msgstr "Descompte (%)"
#: pkg/quote.go:978 #: pkg/quote.go:992
msgid "Quotation product ID must be a number greater than zero." msgid "Quotation product ID must be a number greater than zero."
msgstr "LID del producte de pressupost ha de ser un número major a zero." msgstr "LID del producte de pressupost ha de ser un número major a zero."
#: pkg/quote.go:981 pkg/invoices.go:1096 #: pkg/quote.go:995 pkg/invoices.go:1110
msgid "Product ID must be a positive number or zero." msgid "Product ID must be a positive number or zero."
msgstr "LID del producte ha de ser un número positiu o zero." msgstr "LID del producte ha de ser un número positiu o zero."
#: pkg/quote.go:987 pkg/invoices.go:1102 #: pkg/quote.go:1001 pkg/invoices.go:1116
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:988 pkg/invoices.go:1103 #: pkg/quote.go:1002 pkg/invoices.go:1117
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:990 pkg/invoices.go:1105 #: pkg/quote.go:1004 pkg/invoices.go:1119
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:991 pkg/invoices.go:1106 #: pkg/quote.go:1005 pkg/invoices.go:1120
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."
@ -1207,132 +1218,140 @@ msgctxt "period option"
msgid "Previous year" msgid "Previous year"
msgstr "Any anterior" msgstr "Any anterior"
#: pkg/expenses.go:168 #: pkg/expenses.go:172
msgid "Select a contact." msgid "Select a contact."
msgstr "Escolliu un contacte." msgstr "Escolliu un contacte."
#: pkg/expenses.go:225 pkg/expenses.go:412 #: pkg/expenses.go:229 pkg/expenses.go:421
msgctxt "input" msgctxt "input"
msgid "Contact" msgid "Contact"
msgstr "Contacte" msgstr "Contacte"
#: pkg/expenses.go:231 #: pkg/expenses.go:235
msgctxt "input" msgctxt "input"
msgid "Invoice number" msgid "Invoice number"
msgstr "Número de factura" msgstr "Número de factura"
#: pkg/expenses.go:236 pkg/invoices.go:721 #: pkg/expenses.go:240 pkg/invoices.go:735
msgctxt "input" msgctxt "input"
msgid "Invoice Date" msgid "Invoice Date"
msgstr "Data de factura" msgstr "Data de factura"
#: pkg/expenses.go:251 #: pkg/expenses.go:255
msgctxt "input" msgctxt "input"
msgid "Amount" msgid "Amount"
msgstr "Import" msgstr "Import"
#: pkg/expenses.go:262 pkg/invoices.go:743 #: pkg/expenses.go:266 pkg/invoices.go:757
msgctxt "input" msgctxt "input"
msgid "File" msgid "File"
msgstr "Fitxer" msgstr "Fitxer"
#: pkg/expenses.go:268 pkg/expenses.go:437 #: pkg/expenses.go:272 pkg/expenses.go:446
msgctxt "input" msgctxt "input"
msgid "Expense Status" msgid "Expense Status"
msgstr "Estat de la despesa" msgstr "Estat de la despesa"
#: pkg/expenses.go:308 #: pkg/expenses.go:312
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:309 pkg/invoices.go:794 #: pkg/expenses.go:313 pkg/invoices.go:808
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:312 #: pkg/expenses.go:316
msgid "Amount can not be empty." msgid "Amount can not be empty."
msgstr "No podeu deixar limport en blanc." msgstr "No podeu deixar limport en blanc."
#: pkg/expenses.go:313 #: pkg/expenses.go:317
msgid "Amount must be a number greater than zero." msgid "Amount must be a number greater than zero."
msgstr "Limport ha de ser un número major a zero." msgstr "Limport ha de ser un número major a zero."
#: pkg/expenses.go:315 #: pkg/expenses.go:319
msgid "Selected expense status is not valid." msgid "Selected expense status is not valid."
msgstr "Heu seleccionat un estat de despesa que no és vàlid." msgstr "Heu seleccionat un estat de despesa que no és vàlid."
#: pkg/expenses.go:413 #: pkg/expenses.go:422
msgid "All contacts" msgid "All contacts"
msgstr "Tots els contactes" msgstr "Tots els contactes"
#: pkg/expenses.go:418 pkg/invoices.go:159 #: pkg/expenses.go:427 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:153 pkg/invoices.go:709 #: pkg/expenses.go:675
msgid "expenses.ods"
msgstr "despeses.ods"
#: pkg/invoices.go:153 pkg/invoices.go:723
msgctxt "input" msgctxt "input"
msgid "Invoice Status" msgid "Invoice Status"
msgstr "Estat de la factura" msgstr "Estat de la factura"
#: pkg/invoices.go:553 #: pkg/invoices.go:557
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:657 #: pkg/invoices.go:661
msgid "invoices.zip" msgid "invoices.zip"
msgstr "factures.zip" msgstr "factures.zip"
#: pkg/invoices.go:791 #: pkg/invoices.go:675
msgid "invoices.ods"
msgstr "factures.ods"
#: pkg/invoices.go:805
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:793 #: pkg/invoices.go:807
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:929 #: pkg/invoices.go:943
#, 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:930 #: pkg/invoices.go:944
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:1093 #: pkg/invoices.go:1107
msgid "Invoice product ID must be a number greater than zero." msgid "Invoice product ID must be a number greater than zero."
msgstr "LID del producte de factura ha de ser un número major a zero." msgstr "LID del producte de factura ha de ser un número major a zero."
#: pkg/contacts.go:283 #: pkg/contacts.go:292
msgctxt "input" msgctxt "input"
msgid "Need to input tax details" msgid "Need to input tax details"
msgstr "Necessito poder facturar aquest contacte" msgstr "Necessito poder facturar aquest contacte"
#: pkg/contacts.go:343 #: pkg/contacts.go:352
msgctxt "input" msgctxt "input"
msgid "IBAN" msgid "IBAN"
msgstr "IBAN" msgstr "IBAN"
#: pkg/contacts.go:348 #: pkg/contacts.go:357
msgctxt "bic" msgctxt "bic"
msgid "BIC" msgid "BIC"
msgstr "BIC" msgstr "BIC"
#: pkg/contacts.go:404 #: pkg/contacts.go:413
msgid "Name must have at least two letters." msgid "Name must have at least two letters."
msgstr "El nom ha de tenir com a mínim dues lletres." msgstr "El nom ha de tenir com a mínim dues lletres."
#: pkg/contacts.go:417 #: pkg/contacts.go:426
msgid "This values is not a valid IBAN." msgid "This values is not a valid IBAN."
msgstr "Aquest valor no és un IBAN vàlid." msgstr "Aquest valor no és un IBAN vàlid."
#: pkg/contacts.go:420 #: pkg/contacts.go:429
msgid "This values is not a valid BIC." msgid "This values is not a valid BIC."
msgstr "Aquest valor no és un BIC vàlid." msgstr "Aquest valor no és un BIC vàlid."
#: pkg/contacts.go:534 #: pkg/contacts.go:551
msgctxt "input" msgctxt "input"
msgid "Holded Excel file" msgid "Holded Excel file"
msgstr "Fitxer Excel del Holded" msgstr "Fitxer Excel del Holded"

331
po/es.po
View File

@ -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-07-16 20:50+0200\n" "POT-Creation-Date: 2023-07-18 13:12+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"
@ -126,117 +126,123 @@ msgctxt "action"
msgid "Save" msgid "Save"
msgstr "Guardad" msgstr "Guardad"
#: web/template/invoices/index.gohtml:19 #: web/template/invoices/index.gohtml:28
msgctxt "action" msgctxt "action"
msgid "Download invoices" msgid "Download invoices"
msgstr "Descargar facturas" msgstr "Descargar facturas"
#: web/template/invoices/index.gohtml:21 #: web/template/invoices/index.gohtml:31 web/template/quotes/index.gohtml:31
#: web/template/expenses/index.gohtml:29
msgctxt "action"
msgid "Export list"
msgstr "Exportar listado"
#: web/template/invoices/index.gohtml:33
msgctxt "action" msgctxt "action"
msgid "New invoice" msgid "New invoice"
msgstr "Nueva factura" msgstr "Nueva factura"
#: web/template/invoices/index.gohtml:45 web/template/dashboard.gohtml:23 #: web/template/invoices/index.gohtml:57 web/template/dashboard.gohtml:23
#: web/template/quotes/index.gohtml:45 web/template/contacts/index.gohtml:38 #: web/template/quotes/index.gohtml:57 web/template/contacts/index.gohtml:38
#: web/template/expenses/index.gohtml:39 web/template/products/index.gohtml:36 #: web/template/expenses/index.gohtml:56 web/template/products/index.gohtml:36
msgctxt "action" msgctxt "action"
msgid "Filter" msgid "Filter"
msgstr "Filtrar" msgstr "Filtrar"
#: web/template/invoices/index.gohtml:48 web/template/quotes/index.gohtml:48 #: web/template/invoices/index.gohtml:60 web/template/quotes/index.gohtml:60
#: web/template/contacts/index.gohtml:41 web/template/expenses/index.gohtml:42 #: web/template/contacts/index.gohtml:41 web/template/expenses/index.gohtml:59
#: web/template/products/index.gohtml:39 #: web/template/products/index.gohtml:39
msgctxt "action" msgctxt "action"
msgid "Reset" msgid "Reset"
msgstr "Restablecer" msgstr "Restablecer"
#: web/template/invoices/index.gohtml:54 #: web/template/invoices/index.gohtml:66
msgctxt "invoice" msgctxt "invoice"
msgid "All" msgid "All"
msgstr "Todas" msgstr "Todas"
#: web/template/invoices/index.gohtml:55 web/template/invoices/view.gohtml:38 #: web/template/invoices/index.gohtml:67 web/template/invoices/view.gohtml:38
#: web/template/quotes/index.gohtml:55 web/template/quotes/view.gohtml:37 #: web/template/quotes/index.gohtml:67 web/template/quotes/view.gohtml:37
msgctxt "title" msgctxt "title"
msgid "Date" msgid "Date"
msgstr "Fecha" msgstr "Fecha"
#: web/template/invoices/index.gohtml:56 #: web/template/invoices/index.gohtml:68
msgctxt "title" msgctxt "title"
msgid "Invoice Num." msgid "Invoice Num."
msgstr "N.º factura" msgstr "N.º factura"
#: web/template/invoices/index.gohtml:57 web/template/quotes/index.gohtml:57 #: web/template/invoices/index.gohtml:69 web/template/quotes/index.gohtml:69
msgctxt "title" msgctxt "title"
msgid "Customer" msgid "Customer"
msgstr "Cliente" msgstr "Cliente"
#: web/template/invoices/index.gohtml:58 web/template/quotes/index.gohtml:58 #: web/template/invoices/index.gohtml:70 web/template/quotes/index.gohtml:70
#: web/template/expenses/index.gohtml:51 #: web/template/expenses/index.gohtml:68
msgctxt "title" msgctxt "title"
msgid "Status" msgid "Status"
msgstr "Estado" msgstr "Estado"
#: web/template/invoices/index.gohtml:59 web/template/quotes/index.gohtml:59 #: web/template/invoices/index.gohtml:71 web/template/quotes/index.gohtml:71
#: web/template/contacts/index.gohtml:50 web/template/expenses/index.gohtml:52 #: web/template/contacts/index.gohtml:50 web/template/expenses/index.gohtml:69
#: web/template/products/index.gohtml:46 #: web/template/products/index.gohtml:46
msgctxt "title" msgctxt "title"
msgid "Tags" msgid "Tags"
msgstr "Etiquetes" msgstr "Etiquetes"
#: web/template/invoices/index.gohtml:60 web/template/quotes/index.gohtml:60 #: web/template/invoices/index.gohtml:72 web/template/quotes/index.gohtml:72
#: web/template/expenses/index.gohtml:53 #: web/template/expenses/index.gohtml:70
msgctxt "title" msgctxt "title"
msgid "Amount" msgid "Amount"
msgstr "Importe" msgstr "Importe"
#: web/template/invoices/index.gohtml:61 web/template/quotes/index.gohtml:61 #: web/template/invoices/index.gohtml:73 web/template/quotes/index.gohtml:73
#: web/template/expenses/index.gohtml:54 #: web/template/expenses/index.gohtml:71
msgctxt "title" msgctxt "title"
msgid "Download" msgid "Download"
msgstr "Descargar" msgstr "Descargar"
#: web/template/invoices/index.gohtml:62 web/template/quotes/index.gohtml:62 #: web/template/invoices/index.gohtml:74 web/template/quotes/index.gohtml:74
#: web/template/contacts/index.gohtml:51 web/template/expenses/index.gohtml:55 #: web/template/contacts/index.gohtml:51 web/template/expenses/index.gohtml:72
#: web/template/products/index.gohtml:48 #: web/template/products/index.gohtml:48
msgctxt "title" msgctxt "title"
msgid "Actions" msgid "Actions"
msgstr "Acciones" msgstr "Acciones"
#: web/template/invoices/index.gohtml:69 #: web/template/invoices/index.gohtml:81
msgctxt "action" msgctxt "action"
msgid "Select invoice %v" msgid "Select invoice %v"
msgstr "Seleccionar factura %v" msgstr "Seleccionar factura %v"
#: web/template/invoices/index.gohtml:110 #: web/template/invoices/index.gohtml:122
msgctxt "action" msgctxt "action"
msgid "Download invoice %s" msgid "Download invoice %s"
msgstr "Descargar factura %s" msgstr "Descargar factura %s"
#: web/template/invoices/index.gohtml:118 #: web/template/invoices/index.gohtml:130
msgid "Actions for invoice %s" msgid "Actions for invoice %s"
msgstr "Acciones para la factura %s" msgstr "Acciones para la factura %s"
#: web/template/invoices/index.gohtml:126 web/template/invoices/view.gohtml:19 #: web/template/invoices/index.gohtml:138 web/template/invoices/view.gohtml:19
#: web/template/quotes/index.gohtml:125 web/template/quotes/view.gohtml:22 #: web/template/quotes/index.gohtml:137 web/template/quotes/view.gohtml:22
#: web/template/contacts/index.gohtml:82 web/template/expenses/index.gohtml:117 #: web/template/contacts/index.gohtml:82 web/template/expenses/index.gohtml:134
#: web/template/products/index.gohtml:78 #: web/template/products/index.gohtml:78
msgctxt "action" msgctxt "action"
msgid "Edit" msgid "Edit"
msgstr "Editar" msgstr "Editar"
#: web/template/invoices/index.gohtml:134 web/template/invoices/view.gohtml:16 #: web/template/invoices/index.gohtml:146 web/template/invoices/view.gohtml:16
#: web/template/quotes/index.gohtml:133 web/template/quotes/view.gohtml:19 #: web/template/quotes/index.gohtml:145 web/template/quotes/view.gohtml:19
msgctxt "action" msgctxt "action"
msgid "Duplicate" msgid "Duplicate"
msgstr "Duplicar" msgstr "Duplicar"
#: web/template/invoices/index.gohtml:144 #: web/template/invoices/index.gohtml:156
msgid "No invoices added yet." msgid "No invoices added yet."
msgstr "No hay facturas." msgstr "No hay facturas."
#: web/template/invoices/index.gohtml:151 web/template/quotes/index.gohtml:158 #: web/template/invoices/index.gohtml:163 web/template/quotes/index.gohtml:170
#: web/template/expenses/index.gohtml:134 #: web/template/expenses/index.gohtml:151
msgid "Total" msgid "Total"
msgstr "Total" msgstr "Total"
@ -363,41 +369,41 @@ msgctxt "title"
msgid "New Quotation" msgid "New Quotation"
msgstr "Nuevo presupuesto" msgstr "Nuevo presupuesto"
#: web/template/quotes/index.gohtml:19 #: web/template/quotes/index.gohtml:28
msgctxt "action" msgctxt "action"
msgid "Download quotations" msgid "Download quotations"
msgstr "Descargar presupuestos" msgstr "Descargar presupuestos"
#: web/template/quotes/index.gohtml:21 #: web/template/quotes/index.gohtml:33
msgctxt "action" msgctxt "action"
msgid "New quotation" msgid "New quotation"
msgstr "Nuevo presupuesto" msgstr "Nuevo presupuesto"
#: web/template/quotes/index.gohtml:54 #: web/template/quotes/index.gohtml:66
msgctxt "quote" msgctxt "quote"
msgid "All" msgid "All"
msgstr "Todos" msgstr "Todos"
#: web/template/quotes/index.gohtml:56 #: web/template/quotes/index.gohtml:68
msgctxt "title" msgctxt "title"
msgid "Quotation Num." msgid "Quotation Num."
msgstr "N.º de presupuesto" msgstr "N.º de presupuesto"
#: web/template/quotes/index.gohtml:69 #: web/template/quotes/index.gohtml:81
msgctxt "action" msgctxt "action"
msgid "Select quotation %v" msgid "Select quotation %v"
msgstr "Seleccionar presupuesto %v" msgstr "Seleccionar presupuesto %v"
#: web/template/quotes/index.gohtml:117 #: web/template/quotes/index.gohtml:129
msgid "Actions for quote %s" msgid "Actions for quote %s"
msgstr "Acciones para el presupuesto %s" msgstr "Acciones para el presupuesto %s"
#: web/template/quotes/index.gohtml:141 web/template/quotes/view.gohtml:16 #: web/template/quotes/index.gohtml:153 web/template/quotes/view.gohtml:16
msgctxt "action" msgctxt "action"
msgid "Create invoice" msgid "Create invoice"
msgstr "Crear factura" msgstr "Crear factura"
#: web/template/quotes/index.gohtml:151 #: web/template/quotes/index.gohtml:163
msgid "No quotations added yet." msgid "No quotations added yet."
msgstr "No hay presupuestos." msgstr "No hay presupuestos."
@ -488,7 +494,7 @@ msgctxt "action"
msgid "New contact" msgid "New contact"
msgstr "Nuevo contacto" msgstr "Nuevo contacto"
#: web/template/contacts/index.gohtml:47 web/template/expenses/index.gohtml:48 #: web/template/contacts/index.gohtml:47 web/template/expenses/index.gohtml:65
msgctxt "title" msgctxt "title"
msgid "Contact" msgid "Contact"
msgstr "Contacto" msgstr "Contacto"
@ -569,26 +575,26 @@ msgctxt "title"
msgid "Expenses" msgid "Expenses"
msgstr "Gastos" msgstr "Gastos"
#: web/template/expenses/index.gohtml:16 #: web/template/expenses/index.gohtml:32
msgctxt "action" msgctxt "action"
msgid "New expense" msgid "New expense"
msgstr "Nuevo gasto" msgstr "Nuevo gasto"
#: web/template/expenses/index.gohtml:49 #: web/template/expenses/index.gohtml:66
msgctxt "title" msgctxt "title"
msgid "Invoice Date" msgid "Invoice Date"
msgstr "Fecha de factura" msgstr "Fecha de factura"
#: web/template/expenses/index.gohtml:50 #: web/template/expenses/index.gohtml:67
msgctxt "title" msgctxt "title"
msgid "Invoice Number" msgid "Invoice Number"
msgstr "Número de factura" msgstr "Número de factura"
#: web/template/expenses/index.gohtml:109 #: web/template/expenses/index.gohtml:126
msgid "Actions for expense %s" msgid "Actions for expense %s"
msgstr "Acciones para el gasto %s" msgstr "Acciones para el gasto %s"
#: web/template/expenses/index.gohtml:127 #: web/template/expenses/index.gohtml:144
msgid "No expenses added yet." msgid "No expenses added yet."
msgstr "No hay gastos." msgstr "No hay gastos."
@ -695,7 +701,7 @@ msgctxt "title"
msgid "Edit Product “%s”" msgid "Edit Product “%s”"
msgstr "Edición del producto «%s»" msgstr "Edición del producto «%s»"
#: pkg/login.go:37 pkg/company.go:127 pkg/profile.go:40 pkg/contacts.go:267 #: pkg/login.go:37 pkg/company.go:127 pkg/profile.go:40 pkg/contacts.go:276
msgctxt "input" msgctxt "input"
msgid "Email" msgid "Email"
msgstr "Correo-e" msgstr "Correo-e"
@ -709,7 +715,7 @@ msgstr "Contraseña"
msgid "Email can not be empty." msgid "Email can not be empty."
msgstr "No podéis dejar el correo-e en blanco." msgstr "No podéis dejar el correo-e en blanco."
#: pkg/login.go:71 pkg/company.go:284 pkg/profile.go:90 pkg/contacts.go:411 #: pkg/login.go:71 pkg/company.go:284 pkg/profile.go:90 pkg/contacts.go:420
msgid "This value is not a valid email. It should be like name@domain.com." 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." msgstr "Este valor no es un correo-e válido. Tiene que ser parecido a nombre@dominio.es."
@ -721,84 +727,84 @@ 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:268 pkg/quote.go:887 #: pkg/products.go:172 pkg/products.go:276 pkg/quote.go:901
#: pkg/invoices.go:1002 pkg/contacts.go:140 pkg/contacts.go:253 #: pkg/invoices.go:1016 pkg/contacts.go:149 pkg/contacts.go:262
msgctxt "input" msgctxt "input"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
#: pkg/products.go:169 pkg/products.go:295 pkg/quote.go:174 pkg/quote.go:694 #: pkg/products.go:177 pkg/products.go:303 pkg/quote.go:174 pkg/quote.go:708
#: pkg/expenses.go:274 pkg/expenses.go:433 pkg/invoices.go:174 #: pkg/expenses.go:278 pkg/expenses.go:442 pkg/invoices.go:174
#: pkg/invoices.go:732 pkg/invoices.go:1304 pkg/contacts.go:145 #: pkg/invoices.go:746 pkg/invoices.go:1331 pkg/contacts.go:154
#: pkg/contacts.go:353 #: pkg/contacts.go:362
msgctxt "input" msgctxt "input"
msgid "Tags" msgid "Tags"
msgstr "Etiquetes" msgstr "Etiquetes"
#: pkg/products.go:173 pkg/quote.go:178 pkg/expenses.go:443 pkg/invoices.go:178 #: pkg/products.go:181 pkg/quote.go:178 pkg/expenses.go:452 pkg/invoices.go:178
#: pkg/contacts.go:149 #: pkg/contacts.go:158
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:182 pkg/expenses.go:447 pkg/invoices.go:182 #: pkg/products.go:185 pkg/quote.go:182 pkg/expenses.go:456 pkg/invoices.go:182
#: pkg/contacts.go:153 #: pkg/contacts.go:162
msgctxt "tag condition" msgctxt "tag condition"
msgid "All" msgid "All"
msgstr "Todas" msgstr "Todas"
#: pkg/products.go:178 pkg/expenses.go:448 pkg/invoices.go:183 #: pkg/products.go:186 pkg/expenses.go:457 pkg/invoices.go:183
#: pkg/contacts.go:154 #: pkg/contacts.go:163
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:187 pkg/expenses.go:452 pkg/invoices.go:187 #: pkg/products.go:190 pkg/quote.go:187 pkg/expenses.go:461 pkg/invoices.go:187
#: pkg/contacts.go:158 #: pkg/contacts.go:167
msgctxt "tag condition" msgctxt "tag condition"
msgid "Any" msgid "Any"
msgstr "Cualquiera" msgstr "Cualquiera"
#: pkg/products.go:183 pkg/expenses.go:453 pkg/invoices.go:188 #: pkg/products.go:191 pkg/expenses.go:462 pkg/invoices.go:188
#: pkg/contacts.go:159 #: pkg/contacts.go:168
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:274 pkg/quote.go:901 pkg/invoices.go:1016 #: pkg/products.go:282 pkg/quote.go:915 pkg/invoices.go:1030
msgctxt "input" msgctxt "input"
msgid "Description" msgid "Description"
msgstr "Descripción" msgstr "Descripción"
#: pkg/products.go:279 pkg/quote.go:905 pkg/invoices.go:1020 #: pkg/products.go:287 pkg/quote.go:919 pkg/invoices.go:1034
msgctxt "input" msgctxt "input"
msgid "Price" msgid "Price"
msgstr "Precio" msgstr "Precio"
#: pkg/products.go:289 pkg/quote.go:934 pkg/expenses.go:242 #: pkg/products.go:297 pkg/quote.go:948 pkg/expenses.go:246
#: pkg/invoices.go:1049 #: pkg/invoices.go:1063
msgctxt "input" msgctxt "input"
msgid "Taxes" msgid "Taxes"
msgstr "Impuestos" msgstr "Impuestos"
#: pkg/products.go:314 pkg/quote.go:983 pkg/profile.go:92 pkg/invoices.go:1098 #: pkg/products.go:322 pkg/quote.go:997 pkg/profile.go:92 pkg/invoices.go:1112
#: pkg/contacts.go:403 #: pkg/contacts.go:412
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:315 pkg/quote.go:984 pkg/invoices.go:1099 #: pkg/products.go:323 pkg/quote.go:998 pkg/invoices.go:1113
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:316 pkg/quote.go:985 pkg/invoices.go:1100 #: pkg/products.go:324 pkg/quote.go:999 pkg/invoices.go:1114
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:318 pkg/quote.go:993 pkg/expenses.go:310 #: pkg/products.go:326 pkg/quote.go:1007 pkg/expenses.go:314
#: pkg/invoices.go:1108 #: pkg/invoices.go:1122
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:319 pkg/quote.go:994 pkg/expenses.go:311 #: pkg/products.go:327 pkg/quote.go:1008 pkg/expenses.go:315
#: pkg/invoices.go:1109 #: pkg/invoices.go:1123
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."
@ -807,47 +813,47 @@ msgctxt "input"
msgid "Trade name" msgid "Trade name"
msgstr "Nombre comercial" msgstr "Nombre comercial"
#: pkg/company.go:118 pkg/contacts.go:259 #: pkg/company.go:118 pkg/contacts.go:268
msgctxt "input" msgctxt "input"
msgid "Phone" msgid "Phone"
msgstr "Teléfono" msgstr "Teléfono"
#: pkg/company.go:136 pkg/contacts.go:275 #: pkg/company.go:136 pkg/contacts.go:284
msgctxt "input" msgctxt "input"
msgid "Web" msgid "Web"
msgstr "Web" msgstr "Web"
#: pkg/company.go:144 pkg/contacts.go:287 #: pkg/company.go:144 pkg/contacts.go:296
msgctxt "input" msgctxt "input"
msgid "Business name" msgid "Business name"
msgstr "Nombre y apellidos" msgstr "Nombre y apellidos"
#: pkg/company.go:154 pkg/contacts.go:297 #: pkg/company.go:154 pkg/contacts.go:306
msgctxt "input" msgctxt "input"
msgid "VAT number" msgid "VAT number"
msgstr "DNI / NIF" msgstr "DNI / NIF"
#: pkg/company.go:160 pkg/contacts.go:303 #: pkg/company.go:160 pkg/contacts.go:312
msgctxt "input" msgctxt "input"
msgid "Address" msgid "Address"
msgstr "Dirección" msgstr "Dirección"
#: pkg/company.go:169 pkg/contacts.go:312 #: pkg/company.go:169 pkg/contacts.go:321
msgctxt "input" msgctxt "input"
msgid "City" msgid "City"
msgstr "Población" msgstr "Población"
#: pkg/company.go:175 pkg/contacts.go:318 #: pkg/company.go:175 pkg/contacts.go:327
msgctxt "input" msgctxt "input"
msgid "Province" msgid "Province"
msgstr "Provincia" msgstr "Provincia"
#: pkg/company.go:181 pkg/contacts.go:324 #: pkg/company.go:181 pkg/contacts.go:333
msgctxt "input" msgctxt "input"
msgid "Postal code" msgid "Postal code"
msgstr "Código postal" msgstr "Código postal"
#: pkg/company.go:190 pkg/contacts.go:333 #: pkg/company.go:190 pkg/contacts.go:342
msgctxt "input" msgctxt "input"
msgid "Country" msgid "Country"
msgstr "País" msgstr "País"
@ -882,23 +888,23 @@ msgctxt "input"
msgid "Legal disclaimer" msgid "Legal disclaimer"
msgstr "Nota legal" msgstr "Nota legal"
#: pkg/company.go:271 pkg/contacts.go:385 #: pkg/company.go:271 pkg/contacts.go:394
msgid "Selected country is not valid." msgid "Selected country is not valid."
msgstr "Habéis escogido un país que no es válido." msgstr "Habéis escogido un país que no es válido."
#: pkg/company.go:275 pkg/contacts.go:388 #: pkg/company.go:275 pkg/contacts.go:397
msgid "Business name can not be empty." msgid "Business name can not be empty."
msgstr "No podéis dejar el nombre y los apellidos en blanco." msgstr "No podéis dejar el nombre y los apellidos en blanco."
#: pkg/company.go:276 pkg/contacts.go:389 #: pkg/company.go:276 pkg/contacts.go:398
msgid "Business name must have at least two letters." msgid "Business name must have at least two letters."
msgstr "El nombre y los apellidos deben contener como mínimo dos letras." msgstr "El nombre y los apellidos deben contener como mínimo dos letras."
#: pkg/company.go:277 pkg/contacts.go:391 #: pkg/company.go:277 pkg/contacts.go:400
msgid "VAT number can not be empty." msgid "VAT number can not be empty."
msgstr "No podéis dejar el DNI o NIF en blanco." msgstr "No podéis dejar el DNI o NIF en blanco."
#: pkg/company.go:278 pkg/contacts.go:392 #: pkg/company.go:278 pkg/contacts.go:401
msgid "This value is not a valid VAT number." msgid "This value is not a valid VAT number."
msgstr "Este valor no es un DNI o NIF válido." msgstr "Este valor no es un DNI o NIF válido."
@ -906,31 +912,31 @@ msgstr "Este valor no es un DNI o NIF válido."
msgid "Phone can not be empty." msgid "Phone can not be empty."
msgstr "No podéis dejar el teléfono en blanco." msgstr "No podéis dejar el teléfono en blanco."
#: pkg/company.go:281 pkg/contacts.go:408 #: pkg/company.go:281 pkg/contacts.go:417
msgid "This value is not a valid phone number." msgid "This value is not a valid phone number."
msgstr "Este valor no es un teléfono válido." msgstr "Este valor no es un teléfono válido."
#: pkg/company.go:287 pkg/contacts.go:414 #: pkg/company.go:287 pkg/contacts.go:423
msgid "This value is not a valid web address. It should be like https://domain.com/." 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/." 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:394 #: pkg/company.go:289 pkg/contacts.go:403
msgid "Address can not be empty." msgid "Address can not be empty."
msgstr "No podéis dejar la dirección en blanco." msgstr "No podéis dejar la dirección en blanco."
#: pkg/company.go:290 pkg/contacts.go:395 #: pkg/company.go:290 pkg/contacts.go:404
msgid "City can not be empty." msgid "City can not be empty."
msgstr "No podéis dejar la población en blanco." msgstr "No podéis dejar la población en blanco."
#: pkg/company.go:291 pkg/contacts.go:396 #: pkg/company.go:291 pkg/contacts.go:405
msgid "Province can not be empty." msgid "Province can not be empty."
msgstr "No podéis dejar la provincia en blanco." msgstr "No podéis dejar la provincia en blanco."
#: pkg/company.go:292 pkg/contacts.go:398 #: pkg/company.go:292 pkg/contacts.go:407
msgid "Postal code can not be empty." msgid "Postal code can not be empty."
msgstr "No podéis dejar el código postal en blanco." msgstr "No podéis dejar el código postal en blanco."
#: pkg/company.go:293 pkg/contacts.go:399 #: pkg/company.go:293 pkg/contacts.go:408
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."
@ -1007,7 +1013,7 @@ 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:147 pkg/quote.go:672 pkg/invoices.go:147 pkg/invoices.go:715 #: pkg/quote.go:147 pkg/quote.go:686 pkg/invoices.go:147 pkg/invoices.go:729
msgctxt "input" msgctxt "input"
msgid "Customer" msgid "Customer"
msgstr "Cliente" msgstr "Cliente"
@ -1016,12 +1022,12 @@ msgstr "Cliente"
msgid "All customers" msgid "All customers"
msgstr "Todos los clientes" msgstr "Todos los clientes"
#: pkg/quote.go:153 pkg/quote.go:666 #: pkg/quote.go:153 pkg/quote.go:680
msgctxt "input" msgctxt "input"
msgid "Quotation Status" msgid "Quotation Status"
msgstr "Estado del presupuesto" msgstr "Estado del presupuesto"
#: pkg/quote.go:154 pkg/expenses.go:438 pkg/invoices.go:154 #: pkg/quote.go:154 pkg/expenses.go:447 pkg/invoices.go:154
msgid "All status" msgid "All status"
msgstr "Todos los estados" msgstr "Todos los estados"
@ -1030,12 +1036,12 @@ msgctxt "input"
msgid "Quotation Number" msgid "Quotation Number"
msgstr "Número de presupuesto" msgstr "Número de presupuesto"
#: pkg/quote.go:164 pkg/expenses.go:423 pkg/invoices.go:164 #: pkg/quote.go:164 pkg/expenses.go:432 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:169 pkg/expenses.go:428 pkg/invoices.go:169 #: pkg/quote.go:169 pkg/expenses.go:437 pkg/invoices.go:169
msgctxt "input" msgctxt "input"
msgid "To Date" msgid "To Date"
msgstr "Hasta la fecha" msgstr "Hasta la fecha"
@ -1048,99 +1054,104 @@ msgstr "Los presupuestos deben tener todas las etiquetas."
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:614 #: pkg/quote.go:618
msgid "quotations.zip" msgid "quotations.zip"
msgstr "presupuestos.zip" msgstr "presupuestos.zip"
#: pkg/quote.go:620 pkg/quote.go:1149 pkg/quote.go:1157 pkg/expenses.go:620 #: pkg/quote.go:632
#: pkg/invoices.go:663 pkg/invoices.go:1279 pkg/invoices.go:1287 msgid "quotations.ods"
msgstr "presupuestos.ods"
#: pkg/quote.go:634 pkg/quote.go:1176 pkg/quote.go:1184 pkg/expenses.go:651
#: pkg/expenses.go:677 pkg/invoices.go:677 pkg/invoices.go:1306
#: pkg/invoices.go:1314
msgid "Invalid action" msgid "Invalid action"
msgstr "Acción inválida." msgstr "Acción inválida."
#: pkg/quote.go:673 #: pkg/quote.go:687
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:678 #: pkg/quote.go:692
msgctxt "input" msgctxt "input"
msgid "Quotation Date" msgid "Quotation Date"
msgstr "Fecha del presupuesto" msgstr "Fecha del presupuesto"
#: pkg/quote.go:684 #: pkg/quote.go:698
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:689 pkg/invoices.go:727 #: pkg/quote.go:703 pkg/invoices.go:741
msgctxt "input" msgctxt "input"
msgid "Notes" msgid "Notes"
msgstr "Notas" msgstr "Notas"
#: pkg/quote.go:698 pkg/invoices.go:737 #: pkg/quote.go:712 pkg/invoices.go:751
msgctxt "input" msgctxt "input"
msgid "Payment Method" msgid "Payment Method"
msgstr "Método de pago" msgstr "Método de pago"
#: pkg/quote.go:699 #: pkg/quote.go:713
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:735 #: pkg/quote.go:749
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:737 pkg/invoices.go:792 #: pkg/quote.go:751 pkg/invoices.go:806
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:739 #: pkg/quote.go:753
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:740 #: pkg/quote.go:754
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:743 pkg/invoices.go:796 #: pkg/quote.go:757 pkg/invoices.go:810
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:877 pkg/quote.go:882 pkg/invoices.go:992 pkg/invoices.go:997 #: pkg/quote.go:891 pkg/quote.go:896 pkg/invoices.go:1006 pkg/invoices.go:1011
msgctxt "input" msgctxt "input"
msgid "Id" msgid "Id"
msgstr "Identificador" msgstr "Identificador"
#: pkg/quote.go:915 pkg/invoices.go:1030 #: pkg/quote.go:929 pkg/invoices.go:1044
msgctxt "input" msgctxt "input"
msgid "Quantity" msgid "Quantity"
msgstr "Cantidad" msgstr "Cantidad"
#: pkg/quote.go:924 pkg/invoices.go:1039 #: pkg/quote.go:938 pkg/invoices.go:1053
msgctxt "input" msgctxt "input"
msgid "Discount (%)" msgid "Discount (%)"
msgstr "Descuento (%)" msgstr "Descuento (%)"
#: pkg/quote.go:978 #: pkg/quote.go:992
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:981 pkg/invoices.go:1096 #: pkg/quote.go:995 pkg/invoices.go:1110
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:987 pkg/invoices.go:1102 #: pkg/quote.go:1001 pkg/invoices.go:1116
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:988 pkg/invoices.go:1103 #: pkg/quote.go:1002 pkg/invoices.go:1117
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:990 pkg/invoices.go:1105 #: pkg/quote.go:1004 pkg/invoices.go:1119
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:991 pkg/invoices.go:1106 #: pkg/quote.go:1005 pkg/invoices.go:1120
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."
@ -1207,132 +1218,140 @@ msgctxt "period option"
msgid "Previous year" msgid "Previous year"
msgstr "Año anterior" msgstr "Año anterior"
#: pkg/expenses.go:168 #: pkg/expenses.go:172
msgid "Select a contact." msgid "Select a contact."
msgstr "Escoged un contacto" msgstr "Escoged un contacto"
#: pkg/expenses.go:225 pkg/expenses.go:412 #: pkg/expenses.go:229 pkg/expenses.go:421
msgctxt "input" msgctxt "input"
msgid "Contact" msgid "Contact"
msgstr "Contacto" msgstr "Contacto"
#: pkg/expenses.go:231 #: pkg/expenses.go:235
msgctxt "input" msgctxt "input"
msgid "Invoice number" msgid "Invoice number"
msgstr "Número de factura" msgstr "Número de factura"
#: pkg/expenses.go:236 pkg/invoices.go:721 #: pkg/expenses.go:240 pkg/invoices.go:735
msgctxt "input" msgctxt "input"
msgid "Invoice Date" msgid "Invoice Date"
msgstr "Fecha de factura" msgstr "Fecha de factura"
#: pkg/expenses.go:251 #: pkg/expenses.go:255
msgctxt "input" msgctxt "input"
msgid "Amount" msgid "Amount"
msgstr "Importe" msgstr "Importe"
#: pkg/expenses.go:262 pkg/invoices.go:743 #: pkg/expenses.go:266 pkg/invoices.go:757
msgctxt "input" msgctxt "input"
msgid "File" msgid "File"
msgstr "Archivo" msgstr "Archivo"
#: pkg/expenses.go:268 pkg/expenses.go:437 #: pkg/expenses.go:272 pkg/expenses.go:446
msgctxt "input" msgctxt "input"
msgid "Expense Status" msgid "Expense Status"
msgstr "Estado del gasto" msgstr "Estado del gasto"
#: pkg/expenses.go:308 #: pkg/expenses.go:312
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:309 pkg/invoices.go:794 #: pkg/expenses.go:313 pkg/invoices.go:808
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:312 #: pkg/expenses.go:316
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:313 #: pkg/expenses.go:317
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:315 #: pkg/expenses.go:319
msgid "Selected expense status is not valid." msgid "Selected expense status is not valid."
msgstr "Habéis escogido un estado de gasto que no es válido." msgstr "Habéis escogido un estado de gasto que no es válido."
#: pkg/expenses.go:413 #: pkg/expenses.go:422
msgid "All contacts" msgid "All contacts"
msgstr "Todos los contactos" msgstr "Todos los contactos"
#: pkg/expenses.go:418 pkg/invoices.go:159 #: pkg/expenses.go:427 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:153 pkg/invoices.go:709 #: pkg/expenses.go:675
msgid "expenses.ods"
msgstr "gastos.ods"
#: pkg/invoices.go:153 pkg/invoices.go:723
msgctxt "input" msgctxt "input"
msgid "Invoice Status" msgid "Invoice Status"
msgstr "Estado de la factura" msgstr "Estado de la factura"
#: pkg/invoices.go:553 #: pkg/invoices.go:557
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:657 #: pkg/invoices.go:661
msgid "invoices.zip" msgid "invoices.zip"
msgstr "facturas.zip" msgstr "facturas.zip"
#: pkg/invoices.go:791 #: pkg/invoices.go:675
msgid "invoices.ods"
msgstr "facturas.ods"
#: pkg/invoices.go:805
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:793 #: pkg/invoices.go:807
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:929 #: pkg/invoices.go:943
#, 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:930 #: pkg/invoices.go:944
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:1093 #: pkg/invoices.go:1107
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."
#: pkg/contacts.go:283 #: pkg/contacts.go:292
msgctxt "input" msgctxt "input"
msgid "Need to input tax details" msgid "Need to input tax details"
msgstr "Necesito facturar este contacto" msgstr "Necesito facturar este contacto"
#: pkg/contacts.go:343 #: pkg/contacts.go:352
msgctxt "input" msgctxt "input"
msgid "IBAN" msgid "IBAN"
msgstr "IBAN" msgstr "IBAN"
#: pkg/contacts.go:348 #: pkg/contacts.go:357
msgctxt "bic" msgctxt "bic"
msgid "BIC" msgid "BIC"
msgstr "BIC" msgstr "BIC"
#: pkg/contacts.go:404 #: pkg/contacts.go:413
msgid "Name must have at least two letters." msgid "Name must have at least two letters."
msgstr "El nombre debe contener como mínimo dos letras." msgstr "El nombre debe contener como mínimo dos letras."
#: pkg/contacts.go:417 #: pkg/contacts.go:426
msgid "This values is not a valid IBAN." msgid "This values is not a valid IBAN."
msgstr "Este valor no es un IBAN válido." msgstr "Este valor no es un IBAN válido."
#: pkg/contacts.go:420 #: pkg/contacts.go:429
msgid "This values is not a valid BIC." msgid "This values is not a valid BIC."
msgstr "Este valor no es un BIC válido." msgstr "Este valor no es un BIC válido."
#: pkg/contacts.go:534 #: pkg/contacts.go:551
msgctxt "input" msgctxt "input"
msgid "Holded Excel file" msgid "Holded Excel file"
msgstr "Archivo Excel de Holded" msgstr "Archivo Excel de Holded"

View File

@ -5,16 +5,33 @@
{{ define "breadcrumbs" -}} {{ define "breadcrumbs" -}}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.expensesIndexPage*/ -}} {{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.expensesIndexPage*/ -}}
<nav data-hx-boost="true" data-hx-target="main"> <nav data-hx-target="main">
<p> <p data-hx-boost="true">
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> / <a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
<a>{{( pgettext "Expenses" "title" )}}</a> <a>{{( pgettext "Expenses" "title" )}}</a>
</p> </p>
<form id="batch-form" action="{{ companyURI "/expenses/batch" }}" method="post">
{{ csrfToken }}
{{ with .Filters }}
{{ template "hidden-select-field" .Contact }}
{{ template "hidden-select-field" .ExpenseStatus }}
{{ template "hidden-field" .FromDate }}
{{ template "hidden-field" .ToDate }}
{{ template "hidden-field" .InvoiceNumber }}
{{ template "hidden-field" .Tags }}
{{ template "hidden-field" .TagsCondition }}
{{ end }}
<p> <p>
{{ template "filters-toggle" }} {{ template "filters-toggle" }}
<button type="submit"
name="action" value="export"
>{{( pgettext "Export list" "action" )}}</button>
<a class="primary button" <a class="primary button"
data-hx-boost="true"
href="{{ companyURI "/expenses/new" }}">{{( pgettext "New expense" "action" )}}</a> href="{{ companyURI "/expenses/new" }}">{{( pgettext "New expense" "action" )}}</a>
</p> </p>
</form>
</nav> </nav>
{{- end }} {{- end }}

View File

@ -12,11 +12,23 @@
<form id="batch-form" action="{{ companyURI "/invoices/batch" }}" method="post"> <form id="batch-form" action="{{ companyURI "/invoices/batch" }}" method="post">
{{ csrfToken }} {{ csrfToken }}
{{ with .Filters }}
{{ template "hidden-select-field" .Customer }}
{{ template "hidden-select-field" .InvoiceStatus }}
{{ template "hidden-field" .FromDate }}
{{ template "hidden-field" .ToDate }}
{{ template "hidden-field" .InvoiceNumber }}
{{ template "hidden-field" .Tags }}
{{ template "hidden-field" .TagsCondition }}
{{ end }}
<p> <p>
{{ template "filters-toggle" }} {{ template "filters-toggle" }}
<button type="submit" <button type="submit"
name="action" value="download" name="action" value="download"
>{{( pgettext "Download invoices" "action" )}}</button> >{{( pgettext "Download invoices" "action" )}}</button>
<button type="submit"
name="action" value="export"
>{{( pgettext "Export list" "action" )}}</button>
<a class="primary button" data-hx-boost="true" <a class="primary button" data-hx-boost="true"
href="{{ companyURI "/invoices/new" }}">{{( pgettext "New invoice" "action" )}}</a> href="{{ companyURI "/invoices/new" }}">{{( pgettext "New invoice" "action" )}}</a>
</p> </p>

View File

@ -12,11 +12,23 @@
<form id="batch-form" action="{{ companyURI "/quotes/batch" }}" method="post"> <form id="batch-form" action="{{ companyURI "/quotes/batch" }}" method="post">
{{ csrfToken }} {{ csrfToken }}
{{ with .Filters }}
{{ template "hidden-field" .Customer }}
{{ template "hidden-select-field" .QuoteStatus }}
{{ template "hidden-field" .FromDate }}
{{ template "hidden-field" .ToDate }}
{{ template "hidden-field" .QuoteNumber }}
{{ template "hidden-field" .Tags }}
{{ template "hidden-field" .TagsCondition }}
{{ end }}
<p> <p>
{{ template "filters-toggle" }} {{ template "filters-toggle" }}
<button type="submit" <button type="submit"
name="action" value="download" name="action" value="download"
>{{( pgettext "Download quotations" "action" )}}</button> >{{( pgettext "Download quotations" "action" )}}</button>
<button type="submit"
name="action" value="export"
>{{( pgettext "Export list" "action" )}}</button>
<a class="primary button" data-hx-boost="true" <a class="primary button" data-hx-boost="true"
href="{{ companyURI "/quotes/new" }}">{{( pgettext "New quotation" "action" )}}</a> href="{{ companyURI "/quotes/new" }}">{{( pgettext "New quotation" "action" )}}</a>
</p> </p>