Skip to content

Commit d06726b

Browse files
committed
WIP
1 parent 4cb76dd commit d06726b

18 files changed

Lines changed: 1672 additions & 45 deletions

File tree

backend/AGENTS.md

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
# `AGENTS.md`
2+
3+
This file provides guidance to AI agents when working with code in this repository.
4+
5+
## Core Architecture
6+
7+
**PyCon Italia** is a comprehensive Django-based conference management platform with:
8+
9+
- **Backend**: Django application managing conferences, submissions, speakers, attendees, and more
10+
- **Frontend**: Next.js/TypeScript/React application deployed on Vercel
11+
- **Database**: PostgreSQL
12+
- **Package Management**: `uv` for Python dependencies, `pnpm` for Node.js dependencies
13+
- **Testing**: Comprehensive test suite using pytest for backend
14+
- **CI/CD**: GitHub Actions for continuous integration and builds
15+
- **Deployment**: Docker containers, infrastructure managed via Terraform
16+
17+
### Repository Structure
18+
19+
- `backend/`: Main Django application code with conference management modules:
20+
- `api/`: GraphQL API endpoints
21+
- `conferences/`: Conference models and management
22+
- `submissions/`: Talk/workshop submission system (CFP)
23+
- `schedule/`: Event scheduling and management
24+
- `users/`: User authentication and profiles
25+
- `participants/`: Attendee management
26+
- `sponsors/`: Sponsorship management
27+
- `grants/`: Financial assistance system (Finaid)
28+
- `billing/`: Payment processing
29+
- `cms/`: Content management system
30+
- `blog/`: News and announcements
31+
- `pages/`: Static page management
32+
- `voting/`: Community voting system
33+
- `reviews/`: Submission review system (Program Committee)
34+
- `badges/`: Digital badge system
35+
- `badge_scanner/`: Badge scanning functionality
36+
- `notifications/`: Email and notification system
37+
- `frontend/`: Next.js application with TypeScript and React
38+
- `association-frontend/`: Association-specific frontend
39+
- `association-backend/`: Association-specific backend
40+
- `toolkit/`: Shared utilities and tools
41+
- `infrastructure/`: Terraform infrastructure configuration
42+
- `.github/`: GitHub Actions workflows and configuration
43+
- `eslint-config-pythonit/`: Shared ESLint configuration
44+
45+
## Conference Management Domain Knowledge
46+
47+
### Conference Lifecycle
48+
49+
The PyCon Italia conference follows a well-defined timeline with specific phases:
50+
51+
1. **Pre-Conference Planning** (6-12 months before)
52+
- Configure conference settings (deadlines, topics, submission types, languages)
53+
- Set up sponsor tiers and packages
54+
- Define audience levels and duration options
55+
56+
2. **Call for Proposals (CFP)** (4-6 months before)
57+
- Speakers submit talks, workshops, posters
58+
- Submission includes: title, abstract, elevator pitch, speaker bio, tags
59+
- "Fake deadlines" strategy: announce deadline, then extend by a week for urgency
60+
61+
3. **Community Voting** (after CFP closes)
62+
- Eligible voters: proposal submitters, ticket holders, past attendees (last 2 years)
63+
- Weighted ranking algorithm prioritizes engaged community members
64+
- Eligibility configured via Pretix event IDs
65+
66+
4. **Internal Review** (Program Committee)
67+
- Numeric scoring system (0=No, 1=Maybe, 2=Yes)
68+
- Random proposal ordering to reduce bias
69+
- Tag-based filtering for reviewer expertise
70+
- Proposals sorted by cumulative scores
71+
72+
5. **Schedule Building**
73+
- Excel draft with session allocation
74+
- Django admin schedule builder interface
75+
- Room configuration and day planning
76+
- Keynote speaker selection (community + sponsor slots)
77+
78+
6. **Financial Aid (Finaid) Process**
79+
- Concurrent with CFP opening
80+
- Multiple grant types: Ticket, Travel, Accommodation
81+
- Committee evaluation with scoring system
82+
- Status workflow: Pending → Approved/Rejected → Confirmed
83+
84+
### Key Domain Concepts
85+
86+
#### Submission System
87+
- **Types**: Talk, Workshop, Poster, Keynote
88+
- **Languages**: IT/EN (configurable)
89+
- **Duration**: Configurable per submission type
90+
- **Audience Levels**: Beginner, Intermediate, Advanced
91+
- **Tags**: Community-driven categorization (often corrected by admins)
92+
93+
#### Voting System
94+
- **Community Voting**: Public voting by eligible community members
95+
- **Internal Review**: Program Committee scoring and comments
96+
- **Ranking Algorithm**: Weighted by voter engagement (`backend/voting/models/ranking.py`)
97+
- **Recalculation**: Required when admins modify submission tags
98+
99+
#### Financial Aid (Grants)
100+
- **Grant Types**:
101+
- Ticket Only
102+
- Ticket + Travel
103+
- Ticket + Accommodation
104+
- Ticket + Travel + Accommodation
105+
- **Travel Amounts** (2024 example):
106+
- From Italy: €100
107+
- From Europe: €250
108+
- Extra Europe: €400
109+
- **Status Flow**: Pending → Approved → Waiting for Confirmation → Confirmed
110+
- **Evaluation Criteria**: Student status, community involvement, geographic diversity, employment status
111+
112+
#### Schedule Management
113+
- **Rooms**: Configurable venue spaces
114+
- **Days**: Conference day configuration
115+
- **Slots**: Time-based scheduling units
116+
- **Schedule Items**: Can be submissions, breaks, keynotes, sponsor slots
117+
- **Conflicts**: System prevents scheduling conflicts
118+
119+
### Important Business Rules
120+
121+
1. **"Fake Deadlines"**: CFP deadlines are often extended by a week after announced closure
122+
2. **Keynote Allocation**: One slot reserved for Keystone sponsor, others community-selected
123+
3. **Voting Eligibility**: Configurable via Pretix event IDs for past attendees
124+
4. **Grant Budget**: Sourced from PSF, EuroPython Society, sponsors, and ticket donations
125+
5. **Speaker Coordination**: Avoid duplicate vouchers for speakers who also receive grants
126+
6. **Tag Corrections**: Admins often fix speaker-provided tags, requiring ranking recalculation
127+
128+
### Code Search Tips
129+
130+
- Use `grep_search` and `file_search` for searching code
131+
- Conference-specific code organization:
132+
- `backend/conferences/` for conference models and configuration
133+
- `backend/submissions/` for CFP and proposal management
134+
- `backend/voting/` for community and internal voting systems
135+
- `backend/grants/` for financial aid processing
136+
- `backend/schedule/` for event scheduling and calendar
137+
- `backend/reviews/` for Program Committee review process
138+
- `backend/participants/` for attendee and speaker management
139+
- Frontend components are in `frontend/src/`
140+
- GraphQL schema is defined in `backend/schema.graphql`
141+
142+
## Development Workflow
143+
144+
### Writing Code
145+
146+
Python code must be formatted by `ruff`. Verify this by running
147+
`ruff format $filepath1 $filepath2 ...` on all modified files. Use a file path
148+
relative to the repo root.
149+
150+
Python code must be linted by `ruff`. Verify this by running
151+
`ruff check $filepath1 $filepath2 ...` on all modified files. Use a file path
152+
relative to the repo root.
153+
154+
Python code must be type checked by `mypy`
155+
156+
### Testing
157+
158+
```bash
159+
# Run all unit tests
160+
docker exec -it pycon-backend-1 uv run pytest
161+
162+
# Run specific test modules
163+
docker exec -it pycon-backend-1 uv run pytest backend/grants/tests/
164+
docker exec -it pycon-backend-1 uv run pytest backend/voting/tests/
165+
docker exec -it pycon-backend-1 uv run pytest backend/submissions/tests/
166+
```
167+
168+
### Code Quality & Linting
169+
170+
```bash
171+
# Python linting and formatting - use uv for package management
172+
uv run ruff format $filepath1 $filepath2 ...
173+
uv run ruff check $filepath1 $filepath2 ...
174+
uv run mypy $filepath1 $filepath2 ...
175+
```
176+
177+
### Frontend Development
178+
179+
```bash
180+
# Frontend development with Next.js
181+
cd frontend/
182+
pnpm dev
183+
184+
# Build frontend
185+
pnpm build
186+
187+
# Run frontend tests
188+
pnpm test
189+
```
190+
191+
### Database Operations
192+
193+
```bash
194+
# Run migrations
195+
docker exec -it pycon-backend-1 uv run python manage.py migrate
196+
197+
# Create migrations for specific apps
198+
docker exec -it pycon-backend-1 uv run python manage.py makemigrations grants
199+
docker exec -it pycon-backend-1 uv run python manage.py makemigrations voting
200+
docker exec -it pycon-backend-1 uv run python manage.py makemigrations submissions
201+
202+
# Check for missing migrations
203+
docker exec -it pycon-backend-1 uv run python manage.py makemigrations --check
204+
```
205+
206+
### Conference Management Commands
207+
208+
```bash
209+
# Calculate rankings (after voting period or tag changes)
210+
docker exec -it pycon-backend-1 uv run python manage.py calculate_rankings
211+
212+
# Generate grant vouchers
213+
docker exec -it pycon-backend-1 uv run python manage.py generate_vouchers
214+
215+
# Send notification emails
216+
docker exec -it pycon-backend-1 uv run python manage.py send_grant_emails
217+
```
218+
219+
## Testing Framework
220+
221+
- **Python**: pytest with Django integration
222+
- **Frontend**: no testing
223+
- **Configuration**: `pytest.ini` and `pyproject.toml` for backend
224+
225+
### Key Testing Patterns
226+
227+
- Use `@pytest.mark.django_db` for database tests
228+
- Use factories for creating test data instead of models directly
229+
- Frontend is not tested
230+
- GraphQL tests can use the schema in `backend/schema.graphql`
231+
- Conference-specific testing:
232+
- Mock Pretix API calls for ticket validation
233+
- Test ranking algorithm with various voting scenarios
234+
- Test grant workflow state transitions
235+
- Test schedule conflict detection
236+
237+
### Test Data Patterns
238+
239+
```python
240+
# Use factories for conference entities
241+
conference = ConferenceFactory()
242+
submission = SubmissionFactory(conference=conference)
243+
grant = GrantFactory(conference=conference)
244+
vote = VoteFactory(submission=submission)
245+
246+
# Test ranking calculations
247+
ranking = RankingFactory(submission=submission)
248+
assert ranking.score == expected_weighted_score
249+
```
250+
251+
## Frontend Architecture
252+
253+
- **Framework**: Next.js with TypeScript
254+
- **Styling**: Tailwind CSS with `@python-italia/pycon-styleguide`
255+
- **State Management**: Apollo Client for GraphQL state
256+
- **Deployment**: Vercel
257+
- **Package Manager**: pnpm
258+
- **Code Generation**: GraphQL Code Generator for TypeScript types
259+
260+
### Conference-Specific Frontend Features
261+
262+
- **CFP Interface**: Multi-step submission form with validation
263+
- **Voting Interface**: Community voting with proposal browsing
264+
- **Review Interface**: Program Committee evaluation dashboard
265+
- **Schedule Display**: Conference schedule with filtering and search
266+
- **Grant Application**: Financial aid request form
267+
- **Admin Dashboards**: Conference management interfaces
268+
269+
## External Integrations
270+
271+
### Pretix Integration
272+
- **Purpose**: Ticket sales and attendee management
273+
- **Key Files**: `pretix.py` (in your provided files)
274+
- **API Usage**: Validate voting eligibility, generate vouchers
275+
- **Configuration**: Requires Pretix API tokens and event IDs
276+
277+
### Email Systems
278+
- **Templates**: Conference-specific email templates for each phase
279+
- **Notifications**: Automated emails for CFP, voting, grants, schedule updates
280+
- **Customization**: Multi-language support (IT/EN)
281+
282+
### Payment Processing
283+
- **Grant Vouchers**: Generated vouchers for approved financial aid
284+
- **Ticket Integration**: Coordination with Pretix for free tickets
285+
- **Reimbursement**: Travel and accommodation fund management
286+
287+
## Common Workflows for AI Agents
288+
289+
### Adding New Conference Features
290+
1. Update conference model in `backend/conferences/models.py`
291+
2. Create database migration
292+
3. Add admin interface configuration
293+
4. Update GraphQL schema and resolvers
294+
5. Implement frontend components
295+
6. Add comprehensive tests
296+
297+
### Modifying Grant Process
298+
1. Update grant model and workflow states
299+
2. Modify evaluation criteria in review system
300+
3. Update email templates for notifications
301+
4. Test state transitions thoroughly
302+
5. Document business rule changes
303+
304+
### Schedule Management
305+
1. Configure rooms and days in admin
306+
2. Use schedule builder interface for slot assignment
307+
3. Handle conflicts and constraints
308+
4. Generate speaker confirmation emails
309+
5. Update public schedule display
310+
311+
Remember: The conference management domain has complex business rules and workflows that evolved over years of running PyCon Italia. Always consider the impact on the entire conference lifecycle when making changes.

