Use slugs too to select invoice products without JavaScript

The product search returns a list of products using its slug as the
“external key”, because i do not want people seeing the id in links,
and the search product list is just a different rendering of the product
index table.

However, now i had two almost identical select queries for product,
one using the product_id and the other its slug, the former intended for
the form to select products using checkboxes—the one non-JavaScript
users see—and the latter for the product search.

Using the slug in both forms i can now simplify the code and have a
single query.
This commit is contained in:
jordi fita mas 2023-04-26 13:50:02 +02:00
parent f2a0cd7d94
commit a06bc3df58
2 changed files with 32 additions and 28 deletions

View File

@ -437,13 +437,13 @@ func mustRenderNewInvoiceProductsForm(w http.ResponseWriter, r *http.Request, ac
}
func mustGetProductChoices(ctx context.Context, conn *Conn, company *Company) []*productChoice {
rows := conn.MustQuery(ctx, "select product.product_id, product.name, to_price(price, decimal_digits) from product join company using (company_id) join currency using (currency_code) where company_id = $1 order by name", company.Id)
rows := conn.MustQuery(ctx, "select product.slug, product.name, to_price(price, decimal_digits) from product join company using (company_id) join currency using (currency_code) where company_id = $1 order by name", company.Id)
defer rows.Close()
var choices []*productChoice
for rows.Next() {
entry := &productChoice{}
if err := rows.Scan(&entry.Id, &entry.Name, &entry.Price); err != nil {
if err := rows.Scan(&entry.Slug, &entry.Name, &entry.Price); err != nil {
panic(err)
}
choices = append(choices, entry)
@ -462,7 +462,7 @@ type newInvoiceProductsPage struct {
}
type productChoice struct {
Id int
Slug string
Name string
Price string
}
@ -664,8 +664,29 @@ func (form *invoiceForm) Update() {
}
}
func (form *invoiceForm) AddProducts(ctx context.Context, conn *Conn, productsId []string) {
form.mustAddProductsFromQuery(ctx, conn, "select '', product_id, name, description, to_price(price, decimal_digits), 1 as quantity, 0 as discount, array_remove(array_agg(tax_id), null) from product join company using (company_id) join currency using (currency_code) left join product_tax using (product_id) where product_id = any ($1) group by product_id, name, description, price, decimal_digits", productsId)
const selectProductBySlug = `
select ''
, product_id
, name
, description
, to_price(price, decimal_digits)
, 1 as quantity
, 0 as discount
, array_remove(array_agg(tax_id), null)
from product
join company using (company_id)
join currency using (currency_code)
left join product_tax using (product_id)
where product.slug = any ($1)
group by product_id
, name
, description
, price
, decimal_digits
`
func (form *invoiceForm) AddProducts(ctx context.Context, conn *Conn, productsSlug []string) {
form.mustAddProductsFromQuery(ctx, conn, selectProductBySlug, productsSlug)
}
func (form *invoiceForm) mustAddProductsFromQuery(ctx context.Context, conn *Conn, sql string, args ...interface{}) {
@ -864,25 +885,8 @@ func (form *invoiceProductForm) Update() {
}
func (form *invoiceProductForm) MustFillFromDatabase(ctx context.Context, conn *Conn, slug string) bool {
return !notFoundErrorOrPanic(conn.QueryRow(ctx, `
select product_id
, name
, description
, to_price(price, decimal_digits)
, 1 as quantity
, 0 as discount
, array_remove(array_agg(tax_id), null)
from product
join company using (company_id)
join currency using (currency_code)
left join product_tax using (product_id)
where product.slug = $1
group by product_id
, name
, description
, price
, decimal_digits
`, slug).Scan(
return !notFoundErrorOrPanic(conn.QueryRow(ctx, selectProductBySlug, []string{slug}).Scan(
form.InvoiceProductId,
form.ProductId,
form.Name,
form.Description,
@ -1006,7 +1010,7 @@ func handleInvoiceAction(w http.ResponseWriter, r *http.Request, action string,
w.WriteHeader(http.StatusOK)
mustRenderNewInvoiceProductsForm(w, r, action, form)
case "add-products":
form.AddProducts(r.Context(), conn, r.Form["id"])
form.AddProducts(r.Context(), conn, r.Form["slug"])
w.WriteHeader(http.StatusOK)
renderForm(w, r, form)
default:

View File

@ -52,10 +52,10 @@
</thead>
<tbody>
{{ with .Products }}
{{- range $product, $key := . }}
{{- range . }}
<tr>
<td><input type="checkbox" name="id" id="new-product-id-{{$key}}" value="{{.Id}}"></td>
<td><label for="new-product-id-{{$key}}">{{ .Name }}</label></td>
<td><input type="checkbox" name="slug" id="product-{{ .Slug }}" value="{{.Slug}}"></td>
<td><label for="product-{{ .Slug }}">{{ .Name }}</label></td>
<td class="numeric">{{ .Price | formatPrice }}</td>
</tr>
{{- end }}