2023-01-29 14:14:31 +00:00
|
|
|
package pkg
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-05-10 16:56:07 +00:00
|
|
|
"fmt"
|
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"
|
2023-05-10 16:56:07 +00:00
|
|
|
"strings"
|
2023-01-29 14:14:31 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
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-05-10 16:56:07 +00:00
|
|
|
Filters *contactFilterForm
|
2023-01-29 14:14:31 +00:00
|
|
|
}
|
|
|
|
|
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)
|
2023-05-10 16:56:07 +00:00
|
|
|
locale := getLocale(r)
|
|
|
|
filters := newContactFilterForm(locale)
|
|
|
|
if err := filters.Parse(r); err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
2023-02-03 11:30:56 +00:00
|
|
|
page := &ContactsIndexPage{
|
2023-05-10 16:56:07 +00:00
|
|
|
Contacts: mustCollectContactEntries(r.Context(), conn, company, filters),
|
|
|
|
Filters: filters,
|
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-04-25 13:28:55 +00:00
|
|
|
mustRenderMainTemplate(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,
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
ContactName: form.Name.String(),
|
2023-03-23 09:46:14 +00:00
|
|
|
Form: form,
|
|
|
|
}
|
2023-04-25 13:28:55 +00:00
|
|
|
mustRenderMainTemplate(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 IBAN and BIC fields to contacts
These two fields are just for information purposes, as Numerus does not
have any way to wire transfer using these, but people might want to keep
these in the contact’s info as a convenience.
Since not every contact should have an IBAN, e.g., customers, and inside
SEPA (European Union and some more countries) the BIC is not required,
they are in two different relations in order to be optional without
using NULL.
For the IBAN i found an already made PostgreSQL module, but for BIC i
had to write a regular expression based on the information i gathered
from Wikipedia, because the ISO standard is not free.
These two parameters for the add_contact and edit_contact functions are
TEXT because i realized that these functions are intended to be used
from the web application, that only deals with texts, so the
ValueOrNil() function was unnecessarily complex and PostreSQL’s
functions were better suited to “convert” from TEXT to IBAN or BIC.
The same is true for EMAIL and URI domains, so i changed their parameter
types to TEXT too.
Closes #54.
2023-07-02 00:08:45 +00:00
|
|
|
conn.MustExec(r.Context(), "select add_contact($1, $2, $3, $4, $5, $6, $7, $8, $9)", company.Id, form.Name, form.Phone, form.Email, form.Web, form.TaxDetails(), form.IBAN, form.BIC, form.Tags)
|
2023-04-25 13:28:55 +00:00
|
|
|
htmxRedirect(w, r, companyURI(company, "/contacts"))
|
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 IBAN and BIC fields to contacts
These two fields are just for information purposes, as Numerus does not
have any way to wire transfer using these, but people might want to keep
these in the contact’s info as a convenience.
Since not every contact should have an IBAN, e.g., customers, and inside
SEPA (European Union and some more countries) the BIC is not required,
they are in two different relations in order to be optional without
using NULL.
For the IBAN i found an already made PostgreSQL module, but for BIC i
had to write a regular expression based on the information i gathered
from Wikipedia, because the ISO standard is not free.
These two parameters for the add_contact and edit_contact functions are
TEXT because i realized that these functions are intended to be used
from the web application, that only deals with texts, so the
ValueOrNil() function was unnecessarily complex and PostreSQL’s
functions were better suited to “convert” from TEXT to IBAN or BIC.
The same is true for EMAIL and URI domains, so i changed their parameter
types to TEXT too.
Closes #54.
2023-07-02 00:08:45 +00:00
|
|
|
slug := conn.MustGetText(r.Context(), "", "select edit_contact($1, $2, $3, $4, $5, $6, $7, $8, $9)", params[0].Value, form.Name, form.Phone, form.Email, form.Web, form.TaxDetails(), form.IBAN, form.BIC, form.Tags)
|
2023-02-03 12:29:10 +00:00
|
|
|
if slug == "" {
|
|
|
|
http.NotFound(w, r)
|
|
|
|
}
|
2023-04-25 13:28:55 +00:00
|
|
|
htmxRedirect(w, r, companyURI(mustGetCompany(r), "/contacts"))
|
2023-02-03 12:29:10 +00:00
|
|
|
}
|
|
|
|
|
2023-05-10 16:56:07 +00:00
|
|
|
type contactFilterForm struct {
|
|
|
|
Name *InputField
|
|
|
|
Tags *TagsField
|
|
|
|
TagsCondition *ToggleField
|
|
|
|
}
|
|
|
|
|
|
|
|
func newContactFilterForm(locale *Locale) *contactFilterForm {
|
|
|
|
return &contactFilterForm{
|
|
|
|
Name: &InputField{
|
|
|
|
Name: "number",
|
|
|
|
Label: pgettext("input", "Name", locale),
|
|
|
|
Type: "search",
|
|
|
|
},
|
|
|
|
Tags: &TagsField{
|
|
|
|
Name: "tags",
|
|
|
|
Label: pgettext("input", "Tags", locale),
|
|
|
|
},
|
|
|
|
TagsCondition: &ToggleField{
|
|
|
|
Name: "tags_condition",
|
|
|
|
Label: pgettext("input", "Tags Condition", locale),
|
|
|
|
Selected: "and",
|
|
|
|
FirstOption: &ToggleOption{
|
|
|
|
Value: "and",
|
|
|
|
Label: pgettext("tag condition", "All", locale),
|
|
|
|
Description: gettext("Invoices must have all the specified labels.", locale),
|
|
|
|
},
|
|
|
|
SecondOption: &ToggleOption{
|
|
|
|
Value: "or",
|
|
|
|
Label: pgettext("tag condition", "Any", locale),
|
|
|
|
Description: gettext("Invoices must have at least one of the specified labels.", locale),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (form *contactFilterForm) Parse(r *http.Request) error {
|
|
|
|
if err := r.ParseForm(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
form.Name.FillValue(r)
|
|
|
|
form.Tags.FillValue(r)
|
|
|
|
form.TagsCondition.FillValue(r)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func mustCollectContactEntries(ctx context.Context, conn *Conn, company *Company, filters *contactFilterForm) []*ContactEntry {
|
|
|
|
args := []interface{}{company.Id}
|
|
|
|
where := []string{"contact.company_id = $1"}
|
|
|
|
appendWhere := func(expression string, value interface{}) {
|
|
|
|
args = append(args, value)
|
|
|
|
where = append(where, fmt.Sprintf(expression, len(args)))
|
|
|
|
}
|
|
|
|
if filters != nil {
|
|
|
|
name := strings.TrimSpace(filters.Name.String())
|
|
|
|
if name != "" {
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
appendWhere("contact.name ilike $%d", "%"+name+"%")
|
2023-05-10 16:56:07 +00:00
|
|
|
}
|
|
|
|
if len(filters.Tags.Tags) > 0 {
|
|
|
|
if filters.TagsCondition.Selected == "and" {
|
|
|
|
appendWhere("contact.tags @> $%d", filters.Tags)
|
|
|
|
} else {
|
|
|
|
appendWhere("contact.tags && $%d", filters.Tags)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rows := conn.MustQuery(ctx, fmt.Sprintf(`
|
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
|
|
|
select slug
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
, name
|
|
|
|
, coalesce(email::text, '')
|
|
|
|
, coalesce(phone::text, '')
|
Replace tag relations with array attributes
It all started when i wanted to try to filter invoices by multiple tags
using an “AND”, instead of “OR” as it was doing until now. But
something felt off and seemed to me that i was doing thing much more
complex than needed, all to be able to list the tags as a suggestion
in the input field—which i am not doing yet.
I found this article series[0] exploring different approaches for
tagging, which includes the one i was using, and comparing their
performance. I have not actually tested it, but it seems that i have
chosen the worst option, in both query time and storage.
I attempted to try using an array attribute to each table, which is more
or less the same they did in the articles but without using a separate
relation for tags, and i found out that all the queries were way easier
to write, and needed two joins less, so it was a no-brainer.
[0]: http://www.databasesoup.com/2015/01/tag-all-things.html
2023-04-07 19:31:35 +00:00
|
|
|
, tags
|
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
|
|
|
from contact
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
left join contact_email using (contact_id)
|
|
|
|
left join contact_phone using (contact_id)
|
2023-05-10 16:56:07 +00:00
|
|
|
where (%s)
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
order by name
|
2023-05-10 16:56:07 +00:00
|
|
|
`, strings.Join(where, ") AND (")), args...)
|
2023-01-29 14:14:31 +00:00
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
var entries []*ContactEntry
|
|
|
|
for rows.Next() {
|
|
|
|
entry := &ContactEntry{}
|
2023-05-10 16:56:07 +00:00
|
|
|
if err := rows.Scan(&entry.Slug, &entry.Name, &entry.Email, &entry.Phone, &entry.Tags); err != nil {
|
2023-01-29 14:14:31 +00:00
|
|
|
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 {
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
locale *Locale
|
|
|
|
Name *InputField
|
|
|
|
HasTaxDetails *CheckField
|
|
|
|
BusinessName *InputField
|
|
|
|
VATIN *InputField
|
|
|
|
Phone *InputField
|
|
|
|
Email *InputField
|
|
|
|
Web *InputField
|
|
|
|
Address *InputField
|
|
|
|
City *InputField
|
|
|
|
Province *InputField
|
|
|
|
PostalCode *InputField
|
|
|
|
Country *SelectField
|
Add IBAN and BIC fields to contacts
These two fields are just for information purposes, as Numerus does not
have any way to wire transfer using these, but people might want to keep
these in the contact’s info as a convenience.
Since not every contact should have an IBAN, e.g., customers, and inside
SEPA (European Union and some more countries) the BIC is not required,
they are in two different relations in order to be optional without
using NULL.
For the IBAN i found an already made PostgreSQL module, but for BIC i
had to write a regular expression based on the information i gathered
from Wikipedia, because the ISO standard is not free.
These two parameters for the add_contact and edit_contact functions are
TEXT because i realized that these functions are intended to be used
from the web application, that only deals with texts, so the
ValueOrNil() function was unnecessarily complex and PostreSQL’s
functions were better suited to “convert” from TEXT to IBAN or BIC.
The same is true for EMAIL and URI domains, so i changed their parameter
types to TEXT too.
Closes #54.
2023-07-02 00:08:45 +00:00
|
|
|
IBAN *InputField
|
|
|
|
BIC *InputField
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +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,
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
Name: &InputField{
|
|
|
|
Name: "name",
|
|
|
|
Label: pgettext("input", "Name", locale),
|
2023-02-01 13:34:40 +00:00
|
|
|
Type: "text",
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
Phone: &InputField{
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
Name: "phone",
|
|
|
|
Label: pgettext("input", "Phone", locale),
|
|
|
|
Type: "tel",
|
2023-02-01 13:34:40 +00:00
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="tel"`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Email: &InputField{
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
Name: "email",
|
|
|
|
Label: pgettext("input", "Email", locale),
|
|
|
|
Type: "email",
|
2023-02-01 13:34:40 +00:00
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="email"`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Web: &InputField{
|
|
|
|
Name: "web",
|
|
|
|
Label: pgettext("input", "Web", locale),
|
|
|
|
Type: "url",
|
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="url"`,
|
|
|
|
},
|
|
|
|
},
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
HasTaxDetails: &CheckField{
|
|
|
|
Name: "has_tax_details",
|
|
|
|
Label: pgettext("input", "Need to input tax details", locale),
|
|
|
|
},
|
|
|
|
BusinessName: &InputField{
|
|
|
|
Name: "business_name",
|
|
|
|
Label: pgettext("input", "Business name", locale),
|
|
|
|
Type: "text",
|
|
|
|
Required: true,
|
|
|
|
Attributes: []template.HTMLAttr{
|
|
|
|
`autocomplete="organization"`,
|
|
|
|
`minlength="2"`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
VATIN: &InputField{
|
|
|
|
Name: "vatin",
|
|
|
|
Label: pgettext("input", "VAT number", locale),
|
|
|
|
Type: "text",
|
|
|
|
Required: true,
|
|
|
|
},
|
2023-02-01 13:34:40 +00:00
|
|
|
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 IBAN and BIC fields to contacts
These two fields are just for information purposes, as Numerus does not
have any way to wire transfer using these, but people might want to keep
these in the contact’s info as a convenience.
Since not every contact should have an IBAN, e.g., customers, and inside
SEPA (European Union and some more countries) the BIC is not required,
they are in two different relations in order to be optional without
using NULL.
For the IBAN i found an already made PostgreSQL module, but for BIC i
had to write a regular expression based on the information i gathered
from Wikipedia, because the ISO standard is not free.
These two parameters for the add_contact and edit_contact functions are
TEXT because i realized that these functions are intended to be used
from the web application, that only deals with texts, so the
ValueOrNil() function was unnecessarily complex and PostreSQL’s
functions were better suited to “convert” from TEXT to IBAN or BIC.
The same is true for EMAIL and URI domains, so i changed their parameter
types to TEXT too.
Closes #54.
2023-07-02 00:08:45 +00:00
|
|
|
IBAN: &InputField{
|
|
|
|
Name: "iban",
|
|
|
|
Label: pgettext("input", "IBAN", locale),
|
|
|
|
Type: "text",
|
|
|
|
},
|
|
|
|
BIC: &InputField{
|
|
|
|
Name: "bic",
|
|
|
|
Label: pgettext("bic", "BIC", locale),
|
|
|
|
Type: "text",
|
|
|
|
},
|
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
|
|
|
|
}
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
form.Name.FillValue(r)
|
|
|
|
form.HasTaxDetails.FillValue(r)
|
2023-02-01 13:34:40 +00:00
|
|
|
form.BusinessName.FillValue(r)
|
|
|
|
form.VATIN.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 IBAN and BIC fields to contacts
These two fields are just for information purposes, as Numerus does not
have any way to wire transfer using these, but people might want to keep
these in the contact’s info as a convenience.
Since not every contact should have an IBAN, e.g., customers, and inside
SEPA (European Union and some more countries) the BIC is not required,
they are in two different relations in order to be optional without
using NULL.
For the IBAN i found an already made PostgreSQL module, but for BIC i
had to write a regular expression based on the information i gathered
from Wikipedia, because the ISO standard is not free.
These two parameters for the add_contact and edit_contact functions are
TEXT because i realized that these functions are intended to be used
from the web application, that only deals with texts, so the
ValueOrNil() function was unnecessarily complex and PostreSQL’s
functions were better suited to “convert” from TEXT to IBAN or BIC.
The same is true for EMAIL and URI domains, so i changed their parameter
types to TEXT too.
Closes #54.
2023-07-02 00:08:45 +00:00
|
|
|
form.IBAN.FillValue(r)
|
|
|
|
form.BIC.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
|
|
|
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
country := "ES"
|
|
|
|
if form.HasTaxDetails.Checked {
|
|
|
|
if validator.CheckValidSelectOption(form.Country, gettext("Selected country is not valid.", form.locale)) {
|
|
|
|
country = form.Country.Selected[0]
|
|
|
|
}
|
|
|
|
validator.CheckRequiredInput(form.BusinessName, gettext("Business name can not be empty.", form.locale))
|
|
|
|
validator.CheckInputMinLength(form.BusinessName, 2, gettext("Business name must have at least two letters.", form.locale))
|
|
|
|
if validator.CheckRequiredInput(form.VATIN, gettext("VAT number can not be empty.", form.locale)) {
|
|
|
|
validator.CheckValidVATINInput(form.VATIN, country, gettext("This value is not a valid VAT number.", form.locale))
|
|
|
|
}
|
|
|
|
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))
|
2023-02-08 12:47:36 +00:00
|
|
|
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
if validator.CheckRequiredInput(form.PostalCode, gettext("Postal code can not be empty.", form.locale)) {
|
|
|
|
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
|
|
|
}
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
|
|
|
|
validator.CheckRequiredInput(form.Name, gettext("Name can not be empty.", form.locale))
|
|
|
|
validator.CheckInputMinLength(form.Name, 2, gettext("Name must have at least two letters.", form.locale))
|
|
|
|
|
|
|
|
if form.Phone.Val != "" {
|
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
|
|
|
}
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
if form.Email.Val != "" {
|
2023-02-01 13:34:40 +00:00
|
|
|
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
|
|
|
}
|
Add IBAN and BIC fields to contacts
These two fields are just for information purposes, as Numerus does not
have any way to wire transfer using these, but people might want to keep
these in the contact’s info as a convenience.
Since not every contact should have an IBAN, e.g., customers, and inside
SEPA (European Union and some more countries) the BIC is not required,
they are in two different relations in order to be optional without
using NULL.
For the IBAN i found an already made PostgreSQL module, but for BIC i
had to write a regular expression based on the information i gathered
from Wikipedia, because the ISO standard is not free.
These two parameters for the add_contact and edit_contact functions are
TEXT because i realized that these functions are intended to be used
from the web application, that only deals with texts, so the
ValueOrNil() function was unnecessarily complex and PostreSQL’s
functions were better suited to “convert” from TEXT to IBAN or BIC.
The same is true for EMAIL and URI domains, so i changed their parameter
types to TEXT too.
Closes #54.
2023-07-02 00:08:45 +00:00
|
|
|
if form.IBAN.Val != "" {
|
|
|
|
validator.CheckValidIBANInput(form.IBAN, gettext("This values is not a valid IBAN.", form.locale))
|
|
|
|
}
|
|
|
|
if form.BIC.Val != "" {
|
|
|
|
validator.CheckValidBICInput(form.IBAN, gettext("This values is not a valid BIC.", form.locale))
|
|
|
|
}
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
|
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, `
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
select name
|
|
|
|
, vatin is not null
|
|
|
|
, business_name
|
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
|
|
|
, substr(vatin::text, 3)
|
|
|
|
, phone
|
|
|
|
, email
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
, uri
|
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
|
|
|
, address
|
|
|
|
, city
|
|
|
|
, province
|
|
|
|
, postal_code
|
|
|
|
, country_code
|
Add IBAN and BIC fields to contacts
These two fields are just for information purposes, as Numerus does not
have any way to wire transfer using these, but people might want to keep
these in the contact’s info as a convenience.
Since not every contact should have an IBAN, e.g., customers, and inside
SEPA (European Union and some more countries) the BIC is not required,
they are in two different relations in order to be optional without
using NULL.
For the IBAN i found an already made PostgreSQL module, but for BIC i
had to write a regular expression based on the information i gathered
from Wikipedia, because the ISO standard is not free.
These two parameters for the add_contact and edit_contact functions are
TEXT because i realized that these functions are intended to be used
from the web application, that only deals with texts, so the
ValueOrNil() function was unnecessarily complex and PostreSQL’s
functions were better suited to “convert” from TEXT to IBAN or BIC.
The same is true for EMAIL and URI domains, so i changed their parameter
types to TEXT too.
Closes #54.
2023-07-02 00:08:45 +00:00
|
|
|
, iban
|
|
|
|
, bic
|
2023-05-27 19:36:10 +00:00
|
|
|
, tags
|
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
|
|
|
from contact
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
left join contact_email using (contact_id)
|
|
|
|
left join contact_phone using (contact_id)
|
|
|
|
left join contact_web using (contact_id)
|
Add IBAN and BIC fields to contacts
These two fields are just for information purposes, as Numerus does not
have any way to wire transfer using these, but people might want to keep
these in the contact’s info as a convenience.
Since not every contact should have an IBAN, e.g., customers, and inside
SEPA (European Union and some more countries) the BIC is not required,
they are in two different relations in order to be optional without
using NULL.
For the IBAN i found an already made PostgreSQL module, but for BIC i
had to write a regular expression based on the information i gathered
from Wikipedia, because the ISO standard is not free.
These two parameters for the add_contact and edit_contact functions are
TEXT because i realized that these functions are intended to be used
from the web application, that only deals with texts, so the
ValueOrNil() function was unnecessarily complex and PostreSQL’s
functions were better suited to “convert” from TEXT to IBAN or BIC.
The same is true for EMAIL and URI domains, so i changed their parameter
types to TEXT too.
Closes #54.
2023-07-02 00:08:45 +00:00
|
|
|
left join contact_iban using (contact_id)
|
|
|
|
left join contact_swift using (contact_id)
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
left join contact_tax_details using (contact_id)
|
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
|
|
|
where slug = $1
|
|
|
|
`, slug).Scan(
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
form.Name,
|
|
|
|
form.HasTaxDetails,
|
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.BusinessName,
|
|
|
|
form.VATIN,
|
|
|
|
form.Phone,
|
|
|
|
form.Email,
|
|
|
|
form.Web,
|
|
|
|
form.Address,
|
|
|
|
form.City,
|
|
|
|
form.Province,
|
|
|
|
form.PostalCode,
|
|
|
|
form.Country,
|
Add IBAN and BIC fields to contacts
These two fields are just for information purposes, as Numerus does not
have any way to wire transfer using these, but people might want to keep
these in the contact’s info as a convenience.
Since not every contact should have an IBAN, e.g., customers, and inside
SEPA (European Union and some more countries) the BIC is not required,
they are in two different relations in order to be optional without
using NULL.
For the IBAN i found an already made PostgreSQL module, but for BIC i
had to write a regular expression based on the information i gathered
from Wikipedia, because the ISO standard is not free.
These two parameters for the add_contact and edit_contact functions are
TEXT because i realized that these functions are intended to be used
from the web application, that only deals with texts, so the
ValueOrNil() function was unnecessarily complex and PostreSQL’s
functions were better suited to “convert” from TEXT to IBAN or BIC.
The same is true for EMAIL and URI domains, so i changed their parameter
types to TEXT too.
Closes #54.
2023-07-02 00:08:45 +00:00
|
|
|
form.IBAN,
|
|
|
|
form.BIC,
|
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))
|
|
|
|
}
|
2023-05-12 09:32:39 +00:00
|
|
|
|
Split contact relation into tax_details, phone, web, and email
We need to have contacts with just a name: we need to assign
freelancer’s quote as expense linked the government, but of course we
do not have a phone or email for that “contact”, much less a VATIN or
other tax details.
It is also interesting for other expenses-only contacts to not have to
input all tax details, as we may not need to invoice then, thus are
useless for us, but sometimes it might be interesting to have them,
“just in case”.
Of course, i did not want to make nullable any of the tax details
required to generate an invoice, otherwise we could allow illegal
invoices. Therefore, that data had to go in a different relation,
and invoice’s foreign key update to point to that relation, not just
customer, or we would again be able to create invalid invoices.
We replaced the contact’s trade name with just name, because we do not
need _three_ names for a contact, but we _do_ need two: the one we use
to refer to them and the business name for tax purposes.
The new contact_phone, contact_web, and contact_email relations could be
simply a nullable field, but i did not see the point, since there are
not that many instances where i need any of this data.
Now company.taxDetailsForm is no longer “the same as contactForm with
some extra fields”, because i have to add a check whether the user needs
to invoice the contact, to check that the required values are there.
I have an additional problem with the contact form when not using
JavaScript: i must set the required field to all tax details fields to
avoid the “(optional)” suffix, and because they _are_ required when
that checkbox is enabled, but i can not set them optional when the check
is unchecked. My solution for now is to ignore the form validation,
and later i will add some JavaScript that adds the validation again,
so it will work in all cases.
2023-06-30 19:32:48 +00:00
|
|
|
func (form *contactForm) TaxDetails() *CustomerTaxDetails {
|
|
|
|
if !form.HasTaxDetails.Checked {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return &CustomerTaxDetails{
|
|
|
|
BusinessName: form.BusinessName.String(),
|
|
|
|
VATIN: form.VATIN.String(),
|
|
|
|
Address: form.Address.String(),
|
|
|
|
City: form.City.String(),
|
|
|
|
Province: form.Province.String(),
|
|
|
|
PostalCode: form.PostalCode.String(),
|
|
|
|
CountryCode: form.Country.String(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-12 09:32:39 +00:00
|
|
|
func ServeEditContactTags(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
|
|
|
conn := getConn(r)
|
|
|
|
locale := getLocale(r)
|
|
|
|
company := getCompany(r)
|
|
|
|
slug := params[0].Value
|
|
|
|
form := newTagsForm(companyURI(company, "/contacts/"+slug+"/tags"), slug, locale)
|
2023-05-27 19:36:10 +00:00
|
|
|
if notFoundErrorOrPanic(conn.QueryRow(r.Context(), `select tags from contact where slug = $1`, form.Slug).Scan(form.Tags)) {
|
2023-05-12 09:32:39 +00:00
|
|
|
http.NotFound(w, r)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
mustRenderStandaloneTemplate(w, r, "tags/edit.gohtml", form)
|
|
|
|
}
|
|
|
|
|
|
|
|
func HandleUpdateContactTags(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
|
|
|
locale := getLocale(r)
|
|
|
|
conn := getConn(r)
|
|
|
|
company := getCompany(r)
|
|
|
|
slug := params[0].Value
|
|
|
|
form := newTagsForm(companyURI(company, "/contacts/"+slug+"/tags/edit"), slug, 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 conn.MustGetText(r.Context(), "", "update contact set tags = $1 where slug = $2 returning slug", form.Tags, form.Slug) == "" {
|
|
|
|
http.NotFound(w, r)
|
|
|
|
}
|
|
|
|
mustRenderStandaloneTemplate(w, r, "tags/view.gohtml", form)
|
|
|
|
}
|