---
phase: 03-registration-form-settings
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - _rejestracja/core/class/RegistrationFormSettings.class.php
  - _rejestracja/Admin/controller/FormSettingsController.php
  - _rejestracja/Admin/template/partial/FormSettings/Index.tpl
  - _rejestracja/Admin/controller/DictionaryController.php
  - _rejestracja/Admin/controller/SetupController.php
  - _rejestracja/controller/IndexController.php
  - _rejestracja/template/partial/Index/Index.tpl
  - _rejestracja/sql/2026-04-24-registration-form-settings.sql
  - _rejestracja/sql/apply-2026-04-24-registration-form-settings.php
autonomous: true
delegation: off
---

<objective>
## Goal
Add an administrator "Ustawienia formularza" page next to "Slowniki" and "Zmienne serwisu", and make registration day options plus every price used by the registration price calculation editable from that page.

## Purpose
The registration form currently mixes editable `mf_parameters` prices with hardcoded one-day prices and hardcoded `participation_days` labels in the Smarty/JavaScript template. The client needs those operational values changeable at any time without editing source code.

## Output
- New admin controller and template for form settings.
- Shared settings helper for reading defaults from `wp_setup` and `mf_parameters`.
- Public registration form and submit flow using the shared settings for day labels and pricing.
- SQL and PHP migration runner to seed default settings on production.
</objective>

<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md

## Prior Work
@.paul/phases/01-registration-form-update/01-01-SUMMARY.md
@.paul/phases/02-registration-dictionary-phrases/02-01-SUMMARY.md

## Source Files
@_rejestracja/controller/IndexController.php
@_rejestracja/template/partial/Index/Index.tpl
@_rejestracja/Admin/controller/SetupController.php
@_rejestracja/Admin/controller/DictionaryController.php
@_rejestracja/Admin/template/partial/Setup/Index.tpl
@_rejestracja/Admin/controller/CalcController.php
@_rejestracja/Admin/template/partial/Calc/Add.tpl
@_rejestracja/Admin/template/partial/Calc/Edit.tpl
@_rejestracja/core/_model/SetupDAL.class.php
@_rejestracja/core/_model/MfParameters.class.php
@_rejestracja/core/_model/MfParametersDAL.class.php
</context>

<acceptance_criteria>

## AC-1: Admin Menu Entry
```gherkin
Given an administrator is on the Dictionary or Setup admin area
When the admin side menu renders
Then the menu includes "Ustawienia formularza" linking to /_rejestracja/Admin/FormSettings/Index next to "Slowniki" and "Zmienne serwisu"
```

## AC-2: Editable Participation Days
```gherkin
Given an administrator opens "Ustawienia formularza"
When they edit the one-day with lodging and one-day without lodging day labels
Then the public registration form renders those labels as participation_days radio options and submitted registrations store the selected configured label
```

## AC-3: Editable Calculation Prices
```gherkin
Given an administrator opens "Ustawienia formularza"
When they edit full conference prices, single-room/accompanying-person/English-conference surcharges, one-day prices, or VAT multiplier
Then calculatePrice on the public form and the server-side saved participant price use the edited values consistently
```

## AC-4: Deployment Seed
```gherkin
Given production has not yet created the new form settings variables
When the deployment SQL or PHP runner is applied
Then default settings are inserted without overwriting existing values and the form still shows the current three November day options and current prices
```

</acceptance_criteria>

<tasks>

<task type="auto">
  <name>Task 1: Add Shared Registration Settings Helper</name>
  <files>_rejestracja/core/class/RegistrationFormSettings.class.php, _rejestracja/sql/2026-04-24-registration-form-settings.sql, _rejestracja/sql/apply-2026-04-24-registration-form-settings.php</files>
  <action>
    Create a `RegistrationFormSettings` helper that centralizes editable values:
    - Read/write day labels from `wp_setup` variables using a clear prefix such as `registration_form_days_lodging` and `registration_form_days_no_lodging`; store list values as newline-separated text to keep the existing `wp_setup` table unchanged.
    - Read/write the VAT multiplier from `wp_setup` as `registration_form_vat_multiplier`, defaulting to `1.23`.
    - Read/write one-day net prices from `wp_setup` as `registration_form_one_day_price_prom` and `registration_form_one_day_price_normal`, defaulting to `1300` and `1600`.
    - Read/write existing full conference and surcharge prices through `mf_parameters` rows, preserving IDs currently used by the form: `1` full conference, `2` single-room surcharge, `3` accompanying person/driver, `4` English conference, `5` legacy one-day.
    - Return a normalized settings array for templates containing `days_lodging`, `days_no_lodging`, `prices`, and `vat_multiplier`.
    - Provide save methods that normalize commas to dots for numbers, trim list entries, and leave unrelated `wp_setup` variables untouched.
    Add SQL and PHP runner files that seed the new `wp_setup` variables only when missing. Do not change database schema.
  </action>
  <verify>Run `php -l _rejestracja/core/class/RegistrationFormSettings.class.php` and `php -l _rejestracja/sql/apply-2026-04-24-registration-form-settings.php`.</verify>
  <done>AC-2, AC-3, and AC-4 have a shared source of truth and deployment defaults.</done>
