๐ Work Summaries
๐ Overviewโ
The Work Summaries service manages weekly work summaries that document work performed, progress made, and deliverables provided during each week of service. These summaries provide transparency to clients about ongoing service delivery.
Source Files:
- Service:
internal/api/v1/projects/services/work-summary.service.js - Controller:
internal/api/v1/projects/controllers/work-summary.controller.js
Key Capabilities:
- Retrieve single work summary with full communication thread
- Support cursor-based pagination for infinite scroll
- Filter by client dashboard scopes
- Enrich with order/product context
- Apply launch date filtering for historical summaries
- Remove brand references from content
๐๏ธ Collections Usedโ
projects.tasksโ
- Operations: Read
- Model:
shared/models/projects-tasks.js - Usage Context: Work summaries stored as special task type
Key Fields for Work Summaries:
{
_id: ObjectId,
type: 'work_summary', // Special task type
account_id: ObjectId,
parent_account: ObjectId,
order_id: ObjectId,
title: String,
status: String,
creator: String,
first_communication_id: ObjectId,
last_communication_id: ObjectId,
created_at: Date,
updated_at: Date
}
communicationsโ
- Operations: Read
- Usage Context: Stores actual work summary content as messages
_store.ordersโ
- Operations: Read
- Usage Context: Product/subscription context
_accountsโ
- Operations: Read
- Usage Context: Client account information
๐ง Business Logic & Functionsโ
Service Layerโ
getWorkSummary(options)โ
Purpose: Retrieves a single work summary with full communication thread, applying brand filtering and access controls.
Parameters:
taskId(ObjectId) - Work summary task IDaccountId(ObjectId) - Parent account IDlimit(Number) - Communications per pageafter(ObjectId, optional) - Cursor for paginationdashboardPreferences(Object, optional) - Client dashboard settings
Returns: Work summary object with communications
{
id: ObjectId,
title: String,
type: 'work_summary',
status: String,
creator: String,
account_id: ObjectId,
parent_account: ObjectId,
order_id: ObjectId,
subaccount: { ... },
order: { ... },
product: {
id: ObjectId,
name: String,
nickname: String,
image: String
},
communications: {
data: [
{
id: ObjectId,
body: String, // Brand references removed
type: String,
attachments: Array,
sent_by: {
id: ObjectId,
name: String,
image: String,
dashclicks: { projects: { role: String } }
},
createdAt: Date
}
],
has_more: Boolean
},
created_at: Date,
updated_at: Date
}
Business Logic Flow:
-
Access Control Setup:
const options = {
_id: taskId,
parent_account: accountId,
type: 'work_summary',
created_at: { $gte: CLIENT_WORK_SUMMARY_LAUNCH_DATE },
};
if (dashboardPreferences?.allow_client_dashboard || dashboardPreferences?.sso) {
options.account_id = { $in: dashboardPreferences.sub_account_ids };
options.parent_account = dashboardPreferences.parent_account;
} -
Launch Date Filtering: Only summaries after
CLIENT_WORK_SUMMARY_LAUNCH_DATEvisible to clients -
Product Type Filtering: Only managed services excluding
'site'and'listings' -
Brand Reference Removal: Uses MongoDB
$functionto sanitize content:body: {
$function: {
body: "function(body) {
if (!body) return body;
return body
.replace(/\\s*(dash[\\s-]?clicks?)\\s*/gi, ' ')
.replace(/\\s+/g, ' ')
.trim();
}",
args: ['$body'],
lang: 'js'
}
}Removes "DashClicks", "Dash Clicks", "dash-clicks" variations
-
Communication Pagination:
- Cursor-based with
afterparameter - Returns
has_moreflag for infinite scroll - Sorts by
createdAtascending for chronological reading
- Cursor-based with
-
User Role Enrichment: Includes sender's project role for context
Key Business Rules:
- โ Launch Date Cutoff: Historical summaries before launch date hidden from clients
- โ Managed Services Only: Excludes site and listings products
- โ Brand Sanitization: Automatic removal of brand references from content
- โ Active Orders Only: Only summaries for active managed subscriptions
๐ Data Flowโ
flowchart TD
A[GET /work-summary/:id] --> B{Dashboard Type?}
B -->|Agency| C[Filter: parent_account = agency]
B -->|Client| D[Filter: account_id in allowed list]
C --> E[Apply Launch Date Filter]
D --> E
E --> F[Lookup Account + Order]
F --> G[Validate Order + Subscription]
G --> H{Valid?}
H -->|No| I[Return Empty]
H -->|Yes| J[Fetch Communications]
J --> K[Remove Brand References]
K --> L[Enrich with User Data]
L --> M[Apply Pagination]
M --> N[Return Work Summary]
๐ Integration Pointsโ
Internal Dependenciesโ
MANAGED_SUBSCRIPTIONS- Service type listCLIENT_WORK_SUMMARY_LAUNCH_DATE- Feature launch constantcatchAsync()- Error handling- Projects Tasks - Stored as special task type
- Communications - Message storage
๐งช Edge Cases & Special Handlingโ
Case: Pre-Launch Work Summaryโ
Condition: Summary created before CLIENT_WORK_SUMMARY_LAUNCH_DATE
Handling:
created_at: {
$gte: CLIENT_WORK_SUMMARY_LAUNCH_DATE;
}
Hidden from results automatically.
Case: Brand Name in Contentโ
Condition: Communication body contains "DashClicks" or variations
Handling: JavaScript function removes all variations:
- "DashClicks" โ removed
- "Dash Clicks" โ removed
- "dash-clicks" โ removed
- Multiple spaces collapsed to single space
Case: Missing Communicationsโ
Condition: No communications exist for work summary
Handling:
communications: {
data: [],
has_more: false
}
Gracefully returns empty array.
โ ๏ธ Important Notesโ
- ๐
Launch Date Enforcement:
CLIENT_WORK_SUMMARY_LAUNCH_DATEconstant controls historical visibility - ๐ท๏ธ Brand Sanitization: Automatic removal prevents white-label exposure
- ๐ Task Type: Work summaries are special
type: 'work_summary'tasks - ๐ Service Filtering: Only covers managed services (excludes site/listings)
- ๐ฌ Communication Thread: Uses same communication system as regular tasks
๐ Related Documentationโ
- Task Management - Related task system
- Activity - Work summaries appear in activity timeline
- Projects Module Overview - Parent module
Last Updated: 2025-10-08
Service Files:services/work-summary.service.js,controllers/work-summary.controller.js
Primary Functions: 1 service function, 1 controller endpoint