Add camp Google Sheets snapshots - #701
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7ded3a23df
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| for instance in formset.deleted_objects: | ||
| instance.delete() | ||
| for instance in instances: | ||
| enabled_before = instance.pk and CampGoogleSheetsIntegration.objects.get(pk=instance.pk).enabled |
There was a problem hiding this comment.
Preserve non-Sheets Camp inlines when saving
When a Camp admin save includes a changed WorkshopTypeInline or WorkshopCategoryInline, Django calls this same save_formset for that inline too, but this branch treats every inline object as a CampGoogleSheetsIntegration. Editing an existing type/category will try to load an integration with the type/category primary key (often raising DoesNotExist), and adding one then hits instance.enabled; either way ordinary Camp formset saves break unless only the Sheets inline changed. Gate this logic to the Sheets formset/model and delegate other formsets to the default save path.
Useful? React with 👍 / 👎.
| participants = UserProfile.objects.filter(camp_participation__year=camp).exclude( | ||
| lecturer_workshops__in=Workshop.objects.filter( | ||
| year=camp, status=Workshop.STATUS_ACCEPTED)).select_related('user').prefetch_related( | ||
| Prefetch('camp_participation', queryset=participation_queryset)).distinct() |
There was a problem hiding this comment.
Include interested-email rows in participant snapshots
The participant admin view also appends CampInterestEmail rows for people who registered interest without an account, and this change even marks CampInterestEmail saves/deletes dirty, but the snapshot projection only reads UserProfile rows with camp_participation. Any camp relying on that interested-email list will publish a participant sheet that silently omits those entries, so the Google snapshot no longer matches the administration table it is meant to mirror.
Useful? React with 👍 / 👎.
| columns = (TableColumn('Imię i nazwisko'), TableColumn('Email'), | ||
| TableColumn('Warsztaty')) |
There was a problem hiding this comment.
Export the full lecturer administration table
The /lecturers/ admin table is rendered through the same people datatable as participants, including hidden profile fields, adulthood, previous editions, and dynamic camp-form answers; this projection reduces lecturers to just name, email, and workshops. For enabled Sheets integrations, lecturer snapshots therefore drop most of the administration data and form responses that staff can see in the Django table, so reuse the person-column/row projection (with the lecturer-specific workshop column) rather than this three-column table.
Useful? React with 👍 / 👎.
| participation = next((item for item in profile.camp_participation.all() | ||
| if item.year_id == camp.pk), None) | ||
| birth = _birth_date(camp, profile) | ||
| adult = '-' if birth is None else _yes_no(camp.start_date >= birth.replace(year=birth.year + 18)) |
There was a problem hiding this comment.
Avoid crashing age calculation for leap-day births
If a camp has a birth-date/PESEL form question and a participant was born on February 29, birth.replace(year=birth.year + 18) raises ValueError for non-leap 18th years, so one such participant prevents the whole worker from publishing any tabs for that camp. The existing view code uses relativedelta(years=18) for this case; use the same approach here (and handle camps without start_date) before writing the snapshot.
Useful? React with 👍 / 👎.
What changed
Adds per-camp Google Sheets snapshot publishing for participant, lecturer, and workshop administration data. Includes the integration state model, transaction-safe queue and worker, Google API adapter, managed-tab provisioning, change scheduling, Camp admin controls, and operational documentation.
Why
Camp administration tables can now be published as recoverable full snapshots without blocking application writes.
Validation
manage.py test wwwapp.tests.test_google_sheets_queue wwwapp.tests.test_google_sheets_projections wwwapp.tests.test_google_sheets_google wwwapp.tests.test_google_sheets_worker wwwapp.tests.test_google_sheets_signals -v 1manage.py makemigrations --check --dry-rungit diff --checkType checking was intentionally excluded by request.
This change is