Begin the dashboard with expenses, gross income, net income, and taxes
For now i use a too-long SQL query for that, but will probably replace it with a view. I have to check that it is correct before i do so, however.
This commit is contained in:
parent
7921b9cf80
commit
ce42880697
|
@ -0,0 +1,64 @@
|
|||
package pkg
|
||||
|
||||
import (
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type DashboardPage struct {
|
||||
Sales string
|
||||
Income string
|
||||
Expenses string
|
||||
VAT string
|
||||
IRPF string
|
||||
NetIncome string
|
||||
}
|
||||
|
||||
func ServeDashboard(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
company := mustGetCompany(r)
|
||||
conn := getConn(r)
|
||||
rows := conn.MustQuery(r.Context(), `
|
||||
select to_price(0, decimal_digits) as sales
|
||||
, to_price(invoice.total, decimal_digits) as income
|
||||
, to_price(expense.total, decimal_digits) as expenses
|
||||
, to_price(tax.vat, decimal_digits) as vat
|
||||
, to_price(tax.irpf, decimal_digits) as irpf
|
||||
, to_price(invoice.total - expense.total - tax.vat + tax.irpf, decimal_digits) as net_income
|
||||
from company
|
||||
left join (
|
||||
select company_id, sum(total)::integer as total
|
||||
from invoice
|
||||
join invoice_amount using (invoice_id)
|
||||
group by company_id
|
||||
) as invoice using (company_id)
|
||||
left join (
|
||||
select company_id, sum(amount)::integer as total
|
||||
from expense
|
||||
group by company_id
|
||||
) as expense using (company_id)
|
||||
left join (
|
||||
select invoice.company_id
|
||||
, sum(case when tax_class.name = 'IVA' then invoice_tax_amount.amount else 0 end)::integer as vat
|
||||
, sum(case when tax_class.name = 'IRPF' then invoice_tax_amount.amount else 0 end)::integer as irpf
|
||||
from invoice
|
||||
join invoice_tax_amount using (invoice_id)
|
||||
join tax using (tax_id)
|
||||
join tax_class using (tax_class_id)
|
||||
group by invoice.company_id
|
||||
) as tax using (company_id)
|
||||
join currency using (currency_code)
|
||||
where company_id = $1
|
||||
`, company.Id)
|
||||
defer rows.Close()
|
||||
|
||||
dashboard := &DashboardPage{}
|
||||
for rows.Next() {
|
||||
if err := rows.Scan(&dashboard.Sales, &dashboard.Income, &dashboard.Expenses, &dashboard.VAT, &dashboard.IRPF, &dashboard.NetIncome); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
panic(rows.Err())
|
||||
}
|
||||
mustRenderMainTemplate(w, r, "dashboard.gohtml", dashboard)
|
||||
}
|
|
@ -45,9 +45,7 @@ func NewRouter(db *Db) http.Handler {
|
|||
companyRouter.PUT("/expenses/:slug/tags", HandleUpdateExpenseTags)
|
||||
companyRouter.GET("/expenses/:slug/tags/edit", ServeEditExpenseTags)
|
||||
companyRouter.GET("/expenses/:slug/download/:filename", ServeExpenseAttachment)
|
||||
companyRouter.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
mustRenderMainTemplate(w, r, "dashboard.gohtml", nil)
|
||||
})
|
||||
companyRouter.GET("/", ServeDashboard)
|
||||
|
||||
router := httprouter.New()
|
||||
router.ServeFiles("/static/*filepath", http.Dir("web/static"))
|
||||
|
|
|
@ -2,6 +2,7 @@ package pkg
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
"golang.org/x/text/number"
|
||||
"html/template"
|
||||
|
@ -33,12 +34,10 @@ func mustRenderTemplate(wr io.Writer, r *http.Request, layout string, filename s
|
|||
return companyURI(company, uri)
|
||||
},
|
||||
"formatPrice": func(price string) string {
|
||||
p := message.NewPrinter(locale.Language)
|
||||
f, err := strconv.ParseFloat(price, 64)
|
||||
if err != nil {
|
||||
f = math.NaN()
|
||||
}
|
||||
return p.Sprintf(locale.CurrencyPattern, company.DecimalDigits, number.Decimal(f), company.CurrencySymbol)
|
||||
return formatPrice(price, locale.Language, locale.CurrencyPattern, company.DecimalDigits, company.CurrencySymbol)
|
||||
},
|
||||
"formatPriceSpan": func(price string) template.HTML {
|
||||
return template.HTML(formatPrice(price, locale.Language, locale.CurrencyPattern, company.DecimalDigits, "<span>"+company.CurrencySymbol+"</span>"))
|
||||
},
|
||||
"formatDate": func(time time.Time) template.HTML {
|
||||
return template.HTML(`<time datetime="` + time.Format("2006-01-02") + `">` + time.Format("02/01/2006") + "</time>")
|
||||
|
@ -152,3 +151,12 @@ func humanizeBytes(s int64, base float64, sizes []string) string {
|
|||
func logn(n, b float64) float64 {
|
||||
return math.Log(n) / math.Log(b)
|
||||
}
|
||||
|
||||
func formatPrice(price string, language language.Tag, currencyPattern string, decimalDigits int, currencySymbol string) string {
|
||||
p := message.NewPrinter(language)
|
||||
f, err := strconv.ParseFloat(price, 64)
|
||||
if err != nil {
|
||||
f = math.NaN()
|
||||
}
|
||||
return p.Sprintf(currencyPattern, decimalDigits, number.Decimal(f), currencySymbol)
|
||||
}
|
||||
|
|
106
po/ca.po
106
po/ca.po
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: numerus\n"
|
||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||
"POT-Creation-Date: 2023-05-11 23:31+0200\n"
|
||||
"POT-Creation-Date: 2023-05-16 14:50+0200\n"
|
||||
"PO-Revision-Date: 2023-01-18 17:08+0100\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||
|
@ -146,13 +146,13 @@ msgctxt "title"
|
|||
msgid "Amount"
|
||||
msgstr "Import"
|
||||
|
||||
#: web/template/invoices/index.gohtml:53
|
||||
#: web/template/invoices/index.gohtml:53 web/template/expenses/index.gohtml:46
|
||||
msgctxt "title"
|
||||
msgid "Download"
|
||||
msgstr "Descàrrega"
|
||||
|
||||
#: web/template/invoices/index.gohtml:54 web/template/contacts/index.gohtml:43
|
||||
#: web/template/expenses/index.gohtml:46 web/template/products/index.gohtml:42
|
||||
#: web/template/expenses/index.gohtml:47 web/template/products/index.gohtml:42
|
||||
msgctxt "title"
|
||||
msgid "Actions"
|
||||
msgstr "Accions"
|
||||
|
@ -163,7 +163,7 @@ msgid "Select invoice %v"
|
|||
msgstr "Selecciona factura %v"
|
||||
|
||||
#: web/template/invoices/index.gohtml:116 web/template/invoices/view.gohtml:19
|
||||
#: web/template/contacts/index.gohtml:69 web/template/expenses/index.gohtml:77
|
||||
#: web/template/contacts/index.gohtml:73 web/template/expenses/index.gohtml:86
|
||||
#: web/template/products/index.gohtml:71
|
||||
msgctxt "action"
|
||||
msgid "Edit"
|
||||
|
@ -218,11 +218,46 @@ msgctxt "action"
|
|||
msgid "Edit invoice"
|
||||
msgstr "Edita factura"
|
||||
|
||||
#: web/template/dashboard.gohtml:2
|
||||
#: web/template/form.gohtml:36
|
||||
msgctxt "label"
|
||||
msgid "(Max. %s)"
|
||||
msgstr "(Màx. %s)"
|
||||
|
||||
#: web/template/dashboard.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Dashboard"
|
||||
msgstr "Tauler"
|
||||
|
||||
#: web/template/dashboard.gohtml:14
|
||||
msgctxt "term"
|
||||
msgid "Sales"
|
||||
msgstr "Vendes"
|
||||
|
||||
#: web/template/dashboard.gohtml:18
|
||||
msgctxt "term"
|
||||
msgid "Income"
|
||||
msgstr "Ingressos"
|
||||
|
||||
#: web/template/dashboard.gohtml:22
|
||||
msgctxt "term"
|
||||
msgid "Expenses"
|
||||
msgstr "Despeses"
|
||||
|
||||
#: web/template/dashboard.gohtml:26
|
||||
msgctxt "term"
|
||||
msgid "VAT"
|
||||
msgstr "IVA"
|
||||
|
||||
#: web/template/dashboard.gohtml:30
|
||||
msgctxt "term"
|
||||
msgid "IRPF"
|
||||
msgstr "IRPF"
|
||||
|
||||
#: web/template/dashboard.gohtml:34
|
||||
msgctxt "term"
|
||||
msgid "Net Income"
|
||||
msgstr "Ingressos nets"
|
||||
|
||||
#: web/template/app.gohtml:23
|
||||
msgctxt "menu"
|
||||
msgid "Account"
|
||||
|
@ -295,7 +330,7 @@ msgctxt "title"
|
|||
msgid "Phone"
|
||||
msgstr "Telèfon"
|
||||
|
||||
#: web/template/contacts/index.gohtml:79
|
||||
#: web/template/contacts/index.gohtml:83
|
||||
msgid "No contacts added yet."
|
||||
msgstr "No hi ha cap contacte."
|
||||
|
||||
|
@ -357,7 +392,7 @@ msgctxt "title"
|
|||
msgid "Expenses"
|
||||
msgstr "Despeses"
|
||||
|
||||
#: web/template/expenses/new.gohtml:32 web/template/expenses/index.gohtml:15
|
||||
#: web/template/expenses/new.gohtml:33 web/template/expenses/index.gohtml:15
|
||||
msgctxt "action"
|
||||
msgid "New expense"
|
||||
msgstr "Nova despesa"
|
||||
|
@ -382,7 +417,7 @@ msgctxt "title"
|
|||
msgid "Invoice Number"
|
||||
msgstr "Número de factura"
|
||||
|
||||
#: web/template/expenses/index.gohtml:87
|
||||
#: web/template/expenses/index.gohtml:96
|
||||
msgid "No expenses added yet."
|
||||
msgstr "No hi ha cap despesa."
|
||||
|
||||
|
@ -391,7 +426,7 @@ msgctxt "title"
|
|||
msgid "Edit Expense “%s”"
|
||||
msgstr "Edició de la despesa «%s»"
|
||||
|
||||
#: web/template/expenses/edit.gohtml:35
|
||||
#: web/template/expenses/edit.gohtml:36
|
||||
msgctxt "action"
|
||||
msgid "Update expense"
|
||||
msgstr "Actualitza despesa"
|
||||
|
@ -527,37 +562,37 @@ msgctxt "input"
|
|||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: pkg/products.go:169 pkg/products.go:290 pkg/expenses.go:193
|
||||
#: pkg/expenses.go:343 pkg/invoices.go:187 pkg/invoices.go:597
|
||||
#: pkg/products.go:169 pkg/products.go:290 pkg/expenses.go:202
|
||||
#: pkg/expenses.go:361 pkg/invoices.go:187 pkg/invoices.go:597
|
||||
#: pkg/invoices.go:1044 pkg/contacts.go:140 pkg/contacts.go:325
|
||||
msgctxt "input"
|
||||
msgid "Tags"
|
||||
msgstr "Etiquetes"
|
||||
|
||||
#: pkg/products.go:173 pkg/expenses.go:347 pkg/invoices.go:191
|
||||
#: pkg/products.go:173 pkg/expenses.go:365 pkg/invoices.go:191
|
||||
#: pkg/contacts.go:144
|
||||
msgctxt "input"
|
||||
msgid "Tags Condition"
|
||||
msgstr "Condició de les etiquetes"
|
||||
|
||||
#: pkg/products.go:177 pkg/expenses.go:351 pkg/invoices.go:195
|
||||
#: pkg/products.go:177 pkg/expenses.go:369 pkg/invoices.go:195
|
||||
#: pkg/contacts.go:148
|
||||
msgctxt "tag condition"
|
||||
msgid "All"
|
||||
msgstr "Totes"
|
||||
|
||||
#: pkg/products.go:178 pkg/expenses.go:352 pkg/invoices.go:196
|
||||
#: pkg/products.go:178 pkg/expenses.go:370 pkg/invoices.go:196
|
||||
#: pkg/contacts.go:149
|
||||
msgid "Invoices must have all the specified labels."
|
||||
msgstr "Les factures han de tenir totes les etiquetes."
|
||||
|
||||
#: pkg/products.go:182 pkg/expenses.go:356 pkg/invoices.go:200
|
||||
#: pkg/products.go:182 pkg/expenses.go:374 pkg/invoices.go:200
|
||||
#: pkg/contacts.go:153
|
||||
msgctxt "tag condition"
|
||||
msgid "Any"
|
||||
msgstr "Qualsevol"
|
||||
|
||||
#: pkg/products.go:183 pkg/expenses.go:357 pkg/invoices.go:201
|
||||
#: pkg/products.go:183 pkg/expenses.go:375 pkg/invoices.go:201
|
||||
#: pkg/contacts.go:154
|
||||
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."
|
||||
|
@ -572,7 +607,7 @@ msgctxt "input"
|
|||
msgid "Price"
|
||||
msgstr "Preu"
|
||||
|
||||
#: pkg/products.go:284 pkg/expenses.go:177 pkg/invoices.go:823
|
||||
#: pkg/products.go:284 pkg/expenses.go:181 pkg/invoices.go:823
|
||||
msgctxt "input"
|
||||
msgid "Taxes"
|
||||
msgstr "Imposts"
|
||||
|
@ -589,12 +624,12 @@ msgstr "No podeu deixar el preu en blanc."
|
|||
msgid "Price must be a number greater than zero."
|
||||
msgstr "El preu ha de ser un número major a zero."
|
||||
|
||||
#: pkg/products.go:313 pkg/expenses.go:215 pkg/expenses.go:220
|
||||
#: pkg/products.go:313 pkg/expenses.go:227 pkg/expenses.go:232
|
||||
#: pkg/invoices.go:877
|
||||
msgid "Selected tax is not valid."
|
||||
msgstr "Heu seleccionat un impost que no és vàlid."
|
||||
|
||||
#: pkg/products.go:314 pkg/expenses.go:216 pkg/expenses.go:221
|
||||
#: pkg/products.go:314 pkg/expenses.go:228 pkg/expenses.go:233
|
||||
#: pkg/invoices.go:878
|
||||
msgid "You can only select a tax of each class."
|
||||
msgstr "Només podeu seleccionar un impost de cada classe."
|
||||
|
@ -703,66 +738,71 @@ msgstr "La confirmació no és igual a la contrasenya."
|
|||
msgid "Selected language is not valid."
|
||||
msgstr "Heu seleccionat un idioma que no és vàlid."
|
||||
|
||||
#: pkg/expenses.go:126
|
||||
#: pkg/expenses.go:129
|
||||
msgid "Select a contact."
|
||||
msgstr "Escolliu un contacte."
|
||||
|
||||
#: pkg/expenses.go:160
|
||||
#: pkg/expenses.go:164
|
||||
msgctxt "input"
|
||||
msgid "Contact"
|
||||
msgstr "Contacte"
|
||||
|
||||
#: pkg/expenses.go:166
|
||||
#: pkg/expenses.go:170
|
||||
msgctxt "input"
|
||||
msgid "Invoice number"
|
||||
msgstr "Número de factura"
|
||||
|
||||
#: pkg/expenses.go:171 pkg/invoices.go:586
|
||||
#: pkg/expenses.go:175 pkg/invoices.go:586
|
||||
msgctxt "input"
|
||||
msgid "Invoice Date"
|
||||
msgstr "Data de factura"
|
||||
|
||||
#: pkg/expenses.go:183
|
||||
#: pkg/expenses.go:187
|
||||
msgctxt "input"
|
||||
msgid "Amount"
|
||||
msgstr "Import"
|
||||
|
||||
#: pkg/expenses.go:213
|
||||
#: pkg/expenses.go:197
|
||||
msgctxt "input"
|
||||
msgid "File"
|
||||
msgstr "Fitxer"
|
||||
|
||||
#: pkg/expenses.go:225
|
||||
msgid "Selected contact is not valid."
|
||||
msgstr "Heu seleccionat un contacte que no és vàlid."
|
||||
|
||||
#: pkg/expenses.go:214 pkg/invoices.go:641
|
||||
#: pkg/expenses.go:226 pkg/invoices.go:641
|
||||
msgid "Invoice date must be a valid date."
|
||||
msgstr "La data de facturació ha de ser vàlida."
|
||||
|
||||
#: pkg/expenses.go:217
|
||||
#: pkg/expenses.go:229
|
||||
msgid "Amount can not be empty."
|
||||
msgstr "No podeu deixar l’import en blanc."
|
||||
|
||||
#: pkg/expenses.go:218
|
||||
#: pkg/expenses.go:230
|
||||
msgid "Amount must be a number greater than zero."
|
||||
msgstr "L’import ha de ser un número major a zero."
|
||||
|
||||
#: pkg/expenses.go:322 pkg/invoices.go:160 pkg/invoices.go:580
|
||||
#: pkg/expenses.go:340 pkg/invoices.go:160 pkg/invoices.go:580
|
||||
msgctxt "input"
|
||||
msgid "Customer"
|
||||
msgstr "Client"
|
||||
|
||||
#: pkg/expenses.go:323 pkg/invoices.go:161
|
||||
#: pkg/expenses.go:341 pkg/invoices.go:161
|
||||
msgid "All customers"
|
||||
msgstr "Tots els clients"
|
||||
|
||||
#: pkg/expenses.go:328 pkg/invoices.go:172
|
||||
#: pkg/expenses.go:346 pkg/invoices.go:172
|
||||
msgctxt "input"
|
||||
msgid "Invoice Number"
|
||||
msgstr "Número de factura"
|
||||
|
||||
#: pkg/expenses.go:333 pkg/invoices.go:177
|
||||
#: pkg/expenses.go:351 pkg/invoices.go:177
|
||||
msgctxt "input"
|
||||
msgid "From Date"
|
||||
msgstr "A partir de la data"
|
||||
|
||||
#: pkg/expenses.go:338 pkg/invoices.go:182
|
||||
#: pkg/expenses.go:356 pkg/invoices.go:182
|
||||
msgctxt "input"
|
||||
msgid "To Date"
|
||||
msgstr "Fins la data"
|
||||
|
|
106
po/es.po
106
po/es.po
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: numerus\n"
|
||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||
"POT-Creation-Date: 2023-05-11 23:31+0200\n"
|
||||
"POT-Creation-Date: 2023-05-16 14:50+0200\n"
|
||||
"PO-Revision-Date: 2023-01-18 17:45+0100\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||
|
@ -146,13 +146,13 @@ msgctxt "title"
|
|||
msgid "Amount"
|
||||
msgstr "Importe"
|
||||
|
||||
#: web/template/invoices/index.gohtml:53
|
||||
#: web/template/invoices/index.gohtml:53 web/template/expenses/index.gohtml:46
|
||||
msgctxt "title"
|
||||
msgid "Download"
|
||||
msgstr "Descargar"
|
||||
|
||||
#: web/template/invoices/index.gohtml:54 web/template/contacts/index.gohtml:43
|
||||
#: web/template/expenses/index.gohtml:46 web/template/products/index.gohtml:42
|
||||
#: web/template/expenses/index.gohtml:47 web/template/products/index.gohtml:42
|
||||
msgctxt "title"
|
||||
msgid "Actions"
|
||||
msgstr "Acciones"
|
||||
|
@ -163,7 +163,7 @@ msgid "Select invoice %v"
|
|||
msgstr "Seleccionar factura %v"
|
||||
|
||||
#: web/template/invoices/index.gohtml:116 web/template/invoices/view.gohtml:19
|
||||
#: web/template/contacts/index.gohtml:69 web/template/expenses/index.gohtml:77
|
||||
#: web/template/contacts/index.gohtml:73 web/template/expenses/index.gohtml:86
|
||||
#: web/template/products/index.gohtml:71
|
||||
msgctxt "action"
|
||||
msgid "Edit"
|
||||
|
@ -218,11 +218,46 @@ msgctxt "action"
|
|||
msgid "Edit invoice"
|
||||
msgstr "Editar factura"
|
||||
|
||||
#: web/template/dashboard.gohtml:2
|
||||
#: web/template/form.gohtml:36
|
||||
msgctxt "label"
|
||||
msgid "(Max. %s)"
|
||||
msgstr "(Máx. %s)"
|
||||
|
||||
#: web/template/dashboard.gohtml:3
|
||||
msgctxt "title"
|
||||
msgid "Dashboard"
|
||||
msgstr "Panel"
|
||||
|
||||
#: web/template/dashboard.gohtml:14
|
||||
msgctxt "term"
|
||||
msgid "Sales"
|
||||
msgstr "Ventas"
|
||||
|
||||
#: web/template/dashboard.gohtml:18
|
||||
msgctxt "term"
|
||||
msgid "Income"
|
||||
msgstr "Ingresos"
|
||||
|
||||
#: web/template/dashboard.gohtml:22
|
||||
msgctxt "term"
|
||||
msgid "Expenses"
|
||||
msgstr "Gastos"
|
||||
|
||||
#: web/template/dashboard.gohtml:26
|
||||
msgctxt "term"
|
||||
msgid "VAT"
|
||||
msgstr "IVA"
|
||||
|
||||
#: web/template/dashboard.gohtml:30
|
||||
msgctxt "term"
|
||||
msgid "IRPF"
|
||||
msgstr "IRPF"
|
||||
|
||||
#: web/template/dashboard.gohtml:34
|
||||
msgctxt "term"
|
||||
msgid "Net Income"
|
||||
msgstr "Ingresos netos"
|
||||
|
||||
#: web/template/app.gohtml:23
|
||||
msgctxt "menu"
|
||||
msgid "Account"
|
||||
|
@ -295,7 +330,7 @@ msgctxt "title"
|
|||
msgid "Phone"
|
||||
msgstr "Teléfono"
|
||||
|
||||
#: web/template/contacts/index.gohtml:79
|
||||
#: web/template/contacts/index.gohtml:83
|
||||
msgid "No contacts added yet."
|
||||
msgstr "No hay contactos."
|
||||
|
||||
|
@ -357,7 +392,7 @@ msgctxt "title"
|
|||
msgid "Expenses"
|
||||
msgstr "Gastos"
|
||||
|
||||
#: web/template/expenses/new.gohtml:32 web/template/expenses/index.gohtml:15
|
||||
#: web/template/expenses/new.gohtml:33 web/template/expenses/index.gohtml:15
|
||||
msgctxt "action"
|
||||
msgid "New expense"
|
||||
msgstr "Nuevo gasto"
|
||||
|
@ -382,7 +417,7 @@ msgctxt "title"
|
|||
msgid "Invoice Number"
|
||||
msgstr "Número de factura"
|
||||
|
||||
#: web/template/expenses/index.gohtml:87
|
||||
#: web/template/expenses/index.gohtml:96
|
||||
msgid "No expenses added yet."
|
||||
msgstr "No hay gastos."
|
||||
|
||||
|
@ -391,7 +426,7 @@ msgctxt "title"
|
|||
msgid "Edit Expense “%s”"
|
||||
msgstr "Edición del gasto «%s»"
|
||||
|
||||
#: web/template/expenses/edit.gohtml:35
|
||||
#: web/template/expenses/edit.gohtml:36
|
||||
msgctxt "action"
|
||||
msgid "Update expense"
|
||||
msgstr "Actualizar gasto"
|
||||
|
@ -527,37 +562,37 @@ msgctxt "input"
|
|||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: pkg/products.go:169 pkg/products.go:290 pkg/expenses.go:193
|
||||
#: pkg/expenses.go:343 pkg/invoices.go:187 pkg/invoices.go:597
|
||||
#: pkg/products.go:169 pkg/products.go:290 pkg/expenses.go:202
|
||||
#: pkg/expenses.go:361 pkg/invoices.go:187 pkg/invoices.go:597
|
||||
#: pkg/invoices.go:1044 pkg/contacts.go:140 pkg/contacts.go:325
|
||||
msgctxt "input"
|
||||
msgid "Tags"
|
||||
msgstr "Etiquetes"
|
||||
|
||||
#: pkg/products.go:173 pkg/expenses.go:347 pkg/invoices.go:191
|
||||
#: pkg/products.go:173 pkg/expenses.go:365 pkg/invoices.go:191
|
||||
#: pkg/contacts.go:144
|
||||
msgctxt "input"
|
||||
msgid "Tags Condition"
|
||||
msgstr "Condición de las etiquetas"
|
||||
|
||||
#: pkg/products.go:177 pkg/expenses.go:351 pkg/invoices.go:195
|
||||
#: pkg/products.go:177 pkg/expenses.go:369 pkg/invoices.go:195
|
||||
#: pkg/contacts.go:148
|
||||
msgctxt "tag condition"
|
||||
msgid "All"
|
||||
msgstr "Todas"
|
||||
|
||||
#: pkg/products.go:178 pkg/expenses.go:352 pkg/invoices.go:196
|
||||
#: pkg/products.go:178 pkg/expenses.go:370 pkg/invoices.go:196
|
||||
#: pkg/contacts.go:149
|
||||
msgid "Invoices must have all the specified labels."
|
||||
msgstr "Las facturas deben tener todas las etiquetas."
|
||||
|
||||
#: pkg/products.go:182 pkg/expenses.go:356 pkg/invoices.go:200
|
||||
#: pkg/products.go:182 pkg/expenses.go:374 pkg/invoices.go:200
|
||||
#: pkg/contacts.go:153
|
||||
msgctxt "tag condition"
|
||||
msgid "Any"
|
||||
msgstr "Cualquiera"
|
||||
|
||||
#: pkg/products.go:183 pkg/expenses.go:357 pkg/invoices.go:201
|
||||
#: pkg/products.go:183 pkg/expenses.go:375 pkg/invoices.go:201
|
||||
#: pkg/contacts.go:154
|
||||
msgid "Invoices must have at least one of the specified labels."
|
||||
msgstr "Las facturas debent tener como mínimo una de las etiquetas."
|
||||
|
@ -572,7 +607,7 @@ msgctxt "input"
|
|||
msgid "Price"
|
||||
msgstr "Precio"
|
||||
|
||||
#: pkg/products.go:284 pkg/expenses.go:177 pkg/invoices.go:823
|
||||
#: pkg/products.go:284 pkg/expenses.go:181 pkg/invoices.go:823
|
||||
msgctxt "input"
|
||||
msgid "Taxes"
|
||||
msgstr "Impuestos"
|
||||
|
@ -589,12 +624,12 @@ msgstr "No podéis dejar el precio en blanco."
|
|||
msgid "Price must be a number greater than zero."
|
||||
msgstr "El precio tiene que ser un número mayor a cero."
|
||||
|
||||
#: pkg/products.go:313 pkg/expenses.go:215 pkg/expenses.go:220
|
||||
#: pkg/products.go:313 pkg/expenses.go:227 pkg/expenses.go:232
|
||||
#: pkg/invoices.go:877
|
||||
msgid "Selected tax is not valid."
|
||||
msgstr "Habéis escogido un impuesto que no es válido."
|
||||
|
||||
#: pkg/products.go:314 pkg/expenses.go:216 pkg/expenses.go:221
|
||||
#: pkg/products.go:314 pkg/expenses.go:228 pkg/expenses.go:233
|
||||
#: pkg/invoices.go:878
|
||||
msgid "You can only select a tax of each class."
|
||||
msgstr "Solo podéis escoger un impuesto de cada clase."
|
||||
|
@ -703,66 +738,71 @@ msgstr "La confirmación no corresponde con la contraseña."
|
|||
msgid "Selected language is not valid."
|
||||
msgstr "Habéis escogido un idioma que no es válido."
|
||||
|
||||
#: pkg/expenses.go:126
|
||||
#: pkg/expenses.go:129
|
||||
msgid "Select a contact."
|
||||
msgstr "Escoged un contacto"
|
||||
|
||||
#: pkg/expenses.go:160
|
||||
#: pkg/expenses.go:164
|
||||
msgctxt "input"
|
||||
msgid "Contact"
|
||||
msgstr "Contacto"
|
||||
|
||||
#: pkg/expenses.go:166
|
||||
#: pkg/expenses.go:170
|
||||
msgctxt "input"
|
||||
msgid "Invoice number"
|
||||
msgstr "Número de factura"
|
||||
|
||||
#: pkg/expenses.go:171 pkg/invoices.go:586
|
||||
#: pkg/expenses.go:175 pkg/invoices.go:586
|
||||
msgctxt "input"
|
||||
msgid "Invoice Date"
|
||||
msgstr "Fecha de factura"
|
||||
|
||||
#: pkg/expenses.go:183
|
||||
#: pkg/expenses.go:187
|
||||
msgctxt "input"
|
||||
msgid "Amount"
|
||||
msgstr "Importe"
|
||||
|
||||
#: pkg/expenses.go:213
|
||||
#: pkg/expenses.go:197
|
||||
msgctxt "input"
|
||||
msgid "File"
|
||||
msgstr "Archivo"
|
||||
|
||||
#: pkg/expenses.go:225
|
||||
msgid "Selected contact is not valid."
|
||||
msgstr "Habéis escogido un contacto que no es válido."
|
||||
|
||||
#: pkg/expenses.go:214 pkg/invoices.go:641
|
||||
#: pkg/expenses.go:226 pkg/invoices.go:641
|
||||
msgid "Invoice date must be a valid date."
|
||||
msgstr "La fecha de factura debe ser válida."
|
||||
|
||||
#: pkg/expenses.go:217
|
||||
#: pkg/expenses.go:229
|
||||
msgid "Amount can not be empty."
|
||||
msgstr "No podéis dejar el importe en blanco."
|
||||
|
||||
#: pkg/expenses.go:218
|
||||
#: pkg/expenses.go:230
|
||||
msgid "Amount must be a number greater than zero."
|
||||
msgstr "El importe tiene que ser un número mayor a cero."
|
||||
|
||||
#: pkg/expenses.go:322 pkg/invoices.go:160 pkg/invoices.go:580
|
||||
#: pkg/expenses.go:340 pkg/invoices.go:160 pkg/invoices.go:580
|
||||
msgctxt "input"
|
||||
msgid "Customer"
|
||||
msgstr "Cliente"
|
||||
|
||||
#: pkg/expenses.go:323 pkg/invoices.go:161
|
||||
#: pkg/expenses.go:341 pkg/invoices.go:161
|
||||
msgid "All customers"
|
||||
msgstr "Todos los clientes"
|
||||
|
||||
#: pkg/expenses.go:328 pkg/invoices.go:172
|
||||
#: pkg/expenses.go:346 pkg/invoices.go:172
|
||||
msgctxt "input"
|
||||
msgid "Invoice Number"
|
||||
msgstr "Número de factura"
|
||||
|
||||
#: pkg/expenses.go:333 pkg/invoices.go:177
|
||||
#: pkg/expenses.go:351 pkg/invoices.go:177
|
||||
msgctxt "input"
|
||||
msgid "From Date"
|
||||
msgstr "A partir de la fecha"
|
||||
|
||||
#: pkg/expenses.go:338 pkg/invoices.go:182
|
||||
#: pkg/expenses.go:356 pkg/invoices.go:182
|
||||
msgctxt "input"
|
||||
msgid "To Date"
|
||||
msgstr "Hasta la fecha"
|
||||
|
|
|
@ -824,6 +824,55 @@ div[x-data="snackbar"] div[role="alert"].enter.end, div[x-data="snackbar"] div[r
|
|||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* Dashboard */
|
||||
#income-statement {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
#income-statement div {
|
||||
display: block;
|
||||
padding: 2rem;
|
||||
width: calc(100%/3);
|
||||
min-width: 33rem;
|
||||
}
|
||||
|
||||
#income-statement div:first-child {
|
||||
background-color: var(--numerus--color--yellow);
|
||||
}
|
||||
|
||||
#income-statement div:nth-child(2) {
|
||||
background-color: var(--numerus--color--green);
|
||||
}
|
||||
|
||||
#income-statement div:nth-child(3) {
|
||||
background-color: var(--numerus--color--red);
|
||||
}
|
||||
|
||||
#income-statement div:nth-child(4),
|
||||
#income-statement div:nth-child(5) {
|
||||
color: var(--numerus--color--dark-gray);
|
||||
}
|
||||
|
||||
#income-statement div:last-child {
|
||||
background-color: var(--numerus--color--black);
|
||||
color: var(--numerus--color--white);
|
||||
}
|
||||
|
||||
#income-statement dt {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
#income-statement dd {
|
||||
text-align: right;
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
#income-statement dd span {
|
||||
font-size: .66666em;
|
||||
}
|
||||
|
||||
/* Remix Icon */
|
||||
|
||||
@font-face {
|
||||
|
|
|
@ -1,9 +1,38 @@
|
|||
{{ define "title" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.DashboardPage*/ -}}
|
||||
{{( pgettext "Dashboard" "title" )}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "breadcrumbs" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.DashboardPage*/ -}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" }}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.DashboardPage*/ -}}
|
||||
<dl id="income-statement">
|
||||
<div>
|
||||
<dt>{{ (pgettext "Sales" "term") }}</dt>
|
||||
<dd>{{ formatPriceSpan .Sales }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>{{ (pgettext "Income" "term") }}</dt>
|
||||
<dd>{{ formatPriceSpan .Income }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>{{ (pgettext "Expenses" "term") }}</dt>
|
||||
<dd>{{ formatPriceSpan .Expenses }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>{{ (pgettext "VAT" "term") }}</dt>
|
||||
<dd>{{ formatPriceSpan .VAT }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>{{ (pgettext "IRPF" "term") }}</dt>
|
||||
<dd>{{ formatPriceSpan .IRPF }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>{{ (pgettext "Net Income" "term") }}</dt>
|
||||
<dd>{{ formatPriceSpan .NetIncome }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{{- end }}
|
||||
|
|
Loading…
Reference in New Issue