Every organization needs to know who they're talking to — customers, members, donors, volunteers, contacts — but most CRM tools live entirely separate from the website and shop that actually generate those relationships.
The pain it solves: Running a separate CRM alongside your website/shop means constant manual syncing, duplicate contact records, and an incomplete picture of each relationship.
How it helps:
ApplicationUser account means a customer can also be given portal/login access without creating a second profile.The happy workday: One click, one full picture of the relationship — purchases, memberships, form responses, and communications, all in one place.
An integrated CRM turns every touchpoint — a purchase, a form submission, a newsletter open — into part of the same relationship record, giving staff a genuinely complete view of each person without stitching together multiple tools.
CRM capability is centered on the Customer model (ExireNexus.Shared/Models/Shop/Customer.cs) and CustomerService (ExireNexus.Services/Services/CustomerService.cs).
Key implementation points:
Customer has a CustomerStatus field and can be grouped via Category (CategoryType-discriminated, consistent with the platform's polymorphic categorization pattern), enabling segmentation without new tables.Customer optionally links to ApplicationUser — the platform deliberately keeps "people the system knows about" (Customer) separate from "people who can log in" (ApplicationUser), letting a contact be tracked in the CRM long before (or without ever) becoming a logged-in user.ShopOrder/ShopOrderItem (purchases), FormResponse (form submissions), UserGroupMember (memberships) — all reference the same Customer ID, so a single query surfaces a customer's full history across modules.CustomerService rather than introducing a parallel "People" or "Contacts" service against the same Customer table — keeping one authoritative service per entity.This design avoids the common CRM integration problem of reconciling records across systems: because Customer is the same row referenced everywhere, there's no synchronization step at all.