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:
parent
f2a0cd7d94
commit
a06bc3df58
|
@ -437,13 +437,13 @@ func mustRenderNewInvoiceProductsForm(w http.ResponseWriter, r *http.Request, ac
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustGetProductChoices(ctx context.Context, conn *Conn, company *Company) []*productChoice {
|
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()
|
defer rows.Close()
|
||||||
|
|
||||||
var choices []*productChoice
|
var choices []*productChoice
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
entry := &productChoice{}
|
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)
|
panic(err)
|
||||||
}
|
}
|
||||||
choices = append(choices, entry)
|
choices = append(choices, entry)
|
||||||
|
@ -462,7 +462,7 @@ type newInvoiceProductsPage struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type productChoice struct {
|
type productChoice struct {
|
||||||
Id int
|
Slug string
|
||||||
Name string
|
Name string
|
||||||
Price string
|
Price string
|
||||||
}
|
}
|
||||||
|
@ -664,8 +664,29 @@ func (form *invoiceForm) Update() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (form *invoiceForm) AddProducts(ctx context.Context, conn *Conn, productsId []string) {
|
const selectProductBySlug = `
|
||||||
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)
|
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{}) {
|
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 {
|
func (form *invoiceProductForm) MustFillFromDatabase(ctx context.Context, conn *Conn, slug string) bool {
|
||||||
return !notFoundErrorOrPanic(conn.QueryRow(ctx, `
|
return !notFoundErrorOrPanic(conn.QueryRow(ctx, selectProductBySlug, []string{slug}).Scan(
|
||||||
select product_id
|
form.InvoiceProductId,
|
||||||
, 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(
|
|
||||||
form.ProductId,
|
form.ProductId,
|
||||||
form.Name,
|
form.Name,
|
||||||
form.Description,
|
form.Description,
|
||||||
|
@ -1006,7 +1010,7 @@ func handleInvoiceAction(w http.ResponseWriter, r *http.Request, action string,
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
mustRenderNewInvoiceProductsForm(w, r, action, form)
|
mustRenderNewInvoiceProductsForm(w, r, action, form)
|
||||||
case "add-products":
|
case "add-products":
|
||||||
form.AddProducts(r.Context(), conn, r.Form["id"])
|
form.AddProducts(r.Context(), conn, r.Form["slug"])
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
renderForm(w, r, form)
|
renderForm(w, r, form)
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -52,10 +52,10 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{ with .Products }}
|
{{ with .Products }}
|
||||||
{{- range $product, $key := . }}
|
{{- range . }}
|
||||||
<tr>
|
<tr>
|
||||||
<td><input type="checkbox" name="id" id="new-product-id-{{$key}}" value="{{.Id}}"></td>
|
<td><input type="checkbox" name="slug" id="product-{{ .Slug }}" value="{{.Slug}}"></td>
|
||||||
<td><label for="new-product-id-{{$key}}">{{ .Name }}</label></td>
|
<td><label for="product-{{ .Slug }}">{{ .Name }}</label></td>
|
||||||
<td class="numeric">{{ .Price | formatPrice }}</td>
|
<td class="numeric">{{ .Price | formatPrice }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
Loading…
Reference in New Issue