</task>

<task type="auto">
  <name>Task 2: Build Admin Form Settings Page</name>
  <files>_rejestracja/Admin/controller/FormSettingsController.php, _rejestracja/Admin/template/partial/FormSettings/Index.tpl, _rejestracja/Admin/controller/DictionaryController.php, _rejestracja/Admin/controller/SetupController.php</files>
  <action>
    Add `FormSettingsController` with `IndexAction` and a `preDispatch` matching the existing admin controller style.
    - On GET, load settings through `RegistrationFormSettings` and assign them to Smarty.
    - On POST, validate required numeric fields with the existing `Validator` style where practical, save through the helper, and show an admin info/error message without redirect loops.
    - Template should group fields into participation days, main prices, surcharge prices, one-day prices, and VAT multiplier.
    - Update the local admin menu arrays in `DictionaryController`, `SetupController`, and the new controller to include `Ustawienia formularza` => `FormSettings`/`Index`.
    - Keep existing Dictionary and Setup behavior unchanged.
  </action>
  <verify>Run `php -l _rejestracja/Admin/controller/FormSettingsController.php` and inspect the generated route URL from the same `Router::GenerateUrl('dictpig', ...)` pattern used by Dictionary/Setup.</verify>
  <done>AC-1, AC-2, and AC-3 are satisfied from the administrator side.</done>
</task>

<task type="auto">
  <name>Task 3: Use Settings in Public Form and Submit Pricing</name>
  <files>_rejestracja/controller/IndexController.php, _rejestracja/template/partial/Index/Index.tpl</files>
  <action>
    Replace hardcoded form settings with data from `RegistrationFormSettings`.
    - In `IndexController::IndexAction`, load settings once and assign JSON-safe arrays for `days_lodging`, `days_no_lodging`, `prices`, and `vat_multiplier`.
    - Replace hardcoded day radio labels in `Index.tpl` with Smarty loops over configured day arrays, keeping `name="participation_days"` and existing option visibility behavior.
    - Replace hardcoded JS one-day prices `1300/1600` and gross values `1599/1968` with the configured net prices and VAT multiplier; gross should be computed from net * VAT multiplier.
    - Update server-side `$resultPrice` calculation so conference fee `5` uses configured one-day promotional/normal price instead of relying on `mf_parameters` ID 5 when the selected `participation_option` is `one_day_lodging` or `one_day_no_lodging`.
    - Keep existing `mf_parameters` behavior for full conference and surcharges so saved registrations/admin summaries continue to resolve existing parameter rows.
    - Preserve legacy fallback for missing POST values and for old session/display data.
  </action>
  <verify>Run `php -l _rejestracja/controller/IndexController.php`, then manually inspect the rendered Smarty syntax for valid `{foreach}` blocks and JavaScript object output.</verify>
  <done>AC-2 and AC-3 are satisfied from the public form through persisted participant price.</done>
</task>

</tasks>

<boundaries>

## DO NOT CHANGE
- Existing `mf_participant` schema and participant status/payment semantics.
- Existing dictionary phrase keys created in Phase 2.
- Existing public form field names: `participation_days`, `participation_option`, `one_day_lodging`, `conference_fee`, and surcharge checkbox names.
- Existing Dictionary and Setup edit flows beyond adding the new menu link.

## SCOPE LIMITS
- Do not redesign the admin UI; follow the current table/dropdown container style.
- Do not replace the legacy `mf_parameters` calculator module; expose the relevant rows in the new settings page and keep compatibility.
- Do not add new third-party dependencies.
- Do not alter compiled Smarty cache files under `temp/compile`.

</boundaries>

<verification>
Before declaring plan complete:
- [ ] `php -l _rejestracja/core/class/RegistrationFormSettings.class.php`
- [ ] `php -l _rejestracja/Admin/controller/FormSettingsController.php`
- [ ] `php -l _rejestracja/controller/IndexController.php`
- [ ] `php -l _rejestracja/sql/apply-2026-04-24-registration-form-settings.php`
- [ ] Confirm no hardcoded `3 listopada`, `4 listopada`, `5 listopada`, `3/4 listopada`, `4/5 listopada`, `1300`, `1600`, `1599`, or `1968` remain in active registration form pricing code except as migration/default seed values.
- [ ] Confirm the admin menu in Dictionary, Setup, and FormSettings includes the new "Ustawienia formularza" entry.
</verification>

<success_criteria>
- Administrators can open `/_rejestracja/Admin/FormSettings/Index`.
- The new page edits configured day options and all prices used by the current public registration calculation.
- Public JS price preview and server-side saved price use the same configured values.
- Deployment seed is idempotent and does not overwrite production edits.
- All verification checks pass.
</success_criteria>

<output>
After completion, create `.paul/phases/03-registration-form-settings/03-01-SUMMARY.md`
</output>
