Compare commits

..

No commits in common. "4d2379555e3547a20c6647183a5fd4f0c276af71" and "843f7746cf4b53399c30a0e31fff362420528d8f" have entirely different histories.

8 changed files with 75 additions and 147 deletions

5
debian/control vendored
View File

@ -32,7 +32,7 @@ Depends:
${misc:Depends}, ${misc:Depends},
golang-github-jackc-pgx-v4-dev golang-github-jackc-pgx-v4-dev
Description: Simple invoicing and accounting web application Description: Simple invoicing and accounting web application
A simple web application to keep invoice and accounting records, intended for A simple web application to keep invoice and accouting records, intended for
freelancers working in Spain. freelancers working in Spain.
. .
This is the dev package. This is the dev package.
@ -41,8 +41,7 @@ Package: numerus
Architecture: any Architecture: any
Depends: Depends:
${shlibs:Depends}, ${shlibs:Depends},
${misc:Depends}, ${misc:Depends}
weasyprint
Built-Using: ${misc:Built-Using} Built-Using: ${misc:Built-Using}
Description: Simple invoicing and accounting web application Description: Simple invoicing and accounting web application
A simple web application to keep invoice and accouting records, intended for A simple web application to keep invoice and accouting records, intended for

View File

@ -1,18 +1,13 @@
package pkg package pkg
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"html/template" "html/template"
"io"
"log"
"math" "math"
"net/http" "net/http"
"os/exec"
"strconv" "strconv"
"strings"
"time" "time"
) )
@ -57,7 +52,7 @@ func mustCollectInvoiceEntries(ctx context.Context, conn *Conn, company *Company
return entries return entries
} }
func ServeInvoice(w http.ResponseWriter, r *http.Request, params httprouter.Params) { func GetInvoiceForm(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
locale := getLocale(r) locale := getLocale(r)
conn := getConn(r) conn := getConn(r)
company := mustGetCompany(r) company := mustGetCompany(r)
@ -70,52 +65,16 @@ func ServeInvoice(w http.ResponseWriter, r *http.Request, params httprouter.Para
return return
} }
pdf := false
if strings.HasSuffix(slug, ".pdf") {
pdf = true
slug = slug[:len(slug)-len(".pdf")]
}
invoice := mustGetInvoice(r.Context(), conn, company, slug) invoice := mustGetInvoice(r.Context(), conn, company, slug)
if invoice == nil { if invoice == nil {
http.NotFound(w, r) http.NotFound(w, r)
return return
} }
if pdf {
cmd := exec.Command("weasyprint", "--stylesheet", "web/static/invoice.css", "-", "-")
var stderr bytes.Buffer
cmd.Stderr = &stderr
stdin, err := cmd.StdinPipe()
if err != nil {
panic(err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
panic(err)
}
defer stdout.Close()
if err = cmd.Start(); err != nil {
panic(err)
}
go func() {
defer stdin.Close()
mustRenderAppTemplate(stdin, r, "invoices/view.gohtml", invoice)
}()
w.Header().Set("Content-Type", "application/pdf")
if _, err = io.Copy(w, stdout); err != nil {
panic(err)
}
if err := cmd.Wait(); err != nil {
log.Printf("ERR - %v\n", stderr.String())
panic(err)
}
} else {
mustRenderAppTemplate(w, r, "invoices/view.gohtml", invoice) mustRenderAppTemplate(w, r, "invoices/view.gohtml", invoice)
} }
}
type invoice struct { type invoice struct {
Number string Number string
Slug string
Date time.Time Date time.Time
Invoicer taxDetails Invoicer taxDetails
Invoicee taxDetails Invoicee taxDetails
@ -146,9 +105,7 @@ type invoiceProduct struct {
} }
func mustGetInvoice(ctx context.Context, conn *Conn, company *Company, slug string) *invoice { func mustGetInvoice(ctx context.Context, conn *Conn, company *Company, slug string) *invoice {
inv := &invoice{ inv := &invoice{}
Slug: slug,
}
var invoiceId int var invoiceId int
var decimalDigits int var decimalDigits int
if notFoundErrorOrPanic(conn.QueryRow(ctx, "select invoice_id, decimal_digits, invoice_number, invoice_date, notes, business_name, vatin, phone, email, address, city, province, postal_code, to_price(subtotal, decimal_digits), to_price(total, decimal_digits) from invoice join contact using (contact_id) join invoice_amount using (invoice_id) join currency using (currency_code) where invoice.slug = $1", slug).Scan(&invoiceId, &decimalDigits, &inv.Number, &inv.Date, &inv.Notes, &inv.Invoicee.Name, &inv.Invoicee.VATIN, &inv.Invoicee.Phone, &inv.Invoicee.Email, &inv.Invoicee.Address, &inv.Invoicee.City, &inv.Invoicee.Province, &inv.Invoicee.PostalCode, &inv.Subtotal, &inv.Total)) { if notFoundErrorOrPanic(conn.QueryRow(ctx, "select invoice_id, decimal_digits, invoice_number, invoice_date, notes, business_name, vatin, phone, email, address, city, province, postal_code, to_price(subtotal, decimal_digits), to_price(total, decimal_digits) from invoice join contact using (contact_id) join invoice_amount using (invoice_id) join currency using (currency_code) where invoice.slug = $1", slug).Scan(&invoiceId, &decimalDigits, &inv.Number, &inv.Date, &inv.Notes, &inv.Invoicee.Name, &inv.Invoicee.VATIN, &inv.Invoicee.Phone, &inv.Invoicee.Email, &inv.Invoicee.Address, &inv.Invoicee.City, &inv.Invoicee.Province, &inv.Invoicee.PostalCode, &inv.Subtotal, &inv.Total)) {

View File

@ -24,7 +24,7 @@ func NewRouter(db *Db) http.Handler {
companyRouter.PUT("/products/:slug", HandleUpdateProduct) companyRouter.PUT("/products/:slug", HandleUpdateProduct)
companyRouter.GET("/invoices", IndexInvoices) companyRouter.GET("/invoices", IndexInvoices)
companyRouter.POST("/invoices", HandleAddInvoice) companyRouter.POST("/invoices", HandleAddInvoice)
companyRouter.GET("/invoices/:slug", ServeInvoice) companyRouter.GET("/invoices/:slug", GetInvoiceForm)
companyRouter.POST("/invoices/new/products", HandleAddProductsToInvoice) companyRouter.POST("/invoices/new/products", HandleAddProductsToInvoice)
companyRouter.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { companyRouter.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
mustRenderAppTemplate(w, r, "dashboard.gohtml", nil) mustRenderAppTemplate(w, r, "dashboard.gohtml", nil)

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-02-26 17:11+0100\n" "POT-Creation-Date: 2023-02-24 11:52+0100\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"
@ -59,7 +59,7 @@ msgid "Name"
msgstr "Nom" msgstr "Nom"
#: web/template/invoices/products.gohtml:43 #: web/template/invoices/products.gohtml:43
#: web/template/invoices/view.gohtml:59 web/template/products/index.gohtml:23 #: web/template/invoices/view.gohtml:42 web/template/products/index.gohtml:23
msgctxt "title" msgctxt "title"
msgid "Price" msgid "Price"
msgstr "Preu" msgstr "Preu"
@ -74,13 +74,13 @@ msgctxt "action"
msgid "Add products" msgid "Add products"
msgstr "Afegeix productes" msgstr "Afegeix productes"
#: web/template/invoices/new.gohtml:41 web/template/invoices/view.gohtml:61 #: web/template/invoices/new.gohtml:41 web/template/invoices/view.gohtml:44
#: web/template/invoices/view.gohtml:87 #: web/template/invoices/view.gohtml:71
msgctxt "title" msgctxt "title"
msgid "Subtotal" msgid "Subtotal"
msgstr "Subtotal" msgstr "Subtotal"
#: web/template/invoices/new.gohtml:51 web/template/invoices/view.gohtml:97 #: web/template/invoices/new.gohtml:51 web/template/invoices/view.gohtml:81
msgctxt "title" msgctxt "title"
msgid "Total" msgid "Total"
msgstr "Total" msgstr "Total"
@ -100,7 +100,7 @@ msgctxt "invoice"
msgid "All" msgid "All"
msgstr "Totes" msgstr "Totes"
#: web/template/invoices/index.gohtml:22 web/template/invoices/view.gohtml:25 #: web/template/invoices/index.gohtml:22 web/template/invoices/view.gohtml:18
msgctxt "title" msgctxt "title"
msgid "Date" msgid "Date"
msgstr "Data" msgstr "Data"
@ -135,26 +135,21 @@ msgctxt "title"
msgid "Download" msgid "Download"
msgstr "Descàrrega" msgstr "Descàrrega"
#: web/template/invoices/index.gohtml:50 #: web/template/invoices/index.gohtml:47
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/view.gohtml:2 web/template/invoices/view.gohtml:24 #: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:17
msgctxt "title" msgctxt "title"
msgid "Invoice %s" msgid "Invoice %s"
msgstr "Factura %s" msgstr "Factura %s"
#: web/template/invoices/view.gohtml:16 #: web/template/invoices/view.gohtml:41
msgctxt "action"
msgid "Download invoice"
msgstr "Descarrega factura"
#: web/template/invoices/view.gohtml:58
msgctxt "title" msgctxt "title"
msgid "Concept" msgid "Concept"
msgstr "Concepte" msgstr "Concepte"
#: web/template/invoices/view.gohtml:60 #: web/template/invoices/view.gohtml:43
msgctxt "title" msgctxt "title"
msgid "Units" msgid "Units"
msgstr "Unitats" msgstr "Unitats"
@ -369,40 +364,40 @@ 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:165 pkg/invoices.go:435 #: pkg/products.go:165 pkg/invoices.go:392
msgctxt "input" msgctxt "input"
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
#: pkg/products.go:171 pkg/invoices.go:440 #: pkg/products.go:171 pkg/invoices.go:397
msgctxt "input" msgctxt "input"
msgid "Description" msgid "Description"
msgstr "Descripció" msgstr "Descripció"
#: pkg/products.go:176 pkg/invoices.go:444 #: pkg/products.go:176 pkg/invoices.go:401
msgctxt "input" msgctxt "input"
msgid "Price" msgid "Price"
msgstr "Preu" msgstr "Preu"
#: pkg/products.go:186 pkg/invoices.go:350 pkg/invoices.go:470 #: pkg/products.go:186 pkg/invoices.go:307 pkg/invoices.go:427
msgctxt "input" msgctxt "input"
msgid "Taxes" msgid "Taxes"
msgstr "Imposts" msgstr "Imposts"
#: pkg/products.go:206 pkg/profile.go:92 pkg/invoices.go:383 #: pkg/products.go:206 pkg/profile.go:92 pkg/invoices.go:340
#: pkg/invoices.go:506 #: pkg/invoices.go:463
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:207 pkg/invoices.go:507 #: pkg/products.go:207 pkg/invoices.go:464
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:208 pkg/invoices.go:508 #: pkg/products.go:208 pkg/invoices.go:465
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:210 pkg/invoices.go:387 pkg/invoices.go:516 #: pkg/products.go:210 pkg/invoices.go:344 pkg/invoices.go:473
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."
@ -465,70 +460,70 @@ msgstr "La confirmació no és igual a la contrasenya."
msgid "Selected language is not valid." msgid "Selected language is not valid."
msgstr "Heu seleccionat un idioma que no és vàlid." msgstr "Heu seleccionat un idioma que no és vàlid."
#: pkg/invoices.go:201 #: pkg/invoices.go:158
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:276 #: pkg/invoices.go:233
msgid "Invalid action" msgid "Invalid action"
msgstr "Acció invàlida." msgstr "Acció invàlida."
#: pkg/invoices.go:327 #: pkg/invoices.go:284
msgctxt "input" msgctxt "input"
msgid "Customer" msgid "Customer"
msgstr "Client" msgstr "Client"
#: pkg/invoices.go:333 #: pkg/invoices.go:290
msgctxt "input" msgctxt "input"
msgid "Number" msgid "Number"
msgstr "Número" msgstr "Número"
#: pkg/invoices.go:339 #: pkg/invoices.go:296
msgctxt "input" msgctxt "input"
msgid "Invoice Date" msgid "Invoice Date"
msgstr "Data de factura" msgstr "Data de factura"
#: pkg/invoices.go:345 #: pkg/invoices.go:302
msgctxt "input" msgctxt "input"
msgid "Notes" msgid "Notes"
msgstr "Notes" msgstr "Notes"
#: pkg/invoices.go:384 #: pkg/invoices.go:341
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:385 #: pkg/invoices.go:342
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/invoices.go:430 #: pkg/invoices.go:387
msgctxt "input" msgctxt "input"
msgid "Id" msgid "Id"
msgstr "Identificador" msgstr "Identificador"
#: pkg/invoices.go:453 #: pkg/invoices.go:410
msgctxt "input" msgctxt "input"
msgid "Quantity" msgid "Quantity"
msgstr "Quantitat" msgstr "Quantitat"
#: pkg/invoices.go:461 #: pkg/invoices.go:418
msgctxt "input" msgctxt "input"
msgid "Discount (%)" msgid "Discount (%)"
msgstr "Descompte (%)" msgstr "Descompte (%)"
#: pkg/invoices.go:510 #: pkg/invoices.go:467
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/invoices.go:511 #: pkg/invoices.go:468
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/invoices.go:513 #: pkg/invoices.go:470
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/invoices.go:514 #: pkg/invoices.go:471
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."

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-02-26 17:11+0100\n" "POT-Creation-Date: 2023-02-24 11:52+0100\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"
@ -59,7 +59,7 @@ msgid "Name"
msgstr "Nombre" msgstr "Nombre"
#: web/template/invoices/products.gohtml:43 #: web/template/invoices/products.gohtml:43
#: web/template/invoices/view.gohtml:59 web/template/products/index.gohtml:23 #: web/template/invoices/view.gohtml:42 web/template/products/index.gohtml:23
msgctxt "title" msgctxt "title"
msgid "Price" msgid "Price"
msgstr "Precio" msgstr "Precio"
@ -74,13 +74,13 @@ msgctxt "action"
msgid "Add products" msgid "Add products"
msgstr "Añadir productos" msgstr "Añadir productos"
#: web/template/invoices/new.gohtml:41 web/template/invoices/view.gohtml:61 #: web/template/invoices/new.gohtml:41 web/template/invoices/view.gohtml:44
#: web/template/invoices/view.gohtml:87 #: web/template/invoices/view.gohtml:71
msgctxt "title" msgctxt "title"
msgid "Subtotal" msgid "Subtotal"
msgstr "Subtotal" msgstr "Subtotal"
#: web/template/invoices/new.gohtml:51 web/template/invoices/view.gohtml:97 #: web/template/invoices/new.gohtml:51 web/template/invoices/view.gohtml:81
msgctxt "title" msgctxt "title"
msgid "Total" msgid "Total"
msgstr "Total" msgstr "Total"
@ -100,7 +100,7 @@ msgctxt "invoice"
msgid "All" msgid "All"
msgstr "Todas" msgstr "Todas"
#: web/template/invoices/index.gohtml:22 web/template/invoices/view.gohtml:25 #: web/template/invoices/index.gohtml:22 web/template/invoices/view.gohtml:18
msgctxt "title" msgctxt "title"
msgid "Date" msgid "Date"
msgstr "Fecha" msgstr "Fecha"
@ -135,26 +135,21 @@ msgctxt "title"
msgid "Download" msgid "Download"
msgstr "Descargar" msgstr "Descargar"
#: web/template/invoices/index.gohtml:50 #: web/template/invoices/index.gohtml:47
msgid "No invoices added yet." msgid "No invoices added yet."
msgstr "No hay facturas." msgstr "No hay facturas."
#: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:24 #: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:17
msgctxt "title" msgctxt "title"
msgid "Invoice %s" msgid "Invoice %s"
msgstr "Factura %s" msgstr "Factura %s"
#: web/template/invoices/view.gohtml:16 #: web/template/invoices/view.gohtml:41
msgctxt "action"
msgid "Download invoice"
msgstr "Descargar factura"
#: web/template/invoices/view.gohtml:58
msgctxt "title" msgctxt "title"
msgid "Concept" msgid "Concept"
msgstr "Concepto" msgstr "Concepto"
#: web/template/invoices/view.gohtml:60 #: web/template/invoices/view.gohtml:43
msgctxt "title" msgctxt "title"
msgid "Units" msgid "Units"
msgstr "Unidades" msgstr "Unidades"
@ -369,40 +364,40 @@ 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:165 pkg/invoices.go:435 #: pkg/products.go:165 pkg/invoices.go:392
msgctxt "input" msgctxt "input"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
#: pkg/products.go:171 pkg/invoices.go:440 #: pkg/products.go:171 pkg/invoices.go:397
msgctxt "input" msgctxt "input"
msgid "Description" msgid "Description"
msgstr "Descripción" msgstr "Descripción"
#: pkg/products.go:176 pkg/invoices.go:444 #: pkg/products.go:176 pkg/invoices.go:401
msgctxt "input" msgctxt "input"
msgid "Price" msgid "Price"
msgstr "Precio" msgstr "Precio"
#: pkg/products.go:186 pkg/invoices.go:350 pkg/invoices.go:470 #: pkg/products.go:186 pkg/invoices.go:307 pkg/invoices.go:427
msgctxt "input" msgctxt "input"
msgid "Taxes" msgid "Taxes"
msgstr "Impuestos" msgstr "Impuestos"
#: pkg/products.go:206 pkg/profile.go:92 pkg/invoices.go:383 #: pkg/products.go:206 pkg/profile.go:92 pkg/invoices.go:340
#: pkg/invoices.go:506 #: pkg/invoices.go:463
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:207 pkg/invoices.go:507 #: pkg/products.go:207 pkg/invoices.go:464
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:208 pkg/invoices.go:508 #: pkg/products.go:208 pkg/invoices.go:465
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:210 pkg/invoices.go:387 pkg/invoices.go:516 #: pkg/products.go:210 pkg/invoices.go:344 pkg/invoices.go:473
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."
@ -465,70 +460,70 @@ msgstr "La confirmación no corresponde con la contraseña."
msgid "Selected language is not valid." msgid "Selected language is not valid."
msgstr "Habéis escogido un idioma que no es válido." msgstr "Habéis escogido un idioma que no es válido."
#: pkg/invoices.go:201 #: pkg/invoices.go:158
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:276 #: pkg/invoices.go:233
msgid "Invalid action" msgid "Invalid action"
msgstr "Acción inválida." msgstr "Acción inválida."
#: pkg/invoices.go:327 #: pkg/invoices.go:284
msgctxt "input" msgctxt "input"
msgid "Customer" msgid "Customer"
msgstr "Cliente" msgstr "Cliente"
#: pkg/invoices.go:333 #: pkg/invoices.go:290
msgctxt "input" msgctxt "input"
msgid "Number" msgid "Number"
msgstr "Número" msgstr "Número"
#: pkg/invoices.go:339 #: pkg/invoices.go:296
msgctxt "input" msgctxt "input"
msgid "Invoice Date" msgid "Invoice Date"
msgstr "Fecha de factura" msgstr "Fecha de factura"
#: pkg/invoices.go:345 #: pkg/invoices.go:302
msgctxt "input" msgctxt "input"
msgid "Notes" msgid "Notes"
msgstr "Notas" msgstr "Notas"
#: pkg/invoices.go:384 #: pkg/invoices.go:341
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:385 #: pkg/invoices.go:342
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/invoices.go:430 #: pkg/invoices.go:387
msgctxt "input" msgctxt "input"
msgid "Id" msgid "Id"
msgstr "Identificador" msgstr "Identificador"
#: pkg/invoices.go:453 #: pkg/invoices.go:410
msgctxt "input" msgctxt "input"
msgid "Quantity" msgid "Quantity"
msgstr "Cantidad" msgstr "Cantidad"
#: pkg/invoices.go:461 #: pkg/invoices.go:418
msgctxt "input" msgctxt "input"
msgid "Discount (%)" msgid "Discount (%)"
msgstr "Descuento (%)" msgstr "Descuento (%)"
#: pkg/invoices.go:510 #: pkg/invoices.go:467
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/invoices.go:511 #: pkg/invoices.go:468
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/invoices.go:513 #: pkg/invoices.go:470
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/invoices.go:514 #: pkg/invoices.go:471
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 percentage entre 0 y 100." msgstr "El descuento tiene que ser un percentage entre 0 y 100."

View File

@ -508,15 +508,6 @@ main > nav {
text-align: right; text-align: right;
} }
.invoice-download {
text-align: center;
}
.invoice-download a {
color: inherit;
text-decoration: none;
}
/* Remix Icon */ /* Remix Icon */
@font-face { @font-face {

View File

@ -39,10 +39,7 @@
<td class="invoice-status-{{ .Status }}">{{ .StatusLabel }}</td> <td class="invoice-status-{{ .Status }}">{{ .StatusLabel }}</td>
<td></td> <td></td>
<td class="numeric">{{ .Total|formatPrice }}</td> <td class="numeric">{{ .Total|formatPrice }}</td>
<td class="invoice-download"><a href="{{ companyURI "/invoices/"}}{{ .Slug }}.pdf" download="{{ .Number}}.pdf" <td></td>
title="{{( pgettext "Download invoice" "action" )}}"
aria-label="{{( pgettext "Download invoice %s" "action" )}}"><i
class="ri-download-line"></i></a></td>
</tr> </tr>
{{- end }} {{- end }}
{{ else }} {{ else }}

View File

@ -10,13 +10,7 @@
<a href="{{ companyURI "/invoices"}}">{{( pgettext "Invoices" "title" )}}</a> / <a href="{{ companyURI "/invoices"}}">{{( pgettext "Invoices" "title" )}}</a> /
<a>{{ .Number }}</a> <a>{{ .Number }}</a>
</p> </p>
<p>
<a class="primary button"
href="{{ companyURI "/invoices/" }}{{ .Slug }}.pdf"
download="{{ .Number}}.pdf">{{( pgettext "Download invoice" "action" )}}</a>
</p>
</nav> </nav>
<link rel="stylesheet" type="text/css" href="/static/invoice.css"> <link rel="stylesheet" type="text/css" href="/static/invoice.css">
<article class="invoice"> <article class="invoice">
<header> <header>