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:
jordi fita mas 2023-05-16 14:56:49 +02:00
parent 7921b9cf80
commit ce42880697
7 changed files with 304 additions and 76 deletions

64
pkg/dashboard.go Normal file
View File

@ -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)
}

View File

@ -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"))

View File

@ -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
View File

@ -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 limport en blanc."
#: pkg/expenses.go:218
#: pkg/expenses.go:230
msgid "Amount must be a number greater than zero."
msgstr "Limport 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
View File

@ -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"

View File

@ -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 {

View File

@ -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 }}