2023-01-29 14:14:31 +00:00
|
|
|
package pkg
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-02-03 11:30:56 +00:00
|
|
|
"github.com/julienschmidt/httprouter"
|
2023-02-01 13:34:40 +00:00
|
|
|
"html/template"
|
2023-01-29 14:14:31 +00:00
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ContactEntry struct {
|
2023-02-03 12:29:10 +00:00
|
|
|
Slug string
|
2023-01-29 14:14:31 +00:00
|
|
|
Name string
|
|
|
|
Email string
|
|
|
|
Phone string
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
Tags []string
|
2023-01-29 14:14:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ContactsIndexPage struct {
|
|
|
|
Contacts []*ContactEntry
|
|
|
|
}
|
|
|
|
|
2023-02-03 11:30:56 +00:00
|
|
|
func IndexContacts(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
|
|
|
conn := getConn(r)
|
2023-02-04 09:43:42 +00:00
|
|
|
company := mustGetCompany(r)
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
tag := r.URL.Query().Get("tag")
|
2023-02-03 11:30:56 +00:00
|
|
|
page := &ContactsIndexPage{
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
Contacts: mustCollectContactEntries(r.Context(), conn, company, tag),
|
2023-02-03 11:30:56 +00:00
|
|
|
}
|
2023-03-23 09:55:02 +00:00
|
|
|
mustRenderMainTemplate(w, r, "contacts/index.gohtml", page)
|
2023-02-03 11:30:56 +00:00
|
|
|
}
|
|
|
|
|
2023-02-03 12:29:10 +00:00
|
|
|
func GetContactForm(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
2023-02-03 11:30:56 +00:00
|
|
|
locale := getLocale(r)
|
|
|
|
conn := getConn(r)
|
|
|
|
form := newContactForm(r.Context(), conn, locale)
|
2023-02-03 12:29:10 +00:00
|
|
|
slug := params[0].Value
|
|
|
|
if slug == "new" {
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
mustRenderNewContactForm(w, r, form)
|
|
|
|
return
|
|
|
|
}
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
if !form.MustFillFromDatabase(r.Context(), conn, slug) {
|
2023-02-14 11:46:11 +00:00
|
|
|
http.NotFound(w, r)
|
|
|
|
return
|
2023-02-03 12:29:10 +00:00
|
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
2023-03-23 09:46:14 +00:00
|
|
|
mustRenderEditContactForm(w, r, slug, form)
|
2023-02-03 11:30:56 +00:00
|
|
|
}
|
|
|
|
|
2023-02-03 12:29:10 +00:00
|
|
|
func mustRenderNewContactForm(w http.ResponseWriter, r *http.Request, form *contactForm) {
|
2023-03-22 13:59:54 +00:00
|
|
|
mustRenderModalTemplate(w, r, "contacts/new.gohtml", form)
|
2023-02-03 11:30:56 +00:00
|
|
|
}
|
|
|
|
|
2023-03-23 09:46:14 +00:00
|
|
|
type editContactPage struct {
|
|
|
|
Slug string
|
|
|
|
ContactName string
|
|
|
|
Form *contactForm
|
|
|
|
}
|
|
|
|
|
|
|
|
func mustRenderEditContactForm(w http.ResponseWriter, r *http.Request, slug string, form *contactForm) {
|
|
|
|
page := &editContactPage{
|
|
|
|
Slug: slug,
|
|
|
|
ContactName: form.BusinessName.Val,
|
|
|
|
Form: form,
|
|
|
|
}
|
|
|
|
mustRenderModalTemplate(w, r, "contacts/edit.gohtml", page)
|
2023-02-03 12:29:10 +00:00
|
|
|
}
|
|
|
|
|
2023-02-03 11:30:56 +00:00
|
|
|
func HandleAddContact(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
|
|
|
conn := getConn(r)
|
|
|
|
locale := getLocale(r)
|
|
|
|
form := newContactForm(r.Context(), conn, locale)
|
|
|
|
if err := form.Parse(r); err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if err := verifyCsrfTokenValid(r); err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusForbidden)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !form.Validate(r.Context(), conn) {
|
2023-03-22 13:59:54 +00:00
|
|
|
if !IsHTMxRequest(r) {
|
|
|
|
w.WriteHeader(http.StatusUnprocessableEntity)
|
|
|
|
}
|
2023-02-03 12:29:10 +00:00
|
|
|
mustRenderNewContactForm(w, r, form)
|
2023-02-03 11:30:56 +00:00
|
|
|
return
|
|
|
|
}
|
2023-02-04 09:43:42 +00:00
|
|
|
company := mustGetCompany(r)
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
conn.MustExec(r.Context(), "select add_contact($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", company.Id, form.BusinessName, form.VATIN, form.TradeName, form.Phone, form.Email, form.Web, form.Address, form.City, form.Province, form.PostalCode, form.Country, form.Tags)
|
2023-03-22 13:59:54 +00:00
|
|
|
if IsHTMxRequest(r) {
|
|
|
|
w.Header().Set("HX-Trigger", "closeModal")
|
|
|
|
w.Header().Set("HX-Refresh", "true")
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
|
|
} else {
|
|
|
|
http.Redirect(w, r, companyURI(company, "/contacts"), http.StatusSeeOther)
|
|
|
|
}
|
2023-01-29 14:14:31 +00:00
|
|
|
}
|
|
|
|
|
2023-02-03 12:29:10 +00:00
|
|
|
func HandleUpdateContact(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
|
|
|
conn := getConn(r)
|
|
|
|
locale := getLocale(r)
|
|
|
|
form := newContactForm(r.Context(), conn, locale)
|
|
|
|
if err := form.Parse(r); err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if err := verifyCsrfTokenValid(r); err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusForbidden)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !form.Validate(r.Context(), conn) {
|
2023-03-23 09:46:14 +00:00
|
|
|
mustRenderEditContactForm(w, r, params[0].Value, form)
|
2023-02-03 12:29:10 +00:00
|
|
|
return
|
|
|
|
}
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
slug := conn.MustGetText(r.Context(), "", "select edit_contact($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", params[0].Value, form.BusinessName, form.VATIN, form.TradeName, form.Phone, form.Email, form.Web, form.Address, form.City, form.Province, form.PostalCode, form.Country, form.Tags)
|
2023-02-03 12:29:10 +00:00
|
|
|
if slug == "" {
|
|
|
|
http.NotFound(w, r)
|
|
|
|
}
|
2023-03-23 09:46:14 +00:00
|
|
|
if IsHTMxRequest(r) {
|
|
|
|
w.Header().Set("HX-Trigger", "closeModal")
|
|
|
|
w.Header().Set("HX-Refresh", "true")
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
|
|
} else {
|
|
|
|
http.Redirect(w, r, companyURI(mustGetCompany(r), "/contacts/"+slug), http.StatusSeeOther)
|
|
|
|
}
|
2023-02-03 12:29:10 +00:00
|
|
|
}
|
|
|
|
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
func mustCollectContactEntries(ctx context.Context, conn *Conn, company *Company, tag string) []*ContactEntry {
|
|
|
|
rows, err := conn.Query(ctx, `
|
|
|
|
select slug
|
|
|
|
, business_name
|
|
|
|
, email
|
|
|
|
, phone
|
|
|
|
, array_agg(coalesce(tag.name::text, ''))
|
|
|
|
from contact
|
|
|
|
left join contact_tag using (contact_id)
|
|
|
|
left join tag using(tag_id)
|
|
|
|
where contact.company_id = $1 and (($2 = '') or (tag.name = $2))
|
|
|
|
group by slug
|
|
|
|
, business_name
|
|
|
|
, email
|
|
|
|
, phone
|
|
|
|
order by business_name
|
|
|
|
`, company.Id, tag)
|
2023-01-29 14:14:31 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
var entries []*ContactEntry
|
|
|
|
for rows.Next() {
|
|
|
|
entry := &ContactEntry{}
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
err = rows.Scan(&entry.Slug, &entry.Name, &entry.Email, &entry.Phone, &entry.Tags)
|
2023-01-29 14:14:31 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
entries = append(entries, entry)
|
|
|
|
}
|
|
|
|
if rows.Err() != nil {
|
|
|
|
panic(rows.Err())
|
|
|
|
}
|
|
|
|
|
|
|
|
return entries
|
|
|
|
}
|
|
|
|
|
2023-02-01 13:34:40 +00:00
|
|
|
type contactForm struct {
|
|
|
|
locale *Locale
|
|
|
|
BusinessName *InputField
|
|
|
|
VATIN *InputField
|
|
|
|
TradeName *InputField
|
|
|
|
Phone *InputField
|
|
|
|
Email *InputField
|
|
|
|
Web *InputField
|
|
|
|
Address *InputField
|
|
|
|
City *InputField
|
|
|
|
Province *InputField
|
|
|
|
PostalCode *InputField
|
|
|
|
Country *SelectField
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
Tags *TagsField
|
2023-02-01 13:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func newContactForm(ctx context.Context, conn *Conn, locale *Locale) *contactForm {
|
|
|
|
return &contactForm{
|
|
|
|
locale: locale,
|
|
|
|
BusinessName: &InputField{
|
|
|
|
Name: "business_name",
|
|
|
|
Label: pgettext("input", "Business name", locale),
|
|
|
|
Type: "text",
|
|
|
|
Required: true,
|
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="organization"`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
VATIN: &InputField{
|
|
|
|
Name: "vatin",
|
|
|
|
Label: pgettext("input", "VAT number", locale),
|
|
|
|
Type: "text",
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
TradeName: &InputField{
|
|
|
|
Name: "trade_name",
|
|
|
|
Label: pgettext("input", "Trade name", locale),
|
|
|
|
Type: "text",
|
|
|
|
},
|
|
|
|
Phone: &InputField{
|
|
|
|
Name: "phone",
|
|
|
|
Label: pgettext("input", "Phone", locale),
|
|
|
|
Type: "tel",
|
|
|
|
Required: true,
|
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="tel"`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Email: &InputField{
|
|
|
|
Name: "email",
|
|
|
|
Label: pgettext("input", "Email", locale),
|
|
|
|
Type: "email",
|
|
|
|
Required: true,
|
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="email"`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Web: &InputField{
|
|
|
|
Name: "web",
|
|
|
|
Label: pgettext("input", "Web", locale),
|
|
|
|
Type: "url",
|
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="url"`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Address: &InputField{
|
|
|
|
Name: "address",
|
|
|
|
Label: pgettext("input", "Address", locale),
|
|
|
|
Type: "text",
|
|
|
|
Required: true,
|
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="address-line1"`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
City: &InputField{
|
|
|
|
Name: "city",
|
|
|
|
Label: pgettext("input", "City", locale),
|
|
|
|
Type: "text",
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
Province: &InputField{
|
|
|
|
Name: "province",
|
|
|
|
Label: pgettext("input", "Province", locale),
|
|
|
|
Type: "text",
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
PostalCode: &InputField{
|
|
|
|
Name: "postal_code",
|
|
|
|
Label: pgettext("input", "Postal code", locale),
|
|
|
|
Type: "text",
|
|
|
|
Required: true,
|
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="postal-code"`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Country: &SelectField{
|
|
|
|
Name: "country",
|
2023-02-08 12:47:36 +00:00
|
|
|
Label: pgettext("input", "Country", locale),
|
2023-02-01 13:34:40 +00:00
|
|
|
Options: mustGetCountryOptions(ctx, conn, locale),
|
2023-02-05 13:06:33 +00:00
|
|
|
Required: true,
|
2023-02-08 12:47:36 +00:00
|
|
|
Selected: []string{"ES"},
|
2023-02-01 13:34:40 +00:00
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="country"`,
|
|
|
|
},
|
|
|
|
},
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
Tags: &TagsField{
|
|
|
|
Name: "tags",
|
|
|
|
Label: pgettext("input", "Tags", locale),
|
|
|
|
},
|
2023-02-01 13:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (form *contactForm) Parse(r *http.Request) error {
|
|
|
|
if err := r.ParseForm(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
form.BusinessName.FillValue(r)
|
|
|
|
form.VATIN.FillValue(r)
|
|
|
|
form.TradeName.FillValue(r)
|
|
|
|
form.Phone.FillValue(r)
|
|
|
|
form.Email.FillValue(r)
|
|
|
|
form.Web.FillValue(r)
|
|
|
|
form.Address.FillValue(r)
|
|
|
|
form.City.FillValue(r)
|
|
|
|
form.Province.FillValue(r)
|
|
|
|
form.PostalCode.FillValue(r)
|
|
|
|
form.Country.FillValue(r)
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
form.Tags.FillValue(r)
|
2023-02-01 13:34:40 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (form *contactForm) Validate(ctx context.Context, conn *Conn) bool {
|
|
|
|
validator := newFormValidator()
|
2023-02-08 12:47:36 +00:00
|
|
|
|
|
|
|
country := ""
|
|
|
|
if validator.CheckValidSelectOption(form.Country, gettext("Selected country is not valid.", form.locale)) {
|
|
|
|
country = form.Country.Selected[0]
|
|
|
|
}
|
|
|
|
|
2023-02-01 13:34:40 +00:00
|
|
|
validator.CheckRequiredInput(form.BusinessName, gettext("Business name can not be empty.", form.locale))
|
|
|
|
if validator.CheckRequiredInput(form.VATIN, gettext("VAT number can not be empty.", form.locale)) {
|
2023-02-08 12:47:36 +00:00
|
|
|
validator.CheckValidVATINInput(form.VATIN, country, gettext("This value is not a valid VAT number.", form.locale))
|
2023-02-01 13:34:40 +00:00
|
|
|
}
|
|
|
|
if validator.CheckRequiredInput(form.Phone, gettext("Phone can not be empty.", form.locale)) {
|
2023-02-08 12:47:36 +00:00
|
|
|
validator.CheckValidPhoneInput(form.Phone, country, gettext("This value is not a valid phone number.", form.locale))
|
2023-02-01 13:34:40 +00:00
|
|
|
}
|
|
|
|
if validator.CheckRequiredInput(form.Email, gettext("Email can not be empty.", form.locale)) {
|
|
|
|
validator.CheckValidEmailInput(form.Email, gettext("This value is not a valid email. It should be like name@domain.com.", form.locale))
|
|
|
|
}
|
|
|
|
if form.Web.Val != "" {
|
2023-02-12 20:01:20 +00:00
|
|
|
validator.CheckValidURL(form.Web, gettext("This value is not a valid web address. It should be like https://domain.com/.", form.locale))
|
2023-02-01 13:34:40 +00:00
|
|
|
}
|
|
|
|
validator.CheckRequiredInput(form.Address, gettext("Address can not be empty.", form.locale))
|
|
|
|
validator.CheckRequiredInput(form.City, gettext("City can not be empty.", form.locale))
|
|
|
|
validator.CheckRequiredInput(form.Province, gettext("Province can not be empty.", form.locale))
|
|
|
|
if validator.CheckRequiredInput(form.PostalCode, gettext("Postal code can not be empty.", form.locale)) {
|
2023-02-08 12:47:36 +00:00
|
|
|
validator.CheckValidPostalCode(ctx, conn, form.PostalCode, country, gettext("This value is not a valid postal code.", form.locale))
|
2023-02-01 13:34:40 +00:00
|
|
|
}
|
|
|
|
return validator.AllOK()
|
2023-01-29 14:14:31 +00:00
|
|
|
}
|
Add tags for contacts too
With Oriol we agreed that contacts should have tags, too, and that the
“tag pool”, as it were, should be shared with the one for invoices (and
all future tags we might add).
I added the contact_tag relation and tag_contact function, just like
with invoices, and then realized that the SQL queries that Go had to
execute were becoming “complex” enough: i had to get not only the slug,
but the contact id to call tag_contact, and all inside a transaction.
Therefore, i opted to create the add_contact and edit_contact functions,
that mirror those for invoice and products, so now each “major” section
has these functions. They also simplified a bit the handling of the
VATIN and phone numbers, because it is now encapsuled inside the
PL/pgSQL function and Go does not know how to assemble the parts.
2023-03-26 00:32:53 +00:00
|
|
|
|
|
|
|
func (form *contactForm) MustFillFromDatabase(ctx context.Context, conn *Conn, slug string) bool {
|
|
|
|
return !notFoundErrorOrPanic(conn.QueryRow(ctx, `
|
|
|
|
select business_name
|
|
|
|
, substr(vatin::text, 3)
|
|
|
|
, trade_name
|
|
|
|
, phone
|
|
|
|
, email
|
|
|
|
, web
|
|
|
|
, address
|
|
|
|
, city
|
|
|
|
, province
|
|
|
|
, postal_code
|
|
|
|
, country_code
|
|
|
|
, string_agg(tag.name, ',')
|
|
|
|
from contact
|
|
|
|
left join contact_tag using (contact_id)
|
|
|
|
left join tag using(tag_id)
|
|
|
|
where slug = $1
|
|
|
|
group by business_name
|
|
|
|
, substr(vatin::text, 3)
|
|
|
|
, trade_name
|
|
|
|
, phone
|
|
|
|
, email
|
|
|
|
, web
|
|
|
|
, address
|
|
|
|
, city
|
|
|
|
, province
|
|
|
|
, postal_code
|
|
|
|
, country_code
|
|
|
|
`, slug).Scan(
|
|
|
|
form.BusinessName,
|
|
|
|
form.VATIN,
|
|
|
|
form.TradeName,
|
|
|
|
form.Phone,
|
|
|
|
form.Email,
|
|
|
|
form.Web,
|
|
|
|
form.Address,
|
|
|
|
form.City,
|
|
|
|
form.Province,
|
|
|
|
form.PostalCode,
|
|
|
|
form.Country,
|
|
|
|
form.Tags))
|
|
|
|
}
|