Party Types & Profiles
Developer guide for the Enezaframework party system. Part of the Party System series.
Table of Contents
- Overview
- PartyCategory
- The Party Models
- How the Type Drives the Profile
- Relationships Reference
- Choosing a Party Type
- Model Samples
- Related Guides
Overview
Every party-based record resolves to exactly one Party. The party_type of that party is PRS (Person) or ORG (Organization), and it decides which profile the framework creates and which conditional inline appears on the detail page. Addresses and contact information are independent of the type and always available.
PartyCategory
PartyCategory is a TextChoices class in enezacommon/models/choices.py:49.
| Value | Label | Profile created | Conditional inline |
|---|---|---|---|
PRS |
Person | Person |
Personal Details |
ORG |
Organization | Business |
Business Details |
Your model's party_category property must return the field that holds one of these values — usually a customer_type or vendortype field declared with choices=PartyCategory.choices.
The Party Models
All party models live in enezacommon/models/Party.py and inherit EnezaSetup (they are entity-scoped setup records).
| Model | Table | Key fields | Relation to Party |
|---|---|---|---|
Party |
party |
party_type, display_name, is_active |
Hub model |
Person |
person |
first_name, middle_name, last_name, birthday, email |
OneToOneField(related_name='person_profile') |
Business |
business |
business_name, business_registration_number |
OneToOneField(related_name='business_profile') |
Address |
address |
address_type, street, city, country, primary_address |
ForeignKey(related_name='addresses') |
ContactInformation |
contactInformation |
contact, contact_type, extension, primary_contact |
ForeignKey(related_name='contact_information') |
Party itself is the shared record:
class Party(EnezaSetup):
party_type = models.CharField(
db_column='PartyType',
max_length=5,
choices=PartyCategory.choices,
verbose_name="Party Type",
)
display_name = models.CharField(
db_column='DisplayName',
max_length=255,
blank=True,
null=True,
verbose_name="Display Name",
)
is_active = models.BooleanField(
db_column='IsActive',
default=True,
verbose_name="Is Active",
)
Do not create
Person/Business/Address/ContactInformationmanually for party-based entities. The profile is created by the signal chain; addresses and contacts are managed by the party inline views. See Party Inline System.
How the Type Drives the Profile
When a Party is created, create_org_or_person_profile (enezacommon/signals.py:43) branches on party_type.
flowchart TD
PARTY[Party created] --> TYPE{party_type}
TYPE -->|PRS| PERSON["Person.objects.get_or_create(party=...)"]
TYPE -->|ORG| BUSINESS["Business.objects.get_or_create(party=...)"]
PERSON --> PVIEW[Personal Details inline]
BUSINESS --> BVIEW[Business Details inline]
PARTY --> STATIC[Address + Contact Information inlines]erDiagram
PARTY ||--o| PERSON : "person_profile (O2O)"
PARTY ||--o| BUSINESS : "business_profile (O2O)"
PARTY ||--o{ ADDRESS : "addresses (FK)"
PARTY ||--o{ CONTACTINFORMATION : "contact_information (FK)"
PARTY {
string party_type "PRS or ORG"
string display_name
bool is_active
}
PERSON {
string first_name
string last_name
string email
}
BUSINESS {
string business_name
string business_registration_number
}
ADDRESS {
string street
string city
string country
}
CONTACTINFORMATION {
string contact
string contact_type
}Relationships Reference
| From | To | Type | Reverse accessor | Used for |
|---|---|---|---|---|
| Your model | Party |
FK PROTECT, nullable |
%(class)s_party |
Links the business record to its party. |
Party |
Person |
OneToOne, nullable | person_profile |
Person profile for PRS. |
Party |
Business |
OneToOne, nullable | business_profile |
Organization profile for ORG. |
Party |
Address |
FK, nullable | addresses |
Any number of addresses, both types. |
Party |
ContactInformation |
FK, nullable | contact_information |
Any number of contacts, both types. |
Party |
PartyContact |
FK / FK | contacts, contact_for |
Optional party-to-party contact roles. |
Choosing a Party Type
- Choose
PRSwhen the record represents an individual — a private customer, a contact person, an employee. - Choose
ORGwhen the record represents a company or legal entity — a corporate customer, a supplier, a branch.
The type is not fixed by the model; it is stored per record through the party category field. A single Customer model can hold both private and corporate customers, and each gets the correct profile and inline.
Model Samples
A model whose type field uses PartyCategory.choices:
# myapp/models/vendortable.py
from django.db import models
from enezaframework.models import EnezaMaster, PartyModelMixin
from enezacommon.models.choices import PartyCategory
class VendorTable(PartyModelMixin, EnezaMaster):
vendorno = models.CharField(
max_length=50,
verbose_name="Vendor No.",
)
searchname = models.CharField(
max_length=255,
verbose_name="Search Name",
)
vendortype = models.CharField(
max_length=5,
choices=PartyCategory.choices,
verbose_name="Vendor Type",
)
@property
def party_category(self):
return self.vendortype
Reading the profile for a saved record:
vendor = VendorTable.objects.get(vendorno="VEND0001")
party = vendor.party
if party.party_type == PartyCategory.PERSON:
profile = party.person_profile
else:
profile = party.business_profile