snapshot: preserve dynamic form builder parity and presets
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
from collections import OrderedDict
|
||||
from django.utils.translation import get_language
|
||||
|
||||
from .models import FormFieldConfig
|
||||
from .models import FormFieldConfig, FormSectionConfig
|
||||
|
||||
|
||||
DEFAULT_FIELD_ORDER = {
|
||||
@@ -58,18 +58,29 @@ DEFAULT_FIELD_ORDER = {
|
||||
}
|
||||
|
||||
ONBOARDING_PAGE_ORDER = ['stammdaten', 'vertrag', 'itsetup', 'abschluss']
|
||||
OFFBOARDING_PAGE_ORDER = ['mitarbeitende', 'austritt', 'abschluss']
|
||||
ONBOARDING_PAGE_LABELS = {
|
||||
'stammdaten': '1. Stammdaten',
|
||||
'vertrag': '2. Vertrag',
|
||||
'itsetup': '3. IT-Setup',
|
||||
'abschluss': '4. Abschluss',
|
||||
}
|
||||
OFFBOARDING_PAGE_LABELS = {
|
||||
'mitarbeitende': '1. Mitarbeitende',
|
||||
'austritt': '2. Austritt',
|
||||
'abschluss': '3. Abschluss',
|
||||
}
|
||||
|
||||
LOCKED_FIELD_RULES = {
|
||||
'onboarding': {'full_name', 'work_email', 'contract_start', 'agreement_confirm'},
|
||||
'offboarding': {'full_name', 'work_email', 'last_working_day'},
|
||||
}
|
||||
|
||||
LOCKED_SECTION_RULES = {
|
||||
'onboarding': {'stammdaten', 'vertrag', 'abschluss'},
|
||||
'offboarding': {'mitarbeitende', 'austritt'},
|
||||
}
|
||||
|
||||
ONBOARDING_DEFAULT_PAGE = {
|
||||
'first_name': 'stammdaten',
|
||||
'last_name': 'stammdaten',
|
||||
@@ -112,6 +123,38 @@ ONBOARDING_DEFAULT_PAGE = {
|
||||
'onboarded_by_email': 'abschluss',
|
||||
'agreement_confirm': 'abschluss',
|
||||
}
|
||||
OFFBOARDING_DEFAULT_PAGE = {
|
||||
'full_name': 'mitarbeitende',
|
||||
'work_email': 'mitarbeitende',
|
||||
'department': 'mitarbeitende',
|
||||
'job_title': 'mitarbeitende',
|
||||
'last_working_day': 'austritt',
|
||||
'notes': 'abschluss',
|
||||
}
|
||||
|
||||
|
||||
def get_section_order(form_type: str) -> list[str]:
|
||||
if form_type == 'onboarding':
|
||||
return ONBOARDING_PAGE_ORDER
|
||||
if form_type == 'offboarding':
|
||||
return OFFBOARDING_PAGE_ORDER
|
||||
return []
|
||||
|
||||
|
||||
def get_section_labels(form_type: str) -> dict[str, str]:
|
||||
if form_type == 'onboarding':
|
||||
return ONBOARDING_PAGE_LABELS
|
||||
if form_type == 'offboarding':
|
||||
return OFFBOARDING_PAGE_LABELS
|
||||
return {}
|
||||
|
||||
|
||||
def get_default_page_map(form_type: str) -> dict[str, str]:
|
||||
if form_type == 'onboarding':
|
||||
return ONBOARDING_DEFAULT_PAGE
|
||||
if form_type == 'offboarding':
|
||||
return OFFBOARDING_DEFAULT_PAGE
|
||||
return {}
|
||||
|
||||
|
||||
def _default_sort(form_type: str, field_name: str) -> int:
|
||||
@@ -134,7 +177,7 @@ def _ensure_configs(form_type: str, field_names: list[str]) -> dict[str, FormFie
|
||||
form_type=form_type,
|
||||
field_name=name,
|
||||
sort_order=_default_sort(form_type, name),
|
||||
page_key=ONBOARDING_DEFAULT_PAGE.get(name, '') if form_type == 'onboarding' else '',
|
||||
page_key=get_default_page_map(form_type).get(name, ''),
|
||||
)
|
||||
for name in missing_names
|
||||
],
|
||||
@@ -151,10 +194,34 @@ def ensure_form_field_configs(form_type: str, field_names: list[str]) -> dict[st
|
||||
return _ensure_configs(form_type, field_names)
|
||||
|
||||
|
||||
def ensure_form_section_configs(form_type: str) -> dict[str, FormSectionConfig]:
|
||||
section_order = get_section_order(form_type)
|
||||
if not section_order:
|
||||
return {}
|
||||
existing = {
|
||||
cfg.section_key: cfg
|
||||
for cfg in FormSectionConfig.objects.filter(form_type=form_type)
|
||||
}
|
||||
missing = [key for key in section_order if key not in existing]
|
||||
if missing:
|
||||
FormSectionConfig.objects.bulk_create(
|
||||
[FormSectionConfig(form_type=form_type, section_key=key, is_visible=True) for key in missing],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
existing = {
|
||||
cfg.section_key: cfg
|
||||
for cfg in FormSectionConfig.objects.filter(form_type=form_type)
|
||||
}
|
||||
return existing
|
||||
|
||||
|
||||
def apply_form_field_config(form_type: str, form) -> None:
|
||||
field_names = list(form.fields.keys())
|
||||
configs = _ensure_configs(form_type, field_names)
|
||||
section_configs = ensure_form_section_configs(form_type)
|
||||
locked = LOCKED_FIELD_RULES.get(form_type, set())
|
||||
locked_sections = LOCKED_SECTION_RULES.get(form_type, set())
|
||||
default_page_map = get_default_page_map(form_type)
|
||||
language_code = get_language()
|
||||
|
||||
for field_name, field in list(form.fields.items()):
|
||||
@@ -173,7 +240,14 @@ def apply_form_field_config(form_type: str, form) -> None:
|
||||
if field_name not in locked and cfg.is_required is not None:
|
||||
field.required = cfg.is_required
|
||||
|
||||
if field_name not in locked and not cfg.is_visible:
|
||||
section_key = cfg.page_key or default_page_map.get(field_name, '')
|
||||
section_hidden = (
|
||||
form_type in {'onboarding', 'offboarding'}
|
||||
and section_key not in locked_sections
|
||||
and section_key in section_configs
|
||||
and not section_configs[section_key].is_visible
|
||||
)
|
||||
if field_name not in locked and (not cfg.is_visible or section_hidden):
|
||||
form.fields.pop(field_name, None)
|
||||
|
||||
ordered_items = sorted(
|
||||
@@ -184,9 +258,138 @@ def apply_form_field_config(form_type: str, form) -> None:
|
||||
),
|
||||
)
|
||||
form.fields = OrderedDict(ordered_items)
|
||||
if form_type == 'onboarding':
|
||||
if form_type in {'onboarding', 'offboarding'}:
|
||||
form._field_page_keys = {
|
||||
name: (configs[name].page_key or ONBOARDING_DEFAULT_PAGE.get(name, 'abschluss'))
|
||||
name: (configs[name].page_key or default_page_map.get(name, ''))
|
||||
for name in form.fields.keys()
|
||||
if name in configs
|
||||
}
|
||||
|
||||
|
||||
FORM_PRESETS = {
|
||||
'onboarding': {
|
||||
'standard': {
|
||||
'label': 'Standard',
|
||||
'sections': {
|
||||
'stammdaten': True,
|
||||
'vertrag': True,
|
||||
'itsetup': True,
|
||||
'abschluss': True,
|
||||
},
|
||||
'fields': {},
|
||||
},
|
||||
'lean': {
|
||||
'label': 'Lean',
|
||||
'sections': {
|
||||
'stammdaten': True,
|
||||
'vertrag': True,
|
||||
'itsetup': False,
|
||||
'abschluss': True,
|
||||
},
|
||||
'fields': {
|
||||
'gender': {'is_visible': False},
|
||||
'order_business_cards': {'is_visible': False},
|
||||
'business_card_name': {'is_visible': False},
|
||||
'business_card_title': {'is_visible': False},
|
||||
'business_card_email': {'is_visible': False},
|
||||
'business_card_phone': {'is_visible': False},
|
||||
'employment_end_date': {'is_visible': False},
|
||||
'group_mailboxes_required_choice': {'is_visible': False},
|
||||
'group_mailboxes': {'is_visible': False},
|
||||
'additional_notes': {'is_required': False},
|
||||
},
|
||||
},
|
||||
'it_heavy': {
|
||||
'label': 'IT-heavy',
|
||||
'sections': {
|
||||
'stammdaten': True,
|
||||
'vertrag': True,
|
||||
'itsetup': True,
|
||||
'abschluss': True,
|
||||
},
|
||||
'fields': {
|
||||
'needed_devices_multi': {'is_required': True},
|
||||
'needed_software_multi': {'is_required': True},
|
||||
'needed_accesses_multi': {'is_required': True},
|
||||
'needed_workspace_groups_multi': {'is_required': True},
|
||||
'needed_resources_multi': {'is_required': True},
|
||||
'additional_hardware_needed_choice': {'is_visible': True},
|
||||
'additional_software_needed_choice': {'is_visible': True},
|
||||
'additional_access_needed_choice': {'is_visible': True},
|
||||
'successor_required_choice': {'is_visible': True},
|
||||
},
|
||||
},
|
||||
},
|
||||
'offboarding': {
|
||||
'standard': {
|
||||
'label': 'Standard',
|
||||
'sections': {
|
||||
'mitarbeitende': True,
|
||||
'austritt': True,
|
||||
'abschluss': True,
|
||||
},
|
||||
'fields': {},
|
||||
},
|
||||
'lean': {
|
||||
'label': 'Lean',
|
||||
'sections': {
|
||||
'mitarbeitende': True,
|
||||
'austritt': True,
|
||||
'abschluss': False,
|
||||
},
|
||||
'fields': {
|
||||
'department': {'is_visible': False},
|
||||
'job_title': {'is_visible': False},
|
||||
'notes': {'is_visible': False},
|
||||
},
|
||||
},
|
||||
'hr_heavy': {
|
||||
'label': 'HR-heavy',
|
||||
'sections': {
|
||||
'mitarbeitende': True,
|
||||
'austritt': True,
|
||||
'abschluss': True,
|
||||
},
|
||||
'fields': {
|
||||
'department': {'is_visible': True, 'is_required': True},
|
||||
'job_title': {'is_visible': True, 'is_required': True},
|
||||
'notes': {'is_visible': True, 'is_required': True},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def apply_form_preset(form_type: str, preset_key: str) -> bool:
|
||||
preset = FORM_PRESETS.get(form_type, {}).get(preset_key)
|
||||
if not preset:
|
||||
return False
|
||||
|
||||
locked_fields = LOCKED_FIELD_RULES.get(form_type, set())
|
||||
locked_sections = LOCKED_SECTION_RULES.get(form_type, set())
|
||||
default_names = list(DEFAULT_FIELD_ORDER.get(form_type, []))
|
||||
ensure_form_field_configs(form_type, default_names)
|
||||
section_configs = ensure_form_section_configs(form_type)
|
||||
|
||||
for section_key, is_visible in preset.get('sections', {}).items():
|
||||
cfg = section_configs.get(section_key)
|
||||
if not cfg or section_key in locked_sections:
|
||||
continue
|
||||
cfg.is_visible = bool(is_visible)
|
||||
cfg.save(update_fields=['is_visible'])
|
||||
|
||||
for cfg in FormFieldConfig.objects.filter(form_type=form_type):
|
||||
if cfg.field_name in locked_fields:
|
||||
cfg.is_visible = True
|
||||
cfg.is_required = None
|
||||
else:
|
||||
cfg.is_visible = True
|
||||
cfg.is_required = None
|
||||
override = preset.get('fields', {}).get(cfg.field_name, {})
|
||||
if 'is_visible' in override:
|
||||
cfg.is_visible = bool(override['is_visible'])
|
||||
if 'is_required' in override:
|
||||
cfg.is_required = override['is_required']
|
||||
cfg.save(update_fields=['is_visible', 'is_required'])
|
||||
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user