After the context is provided in the Kiro chatroom, the system generates three files in sequence: requirements, design, and tasks.
Each file is reviewed to ensure the content aligns with expectations. If any issues are found, the file is updated directly, then update the file to trigger regeneration of the related files.
Once all files are finalized, work begins from the task file. It presents a list of tasks with action buttons, which are executed sequentially to validate the correctness of the AI-generated code.
### 1. Requirements

```markdown!
# Feature Requirements: Add Feeder School Logs to Daily Digest
## Overview
Add feeder school reference logs to the daily digest email to maintain consistency with the latest activity feed. This feature was requested after OA-22554 added feeder school logs to the latest activity, but they were not included in the daily digest.
## Background
- **Related Ticket**: OA-22554 (Add feeder school logs into latest activity)
- **Current State**: Feeder school logs appear in the latest activity feed but not in the daily digest
- **Desired State**: Feeder school logs should appear in both latest activity and daily digest for consistency
## User Stories
### 1. As a school administrator
**I want** to see feeder school reference activities in my daily digest email
**So that** I can stay informed about feeder school reference submissions without checking the dashboard
### 2. As a school administrator
**I want** the daily digest to show the same types of activities as the latest activity feed
**So that** I have a consistent experience across different notification channels
## Acceptance Criteria
### 1.1 Feeder School Activities in Daily Digest
- **Given** a school has feeder schools enabled
- **And** feeder school reference activities occurred within the digest time period
- **When** the daily digest email is generated
- **Then** feeder school reference activities should be included in the "Other Activities" section
- **And** the activities should display with the same format as in the latest activity feed
### 1.2 Feeder School Feature Flag Respect
- **Given** a school does NOT have feeder schools enabled
- **When** the daily digest email is generated
- **Then** feeder school reference activities should NOT be included in the digest
### 1.3 Activity Types Included
- **Given** feeder school activities exist
- **When** collecting activities for the daily digest
- **Then** both `FeederSchoolReference` and `FeederSchoolReferenceBatch` activity types should be included
- **And** they should follow the same filtering rules as other activities (exclude 'sent' verb for FeederSchoolReference)
### 1.4 Consistency with Latest Activity
- **Given** the same time period
- **When** comparing activities in the daily digest vs latest activity feed
- **Then** the same feeder school activities should appear in both places
- **And** the activity descriptions should be identical
## Technical Requirements
### 2.1 Code Changes Required
- Modify `ViewObject::Admin::DailyDigest` to include feeder school activity classes when the school has feeder schools enabled
- Ensure the same filtering logic from `DashboardActivities` is applied (exclude 'sent' verb for FeederSchoolReference)
- Follow the existing pattern used in `StudentActivities` and `DashboardActivities`
### 2.2 Testing Requirements
- Add unit tests for `ViewObject::Admin::DailyDigest` to verify feeder school activities are included
- Test that feeder school activities are excluded when the feature is disabled
- Test that the 'sent' verb is properly filtered out for FeederSchoolReference
- Ensure existing daily digest functionality is not broken
## Non-Functional Requirements
### 3.1 Performance
- Adding feeder school activities should not significantly impact daily digest generation time
- Use the same efficient query patterns as existing activity collection
### 3.2 Maintainability
- Follow the existing code patterns in `StudentActivities` and `DashboardActivities`
- Use the same constant definitions for activity classes
- Maintain consistency in how feature flags are checked
## Out of Scope
- Changing the visual design of the daily digest email
- Adding new types of feeder school activities beyond what's already in latest activity
- Modifying how feeder school activities are logged or tracked
- Changes to the latest activity feed itself
## Dependencies
- Existing feeder school reference functionality
- `enable_feeder_schools?` feature flag on School model
- Activity tracking system (`ActsAsActivity`)
- Daily digest email system
## Success Metrics
- Feeder school activities appear in daily digest when feature is enabled
- No regression in existing daily digest functionality
- Test coverage for new functionality
- Consistent behavior between latest activity and daily digest
```
### 2. Design

