Skip to main content

Fields

πŸ“– Overview​

internal/api/v1/crm/services/field.service.js governs custom property definitions that extend contacts, businesses, and deals. It merges system defaults with account-specific additions, enforces user-config locks, deduplicates titles, spreads option lists (including deal currency choices), and writes both Account.crm.additional_info and UserConfig.fields so UI config stays aligned. Controllers only validate payloads; this service coordinates lookups, locks, and persistence.

πŸ—„οΈ Collections Used​

πŸ“š Full Schema: See Database Collections Documentation

_accounts​

  • Operations: Reads/writes crm.additional_info blobs when fields are added, updated, or removed
  • Model: shared/models/account.js
  • Usage Context: Stores the authoritative list of custom field definitions per entity type

user-config​

  • Operations: Fetches lock state, stores per-user page config (fields[type] ordering and visibility)
  • Model: shared/models/user-config.js
  • Usage Context: Mirrors field metadata so dashboards know ordering, widths, mandatory flags

Utility Layer​

  • fieldUtils.getDefaultFields() supplies baseline definitions that cannot be mutated or deleted
  • fieldUtils.getCurrencyOption() augments deal currency dropdowns with account-specific rates
  • fieldUtils.getFieldCopyTitle() resolves duplicate labels by auto-appending counters

πŸ”„ Data Flow​

flowchart TD
Request -->|Validate| Controller
Controller -->|delegate| FieldService
FieldService -->|load defaults| DefaultFields[(Shared Defaults)]
FieldService -->|merge| AccountBlob[(Account.crm.additional_info)]
FieldService -->|persist| AccountsDB[(Accounts)]
FieldService -->|sync config| UserConfigDB[(UserConfig)]
FieldService --> Response

🧭 Service Entry Points​

Listing & Retrieval​

  • getTypeField({ type, additional_info, account_id, uid })

    • Hydrates the account’s custom additional_info blob or seeds defaults if absent
    • Marks custom entries with custom=true and injects deal currency options
    • Supports type scoping (people, businesses, deals) or returns all when omitted
  • getOneField({ type, id, additional_info })

    • Locates a specific field definition inside the cached additional_info
    • Returns 404 when a custom ID is missing or type mismatch occurs

Creation & Updates​

  • postField({ type, title, valueType, options, uid, account_id, additional_info, field_options })

    • Rejects writes when UserConfig is locked for the requesting user
    • Normalises titles via getFieldCopyTitle to avoid duplicates
    • Persists new field object to Account.crm.additional_info and appends layout config with incremented order
    • Returns the saved field with custom=true and the computed config payload
  • updateField({ type, id, title, options, uid, account_id, additional_info })

    • Blocks edits to default fields and checks per-user lock state
    • Validates unique titles inside the same entity type
    • Updates name and selectable options, then persists the full blob back to the account

Deletion & Cleanup​

  • deleteOneField({ type, id, additional_info, account_id, uid })
    • Prevents deletions of system defaults and ensures the ID exists in the custom list
    • Removes the entry from crm.additional_info, rewrites UserConfig.fields order values, and returns SUCCESS

πŸ”— Integration Points​

Internal Helpers​

  • fieldUtils bundle for defaults, currency options, and unique title generation
  • UserConfig documents track per-user UI locks and column ordering
  • Account writes guarantee all users inherit custom field mutations immediately

External Services​

  • None directlyβ€”attachments and validation happen upstream before service invocation

⚠️ Edge Cases & Guardrails​

  • Locked configuration: When UserConfig.is_locked is true, create/update requests are denied with ACCESS_DENIED
  • Default protections: System fields from getDefaultFields() cannot be updated or deleted
  • Collision handling: getFieldCopyTitle auto-appends counters so duplicate names remain distinct
  • Option integrity: Only option-bearing types (dropdown, singleCheck, multipleCheck) persist options arrays
  • Ordering: Deletions reindex UserConfig.fields[type] to keep sequential order values
πŸ’¬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM