Compare commits

..

1 Commits

Author SHA1 Message Date
jordi fita mas e62cee7e82 Keep products in invoices/quotes sorted by (roughly) insertion order
There was no explicit `order by` in the queries that list the products
of quotes and invoices, so PostgreSQL was free to use any order it
wanted.  In this case, since was am grouping first by name, the result
was sorted by product name.

This is not an issue in most cases, albeit a bit rude to the user,
except for when the products *have* to in the same order the user
entered them, because they are monthly fees or something like that, that
must be ordered by month _number_, not by their _name_; the user will
usually input them in the correct order they want them on the invoice or
quote.

Sorting by *_product_id does *not* guarantee that they will always be
in insertion order, because the sequence can “wrap”, but i think i am
going to have bigger problems at that point.
2023-07-07 10:39:22 +02:00
9 changed files with 10 additions and 39 deletions

3
debian/control vendored
View File

@ -10,9 +10,8 @@ Build-Depends:
golang-github-jackc-pgx-v4-dev, golang-github-jackc-pgx-v4-dev,
golang-github-julienschmidt-httprouter-dev, golang-github-julienschmidt-httprouter-dev,
golang-github-leonelquinteros-gotext-dev, golang-github-leonelquinteros-gotext-dev,
golang-github-rainycape-unidecode-dev,
golang-github-tealeg-xlsx-dev,
golang-golang-x-text-dev, golang-golang-x-text-dev,
golang-github-tealeg-xlsx-dev,
postgresql-all (>= 217~), postgresql-all (>= 217~),
sqitch, sqitch,
pgtap, pgtap,

1
go.mod
View File

@ -7,7 +7,6 @@ require (
github.com/jackc/pgx/v4 v4.15.0 github.com/jackc/pgx/v4 v4.15.0
github.com/julienschmidt/httprouter v1.3.0 github.com/julienschmidt/httprouter v1.3.0
github.com/leonelquinteros/gotext v1.5.0 github.com/leonelquinteros/gotext v1.5.0
github.com/rainycape/unidecode v0.0.0-20150906181237-c9cf8cdbbfe8
github.com/tealeg/xlsx v0.0.0-20181024002044-dbf71b6a931e github.com/tealeg/xlsx v0.0.0-20181024002044-dbf71b6a931e
golang.org/x/text v0.7.0 golang.org/x/text v0.7.0
) )

2
go.sum
View File

@ -92,8 +92,6 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rainycape/unidecode v0.0.0-20150906181237-c9cf8cdbbfe8 h1:iZTHFqK/oFrjyFDkiw5U/RjQxkMlkpq6tHQIO407i+s=
github.com/rainycape/unidecode v0.0.0-20150906181237-c9cf8cdbbfe8/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=

View File

