feat(formbuilder): fix tenancy bugs, add admin + services
Fix multi-tenancy/integrity bugs in the models: Form.slug and Field.key were globally unique (unique=True), so two clubs couldn't reuse a form slug and two forms couldn't reuse a field key — make slug unique per club (constraint already present) and key unique per form. Add a (submission, field) uniqueness constraint on Answer. Register all four models in the admin (Field inline on Form, Answer inline on Submission) and add formbuilder to the admin registration smoke test. Add a service layer: - submit_form(form, member, data): enforces is_active / login_required / open window / max_submissions, validates required + choice fields, and writes a Submission with Answers atomically (FormSubmissionError carries per-field errors). - build_form(form): a live django.forms.Form built from a Form's active fields, mapping each FieldType to the matching form field. - form_report(form): a tabular overview of every submission's answers plus per-value tallies for choice-type fields. Full suite at 100% coverage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
23
formbuilder/services/options.py
Normal file
23
formbuilder/services/options.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""Helpers for interpreting a Field's ``options`` (choice definitions).
|
||||
|
||||
``options`` is a JSON list, either of plain strings (``["a", "b"]``) or of
|
||||
``{"value": ..., "label": ...}`` dicts.
|
||||
"""
|
||||
|
||||
|
||||
def field_choices(field):
|
||||
"""Return ``[(value, label), ...]`` for a choice-type field."""
|
||||
choices = []
|
||||
for option in field.options or []:
|
||||
if isinstance(option, dict):
|
||||
value = option.get("value")
|
||||
label = option.get("label", value)
|
||||
else:
|
||||
value = label = option
|
||||
choices.append((value, label))
|
||||
return choices
|
||||
|
||||
|
||||
def allowed_values(field):
|
||||
"""Return the set of accepted values for a choice-type field."""
|
||||
return {value for value, _ in field_choices(field)}
|
||||
Reference in New Issue
Block a user