```markdown!
# Design Document: Add Feeder School Logs to Daily Digest
## Overview
This document outlines the design for adding feeder school reference activities to the daily digest email, ensuring consistency with the latest activity feed implementation.
## Architecture
### Current Implementation Analysis
#### Latest Activity Implementation
The latest activity feed already includes feeder school activities through two view objects:
1. **`ViewObject::Admin::StudentActivities`** (Student profile activity feed)
- Defines `FEEDER_SCHOOL_ACTIVITY_CLASSES = %w(FeederSchoolReference)`
- Conditionally adds these classes when `@school.enable_feeder_schools?` is true
- Used for individual student activity views
2. **`ViewObject::Admin::DashboardActivities`** (Dashboard activity feed)
- Defines `FEEDER_SCHOOL_ACTIVITY_CLASSES = %w(FeederSchoolReference FeederSchoolReferenceBatch)`
- Includes both individual references and batch operations
- Filters out `sent` verb: `.where.not(trackable_type: 'FeederSchoolReference', verb: 'sent')`
- Conditionally includes in filter options when feeder schools are enabled
#### Daily Digest Implementation
**`ViewObject::Admin::DailyDigest`** currently:
- Collects activities using `VISIBLE_ACTIVITY_CLASSES` from `StudentActivities`
- Does NOT include feeder school activity classes
- Filters activities by time range and various exclusion rules
- Maps activities to `DashboardActivities::ActivityPresenter`
### Design Decision
**Approach**: Extend `ViewObject::Admin::DailyDigest` to conditionally include feeder school activity classes, following the same pattern as `DashboardActivities`.
**Rationale**:
1. Maintains consistency with existing implementations
2. Respects the school's feature flag
3. Minimal code changes required
4. Follows established patterns in the codebase
## Implementation Details
### 1. Modify `ViewObject::Admin::DailyDigest#activity_presenters`
**Current Code Location**: `app/extras/view_object/admin/daily_digest.rb`
**Changes Required**:
def activity_presenters
return @activity_presenters if @activity_presenters
# Build the list of visible activity classes
visible_activity_classes = ViewObject::Admin::StudentActivities::VISIBLE_ACTIVITY_CLASSES
# Add feeder school activities if enabled
if @school.enable_feeder_schools?
visible_activity_classes += ViewObject::Admin::DashboardActivities::FEEDER_SCHOOL_ACTIVITY_CLASSES
end
activities = @school.activities
.includes([:actor, :trackable])
.where(created_at: @start_time..@end_time)
.where('trackable_type IN (?)', visible_activity_classes)
.where.not(trackable_id: nil)
.where('actor_name IS NULL OR actor_name != ?', Activity::PARENT_EMAIL_ACTIVITY_ACTOR_NAME)
.where.not(trackable_type: 'EsignatureDocument', verb: 'view')
.where.not(trackable_type: 'FeederSchoolReference', verb: 'sent') # NEW: Filter out 'sent' verb
.where.not(content: nil)
.where.not(verb: nil)
# ... rest of the method remains the same
end
**Key Changes**:
1. Build `visible_activity_classes` array dynamically
2. Conditionally add `FEEDER_SCHOOL_ACTIVITY_CLASSES` when feature is enabled
3. Add filter to exclude `FeederSchoolReference` activities with `sent` verb (consistent with `DashboardActivities`)
### 2. Activity Classes Included
When feeder schools are enabled, the following activity types will be included:
- `FeederSchoolReference` - Individual feeder school reference activities (excluding 'sent' verb)
- `FeederSchoolReferenceBatch` - Batch feeder school reference operations
### 3. Filtering Rules
The following filtering rules apply to feeder school activities (consistent with existing implementation):
1. **Time Range**: Only activities within `@start_time..@end_time`
2. **Trackable Present**: Must have a valid `trackable_id`
3. **Actor Present**: Must have a valid actor (checked later in the method)
4. **Content Present**: Must have non-nil content
5. **Verb Present**: Must have non-nil verb
6. **Exclude Parent Activities**: Filter out activities with `actor_name = 'parent_email'`
7. **Exclude 'sent' Verb**: For `FeederSchoolReference`, exclude activities with verb 'sent'
### 4. Display Format
Feeder school activities will appear in the "Other Activities" section of the daily digest email, using the same `ActivityPresenter` as other activities. The presentation logic is already handled by:
- `ViewObject::Admin::DashboardActivities::ActivityPresenter`
- `ViewObject::Admin::StudentActivitiesContext::FeederSchoolReference` (if exists)
- `ViewObject::Admin::StudentActivitiesContext::FeederSchoolReferenceBatch` (if exists)
## Testing Strategy
### Unit Tests
**File**: `spec/extras/view_object/admin/daily_digest_spec.rb`
#### Test Cases to Add:
1. **Test: Feeder school activities included when feature enabled**
- Given: School has `enable_feeder_schools?` = true
- And: FeederSchoolReference activity exists in time range
- When: `activity_presenters` is called
- Then: Activity should be included in results
2. **Test: Feeder school activities excluded when feature disabled**
- Given: School has `enable_feeder_schools?` = false
- And: FeederSchoolReference activity exists in time range
- When: `activity_presenters` is called
- Then: Activity should NOT be included in results
3. **Test: FeederSchoolReference 'sent' verb is filtered out**
- Given: School has feeder schools enabled
- And: FeederSchoolReference activity with verb 'sent' exists
- When: `activity_presenters` is called
- Then: Activity should NOT be included in results
4. **Test: FeederSchoolReference other verbs are included**
- Given: School has feeder schools enabled
- And: FeederSchoolReference activity with verb 'completed' exists
- When: `activity_presenters` is called
- Then: Activity should be included in results
5. **Test: FeederSchoolReferenceBatch activities are included**
- Given: School has feeder schools enabled
- And: FeederSchoolReferenceBatch activity exists
- When: `activity_presenters` is called
- Then: Activity should be included in results
### Integration Tests
**File**: `spec/mailers/user_mailer_spec.rb`
#### Test Cases to Add:
1. **Test: Daily digest email includes feeder school activities**
- Given: School has feeder schools enabled
- And: FeederSchoolReference activity exists
- When: Daily digest email is generated
- Then: Email should contain feeder school activity description
## Code Style Considerations
### Ruby Style
- Use 2-space indentation (per project standards)
- Follow existing patterns in `DailyDigest` class
- Use descriptive variable names
- Keep methods focused and readable
### Testing Style
- Follow RSpec best practices
- Use factory_bot for test data creation
- Use descriptive test names with `it 'should ...'` format
- Group related tests with `describe` and `context` blocks
- Use `let` for test data setup
- Follow existing test patterns in `daily_digest_spec.rb`
## Rollout Plan
### Phase 1: Implementation
1. Modify `ViewObject::Admin::DailyDigest#activity_presenters`
2. Write unit tests
3. Verify all tests pass
### Phase 2: Testing
1. Manual testing with schools that have feeder schools enabled
2. Verify daily digest emails contain feeder school activities
3. Verify schools without feeder schools don't see these activities
### Phase 3: Deployment
1. Deploy to staging environment
2. Test with real data
3. Deploy to production
4. Monitor for any issues
## Risk Assessment
### Low Risk
- Changes are isolated to one method
- Following established patterns
- Feature flag provides safety net
- Comprehensive test coverage
### Potential Issues
1. **Performance**: Adding more activity types could slow down digest generation
- **Mitigation**: Use same efficient queries as existing code
2. **Email Size**: More activities could make emails larger
- **Mitigation**: Existing 50-activity limit still applies
3. **Missing Context Classes**: If `StudentActivitiesContext` modules don't exist for feeder school types
- **Mitigation**: Graceful error handling already exists in `ActivityPresenter`
## Success Criteria
1. ✅ Feeder school activities appear in daily digest when feature is enabled
2. ✅ Feeder school activities are excluded when feature is disabled
3. ✅ 'sent' verb is properly filtered out
4. ✅ All existing tests continue to pass
5. ✅ New tests provide adequate coverage
6. ✅ No performance degradation
7. ✅ Consistent behavior with latest activity feed
## References
- **Related Files**:
- `app/extras/view_object/admin/daily_digest.rb`
- `app/extras/view_object/admin/dashboard_activities.rb`
- `app/extras/view_object/admin/student_activities.rb`
- `app/models/feeder_school_reference.rb`
- `app/models/feeder_school_reference_batch.rb`
- `spec/extras/view_object/admin/daily_digest_spec.rb`
- **Related Tickets**:
- OA-22554: Add feeder school logs into latest activity
```
### 3. Tasks

```markdown!
# Implementation Tasks: Add Feeder School Logs to Daily Digest
## Task List
- [ ] 1. Write failing tests for feeder school activities in daily digest
- [ ] 1.1 Add test for feeder school activities included when feature enabled
- [ ] 1.2 Add test for feeder school activities excluded when feature disabled
- [ ] 1.3 Add test for FeederSchoolReference 'sent' verb filtered out
- [ ] 1.4 Add test for FeederSchoolReference other verbs included
- [ ] 1.5 Add test for FeederSchoolReferenceBatch activities included
- [ ] 2. Implement feeder school activities in DailyDigest
- [ ] 2.1 Modify `activity_presenters` method to build visible_activity_classes dynamically
- [ ] 2.2 Add conditional logic to include feeder school classes when enabled
- [ ] 2.3 Add filter to exclude FeederSchoolReference 'sent' verb
- [ ] 3. Verify all tests pass
- [ ] 3.1 Run new tests and verify they pass
- [ ] 3.2 Run existing daily digest tests to ensure no regression
- [ ] 3.3 Run full test suite for related files
- [ ] 4. Manual testing and verification
- [ ] 4.1 Test with school that has feeder schools enabled
- [ ] 4.2 Test with school that has feeder schools disabled
- [ ] 4.3 Verify email content matches latest activity feed
## Task Details
### Task 1: Write failing tests for feeder school activities in daily digest
**File**: `spec/extras/view_object/admin/daily_digest_spec.rb`
**Description**: Following TDD principles, write tests first that define the expected behavior. These tests should initially fail since the functionality doesn't exist yet.
**Test Structure**:
describe '#activity_presenters' do
context 'with feeder school activities' do
# Test cases for feeder school functionality
end
end
**Subtasks**:
#### 1.1 Add test for feeder school activities included when feature enabled
- Create a school with `enable_feeder_schools?` returning true
- Create a FeederSchoolReference activity with a non-'sent' verb (e.g., 'completed')
- Verify the activity appears in `activity_presenters`
#### 1.2 Add test for feeder school activities excluded when feature disabled
- Create a school with `enable_feeder_schools?` returning false
- Create a FeederSchoolReference activity
- Verify the activity does NOT appear in `activity_presenters`
#### 1.3 Add test for FeederSchoolReference 'sent' verb filtered out
- Create a school with feeder schools enabled
- Create a FeederSchoolReference activity with verb 'sent'
- Verify the activity does NOT appear in `activity_presenters`
#### 1.4 Add test for FeederSchoolReference other verbs included
- Create a school with feeder schools enabled
- Create a FeederSchoolReference activity with verb 'completed'
- Verify the activity appears in `activity_presenters`
#### 1.5 Add test for FeederSchoolReferenceBatch activities included
- Create a school with feeder schools enabled
- Create a FeederSchoolReferenceBatch activity
- Verify the activity appears in `activity_presenters`
**Acceptance Criteria**:
- All 5 test cases are written
- Tests follow existing patterns in the spec file
- Tests use factory_bot for data creation
- Tests are descriptive and clear
- Tests initially fail (red phase of TDD)
---
### Task 2: Implement feeder school activities in DailyDigest
**File**: `app/extras/view_object/admin/daily_digest.rb`
**Description**: Modify the `activity_presenters` method to include feeder school activities when the feature is enabled, following the same pattern as `DashboardActivities`.
**Subtasks**:
#### 2.1 Modify `activity_presenters` method to build visible_activity_classes dynamically
- Change from using constant directly to building an array
- Start with `ViewObject::Admin::StudentActivities::VISIBLE_ACTIVITY_CLASSES`
#### 2.2 Add conditional logic to include feeder school classes when enabled
- Check `@school.enable_feeder_schools?`
- If true, add `ViewObject::Admin::DashboardActivities::FEEDER_SCHOOL_ACTIVITY_CLASSES`
- Use the `+=` operator to append to the array
#### 2.3 Add filter to exclude FeederSchoolReference 'sent' verb
- Add `.where.not(trackable_type: 'FeederSchoolReference', verb: 'sent')` to the query chain
- Place it after the existing `.where.not` clauses for consistency
**Implementation Pattern**:
def activity_presenters
return @activity_presenters if @activity_presenters
visible_activity_classes = ViewObject::Admin::StudentActivities::VISIBLE_ACTIVITY_CLASSES
visible_activity_classes += ViewObject::Admin::DashboardActivities::FEEDER_SCHOOL_ACTIVITY_CLASSES if @school.enable_feeder_schools?
activities = @school.activities
.includes([:actor, :trackable])
.where(created_at: @start_time..@end_time)
.where('trackable_type IN (?)', visible_activity_classes)
.where.not(trackable_id: nil)
.where('actor_name IS NULL OR actor_name != ?', Activity::PARENT_EMAIL_ACTIVITY_PARENT_EMAIL_ACTIVITY_ACTOR_NAME)
.where.not(trackable_type: 'EsignatureDocument', verb: 'view')
.where.not(trackable_type: 'FeederSchoolReference', verb: 'sent')
.where.not(content: nil)
.where.not(verb: nil)
# ... rest of method unchanged
end
**Acceptance Criteria**:
- Code follows existing patterns in the file
- Uses 2-space indentation
- Respects the feature flag
- Includes proper filtering for 'sent' verb
- No other functionality is changed
---
### Task 3: Verify all tests pass
**Description**: Run tests to verify the implementation is correct and no regressions were introduced.
**Subtasks**:
#### 3.1 Run new tests and verify they pass
- Run: `bundle exec rspec spec/extras/view_object/admin/daily_digest_spec.rb`
- Verify all new tests pass (green phase of TDD)
- Fix any failing tests
#### 3.2 Run existing daily digest tests to ensure no regression
- Verify all existing tests in `daily_digest_spec.rb` still pass
- Check that no existing functionality was broken
#### 3.3 Run full test suite for related files
- Run: `bundle exec rspec spec/mailers/user_mailer_spec.rb`
- Run: `bundle exec rspec spec/extras/view_object/admin/dashboard_activities_spec.rb` (if exists)
- Verify no regressions in related functionality
**Acceptance Criteria**:
- All new tests pass
- All existing tests pass
- No test failures or errors
- Test output is clean
---
### Task 4: Manual testing and verification
**Description**: Manually test the feature to ensure it works correctly in a real-world scenario.
**Subtasks**:
#### 4.1 Test with school that has feeder schools enabled
- Use Rails console to create test data
- Generate a daily digest for a user
- Verify feeder school activities appear in the email
#### 4.2 Test with school that has feeder schools disabled
- Use a school without feeder schools enabled
- Generate a daily digest
- Verify feeder school activities do NOT appear
#### 4.3 Verify email content matches latest activity feed
- Compare activities in daily digest with latest activity dashboard
- Ensure descriptions are identical
- Verify 'sent' activities are excluded from both
**Acceptance Criteria**:
- Feeder school activities appear correctly when enabled
- Activities are excluded when feature is disabled
- Email content is consistent with latest activity feed
- No errors or exceptions occur
---
## Testing Commands
# Run specific spec file
bundle exec rspec spec/extras/view_object/admin/daily_digest_spec.rb
# Run with specific test
bundle exec rspec spec/extras/view_object/admin/daily_digest_spec.rb:LINE_NUMBER
# Run all related specs
bundle exec rspec spec/extras/view_object/admin/
bundle exec rspec spec/mailers/user_mailer_spec.rb
# Run full test suite (optional)
bundle exec rspec
## Definition of Done
- [ ] All tests written and passing
- [ ] Implementation complete and follows design
- [ ] No regressions in existing functionality
- [ ] Code follows project style guidelines
- [ ] Manual testing completed successfully
- [ ] Feature works consistently with latest activity feed
- [ ] Documentation updated (if needed)
```