A comprehensive Customer Relationship Management software built on Django with extensive customization capabilities
Comprehensive contact and organization management with relationship tracking, custom fields, address management, and communication history. This module forms the core of CRM functionality by managing people and companies.
Individual contact entities with personal information and relationship tracking.
class Contact(CremeEntity):
"""
Individual contact entity with personal and professional information.
Attributes:
- civility: ForeignKey, title/salutation (Mr., Ms., Dr., etc.)
- first_name: str, given name
- last_name: str, family name
- description: str, additional notes
- position: ForeignKey, job position
- is_a_nerd: bool, technical person flag
- birthday: DateField, date of birth
- image: ImageField, profile photo
- skype: str, Skype username
- phone: str, primary phone number
- mobile: str, mobile phone number
- email: str, primary email address
- url_site: URLField, personal website
- sector: ForeignKey, industry sector
- language: ForeignKey, preferred language
Methods:
- get_absolute_url(): Get contact detail URL
- get_pretty_address(): Format complete address
- get_employers(): Get organizations this contact works for
- get_managers(): Get contacts who manage this contact
- get_teammates(): Get colleagues at same organization
- get_contact_summary(): Get formatted contact information
"""
def get_contact_model():
"""
Get the active Contact model class from settings.
Returns:
type[Contact]: The configured contact model class
Example:
ContactModel = get_contact_model()
contact = ContactModel.objects.create(
first_name="John",
last_name="Doe",
email="john@example.com"
)
"""Company and organization entities with business information and contact relationships.
class Organisation(CremeEntity):
"""
Company/organization entity with business information.
Attributes:
- name: str, organization name
- is_managed: bool, whether organization is actively managed
- staff_size: int, number of employees
- capital: PositiveIntegerField, company capital
- siren: str, French SIREN number
- naf: str, French NAF code
- siret: str, French SIRET number
- rcs: str, French RCS number
- tvaintra: str, EU VAT number
- subject_to_vat: bool, VAT registration status
- annual_revenue: PositiveIntegerField, yearly revenue
- description: str, company description
- phone: str, main phone number
- fax: str, fax number
- email: str, primary email address
- url_site: URLField, company website
- sector: ForeignKey, industry sector
- legal_form: ForeignKey, legal structure
- creation_date: DateField, company founding date
- image: ImageField, company logo
Methods:
- get_absolute_url(): Get organization detail URL
- get_pretty_address(): Format complete address
- get_employees(): Get contacts who work for this organization
- get_managers(): Get management contacts
- get_subsidiaries(): Get subsidiary organizations
- get_parent_orga(): Get parent organization
- get_customers(): Get customer organizations
- get_suppliers(): Get supplier organizations
"""
def get_organisation_model():
"""
Get the active Organisation model class from settings.
Returns:
type[Organisation]: The configured organisation model class
Example:
OrganisationModel = get_organisation_model()
org = OrganisationModel.objects.create(
name="Example Corp",
email="info@example.com",
phone="+1-555-0123"
)
"""Address storage and management with geolocation support.
class Address(CremeModel):
"""
Address information for contacts and organizations.
Attributes:
- name: str, address label/name
- address: str, street address
- po_box: str, post office box
- zipcode: str, postal code
- city: str, city name
- department: str, department/state
- country: str, country name
- latitude: DecimalField, GPS latitude
- longitude: DecimalField, GPS longitude
- content_type: ContentType, entity type this address belongs to
- object_id: int, entity ID this address belongs to
Methods:
- get_pretty_address(): Format complete address string
- __str__(): String representation of address
- geocode(): Update latitude/longitude coordinates
"""Supporting models for contact categorization and organization.
class Civility(CremeModel):
"""
Title/salutation options for contacts.
Attributes:
- title: str, title text (Mr., Ms., Dr., Prof., etc.)
- shortcut: str, abbreviated form
Methods:
- __str__(): Return title text
"""
class Position(CremeModel):
"""
Job positions and roles.
Attributes:
- title: str, position title
- description: str, position description
Methods:
- __str__(): Return position title
"""
class Sector(CremeModel):
"""
Industry sectors for categorizing contacts and organizations.
Attributes:
- title: str, sector name
- order: int, display order
Methods:
- __str__(): Return sector title
"""
class LegalForm(CremeModel):
"""
Legal forms/structures for organizations.
Attributes:
- title: str, legal form name
- shortcut: str, abbreviated form
Methods:
- __str__(): Return legal form title
"""Employee count categorization for organizations.
class StaffSize(CremeModel):
"""
Staff size categories for organizations.
Attributes:
- size: str, size category description
- order: int, display order
Methods:
- __str__(): Return size description
Common Values:
- "1-10 employees"
- "11-50 employees"
- "51-200 employees"
- "201-1000 employees"
- "1000+ employees"
"""from creme.persons import get_contact_model
ContactModel = get_contact_model()
# Create a basic contact
contact = ContactModel.objects.create(
first_name="John",
last_name="Doe",
email="john@example.com",
phone="+1-555-0123"
)
# Create contact with full information
from creme.persons.models import Civility, Position, Sector
mr_civility = Civility.objects.get(title="Mr.")
ceo_position = Position.objects.get(title="CEO")
tech_sector = Sector.objects.get(title="Technology")
contact = ContactModel.objects.create(
civility=mr_civility,
first_name="Jane",
last_name="Smith",
email="jane.smith@techcorp.com",
phone="+1-555-0456",
mobile="+1-555-0789",
position=ceo_position,
sector=tech_sector,
is_a_nerd=True,
birthday=datetime.date(1980, 5, 15)
)from creme.persons import get_organisation_model
OrganisationModel = get_organisation_model()
# Create a basic organization
org = OrganisationModel.objects.create(
name="Tech Solutions Inc.",
email="info@techsolutions.com",
phone="+1-555-0100",
url_site="https://www.techsolutions.com"
)
# Create organization with detailed information
from creme.persons.models import LegalForm, StaffSize
llc_form = LegalForm.objects.get(title="LLC")
medium_size = StaffSize.objects.get(size="51-200 employees")
org = OrganisationModel.objects.create(
name="Innovation Corp",
email="contact@innovation.com",
phone="+1-555-0200",
legal_form=llc_form,
staff_size=medium_size,
sector=tech_sector,
annual_revenue=5000000,
capital=1000000,
subject_to_vat=True,
creation_date=datetime.date(2010, 1, 15)
)from creme.persons.models import Address
from django.contrib.contenttypes.models import ContentType
# Add address to contact
contact_ct = ContentType.objects.get_for_model(ContactModel)
address = Address.objects.create(
name="Home",
address="123 Main Street",
city="New York",
zipcode="10001",
country="USA",
content_type=contact_ct,
object_id=contact.id
)
# Add address to organization
org_ct = ContentType.objects.get_for_model(OrganisationModel)
office_address = Address.objects.create(
name="Head Office",
address="456 Business Plaza",
city="San Francisco",
zipcode="94105",
country="USA",
content_type=org_ct,
object_id=org.id
)from creme.creme_core.models import Relation, RelationType
# Create employment relationship
employed_rel = RelationType.objects.get(pk='persons-subject_employed_by')
Relation.objects.create(
user=request.user,
subject_entity=contact,
object_entity=org,
type=employed_rel
)
# Create management relationship
manages_rel = RelationType.objects.get(pk='persons-subject_manages')
Relation.objects.create(
user=request.user,
subject_entity=manager_contact,
object_entity=employee_contact,
type=manages_rel
)
# Create customer relationship
customer_rel = RelationType.objects.get(pk='persons-subject_customer_supplier')
Relation.objects.create(
user=request.user,
subject_entity=customer_org,
object_entity=supplier_org,
type=customer_rel
)# Find contacts by criteria
tech_contacts = ContactModel.objects.filter(
sector__title="Technology",
is_a_nerd=True
)
# Find organizations by size
large_orgs = OrganisationModel.objects.filter(
staff_size__size__contains="1000+"
)
# Find contacts at specific organization
org_employees = ContactModel.objects.filter(
relations_as_subject__type__pk='persons-subject_employed_by',
relations_as_subject__object_entity=org
)
# Find organization's customers
customers = OrganisationModel.objects.filter(
relations_as_object__type__pk='persons-subject_customer_supplier',
relations_as_object__subject_entity=org
)
# Search contacts by name
matching_contacts = ContactModel.objects.filter(
models.Q(first_name__icontains="John") |
models.Q(last_name__icontains="John")
)# Get formatted addresses
contact_address = contact.get_pretty_address()
print(f"Contact address: {contact_address}")
# Geocode addresses (requires geolocation module)
if address.latitude is None:
address.geocode() # Updates latitude/longitude
address.save()
# Find nearby contacts (requires geolocation calculations)
from django.db.models import Q
import math
def find_nearby_contacts(center_lat, center_lng, radius_km=10):
"""Find contacts within radius of coordinates."""
# Approximate degree conversion (rough calculation)
lat_range = radius_km / 111.0 # ~111km per degree latitude
lng_range = radius_km / (111.0 * math.cos(math.radians(center_lat)))
return ContactModel.objects.filter(
addresses__latitude__range=(center_lat - lat_range, center_lat + lat_range),
addresses__longitude__range=(center_lng - lng_range, center_lng + lng_range)
).distinct()The contact and organization system integrates with all other CRM modules:
Install with Tessl CLI
npx tessl i tessl/pypi-creme-crmdocs