Implement AnimalAttributesUpdated event handling:
- Update IntervalProjection to close old attr intervals and open new ones
- Update AnimalRegistryProjection to update registry tables
- Update EventAnimalsProjection to track event-animal links
- Add update_attributes() to AnimalService
Only attributes that actually change create new intervals.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement AnimalMoved event handling:
- Update AnimalRegistryProjection for move events
- Update IntervalProjection to close/open location intervals
- Update EventAnimalsProjection to link move events to animals
- Add move_animals() to AnimalService with validations
Validations include:
- Destination location must exist and be active
- All animals must be from a single location
- Cannot move to the same location as current
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements Step 3.3: Animal Cohort Creation
- Add AnimalRegistryProjection for animal_registry and live_animals_by_location
- Add EventAnimalsProjection for event_animals link table
- Add IntervalProjection for location and attribute intervals
- Add AnimalService with create_cohort() for coordinating event + projections
- Add seeded_db fixture to conftest.py
- Update projections/__init__.py with new exports
All operations atomic within single transaction. Includes validation for
location (exists, active) and species (exists, active).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>