Compare commits
2 Commits
843f7746cf
...
4d2379555e
Author | SHA1 | Date |
---|---|---|
jordi fita mas | 4d2379555e | |
jordi fita mas | 47d3e1940c |
|
@ -32,7 +32,7 @@ Depends:
|
|||
${misc:Depends},
|
||||
golang-github-jackc-pgx-v4-dev
|
||||
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 accounting records, intended for
|
||||
freelancers working in Spain.
|
||||
.
|
||||
This is the dev package.
|
||||
|
@ -41,7 +41,8 @@ Package: numerus
|
|||
Architecture: any
|
||||
Depends:
|
||||
${shlibs:Depends},
|
||||
${misc:Depends}
|
||||
${misc:Depends},
|
||||
weasyprint
|
||||
Built-Using: ${misc:Built-Using}
|
||||
Description: Simple invoicing and accounting web application
|
||||
A simple web application to keep invoice and accouting records, intended for
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
package pkg
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"html/template"
|
||||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -52,7 +57,7 @@ func mustCollectInvoiceEntries(ctx context.Context, conn *Conn, company *Company
|
|||
return entries
|
||||
}
|
||||
|
||||
func GetInvoiceForm(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||
func ServeInvoice(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||
locale := getLocale(r)
|
||||
conn := getConn(r)
|
||||
company := mustGetCompany(r)
|
||||
|
@ -65,16 +70,52 @@ func GetInvoiceForm(w http.ResponseWriter, r *http.Request, params httprouter.Pa
|
|||
return
|
||||
}
|
||||
|
||||
pdf := false
|
||||
if strings.HasSuffix(slug, ".pdf") {
|
||||
pdf = true
|
||||
slug = slug[:len(slug)-len(".pdf")]
|
||||
}
|
||||
invoice := mustGetInvoice(r.Context(), conn, company, slug)
|
||||
if invoice == nil {
|
||||
http.NotFound(w, r)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
type invoice struct {
|
||||
Number string
|
||||
Slug string
|
||||
Date time.Time
|
||||
Invoicer taxDetails
|
||||
Invoicee taxDetails
|
||||
|
@ -105,7 +146,9 @@ type invoiceProduct struct {
|
|||
}
|
||||
|
||||
func mustGetInvoice(ctx context.Context, conn *Conn, company *Company, slug string) *invoice {
|
||||
inv := &invoice{}
|
||||
inv := &invoice{
|
||||
Slug: slug,
|
||||
}
|
||||
var invoiceId 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)) {
|
||||
|
|
|
@ -24,7 +24,7 @@ func NewRouter(db *Db) http.Handler {
|
|||
companyRouter.PUT("/products/:slug", HandleUpdateProduct)
|
||||
companyRouter.GET("/invoices", IndexInvoices)
|
||||
companyRouter.POST("/invoices", HandleAddInvoice)
|
||||
companyRouter.GET("/invoices/:slug", GetInvoiceForm)
|
||||
companyRouter.GET("/invoices/:slug", ServeInvoice)
|
||||
companyRouter.POST("/invoices/new/products", HandleAddProductsToInvoice)
|
||||
companyRouter.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
mustRenderAppTemplate(w, r, "dashboard.gohtml", nil)
|
||||
|
|
73
po/ca.po
73
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-02-24 11:52+0100\n"
|
||||
"POT-Creation-Date: 2023-02-26 17:11+0100\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"
|
||||
|
@ -59,7 +59,7 @@ msgid "Name"
|
|||
msgstr "Nom"
|
||||
|
||||
#: web/template/invoices/products.gohtml:43
|
||||
#: web/template/invoices/view.gohtml:42 web/template/products/index.gohtml:23
|
||||
#: web/template/invoices/view.gohtml:59 web/template/products/index.gohtml:23
|
||||
msgctxt "title"
|
||||
msgid "Price"
|
||||
msgstr "Preu"
|
||||
|
@ -74,13 +74,13 @@ msgctxt "action"
|
|||
msgid "Add products"
|
||||
msgstr "Afegeix productes"
|
||||
|
||||
#: web/template/invoices/new.gohtml:41 web/template/invoices/view.gohtml:44
|
||||
#: web/template/invoices/view.gohtml:71
|
||||
#: web/template/invoices/new.gohtml:41 web/template/invoices/view.gohtml:61
|
||||
#: web/template/invoices/view.gohtml:87
|
||||
msgctxt "title"
|
||||
msgid "Subtotal"
|
||||
msgstr "Subtotal"
|
||||
|
||||
#: web/template/invoices/new.gohtml:51 web/template/invoices/view.gohtml:81
|
||||
#: web/template/invoices/new.gohtml:51 web/template/invoices/view.gohtml:97
|
||||
msgctxt "title"
|
||||
msgid "Total"
|
||||
msgstr "Total"
|
||||
|
@ -100,7 +100,7 @@ msgctxt "invoice"
|
|||
msgid "All"
|
||||
msgstr "Totes"
|
||||
|
||||
#: web/template/invoices/index.gohtml:22 web/template/invoices/view.gohtml:18
|
||||
#: web/template/invoices/index.gohtml:22 web/template/invoices/view.gohtml:25
|
||||
msgctxt "title"
|
||||
msgid "Date"
|
||||
msgstr "Data"
|
||||
|
@ -135,21 +135,26 @@ msgctxt "title"
|
|||
msgid "Download"
|
||||
msgstr "Descàrrega"
|
||||
|
||||
#: web/template/invoices/index.gohtml:47
|
||||
#: web/template/invoices/index.gohtml:50
|
||||
msgid "No invoices added yet."
|
||||
msgstr "No hi ha cap factura."
|
||||
|
||||
#: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:17
|
||||
#: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:24
|
||||
msgctxt "title"
|
||||
msgid "Invoice %s"
|
||||
msgstr "Factura %s"
|
||||
|
||||
#: web/template/invoices/view.gohtml:41
|
||||
#: web/template/invoices/view.gohtml:16
|
||||
msgctxt "action"
|
||||
msgid "Download invoice"
|
||||
msgstr "Descarrega factura"
|
||||
|
||||
#: web/template/invoices/view.gohtml:58
|
||||
msgctxt "title"
|
||||
msgid "Concept"
|
||||
msgstr "Concepte"
|
||||
|
||||
#: web/template/invoices/view.gohtml:43
|
||||
#: web/template/invoices/view.gohtml:60
|
||||
msgctxt "title"
|
||||
msgid "Units"
|
||||
msgstr "Unitats"
|
||||
|
@ -364,40 +369,40 @@ msgstr "No podeu deixar la contrasenya en blanc."
|
|||
msgid "Invalid user or password."
|
||||
msgstr "Nom d’usuari o contrasenya incorrectes."
|
||||
|
||||
#: pkg/products.go:165 pkg/invoices.go:392
|
||||
#: pkg/products.go:165 pkg/invoices.go:435
|
||||
msgctxt "input"
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: pkg/products.go:171 pkg/invoices.go:397
|
||||
#: pkg/products.go:171 pkg/invoices.go:440
|
||||
msgctxt "input"
|
||||
msgid "Description"
|
||||
msgstr "Descripció"
|
||||
|
||||
#: pkg/products.go:176 pkg/invoices.go:401
|
||||
#: pkg/products.go:176 pkg/invoices.go:444
|
||||
msgctxt "input"
|
||||
msgid "Price"
|
||||
msgstr "Preu"
|
||||
|
||||
#: pkg/products.go:186 pkg/invoices.go:307 pkg/invoices.go:427
|
||||
#: pkg/products.go:186 pkg/invoices.go:350 pkg/invoices.go:470
|
||||
msgctxt "input"
|
||||
msgid "Taxes"
|
||||
msgstr "Imposts"
|
||||
|
||||
#: pkg/products.go:206 pkg/profile.go:92 pkg/invoices.go:340
|
||||
#: pkg/invoices.go:463
|
||||
#: pkg/products.go:206 pkg/profile.go:92 pkg/invoices.go:383
|
||||
#: pkg/invoices.go:506
|
||||
msgid "Name can not be empty."
|
||||
msgstr "No podeu deixar el nom en blanc."
|
||||
|
||||
#: pkg/products.go:207 pkg/invoices.go:464
|
||||
#: pkg/products.go:207 pkg/invoices.go:507
|
||||
msgid "Price can not be empty."
|
||||
msgstr "No podeu deixar el preu en blanc."
|
||||
|
||||
#: pkg/products.go:208 pkg/invoices.go:465
|
||||
#: pkg/products.go:208 pkg/invoices.go:508
|
||||
msgid "Price must be a number greater than zero."
|
||||
msgstr "El preu ha de ser un número major a zero."
|
||||
|
||||
#: pkg/products.go:210 pkg/invoices.go:344 pkg/invoices.go:473
|
||||
#: pkg/products.go:210 pkg/invoices.go:387 pkg/invoices.go:516
|
||||
msgid "Selected tax is not valid."
|
||||
msgstr "Heu seleccionat un impost que no és vàlid."
|
||||
|
||||
|
@ -460,70 +465,70 @@ 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/invoices.go:158
|
||||
#: pkg/invoices.go:201
|
||||
msgid "Select a customer to bill."
|
||||
msgstr "Escolliu un client a facturar."
|
||||
|
||||
#: pkg/invoices.go:233
|
||||
#: pkg/invoices.go:276
|
||||
msgid "Invalid action"
|
||||
msgstr "Acció invàlida."
|
||||
|
||||
#: pkg/invoices.go:284
|
||||
#: pkg/invoices.go:327
|
||||
msgctxt "input"
|
||||
msgid "Customer"
|
||||
msgstr "Client"
|
||||
|
||||
#: pkg/invoices.go:290
|
||||
#: pkg/invoices.go:333
|
||||
msgctxt "input"
|
||||
msgid "Number"
|
||||
msgstr "Número"
|
||||
|
||||
#: pkg/invoices.go:296
|
||||
#: pkg/invoices.go:339
|
||||
msgctxt "input"
|
||||
msgid "Invoice Date"
|
||||
msgstr "Data de factura"
|
||||
|
||||
#: pkg/invoices.go:302
|
||||
#: pkg/invoices.go:345
|
||||
msgctxt "input"
|
||||
msgid "Notes"
|
||||
msgstr "Notes"
|
||||
|
||||
#: pkg/invoices.go:341
|
||||
#: pkg/invoices.go:384
|
||||
msgid "Invoice date can not be empty."
|
||||
msgstr "No podeu deixar la data de la factura en blanc."
|
||||
|
||||
#: pkg/invoices.go:342
|
||||
#: pkg/invoices.go:385
|
||||
msgid "Invoice date must be a valid date."
|
||||
msgstr "La data de facturació ha de ser vàlida."
|
||||
|
||||
#: pkg/invoices.go:387
|
||||
#: pkg/invoices.go:430
|
||||
msgctxt "input"
|
||||
msgid "Id"
|
||||
msgstr "Identificador"
|
||||
|
||||
#: pkg/invoices.go:410
|
||||
#: pkg/invoices.go:453
|
||||
msgctxt "input"
|
||||
msgid "Quantity"
|
||||
msgstr "Quantitat"
|
||||
|
||||
#: pkg/invoices.go:418
|
||||
#: pkg/invoices.go:461
|
||||
msgctxt "input"
|
||||
msgid "Discount (%)"
|
||||
msgstr "Descompte (%)"
|
||||
|
||||
#: pkg/invoices.go:467
|
||||
#: pkg/invoices.go:510
|
||||
msgid "Quantity can not be empty."
|
||||
msgstr "No podeu deixar la quantitat en blanc."
|
||||
|
||||
#: pkg/invoices.go:468
|
||||
#: pkg/invoices.go:511
|
||||
msgid "Quantity must be a number greater than zero."
|
||||
msgstr "La quantitat ha de ser un número major a zero."
|
||||
|
||||
#: pkg/invoices.go:470
|
||||
#: pkg/invoices.go:513
|
||||
msgid "Discount can not be empty."
|
||||
msgstr "No podeu deixar el descompte en blanc."
|
||||
|
||||
#: pkg/invoices.go:471
|
||||
#: pkg/invoices.go:514
|
||||
msgid "Discount must be a percentage between 0 and 100."
|
||||
msgstr "El descompte ha de ser un percentatge entre 0 i 100."
|
||||
|
||||
|
|
73
po/es.po
73
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-02-24 11:52+0100\n"
|
||||
"POT-Creation-Date: 2023-02-26 17:11+0100\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"
|
||||
|
@ -59,7 +59,7 @@ msgid "Name"
|
|||
msgstr "Nombre"
|
||||
|
||||
#: web/template/invoices/products.gohtml:43
|
||||
#: web/template/invoices/view.gohtml:42 web/template/products/index.gohtml:23
|
||||
#: web/template/invoices/view.gohtml:59 web/template/products/index.gohtml:23
|
||||
msgctxt "title"
|
||||
msgid "Price"
|
||||
msgstr "Precio"
|
||||
|
@ -74,13 +74,13 @@ msgctxt "action"
|
|||
msgid "Add products"
|
||||
msgstr "Añadir productos"
|
||||
|
||||
#: web/template/invoices/new.gohtml:41 web/template/invoices/view.gohtml:44
|
||||
#: web/template/invoices/view.gohtml:71
|
||||
#: web/template/invoices/new.gohtml:41 web/template/invoices/view.gohtml:61
|
||||
#: web/template/invoices/view.gohtml:87
|
||||
msgctxt "title"
|
||||
msgid "Subtotal"
|
||||
msgstr "Subtotal"
|
||||
|
||||
#: web/template/invoices/new.gohtml:51 web/template/invoices/view.gohtml:81
|
||||
#: web/template/invoices/new.gohtml:51 web/template/invoices/view.gohtml:97
|
||||
msgctxt "title"
|
||||
msgid "Total"
|
||||
msgstr "Total"
|
||||
|
@ -100,7 +100,7 @@ msgctxt "invoice"
|
|||
msgid "All"
|
||||
msgstr "Todas"
|
||||
|
||||
#: web/template/invoices/index.gohtml:22 web/template/invoices/view.gohtml:18
|
||||
#: web/template/invoices/index.gohtml:22 web/template/invoices/view.gohtml:25
|
||||
msgctxt "title"
|
||||
msgid "Date"
|
||||
msgstr "Fecha"
|
||||
|
@ -135,21 +135,26 @@ msgctxt "title"
|
|||
msgid "Download"
|
||||
msgstr "Descargar"
|
||||
|
||||
#: web/template/invoices/index.gohtml:47
|
||||
#: web/template/invoices/index.gohtml:50
|
||||
msgid "No invoices added yet."
|
||||
msgstr "No hay facturas."
|
||||
|
||||
#: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:17
|
||||
#: web/template/invoices/view.gohtml:2 web/template/invoices/view.gohtml:24
|
||||
msgctxt "title"
|
||||
msgid "Invoice %s"
|
||||
msgstr "Factura %s"
|
||||
|
||||
#: web/template/invoices/view.gohtml:41
|
||||
#: web/template/invoices/view.gohtml:16
|
||||
msgctxt "action"
|
||||
msgid "Download invoice"
|
||||
msgstr "Descargar factura"
|
||||
|
||||
#: web/template/invoices/view.gohtml:58
|
||||
msgctxt "title"
|
||||
msgid "Concept"
|
||||
msgstr "Concepto"
|
||||
|
||||
#: web/template/invoices/view.gohtml:43
|
||||
#: web/template/invoices/view.gohtml:60
|
||||
msgctxt "title"
|
||||
msgid "Units"
|
||||
msgstr "Unidades"
|
||||
|
@ -364,40 +369,40 @@ msgstr "No podéis dejar la contraseña en blanco."
|
|||
msgid "Invalid user or password."
|
||||
msgstr "Nombre de usuario o contraseña inválido."
|
||||
|
||||
#: pkg/products.go:165 pkg/invoices.go:392
|
||||
#: pkg/products.go:165 pkg/invoices.go:435
|
||||
msgctxt "input"
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: pkg/products.go:171 pkg/invoices.go:397
|
||||
#: pkg/products.go:171 pkg/invoices.go:440
|
||||
msgctxt "input"
|
||||
msgid "Description"
|
||||
msgstr "Descripción"
|
||||
|
||||
#: pkg/products.go:176 pkg/invoices.go:401
|
||||
#: pkg/products.go:176 pkg/invoices.go:444
|
||||
msgctxt "input"
|
||||
msgid "Price"
|
||||
msgstr "Precio"
|
||||
|
||||
#: pkg/products.go:186 pkg/invoices.go:307 pkg/invoices.go:427
|
||||
#: pkg/products.go:186 pkg/invoices.go:350 pkg/invoices.go:470
|
||||
msgctxt "input"
|
||||
msgid "Taxes"
|
||||
msgstr "Impuestos"
|
||||
|
||||
#: pkg/products.go:206 pkg/profile.go:92 pkg/invoices.go:340
|
||||
#: pkg/invoices.go:463
|
||||
#: pkg/products.go:206 pkg/profile.go:92 pkg/invoices.go:383
|
||||
#: pkg/invoices.go:506
|
||||
msgid "Name can not be empty."
|
||||
msgstr "No podéis dejar el nombre en blanco."
|
||||
|
||||
#: pkg/products.go:207 pkg/invoices.go:464
|
||||
#: pkg/products.go:207 pkg/invoices.go:507
|
||||
msgid "Price can not be empty."
|
||||
msgstr "No podéis dejar el precio en blanco."
|
||||
|
||||
#: pkg/products.go:208 pkg/invoices.go:465
|
||||
#: pkg/products.go:208 pkg/invoices.go:508
|
||||
msgid "Price must be a number greater than zero."
|
||||
msgstr "El precio tiene que ser un número mayor a cero."
|
||||
|
||||
#: pkg/products.go:210 pkg/invoices.go:344 pkg/invoices.go:473
|
||||
#: pkg/products.go:210 pkg/invoices.go:387 pkg/invoices.go:516
|
||||
msgid "Selected tax is not valid."
|
||||
msgstr "Habéis escogido un impuesto que no es válido."
|
||||
|
||||
|
@ -460,70 +465,70 @@ 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/invoices.go:158
|
||||
#: pkg/invoices.go:201
|
||||
msgid "Select a customer to bill."
|
||||
msgstr "Escoged un cliente a facturar."
|
||||
|
||||
#: pkg/invoices.go:233
|
||||
#: pkg/invoices.go:276
|
||||
msgid "Invalid action"
|
||||
msgstr "Acción inválida."
|
||||
|
||||
#: pkg/invoices.go:284
|
||||
#: pkg/invoices.go:327
|
||||
msgctxt "input"
|
||||
msgid "Customer"
|
||||
msgstr "Cliente"
|
||||
|
||||
#: pkg/invoices.go:290
|
||||
#: pkg/invoices.go:333
|
||||
msgctxt "input"
|
||||
msgid "Number"
|
||||
msgstr "Número"
|
||||
|
||||
#: pkg/invoices.go:296
|
||||
#: pkg/invoices.go:339
|
||||
msgctxt "input"
|
||||
msgid "Invoice Date"
|
||||
msgstr "Fecha de factura"
|
||||
|
||||
#: pkg/invoices.go:302
|
||||
#: pkg/invoices.go:345
|
||||
msgctxt "input"
|
||||
msgid "Notes"
|
||||
msgstr "Notas"
|
||||
|
||||
#: pkg/invoices.go:341
|
||||
#: pkg/invoices.go:384
|
||||
msgid "Invoice date can not be empty."
|
||||
msgstr "No podéis dejar la fecha de la factura en blanco."
|
||||
|
||||
#: pkg/invoices.go:342
|
||||
#: pkg/invoices.go:385
|
||||
msgid "Invoice date must be a valid date."
|
||||
msgstr "La fecha de factura debe ser válida."
|
||||
|
||||
#: pkg/invoices.go:387
|
||||
#: pkg/invoices.go:430
|
||||
msgctxt "input"
|
||||
msgid "Id"
|
||||
msgstr "Identificador"
|
||||
|
||||
#: pkg/invoices.go:410
|
||||
#: pkg/invoices.go:453
|
||||
msgctxt "input"
|
||||
msgid "Quantity"
|
||||
msgstr "Cantidad"
|
||||
|
||||
#: pkg/invoices.go:418
|
||||
#: pkg/invoices.go:461
|
||||
msgctxt "input"
|
||||
msgid "Discount (%)"
|
||||
msgstr "Descuento (%)"
|
||||
|
||||
#: pkg/invoices.go:467
|
||||
#: pkg/invoices.go:510
|
||||
msgid "Quantity can not be empty."
|
||||
msgstr "No podéis dejar la cantidad en blanco."
|
||||
|
||||
#: pkg/invoices.go:468
|
||||
#: pkg/invoices.go:511
|
||||
msgid "Quantity must be a number greater than zero."
|
||||
msgstr "La cantidad tiene que ser un número mayor a cero."
|
||||
|
||||
#: pkg/invoices.go:470
|
||||
#: pkg/invoices.go:513
|
||||
msgid "Discount can not be empty."
|
||||
msgstr "No podéis dejar el descuento en blanco."
|
||||
|
||||
#: pkg/invoices.go:471
|
||||
#: pkg/invoices.go:514
|
||||
msgid "Discount must be a percentage between 0 and 100."
|
||||
msgstr "El descuento tiene que ser un percentage entre 0 y 100."
|
||||
|
||||
|
|
|
@ -508,6 +508,15 @@ main > nav {
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
.invoice-download {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.invoice-download a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Remix Icon */
|
||||
|
||||
@font-face {
|
||||
|
|
|
@ -39,7 +39,10 @@
|
|||
<td class="invoice-status-{{ .Status }}">{{ .StatusLabel }}</td>
|
||||
<td></td>
|
||||
<td class="numeric">{{ .Total|formatPrice }}</td>
|
||||
<td></td>
|
||||
<td class="invoice-download"><a href="{{ companyURI "/invoices/"}}{{ .Slug }}.pdf" download="{{ .Number}}.pdf"
|
||||
title="{{( pgettext "Download invoice" "action" )}}"
|
||||
aria-label="{{( pgettext "Download invoice %s" "action" )}}"><i
|
||||
class="ri-download-line"></i></a></td>
|
||||
</tr>
|
||||
{{- end }}
|
||||
{{ else }}
|
||||
|
|
|
@ -10,7 +10,13 @@
|
|||
<a href="{{ companyURI "/invoices"}}">{{( pgettext "Invoices" "title" )}}</a> /
|
||||
<a>{{ .Number }}</a>
|
||||
</p>
|
||||
<p>
|
||||
<a class="primary button"
|
||||
href="{{ companyURI "/invoices/" }}{{ .Slug }}.pdf"
|
||||
download="{{ .Number}}.pdf">{{( pgettext "Download invoice" "action" )}}</a>
|
||||
</p>
|
||||
</nav>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/static/invoice.css">
|
||||
<article class="invoice">
|
||||
<header>
|
||||
|
|
Loading…
Reference in New Issue