numerus/pkg/invoices.go

153 lines
3.9 KiB
Go
Raw Normal View History

2023-02-11 21:16:48 +00:00
package pkg
import (
"context"
"fmt"
"github.com/julienschmidt/httprouter"
"html/template"
"net/http"
"time"
)
type InvoicesIndexPage struct {
}
func IndexInvoices(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
page := &InvoicesIndexPage{}
mustRenderAppTemplate(w, r, "invoices/index.gohtml", page)
}
func GetInvoiceForm(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
locale := getLocale(r)
conn := getConn(r)
company := mustGetCompany(r)
form := newInvoiceForm(r.Context(), conn, locale, company)
slug := params[0].Value
if slug == "new" {
form.Customer.EmptyLabel = gettext("Select a customer to bill.", locale)
form.Date.Val = time.Now().Format("2006-01-02")
w.WriteHeader(http.StatusOK)
mustRenderNewInvoiceForm(w, r, form)
return
}
}
func mustRenderNewInvoiceForm(w http.ResponseWriter, r *http.Request, form *invoiceForm) {
mustRenderAppTemplate(w, r, "invoices/new.gohtml", form)
}
func HandleAddInvoice(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
r.ParseForm()
w.Write([]byte("OK"))
}
type invoiceProductForm struct {
ProductId *InputField
Name *InputField
Description *InputField
Price *InputField
Quantity *InputField
Discount *InputField
Tax *SelectField
}
type invoiceForm struct {
locale *Locale
company *Company
Customer *SelectField
Number *InputField
Date *InputField
Notes *InputField
Products []*invoiceProductForm
}
func newInvoiceForm(ctx context.Context, conn *Conn, locale *Locale, company *Company) *invoiceForm {
return &invoiceForm{
locale: locale,
company: company,
Customer: &SelectField{
Name: "customer",
Label: pgettext("input", "Customer", locale),
Required: true,
Options: MustGetOptions(ctx, conn, "select contact_id::text, business_name from contact where company_id = $1 order by business_name", company.Id),
},
Number: &InputField{
Name: "number",
Label: pgettext("input", "Number", locale),
Type: "text",
Required: false,
},
Date: &InputField{
Name: "date",
Label: pgettext("input", "Invoice Date", locale),
Type: "date",
Required: true,
},
Notes: &InputField{
Name: "description",
Label: pgettext("input", "Notes", locale),
Type: "textarea",
},
Products: []*invoiceProductForm{
newInvoiceProductForm(ctx, conn, company, locale),
},
}
}
func newInvoiceProductForm(ctx context.Context, conn *Conn, company *Company, locale *Locale) *invoiceProductForm {
return &invoiceProductForm{
ProductId: &InputField{
Name: "product[][id]",
Label: pgettext("input", "Id", locale),
Type: "hidden",
Required: true,
},
Name: &InputField{
Name: "product[][name]",
Label: pgettext("input", "Name", locale),
Type: "text",
Required: true,
},
Description: &InputField{
Name: "product[][description]",
Label: pgettext("input", "Description", locale),
Type: "textarea",
},
Price: &InputField{
Name: "product[][price]",
Label: pgettext("input", "Price", locale),
Type: "number",
Required: true,
Attributes: []template.HTMLAttr{
`min="0"`,
template.HTMLAttr(fmt.Sprintf(`step="%v"`, company.MinCents())),
},
},
Quantity: &InputField{
Name: "product[][quantity]",
Label: pgettext("input", "Quantity", locale),
Type: "number",
Required: true,
Attributes: []template.HTMLAttr{
`min="0"`,
},
},
Discount: &InputField{
Name: "product[][discount]",
Label: pgettext("input", "Discount (%)", locale),
Type: "number",
Required: true,
Attributes: []template.HTMLAttr{
`min="0"`,
`max="100"`,
},
},
Tax: &SelectField{
Name: "product[][tax]",
Label: pgettext("input", "Taxes", locale),
Multiple: true,
Options: MustGetOptions(ctx, conn, "select tax_id::text, name from tax where company_id = $1 order by name", company.Id),
},
}
}