backend/api/grants/mutations.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ def send_grant(self, info: Info, input: SendGrantInput) -> SendGrantResult:
279279
},
280280
)
281281

282+
# Grant creation is logged by signal (which detects user from instance.user_id)
282283
# hack because we return django models
283284
instance.__strawberry_definition__ = Grant.__strawberry_definition__
284285
return instance
@@ -299,6 +300,7 @@ def update_grant(self, info: Info, input: UpdateGrantInput) -> UpdateGrantResult
299300

300301
for attr, value in asdict(input).items():
301302
setattr(instance, attr, value)
303+
# Grant updates are logged by signals automatically
302304
instance.save()
303305

304306
Participant.objects.update_or_create(
@@ -332,6 +334,8 @@ def send_grant_reply(
332334
if grant.status in (GrantModel.Status.pending, GrantModel.Status.rejected):
333335
return SendGrantReplyError(message="You cannot reply to this grant")
334336

337+
# Mark actor for history logging
338+
grant._history_actor = request.user
335339
grant.status = input.status.to_grant_status()
336340
grant.save()
337341

backend/api/grants/tests/test_send_grant.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import pytest
22

33
from conferences.tests.factories import ConferenceFactory
4-
from grants.models import Grant
4+
from grants.models import Grant, GrantHistory
55
from grants.tests.factories import GrantFactory
66
from notifications.models import EmailTemplateIdentifier
77
from notifications.tests.factories import EmailTemplateFactory
@@ -119,6 +119,15 @@ def test_send_grant(
119119
user=user, conference=conference, privacy_policy="grant"
120120
).exists()
121121

122+
# Verify grant history entry is created correctly
123+
assert GrantHistory.objects.filter(grant_id=grant.id).count() == 1
124+
125+
history_entry = GrantHistory.objects.get(grant_id=grant.id)
126+
assert history_entry.event_type == GrantHistory.EventType.CREATED
127+
assert history_entry.actor_type == GrantHistory.ActorType.USER
128+
assert history_entry.actor == user
129+
assert history_entry.message == "Grant application created"
130+
122131
# Verify that the correct email template was used and email was sent
123132
emails_sent = sent_emails()
124133
assert emails_sent.count() == 1

0 commit comments

Comments
 (0)