@ -658,7 +658,7 @@ func mustWriteInvoicesPdf(r *http.Request, slugs []string) []byte {
if inv == nil { if inv == nil {
continue continue
} }
f, err := w.Create(fmt.Sprintf("%s-%s.pdf", inv.Number, slugify(inv.Invoicee.Name))) f, err := w.Create(inv.Number + ".pdf")
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -1,22 +0,0 @@
package pkg
import (
"github.com/rainycape/unidecode"
"regexp"
"strings"
)
var (
nonValidChars = regexp.MustCompile("[^a-z0-9-_]")
multipleDashes = regexp.MustCompile("-+")
)
func slugify(s string) (slug string) {
slug = strings.TrimSpace(s)
slug = unidecode.Unidecode(slug)
slug = strings.ToLower(slug)
slug = nonValidChars.ReplaceAllString(slug, "-")
slug = multipleDashes.ReplaceAllString(slug, "-")
slug = strings.Trim(slug, "-_")
return slug
}

View File

@ -86,9 +86,6 @@ func mustRenderTemplate(wr io.Writer, r *http.Request, layout string, filename s
sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"} sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"}
return humanizeBytes(bytes, 1024, sizes) return humanizeBytes(bytes, 1024, sizes)
}, },
"slugify": func(s string) string {
return slugify(s)
},
}) })
if _, err := t.ParseFiles(templateFile(filename), templateFile(layout), templateFile("form.gohtml")); err != nil { if _, err := t.ParseFiles(templateFile(filename), templateFile(layout), templateFile("form.gohtml")); err != nil {
panic(err) panic(err)

View File

@ -4,8 +4,8 @@
{{ define "breadcrumbs" -}} {{ define "breadcrumbs" -}}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InvoicesIndexPage*/ -}} {{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InvoicesIndexPage*/ -}}
<nav data-hx-target="main"> <nav data-hx-target="main" data-hx-boost="true">
<p data-hx-boost="true"> <p>
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> / <a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
<a>{{( pgettext "Invoices" "title" )}}</a> <a>{{( pgettext "Invoices" "title" )}}</a>
</p> </p>
@ -17,7 +17,7 @@
<button type="submit" <button type="submit"
name="action" value="download" name="action" value="download"
>{{( pgettext "Download invoices" "action" )}}</button> >{{( pgettext "Download invoices" "action" )}}</button>
<a class="primary button" data-hx-boost="true" <a class="primary button"
href="{{ companyURI "/invoices/new" }}">{{( pgettext "New invoice" "action" )}}</a> href="{{ companyURI "/invoices/new" }}">{{( pgettext "New invoice" "action" )}}</a>
</p> </p>
</form> </form>
@ -104,7 +104,7 @@
<td class="numeric">{{ .Total|formatPrice }}</td> <td class="numeric">{{ .Total|formatPrice }}</td>
{{- $title = .Number | printf (pgettext "Download invoice %s" "action") -}} {{- $title = .Number | printf (pgettext "Download invoice %s" "action") -}}
<td class="invoice-download"><a href="{{ companyURI "/invoices/"}}{{ .Slug }}.pdf" <td class="invoice-download"><a href="{{ companyURI "/invoices/"}}{{ .Slug }}.pdf"
download="{{ .Number}}-{{ .CustomerName | slugify}}.pdf" download="{{ .Number}}.pdf"
title="{{( pgettext "Download invoice" "action" )}}" title="{{( pgettext "Download invoice" "action" )}}"
aria-label="{{ $title }}"><i aria-label="{{ $title }}"><i
class="ri-download-line"></i></a></td> class="ri-download-line"></i></a></td>

View File

@ -19,7 +19,7 @@
href="{{ companyURI "/invoices/"}}{{ .Slug }}/edit">{{( pgettext "Edit" "action" )}}</a> href="{{ companyURI "/invoices/"}}{{ .Slug }}/edit">{{( pgettext "Edit" "action" )}}</a>
<a class="primary button" <a class="primary button"
href="{{ companyURI "/invoices/" }}{{ .Slug }}.pdf" href="{{ companyURI "/invoices/" }}{{ .Slug }}.pdf"
download="{{ .Number}}-{{ .Invoicee.Name | slugify }}.pdf">{{( pgettext "Download invoice" "action" )}}</a> download="{{ .Number}}.pdf">{{( pgettext "Download invoice" "action" )}}</a>
</p> </p>
</nav> </nav>
{{- end }} {{- end }}

View File

@ -4,8 +4,8 @@
{{ define "breadcrumbs" -}} {{ define "breadcrumbs" -}}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.QuotesIndexPage*/ -}} {{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.QuotesIndexPage*/ -}}
<nav data-hx-target="main"> <nav data-hx-target="main" data-hx-boost="true">
<p data-hx-boost="true"> <p>
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> / <a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
<a>{{( pgettext "Quotations" "title" )}}</a> <a>{{( pgettext "Quotations" "title" )}}</a>
</p> </p>
@ -17,7 +17,7 @@
<button type="submit" <button type="submit"
name="action" value="download" name="action" value="download"
>{{( pgettext "Download quotations" "action" )}}</button> >{{( pgettext "Download quotations" "action" )}}</button>
<a class="primary button" data-hx-boost="true" <a class="primary button"
href="{{ companyURI "/quotes/new" }}">{{( pgettext "New quotation" "action" )}}</a> href="{{ companyURI "/quotes/new" }}">{{( pgettext "New quotation" "action" )}}</a>
</p> </p>
</form> </form>