Documentation
¶
Overview ¶
Package crm mounts the Hanzo Cloud /v1/crm/* surface: a native-Go, per-org CRM (companies, contacts, opportunities) on Base/SQLite. It is the first slice of the "collapse the business apps into the unified cloud binary" program (universe/docs/architecture/unified-backend-go.md) — a native-Go port of the Twenty CRM core model, NOT a proxy to a NestJS backend.
The three entities are faithful to Twenty's `company` / `person` / `opportunity` standard objects, with Twenty's composite fields (FULL_NAME, EMAILS, CURRENCY, LINKS, ADDRESS) flattened to scalar columns for SQLite.
Tenant isolation is enforced SERVER-SIDE on every request: the org is c.Org() — the value SanitizeIdentity minted from the VALIDATED bearer owner claim (HIP-0026) — and NEVER a client-supplied header. Every store query filters WHERE org=?, so one tenant can never read or mutate another's data.
Surface (all org-scoped; /v1 only):
GET /v1/crm/summary per-org row counts (companies/contacts/opps)
GET /v1/crm/companies list companies -> {data:[…]}
POST /v1/crm/companies create a company -> Company (201)
GET /v1/crm/companies/:id company detail -> Company
PUT /v1/crm/companies/:id update a company -> Company
DELETE /v1/crm/companies/:id delete a company (+ clear refs)
GET /v1/crm/contacts list contacts (?companyId=) -> {data:[…]}
POST /v1/crm/contacts create a contact -> Contact (201)
GET /v1/crm/contacts/:id contact detail -> Contact
PUT /v1/crm/contacts/:id update a contact -> Contact
DELETE /v1/crm/contacts/:id delete a contact (+ clear refs)
GET /v1/crm/opportunities list opportunities (?stage=) -> {data:[…]}
POST /v1/crm/opportunities create an opportunity -> Opportunity (201)
GET /v1/crm/opportunities/:id opportunity detail -> Opportunity
PUT /v1/crm/opportunities/:id update an opportunity -> Opportunity
DELETE /v1/crm/opportunities/:id delete an opportunity
Order 131: binds /v1/crm/* before the AI subsystem's /v1/* catch-all (150). serve.go auto-registers GET /v1/crm/health.
Index ¶
- func Mount(app *zip.App, deps cloud.Deps) error
- func Shutdown() error
- type Company
- type Contact
- type Opportunity
- type Store
- func (s *Store) Close() error
- func (s *Store) Counts(ctx context.Context, org string) (companies, contacts, opps int, err error)
- func (s *Store) CreateCompany(ctx context.Context, c Company) (Company, error)
- func (s *Store) CreateContact(ctx context.Context, c Contact) (Contact, error)
- func (s *Store) CreateOpportunity(ctx context.Context, o Opportunity) (Opportunity, error)
- func (s *Store) DeleteCompany(ctx context.Context, org, id string) (bool, error)
- func (s *Store) DeleteContact(ctx context.Context, org, id string) (bool, error)
- func (s *Store) DeleteOpportunity(ctx context.Context, org, id string) (bool, error)
- func (s *Store) GetCompany(ctx context.Context, org, id string) (Company, error)
- func (s *Store) GetContact(ctx context.Context, org, id string) (Contact, error)
- func (s *Store) GetOpportunity(ctx context.Context, org, id string) (Opportunity, error)
- func (s *Store) ListCompanies(ctx context.Context, org string, limit int) ([]Company, error)
- func (s *Store) ListContacts(ctx context.Context, org, companyID string, limit int) ([]Contact, error)
- func (s *Store) ListOpportunities(ctx context.Context, org, stage string, limit int) ([]Opportunity, error)
- func (s *Store) UpdateCompany(ctx context.Context, c Company) (Company, error)
- func (s *Store) UpdateContact(ctx context.Context, c Contact) (Contact, error)
- func (s *Store) UpdateOpportunity(ctx context.Context, o Opportunity) (Opportunity, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Company ¶
type Company struct {
ID string `json:"id"`
Org string `json:"-"`
Name string `json:"name"`
DomainName string `json:"domainName"`
Employees int64 `json:"employees"`
City string `json:"city"`
Country string `json:"country"`
ARR int64 `json:"arr"`
Currency string `json:"currency"`
ICP bool `json:"idealCustomerProfile"`
Linkedin string `json:"linkedinLink"`
XLink string `json:"xLink"`
CreatedAt int64 `json:"createdAt"`
UpdatedAt int64 `json:"updatedAt"`
}
Company is an org-scoped account record, faithful to Twenty's `company` standard object (composites flattened to scalar columns for SQLite): ARR is minor units (cents) of Currency; ICP is the ideal-customer-profile flag.
type Contact ¶
type Contact struct {
ID string `json:"id"`
Org string `json:"-"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
Email string `json:"email"`
Phone string `json:"phone"`
JobTitle string `json:"jobTitle"`
City string `json:"city"`
CompanyID string `json:"companyId"`
Linkedin string `json:"linkedinLink"`
XLink string `json:"xLink"`
CreatedAt int64 `json:"createdAt"`
UpdatedAt int64 `json:"updatedAt"`
}
Contact is an org-scoped person record, faithful to Twenty's `person` standard object (FULL_NAME/EMAILS/PHONES composites flattened). CompanyID is an optional in-org relation to a Company.
type Opportunity ¶
type Opportunity struct {
ID string `json:"id"`
Org string `json:"-"`
Name string `json:"name"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
Stage string `json:"stage"`
CloseDate int64 `json:"closeDate"`
CompanyID string `json:"companyId"`
PointOfContact string `json:"pointOfContactId"`
CreatedAt int64 `json:"createdAt"`
UpdatedAt int64 `json:"updatedAt"`
}
Opportunity is an org-scoped deal record, faithful to Twenty's `opportunity` standard object. Amount is minor units (cents) of Currency; CloseDate is a unix second (0 == unset). Stage is validated against the default pipeline.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the CRM database. ONE SQLite file ({DataDir}/crm.db) holds every org's records; tenant isolation is the `org` column, enforced on EVERY query. This mirrors clients/prompts and clients/eval exactly (the ONE storage pattern). MaxOpenConns(1) serializes writes against the single-writer file.
func (*Store) Counts ¶
Counts returns per-org row counts across the three entities — a real, non-fabricated summary for the CRM module's overview cards.
func (*Store) CreateCompany ¶
func (*Store) CreateContact ¶
func (*Store) CreateOpportunity ¶
func (s *Store) CreateOpportunity(ctx context.Context, o Opportunity) (Opportunity, error)
func (*Store) DeleteCompany ¶
DeleteCompany removes a company and NULLs any dangling contact/opportunity refs to it within the same org (no orphaned foreign refs). One transaction.
func (*Store) DeleteContact ¶
DeleteContact removes a contact and clears any opportunity point-of-contact refs to it within the org. One transaction.
func (*Store) DeleteOpportunity ¶
func (*Store) GetCompany ¶
func (*Store) GetContact ¶
func (*Store) GetOpportunity ¶
func (*Store) ListCompanies ¶
func (*Store) ListContacts ¶
func (s *Store) ListContacts(ctx context.Context, org, companyID string, limit int) ([]Contact, error)
ListContacts lists the org's contacts, optionally filtered to one company (companyID=="" means all). Most-recently-updated first.
func (*Store) ListOpportunities ¶
func (s *Store) ListOpportunities(ctx context.Context, org, stage string, limit int) ([]Opportunity, error)
ListOpportunities lists the org's opportunities, optionally filtered by stage (stage=="" means all). Most-recently-updated first.
func (*Store) UpdateCompany ¶
func (*Store) UpdateContact ¶
func (*Store) UpdateOpportunity ¶
func (s *Store) UpdateOpportunity(ctx context.Context, o Opportunity) (Opportunity, error)