Proposal: rework name fields to make name entity
Overview
A recent discussion with Guy and #2883 (closed), plus the ongoing mayhem of organization names and personal experience with a variety of great and terrible name handling systems, have led me to think that the solution to names isn't creating more or better-labeled fields for more types of names but rather to make name its own entity akin to phone, email, address, website, etc.
Once name is an entity, each contact could have multiple names, one primary, but with a bunch of possible types:
- legal name
- trade name
- nickname
- former name
- name in other language/culture
- name in an external system
- common mistakes
There could also be a bunch of name renderings - ways the name is displayed or inserted:
- sort name
- display name
- name for greetings
- name for listings
The latter could generate the existing greetings and potentially others. In particular, I think there's a real gap for how you insert someone's name in emails where you don't want "Dear", "Hi", or any other greeting as such.
Finally, the duplicate matching process could look for any of the possible names, cutting down on duplicates.
Example use-case
Organization has multiple names
An organization has their corporate name, colloquial name, and the name of their main product. These all refer to the same contact, but employees might fill the current employer field as one of the various ways. As an admin, you want to avoid having to merge them all the time. As a routine user, you will want to know all the various ways an organization is termed. As a bookkeeper, you will want to send invoices, checks, receipts, etc. with the correct entity name.
In this case, there are three name entities:
Organization name | Name type | Is primary |
---|---|---|
Widget Productions | General | true |
Widget Productions, Inc. | Legal | false |
WidgetPro | General | false |
Widgetizer | Product | false |
There would be a couple of name renderings:
Rendering type | Value |
---|---|
Display Name | Widget Productions |
Sort Name | Widget Productions |
Billing name | Widget Productions, Inc. |
Minister has variety of prefixes
Someone's name is styled differently when it is listed versus when they are addressed. In this case, a minister is styled "The Reverend Sally Jones" or "Rev. Sally Jones" when listed somewhere but her salutation is "Ms. Jones".
I think she'd have only one entry as a name entity but several renderings:
Prefix | Title | First name | Middle Name | Last name | Suffix | Name type | Is primary |
---|---|---|---|---|---|---|---|
Ms. | The Reverend | Sally | Lynn | Jones | null | General | true |
These values are going to depend upon your sitewide preferences and choices for this contact, but a reasonable default might produce the following:
Rendering type | Value |
---|---|
Display Name | Sally Lynn Jones |
Sort Name | Jones, Sally Lynn |
Addressee | The Reverend Sally Jones |
Email greeting | Dear Sally |
Postal greeting | Dear Ms. Jones |
Short name | Sally |
An organization has a different name in another language
This should be self-explanatory:
Organization name | Name type | Is primary |
---|---|---|
Médecins Sans Frontières | General | true |
Doctors Without Borders | Localized | false |
Rendering type | Value |
---|---|
Display Name | Médecins Sans Frontières |
Sort Name | Médecins Sans Frontières |
English Name | Doctors Without Borders |
Someone's family name comes before their given name
I'm on the fence about how this should be handled, but all I know is that we currently handle it terribly (except maybe in translations that assume it?) One option might be to call the fields first, middle, and last names according to position (Ai being the family name, but it comes first):
Prefix | Title | First name | Middle Name | Last name | Suffix | Name type | Is primary |
---|---|---|---|---|---|---|---|
Mr. | null | Ai | null | Weiwei | null | General | true |
Alternatively, we could name the fields according to function:
Prefix | Title | Given name | Additional name | Surname | Suffix | Name type | Is primary |
---|---|---|---|---|---|---|---|
Mr. | null | Weiwei | null | Ai | null | General | true |
In either case, the renderings should be like
Rendering type | Value |
---|---|
Display Name | Ai Weiwei |
Sort Name | Ai Weiwei |
Addressee | Mr. Ai Weiwei |
Email greeting | Dear Weiwei |
Postal greeting | Dear Mr. Ai |
Short name | Weiwei |
Clinic needs to retain legal name for insurance billing
Someone's real name doesn't match their legal name, let alone their nickname. While most organizations wouldn't want or need to record a contact's dead name, a clinic might need it for billing correspondence. In this case, a patient is named Stephen, or Steve for short, but his legal name is Barbara.
Prefix | Title | First name | Middle Name | Last name | Suffix | Name type | Is primary |
---|---|---|---|---|---|---|---|
Mr. | null | Stephen | Wayne | Smith | null | General | true |
Mr. | null | Steve | null | Smith | null | Nickname | false |
null | null | Barbara | Wayne | Smith | null | Legal | false |
All of the name renderings would use the primary name or nickname, but the clinic could add an additional name rendering for how they refer to patients when billing to the insurance company.
Rendering type | Value |
---|---|
Display Name | Stephen Wayne Smith |
Sort Name | Smith, Stephen Wayne |
Addressee | Mr. Stephen Smith |
Email greeting | Dear Steve |
Postal greeting | Dear Mr. Smith |
Short name | Steve |
Insurance name | Barbara Smith |
Household name possibilities
The current household name field befuddles lots of people and, in my opinion, makes households less attractive to use. If a household can have multiple names, it might be more useful.
You might use a Household name field that has everyone all listed out, or you could use the Last name field.
Household name | Last name | Name type | Is primary |
---|---|---|---|
Katherine Williams and Kendra Green | null | General | true |
null | Williams-Green | General | false |
Rendering type | Value |
---|---|
Display Name | Katherine Williams and Kendra Green |
Sort Name | Katherine Williams and Kendra Green |
Addressee | The Williams-Green Household |
Email greeting | Dear Katherine Williams and Kendra Green |
Postal greeting | Dear Katherine Williams and Kendra Green |
Or if everyone shares a last name, a single name entity could do it all:
Given name | Surname | Name type | Is primary |
---|---|---|---|
Jack and Jill | Hill | General | true |
(If we don't feel the need to stick with the legacy name field names, there's really no reason that "Given name" couldn't replace Organization name and Household name, too, so this illustrates that.)
Rendering type | Value |
---|---|
Display Name | Jack and Jill Hill |
Sort Name | Hill, Jack and Jill |
Addressee | The Hill Household |
Email greeting | Dear Jack and Jill |
Postal greeting | Dear Jack and Jill Hill |
Current behavior
Right now, each of these situations is pretty annoying. It might require a separate custom field, located away from the name fields. It might make it difficult to automatically and accurately generate greetings for many people.
Currently, there are fields in the civicrm_contact
table for each name part, plus nickname and legal name.
The only name renderings are display name and sort name (set sitewide), and addressee and email and postal greetings (site-wide presets and defaults, with custom options).
There's no provision for additional renderings or any way to do fallbacks like pick a nickname and fall back to a first name.
There's a limited number of alternative names for a contact.
Alternative names are not compared against primary names when deduping.
Proposed behavior
Schema
The name fields would be gone from the contact entity, and a new civicrm_contact_name
entity is added with one of the following sets of fields:
Traditional | Radical |
---|---|
id | id |
contact_id | contact_id |
contact_name_type | contact_name_type |
is_primary | is_primary |
first_name | given_name |
middle_name | additional_name |
last_name | surname |
prefix_id | prefix_id |
suffix_id | suffix_id |
formal_title | formal_title |
household_name | |
organization_name |
The contact_name_type
would have reserved options General, Nickname, Legal, and Localized, but more could be added.
A new civicrm_contact_rendering
entity is added with the following set of fields:
Fields |
---|
id |
contact_id |
contact_rendering_type |
contact_rendering_template_id |
value |
The contact_rendering_type
would have reserved options Display name, Sort name, Addressee, Email greeting, Postal greeting, and Short name, but more could be added.
The contact_rendering_template_id
would be akin to the existing addressee_id
, email_greeting_id
, and postal_greeting_id
, while value
would be the actual generated or custom value.
Upgrade
On upgrade, the civicrm_contact_name
would be populated with the main name fields, with nickname and legal name as additional rows. On upgrade, the civicrm_contact_rendering
would be populated with rows for each contact's display name, sort name, addressee, and greetings.
Contact rendering templates
The contact rendering templates would have the option to specify a contact name type to provide the default value, with a fallback to the primary contact name. For example, email greeting might default to "Dear {nickname.first_name}", where it picks the value of first_name
from a contact's name entry with the name type of Nickname, and if that isn't available, it picks the primary name entry's value for first_name
.
Dedupe
When matching contacts on any of the name fields, the dedupe process would compare against all rows in the civicrm_contact_name
field, regardless of contact_name_type
or if it's the primary name.
Comments
This is all very early in the process: I think it's important to do something like this, but I don't have my heart on the specific mechanisms here. I think it would need to be evaluated for performance in a variety of ways, but I don't expect it would have too huge of an impact.