Notes
π Overviewβ
internal/api/v1/crm/services/note.service.js manages note lifecycle for contacts and deals. It enforces owner/follower visibility rules, hydrates associations, keeps threaded comments in sync, and mirrors changes to the CRM activity timeline via addActivity. Controllers only validate inputsβthis service performs Mongo queries, population, and permission checks.
ποΈ Collections Usedβ
π Full Schema: See Database Collections Documentation
crm.notesβ
- Operations: CRUD, comment threading, pin toggles
- Model:
shared/models/crm-note.js - Usage Context: Stores note content, attachments, entity associations, and pinned state
crm.activityβ
- Operations: Inserts timeline entries for note creation/update events
- Model:
shared/models/activity.js - Usage Context: Keeps the global activity feed aligned with note actions
crm.contacts, crm.dealsβ
- Operations: Visibility lookups, population, follower access checks
- Models:
shared/models/contact.js,shared/models/deal.js - Usage Context: Ensure the requesting user can read/write the target entity before notes mutate
π Data Flowβ
flowchart TD
UI[Client Request] -->|REST| Controller
Controller -->|Validate & sanitize| NoteService
NoteService -->|verify scope| Entities[Contacts / Deals]
NoteService -->|persist| Notes[(crm.notes)]
NoteService -->|fan-out| Activity[(crm.activity)]
NoteService -->|thread ops| Comments[(Embedded Comments)]
Notes -->|populate| Response
Activity -->|timeline sync| Response
π§ Service Entry Pointsβ
Listing & Retrievalβ
-
getNote({ account_id, uid, contact_id, deal_id, page, limit, expand, type, is_owner, auth })- Applies owner/follower filters and association scopes
- Prioritizes pinned notes, then sorts by
createddescending - Populates contact/deal summaries when
expandis toggled
-
filterNote({ account_id, uid, body, is_owner, auth, expand })- Accepts advanced filters (search body, type, associations)
- Mirrors list pagination while respecting visibility
- Supports expansion for UI rich cards
-
getOneNote({ account_id, uid, id, is_owner, auth, expand })- Fetches a single note with attachments and embedded comments
- Validates entity ownership before returning hydrated payload
Creation & Updatesβ
-
postNote({ account_id, uid, body, is_owner, auth })- Requires at least one entity association (contact or deal)
- Persists note, attachments, pin flag, and association metadata
- Dispatches a
noteactivity viaaddActivity
-
updateNote({ account_id, uid, id, body, is_owner, auth, expand })- Restricts edits to creators or users with entity access
- Handles content edits, re-pin, attachment replacement, and association changes
- Re-populates relationships for response consistency
Deletion & Cleanupβ
deleteOneNote({ account_id, uid, id, is_owner, auth })- Confirms note visibility scope before deletion
- Removes note and coordinates downstream cleanup (attachments, activity entries)
Comment Threadingβ
-
postCommentsNote({ account_id, uid, id, body, is_owner, auth })- Appends a comment with author metadata and timestamps
- Rehydrates comment thread for the response payload
-
putCommentNote({ account_id, uid, id, comment_id, body, is_owner, auth })- Allows comment text updates for original commenter or note owner
- Maintains comment chronology and metadata integrity
-
deleteCommentNote({ account_id, uid, id, comment_id, is_owner, auth })- Removes comment while preserving the remaining thread order
- Returns refreshed note payload for instant UI updates
π Integration Pointsβ
Internal Dependenciesβ
addActivityutility to broadcast note actions into the CRM activity feednoteExpandOptionsto control population depth whenexpand=truegeneratePaginationhelper for consistent list metadatacatch-errors.notAllowedfor standardized permission denials
External Servicesβ
- None directlyβfile attachments are validated prior to service invocation
β οΈ Edge Cases & Guardrailsβ
- Owner visibility: When contacts are owner/follower restricted, the requester must be the creator, owner, or follower to interact with the note
- Pinned ordering: Lists always return pinned notes first; service ensures stable sorting for deterministic pagination
- Expand toggle: Setting
expand=truereturns fully populated associations; default responses trim fields for payload efficiency - Attachment lifecycle: Upstream middleware must sanitize uploads; service cleanup runs during note deletion to avoid orphaned files
- Comment auth: Comment edits/deletes require the original commenter or note creator credentials