- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
4 hours ago
Assign an unassigned resource assignment to one or more users so that the allocated work is distributed from the resource pool to specific team members, ready for execution.
1. Before you begin
- Role required: resource_manager with canWrite and canCreate access on sn_plng_att_core_resource_assignment.
- The assignment must be an unassigned user-type resource assignment (not a group or resource plan row).
- The assignment must have planning attributes associated with the task.
- The assignment dates must be within the project/task date range. If the assignment dates fall outside the task dates, the system blocks the operation.
- The assignment must not be an operational work assignment.
- Selected resources must be available for the assignment period (employee profile must not be expired for the full assignment date range, unless validations are explicitly skipped).
About this task
The Assign flow distributes effort from an unassigned resource assignment to one or more selected users. It is available in the Resource Management Workspace and supports multiple distribution modes.
Entire Effort Distribution — The system distributes the full unassigned effort equally across all selected users. For example, assigning 3 FTE to 3 users results in each user receiving 1 FTE. Hours are calculated based on each user's working calendar. If the effort cannot be divided evenly, leftover hours are distributed in a round-robin fashion across the users.
Manual Distribution — The resource manager specifies a custom effort value (in hours or FTE) to distribute. This allows partial assignment — for instance, distributing only 500 hours out of 600 total, with the remaining 100 hours retained on the unassigned assignment for future assignment.
Auto Assign — The system automatically selects eligible users from the resource group associated with the assignment and distributes the entire effort. This is useful when specific user selection is not required.
Preview — Before committing an assignment, the resource manager can preview how hours will be distributed across users and time periods. The preview displays a read-only allocation heatmap grid. No data is modified during preview.
Async Assignment — When the number of selected users exceeds a threshold, the system processes the assignment asynchronously via a background event (sn_rm_ws.assign_asmt). A progress message is displayed, and the board can be refreshed to view results once processing completes.
Key behavior: When the last user's allocation fully consumes the remaining unassigned hours (or the remainder falls below the minimum allocation interval), the system reuses the original unassigned assignment record for that user instead of creating a new one. This avoids unnecessary record creation. When effort is only partially distributed, the leftover hours remain on the original unassigned assignment, which stays in the resource pool for future assignment.
2. Procedure
- Navigate to Navigate to Workspaces > Resource Management Workspace and open a resource board.
- Enable the "Unassigned tasks" toggle on the resource board to display unassigned assignments.
- Locate the unassigned resource assignment row on the board.
- Select the row context menu (three vertical dots) and choose Assign work.
- The Assign Work modal opens. Configure the assignment:
- Assign by: Choose "Manual Assign" (default) to select specific users, or "Auto Assign" to let the system choose users from the resource group.
- User selection (manual mode): Use the typeahead search to find and select one or more users. Selected users must belong to the resource group and have valid employee profiles.
- Effort distribution: Choose "Entire" to distribute all effort, or "Manual" to specify a custom value.
- Effort type: Choose "FTE" or "Hours" depending on the preferred unit.
- Effort value (manual distribution only): Enter the amount of effort to distribute. The value must be positive and within the available unassigned effort.
- (Optional) Click Preview to see how hours will be allocated across users and time periods before committing. The preview displays a read-only heatmap grid showing per-user, per-period allocations.
- Click Assign resources to confirm the assignment.
- A success message appears once the allocation completes. The board refreshes to reflect the new assignments.
- If the entire effort is distributed, the success message reads: "Allocation is completed successfully for the selected resources."
- If only partial effort is distributed, the message reads: "Assignment is partially allocated for selected resources and remaining effort is retained on the resource assignment."
- For async assignments (large user lists), the message reads: "Allocation is in progress... Refresh the page after some time to view the allocations."
3. Examples
Example 1: Distribute 2 FTE equally to 3 users
A project task has an unassigned resource assignment of 2 FTE over 6 months (March–September 2024). The resource manager opens the Assign Work modal, selects three users, and chooses "Entire" effort distribution.
Result: The system converts 2 FTE to 352 hours for April 2024 (based on 176 working hours/month × 2 FTE). Each user receives 117 hours (352 ÷ 3 = 117.33, floored to the minimum allocation interval). The remaining 1 hour will then be assigned to first user by accumulating leftover hours from each users.
Example 2: Multi-Month Distribution
Setup: Unassigned RA spans Jan–Mar 2027, 1 FTE.
• January: 22 working days → 176 hours
• February: 20 working days → 160 hours
• March: 23 working days → 184 hours
Assigned to 2 users. Calendar Event Duration = 60 minutes.
Calculation per month:
January (176 hours):
rawHoursPerUser = 176 / 2 = 88 hours
roundOff(88) = 88. Both users get 88. Leftover = 0.
February (160 hours):
rawHoursPerUser = 160 / 2 = 80 hours
roundOff(80) = 80. Both users get 80. Leftover = 0.
March (184 hours):
rawHoursPerUser = 184 / 2 = 92 hours
roundOff(92) = 92. Both users get 92. Leftover = 0.
Total per user: 88 + 80 + 92 = 260 hours
Grand total: 520 = 176 + 160 + 184. No leftover.
Example 3: Multi-Month with Leftover and Carry-Forward
January (176 hrs):
rawHoursPerUser = 176/3 = 58.6666
floor → 58.66 → roundOff (Math.floor at interval) → 58
Initial: A=58, B=58, C=58. Assigned=174.
Leftover = 0.6666×3 = 1.9998. Round-robin: 1 hr to A (i=0→1). Carry=0.9998.
Final: A=59, B=58, C=58. Total=175.
February (160 hrs):
rawHoursPerUser = 160/3 = 53.3333 → 53
Initial: A=53, B=53, C=53. Assigned=159.
Leftover = 0.9999 + carry 0.9998 = 1.9997. Round-robin: 1 hr to B (i=1→2). Carry=0.9997.
Final: A=53, B=54, C=53. Total=160.
March (184 hrs):
rawHoursPerUser = 184/3 = 61.3333 → 61
Initial: A=61, B=61, C=61. Assigned=183.
Leftover = 0.9999 + carry 0.9997 = 1.9996. Round-robin: 1 hr to C (i=2→0).
No next month → 0.9996 discarded (stays on unassigned RA).
Final: A=61, B=61, C=62. Total=184.
Totals:
A: 59+53+61 = 173 hrs
B: 58+54+61 = 173 hrs
C: 58+53+62 = 173 hrs
Grand total: 519 hrs. Unassigned remaining: ~1 hr (0.9996).
Conservation: 519 + ~1 = 520 = 176+160+184
Example 4: Assign with a user who has an expired employee profile
Setup
- Unassigned resource assignment: 2 FTE over 7 months (March–September 2024)
- Users selected: User A and User B
- User A's employee profile expired on 2024-06-01 (available March–May, unavailable June–September)
- User B's profile is active through the entire assignment period
- Calendar Event Duration: 60 minutes
How the system handles it
The system divides hours equally between 2 users for each month. Since the effort is 2 FTE and there are 2 users, each user's share per month equals the working days multiplied by 8 hours (1 FTE worth). This always results in a whole number, so there is no leftover or round-robin needed.
For months where User A is unavailable, the system detects zero working days and assigns 0 hours to User A. User A's unclaimed share is not redistributed to User B — the system always divides by the total number of selected users (2), regardless of availability. The unclaimed share remains on the unassigned resource assignment.
Month-wise distribution
- March 2024 — 21 working days, 336 total hours
- User A: 168 hours
- User B: 168 hours
- Unassigned remaining: 0 hours
- April 2024 — 22 working days, 352 total hours
- User A: 176 hours
- User B: 176 hours
- Unassigned remaining: 0 hours
- May 2024 — 23 working days, 368 total hours
- User A: 184 hours
- User B: 184 hours
- Unassigned remaining: 0 hours
- June 2024 — 20 working days, 320 total hours
- User A: 0 hours (profile expired)
- User B: 160 hours
- Unassigned remaining: 160 hours
- July 2024 — 23 working days, 368 total hours
- User A: 0 hours (profile expired)
- User B: 184 hours
- Unassigned remaining: 184 hours
- August 2024 — 22 working days, 352 total hours
- User A: 0 hours (profile expired)
- User B: 176 hours
- Unassigned remaining: 176 hours
- September 2024 — 21 working days, 336 total hours
- User A: 0 hours (profile expired)
- User B: 168 hours
- Unassigned remaining: 168 hours
Totals
- User A: 528 hours (March–May only)
- User B: 1,216 hours (all 7 months)
- Remaining on unassigned assignment: 688 hours (June–September)
- Conservation check: 528 + 1,216 + 688 = 2,432 = original total ✓
The resource manager can later reassign the remaining 688 hours to another user through the Assign Work modal.
Example 5: Preview before assigning
Before committing, the resource manager clicks "Preview" after selecting users. A read-only heatmap grid appears showing the projected allocation for each user across each time period (month or week). The preview includes columns for Resource assignee, Resource status, Start date, End date, and per-period effort values.
Result: The resource manager reviews the allocation distribution. No assignment records are created or modified. The manager can then click "Assign resources" to proceed, or close the modal to cancel.
Example 6: Auto assign with a large team
A resource group has 50+ members. The resource manager selects "Auto Assign" mode instead of manually selecting users. The system retrieves all eligible users from the resource group.
Result: Because the user count exceeds the synchronous threshold, the system fires an asynchronous event (sn_rm_ws.assign_asmt). The message "Allocation is in progress... Refresh the page after some time to view the allocations." appears. The allocation status is marked as "in_progress" and updated to "allocated" upon completion.
4. Role of the Calendar Event Duration Property
The Calendar Event Duration property (com.snc.resource_management.calendar_event_duration) controls the minimum time unit for resource allocations. It defines the smallest "slot" of time that can be allocated. Common values are 60 minutes (1 hour), 30 minutes, or 15 minutes or 0.6. This property directly influences how hours are rounded during the assign flow.
How it works:
After the system calculates the raw hours to distribute per user per time period, those hours are rounded down to the nearest multiple of the Calendar Event Duration. This rounding is performed by the roundOffBasedOnCalendarEventProperty function:
Formula:
- 1. Start with the raw calculated hours.
2. Convert to minutes: timeInMinutes = hours × 60
3. Calculate how many complete calendar event units fit: units = floor(timeInMinutes / minTimeUnit)
4. Calculate the allocation interval factor: factor = minTimeUnit / 60
5. Final hours = units × factor
For example, with a 60-minute calendar event duration:
• Raw hours = 117.33 → timeInMinutes = 7039.8 → units = floor(7039.8 / 60) = 117 → final = 117 × 1 = 117 hours
• Raw hours = 88.75 → timeInMinutes = 5325 → units = floor(5325 / 60) = 88 → final = 88 × 1 = 88 hours
With a 30-minute calendar event duration:
• Raw hours = 117.33 → timeInMinutes = 7039.8 → units = floor(7039.8 / 30) = 234 → final = 234 × 0.5 = 117 hours
• Raw hours = 88.75 → timeInMinutes = 5325 → units = floor(5325 / 30) = 177 → final = 177 × 0.5 = 88.5 hours
With a 15-minute calendar event duration:
• Raw hours = 117.33 → timeInMinutes = 7039.8 → units = floor(7039.8 / 15) = 469 → final = 469 × 0.25 = 117.25 hours
Where is rounding applied:
- During distribution: When calculating per-user hours from the heatmap — after flooring to 2 decimals, hours are rounded to the calendar event interval.
- During leftover allocation: When distributing fractional leftover hours in round-robin, each incremental allocation is rounded to the calendar event interval.
- During contour update: After subtracting assigned hours from the unassigned contour, the remaining hours are rounded to the calendar event interval to keep the contour clean.
- During effort conversion: When converting hours to FTE or man-days for display, hours are first rounded to the calendar event interval.
Key impact: The difference between the raw calculated hours and the rounded hours becomes "leftover hours" — these are not lost but are collected and redistributed in a round-robin phase. If the leftover is too small even for a single calendar event unit, it is carry-forwarded to the next time period. If it cannot be distributed at all (remains below the minimum interval even after carry-forward), it stays on the unassigned assignment.
5. Contour Management
A "contour" is the time-phased distribution of hours across a resource assignment — essentially, how many hours are allocated in each time period (month or week). Contour management refers to how the system creates, distributes, and updates these time-phased allocations during the assign flow.
General formula for contour distribution:
For each time period (heatmap unit = month or week), the system calculates per-user hours using this logic:
Step 1 — Determine raw hours per user per time period:
For Entire Effort Distribution (FTE distribution):
hoursPerUser = totalHoursInPeriod / numberOfUsers
For Manual Hours Distribution:
hoursPerUser = (requestedHours × hoursInThisPeriod) / (totalAssignmentHours × numberOfUsers)
This proportionally allocates the requested hours based on how much of the total assignment
falls in each time period.
For Manual FTE Distribution:
ftePerUser = requestedFTE / numberOfUsers
hoursPerUser = ftePerUser × avgDailyFTE × workingDaysInPeriod
Step 2 — Validate distributable minimum:
Both the per-user average (from the assignment) and the requested hours must meet the minimum
allocation interval (in minutes). If either is below the threshold, 0 hours are assigned for
that user in that period.
canDistribute = (hoursInMinutes / minAllocationInterval) >= 1
Step 3 — Take the minimum of assignment hours and requested hours:
hoursToBeDist = min(assignmentHoursPerUser, requestedHoursPerUser)
This ensures you never assign more hours than available in the unassigned contour or more
than the user requested.
Step 4 — Floor to 2 decimals, then round to calendar event property:
maxHoursForUser = roundOffBasedOnCalendarEventProperty(floorToDecimals(hoursToBeDist))
Step 5 — Cap by user availability:
availableHours = (24 × workingDays) − totalBlockedHours
If maxHoursForUser > availableHours (and over-allocation is not allowed),
the system caps the allocation at availableHours.
Step 6 — Collect leftover = hoursToBeDist − maxHoursForUser (the rounding/capping residual)
Step 7 — Round-robin leftover distribution:
After processing all users for all periods, the system iterates over collected leftovers.
In each time period, it distributes leftover hours one minimum step (1/decimalMultiple) at a time
to each user in turn, round-robin, until no more leftovers remain or the total assigned reaches
the original period total. If leftover hours in a period are too small to distribute, they are
carry-forwarded to the next time period.
When the contour is NOT fully preserved (deviations from the formula):
- User not available: If a user has no working days in a time period (e.g., profile not yet active, or expired), the user receives 0 hours for that period. The hours that would have gone to that user are not automatically redistributed to other users — they remain as leftover on the unassigned assignment.
- Blocked hours from other assignments: If a user already has existing allocations from other assignments, the available hours = (24 × workingDays) − blockedHours. The assigned hours are capped at the available capacity. This means the user may receive fewer hours than the formula suggests.
- Below minimum allocation interval: When the raw hours per user per period fall below the minimum allocation interval (e.g., less than 1 hour for a 60-minute interval), the system assigns 0 hours for that user in that period.
- Fractional leftovers below minimum step: After flooring and rounding to the calendar event interval, the leftover hours may be too small to constitute even one minimum step. These micro-leftovers are carry-forwarded to the next time period. If the last period also cannot absorb them, they remain on the unassigned assignment.
- Expired employee profile (partial availability): If the employee profile has an end date within the assignment range, the user receives 0 hours for all periods after the profile expiration. This creates an asymmetric distribution where other users do not automatically absorb the expired user's share.
- Over-allocation setting: When the system property com.snc.resource_management.allocate_more_than_24hours_per_day is false (default), per-day allocation is capped at 24 hours minus blocked hours. When true, this cap is removed.
Contour update on the unassigned assignment:
After each user's allocation is created, the system updates the unassigned assignment's contour:
remainingHours[period] = originalUnassignedHours[period] − userAllocatedHours[period] + hoursNotAllocated
remainingHours[period] = roundOffBasedOnCalendarEventProperty(remainingHours[period])
The "hoursNotAllocated" accounts for any hours that could not be written to allocation dailies (e.g., due to schedule constraints). This ensures the unassigned contour accurately reflects what remains after each user's allocation, rounded to the calendar event interval.
6. Leftover Hours — Detailed Examples
Leftover hours arise from two sources: (a) rounding down to the calendar event interval, and (b) inability to distribute effort due to user unavailability or capacity constraints. Understanding leftover handling is critical to verifying that no effort is silently lost.
Example 7: Rounding leftover from equal distribution
Setup: An unassigned assignment has 352 hours in April 2024 (2 FTE × 176 working hours). The resource manager assigns to 3 users with "Entire" effort distribution. Calendar Event Duration = 60 minutes.
Calculation per user per month:
rawHoursPerUser = 352 / 3 = 117.33 hours
floorToDecimals(117.33) = 117.33
roundOffBasedOnCalendarEventProperty(117.33) → timeInMinutes = 7039.8 → units = floor(7039.8/60) = 117 → 117 hours
leftover per user = 117.33 − 117 = 0.33 hours
Total leftover = 0.33 × 3 users = 1.0 hour (approximately)
Round-robin phase:
minStep = 1 / (60/60) = 1 hour
1.0 hour ≥ 1 hour (minStep), so distribute:
• User 1 gets +1 hour → 118 hours total
• Remaining leftover: 0.0 hours
But assigned total is now 117 + 117 + 118 = 352 = original total. Leftover on unassigned = 0 hours → assignment is fully consumed, so original assignment is reused for User 3.
Example 8: Leftover from manual partial assignment
Setup: An unassigned assignment has 600 hours over 3 months (200 hours each in July, August, September). The resource manager assigns 500 hours manually to 3 users. Calendar Event Duration = 60 minutes.
Calculation for each month:
Proportional hours per month = (500 × 200) / (600 × 3) = 55.55 hours per user per month
floorToDecimals(55.55) = 55.55
roundOffBasedOnCalendarEventProperty(55.55) = 55 hours
leftover per user per month = 55.55 − 55 = 0.55 hours
Total leftover per month = 0.55 × 3 = 1.65 hours
Round-robin phase (per month):
minStep = 1 hour
1.65 ≥ 1, distribute:
• User 1 gets +1 hour → 56 hours. Remaining = 0.65
• 0.65 < 1 (minStep), so carry forward 0.65 to next month
Month 2: leftover = 1.65 + 0.65 (carried) = 2.30
• User 2 gets +1 → 56 hours. Remaining = 1.30
• User 3 gets +1 → 56 hours. Remaining = 0.30
• 0.30 < 1, carry forward to Month 3
Month 3: leftover = 1.65 + 0.30 = 1.95
• User 1 gets +1 → 56 hours. Remaining = 0.95
• 0.95 < 1, cannot distribute further
Final distribution:
User 1: 56 + 55 + 56 = 167 hours
User 2: 55 + 56 + 55 = 166 hours
User 3: 55 + 56 + 55 = 166 hours
Total assigned: 499 hours (0.95 hours lost to rounding)
Remaining on unassigned: 600 − 499 = 101 hours → partial allocation message
Example 9: Leftover due to user unavailability
Setup: An unassigned assignment has 184 hours in July 2024 (1 FTE). Assigned to 2 users: User A's employee profile expired on 2024-06-01, User B is active. Calendar Event Duration = 60 minutes.
Calculation:
rawHoursPerUser = 184 / 2 = 92 hours
User A: _isUserAvailable returns false (profile expired) → 0 hours
User B: _isUserAvailable returns true → 92 hours assigned
Leftover:
User A's 92 hours are NOT redistributed to User B. They remain on the unassigned assignment.
Remaining on unassigned = 184 − 92 = 92 hours → partial allocation message.
Why not redistributed? The formula calculates per-user hours upfront (total ÷ users). When a user is unavailable, those hours are simply not assigned — the system does not recalculate the distribution for the remaining available users. This is by design: the resource manager chose to split equally among N users, and the system honors that split. If different behavior is desired, the manager should deselect unavailable users before assigning.
Example 10: Leftover due to blocked hours (capacity constraint)
Setup: An unassigned assignment has 180 hours in August 2024 (23 working days × ~7.83 hrs/day). Assigned to 2 users. User A already has 150 hours of existing allocations (blocked hours) from another task. Calendar Event Duration = 60 minutes. Over-allocation = false.
Calculation:
rawHoursPerUser = 180 / 2 = 90 hours per user
User A:
workingDays = 23, availableHours = (24 × 23) − 150 = 552 − 150 = 402 hours
90 hours ≤ 402 → User A gets 90 hours (no capping needed)
User B:
Suppose User B has 500 blocked hours (very heavy load):
availableHours = 552 − 500 = 52 hours
90 hours > 52 → User B is capped at 52 hours
Leftover from User B: 90 − 52 = 38 hours → not redistributed to User A
Remaining on unassigned: 180 − 90 − 52 = 38 hours → partial allocation message
Example 11: Leftover carry-forward across months
Setup: An unassigned assignment has 3 hours spread across 3 months (1 hour each in Jan, Feb, Mar). Assigned to 2 users. Calendar Event Duration = 60 minutes.
Calculation per month:
rawHoursPerUser = 1 / 2 = 0.5 hours
roundOffBasedOnCalendarEventProperty(0.5) = 0 hours (0.5 × 60 = 30 min, units = floor(30/60) = 0)
Both users get 0 hours in every month.
Leftover: 0.5 × 2 = 1.0 hour per month
Round-robin:
Month 1: leftover = 1.0 hour. minStep = 1 hour.
• Assigned already = 0, total = 1. Can assign 1 more? 0 + 1 ≤ 1 → yes.
• User 1 gets +1 → 1 hour. Remaining = 0 → done for this month.
Month 2: leftover = 1.0 hour.
• User 2 gets +1 → 1 hour.
Month 3: leftover = 1.0 hour.
• User 1 gets +1 → 1 hour.
Final: User 1 = 2 hours, User 2 = 1 hour. Total = 3 hours (fully assigned).
Note: Even though the formula gave 0 hours per user per month, the round-robin phase recovered all hours. This demonstrates that the leftover mechanism prevents effort loss even when individual period amounts are below the calendar event interval.
