Werkbon Formulier (Form 40)
Overzicht
Section titled “Overzicht”Form 40 is het hoofdformulier van de applicatie. Het wordt gebruikt om werkbonnen aan te maken, gekoppeld aan een bestaande melding.
| Form ID | 40 |
| Template | page-jobs-form.php |
| URL | /werkbon-invullen/?job_id=123 |
| CPT output | file (werkbon) |
| Gekoppeld aan | job (melding) via file-job relatie |
Field Mapping
Section titled “Field Mapping”Volledige mapping van alle Form 40 velden naar ACF meta keys:
| Key | Field ID | ACF Meta Key | Type | Beschrijving |
|---|---|---|---|---|
| job_id | 58 | file-job | hidden | Gekoppelde melding post ID |
| date | 49 | file-date | date (Flatpickr) | Datum werkbon |
| street_select | 23 | — | Select2 | Straat (adres chain start) |
| number_select | 24 | — | Select2 | Huisnummer |
| addition_select | 25 | — | Select2 | Toevoeging |
| zipcode_auto | 26 | — | readonly | Auto-ingevuld postcode |
| city_auto | 27 | — | readonly | Auto-ingevulde stad |
| streetname | 17 | file-streetname | hidden | Sync vanuit select → opgeslagen |
| number | 52 | file-number | hidden | Sync vanuit select → opgeslagen |
| addition | 19 | file-addition | hidden | Sync vanuit select → opgeslagen |
| zipcode | 20 | file-zipcode | hidden | Sync vanuit select → opgeslagen |
| city | 21 | file-city | hidden | Sync vanuit select → opgeslagen |
| custom_toggle | 22 | — | checkbox | Schakel naar vrije tekst adres |
| street_custom | 2 | — | text | Vrij straatveld (fallback) |
| number_custom | 15 | — | text | Vrij nummerveld |
| addition_custom | 14 | — | text | Vrij toevoegingveld |
| zipcode_custom | 13 | — | text | Vrij postcodeveld |
| city_custom | 4 | — | text | Vrij stadsveld |
| description | 5 | file-description | textarea | Leesbare tekst (gegenereerd door JS) |
| description_json | 53 | file-description-json | hidden | JSON werkzaamheden array |
| material | 37 | file-material | textarea | Leesbaar: “qty x label” |
| material_json | 55 | file-material-json | hidden | JSON materiaal array |
| company | 68 | file-company | text | Bedrijfsnaam |
| firstname | 69 | file-firstname | text | Voornaam |
| lastname | 70 | file-lastname | text | Achternaam |
| 71 | file-email | Email adres | ||
| phone | 82 | file-phone | text | Telefoon |
| contact_id | 78 | file-contact | hidden | Contact post ID |
| moneybird_id | 80 | — | hidden | Moneybird extern ID |
| type | 74 | file-type | select | maasdelta / particulier / zakelijk |
| employer | 10 | file-employer | checkbox | Monteur(s) user IDs |
| note | 28 | file-note | textarea | Interne notitie |
| signature | 64 | — | signature | Handtekening afbeelding |
| verify | — | — | checkbox | Verificatie voor submit |
Server-side Submit Chain
Section titled “Server-side Submit Chain”Exacte uitvoeringsvolgorde na form submission:
| Stap | Priority | Hook | Callback | Bestand | Doel |
|---|---|---|---|---|---|
| 1 | 5 | wpforms_process_filter | wpf_dev_filter_placeholder_values | wpforms.php | Filter placeholder waarden (’…’, ‘Selecteer…‘) |
| 2 | 10 | wpforms_process_filter | wpf_dev_process_filter_choices_values | wpforms.php | Swap value ↔ value_raw voor show_values velden |
| 3 | 10 | wpforms_process_filter | [phone normalizer] | wpforms-normalize-phone.php | Telefoon field 82 → E.164 format |
| 4 | 10 | wpforms_post_submissions_process_meta | [employer parser] | update-employers-after-submit.php | Field 10 (employer) → array[int] |
| 5 | 10 | wpforms_process_complete | [file creator] | wpforms-create-file-post.php | FILE CPT aanmaken |
| 6 | 10 | wpforms_process_complete_40 | [status updater] | change-job-status-on-file-complete.php | Job status → 2 (Afgerond) |
Stap 5: FILE Post Aanmaak (Detail)
Section titled “Stap 5: FILE Post Aanmaak (Detail)”Bestand: wpforms-create-file-post.php
- Check
form_data['id'] === 40 - Laad field map via
beam_get_form40_field_map() - Bouw post title:
YYYYMMDD: straat nr toevoeging, stad(ofYYYYMMDD: Werkbonals adres leeg) wp_insert_post(['post_type' => 'file', 'post_status' => 'publish'])beam_save_form_values_to_meta(40, $file_id, $fields, ['contact_id'])— alle velden behalve contact- Link job: field 58 →
update_field('file-job', $job_id, $file_id) - Contact upsert:
hra_upsert_contact_from_wpforms_cached($fields, $form_data, $entry_id)- Zoekt bestaand contact of maakt nieuw aan (zie Contact Systeem)
- Returns contact_id
- Link contact:
hra_set_relationship_field($file_id, 'file-contact', $contact_id) - Clear caches:
clean_post_cache(),wp_cache_delete(),acf_flush_value_cache() - Trigger:
do_action('acf/save_post', $file_id)→ Make.com webhook (zie Integraties)
Stap 6: Job Status Update
Section titled “Stap 6: Job Status Update”Bestand: change-job-status-on-file-complete.php
- Leest field 58 (job_id) uit form data
- Valideert:
get_post_type($job_id) === 'job' update_field('job-status', '2', $job_id)→ status wordt Afgerond
Prefill Systeem
Section titled “Prefill Systeem”URL Parameters
Section titled “URL Parameters”| Parameter | Voorbeeld | Beschrijving |
|---|---|---|
job_id | ?job_id=123 | Primair — PHP leest alle job ACF velden |
wpf40_58 | ?wpf40_58=123 | Legacy — individueel veld prefill |
wpf40_68 | ?wpf40_68=Bedrijf | Legacy — elk veld via field ID |
wpf40_10[] | ?wpf40_10[]=5&wpf40_10[]=8 | Team/monteur prefill (meerdere) |
PHP Prefill Flow
Section titled “PHP Prefill Flow”Bestand: form-prefill.php
?job_id=123 ↓beam_wpf40_has_prefill() → true ↓beam_get_job_prefill_data($job_id) ├─ Leest alle ACF velden van job post ├─ Mapped naar form field values: │ job-company → field 68 │ job-firstname → field 69 │ job-streetname → field 17/23 │ job-contact → field 78 (contact post ID) │ ... └─ beam_resolve_address_php() → adres resolutionClient-side Prefill
Section titled “Client-side Prefill”Na PHP prefill neemt JavaScript het over:
form-field-locks.jsdetecteert URL params → vergrendelt alle contact + adres velden- “Bewerk” knop verschijnt boven de vergrendelde velden
BEAM_CONTACT_PREFILL_BUSY = truepauzeert de lock cycle- Team prefill:
wpf40_10[]params → checkbox matching op value (ID) of label text
Werkzaamheden Systeem
Section titled “Werkzaamheden Systeem”Bestand: form-work.php (847 regels)
Modal Interface
Section titled “Modal Interface”| Element | Type | Beschrijving |
|---|---|---|
| #location_select | Multi-select | Locaties kiezen (Keuken, Badkamer, etc.) |
| #work_select | Single-select | Type werkzaamheid |
| #file_time_extra | Select | Optionele tijd: 0-8 uur in 0.5 stappen |
| #file_date_extra | Flatpickr | Optionele datum |
Werkzaamheden Tabel
Section titled “Werkzaamheden Tabel”- 3 kolommen: info (met drag handle), extra tijd, acties (edit/delete)
- jQuery UI sortable voor drag-drop herordenen
- Data attributes per rij:
data-locations,data-works,data-extra-time,data-extra-date
Frequent Combo’s
Section titled “Frequent Combo’s”Preset knoppen voor veelgebruikte combinaties:
- “Riool ontstopt met hogedruk” �� vult locatie, werk, tijd in
- Klik → modal wordt gevuld → gebruiker kan aanpassen → toevoegen
Edit / Delete
Section titled “Edit / Delete”- Pencil icon: laad rij terug in modal → knoptekst wordt “Bijwerken”
- Trash icon: verwijder rij uit tabel
- Na elke wijziging: automatische sync naar form velden
Sync naar Form Velden
Section titled “Sync naar Form Velden”Field #5 — leesbare tekst (file-description):
Keuken, Badkamer: Riool ontstopt met hogedruk (05-04-2026 - 1,5 uur)Badkamer: Lekkage verholpenGrammatica: locaties komma-gescheiden, dan werkzaamheid, optioneel datum en tijd.
Field #53 — JSON (file-description-json):
[ { "index": 0, "main": "Riool ontstopt met hogedruk", "date_display": "05-04-2026", "extra_display": "1,5 uur", "locations": ["Keuken", "Badkamer"], "works": ["Hogedruk reinigen"], "extra_time": "1.5", "extra_date": "2026-04-05" }]Materiaal Systeem
Section titled “Materiaal Systeem”Bestand: form-material.php (409 regels)
Toggle
Section titled “Toggle”- Checkbox: “Is er materiaal gebruikt?”
- Multi-select verschijnt bij aanvinken
- Conditional logic: observer checkt
.wpforms-conditional-hideclass
Select & Tabel
Section titled “Select & Tabel”- Categorieën als optgroups (alfabetisch gesorteerd, “Overig” altijd laatst)
- Materialen alfabetisch binnen categorie
- Quantity tabel met +/- knoppen per materiaal
Sync naar Form Velden
Section titled “Sync naar Form Velden”Field #37 — leesbare tekst (file-material):
2 x PVC Buis 110mm1 x Ontstopperveer 16mmField #55 — JSON (file-material-json):
[ {"id": "mat_001", "label": "PVC Buis 110mm", "qty": 2}, {"id": "mat_042", "label": "Ontstopperveer 16mm", "qty": 1}]Overview Panel
Section titled “Overview Panel”Bestand: file-overview-sync.js (8.1KB)
8 secties die real-time synchroniseren met form velden:
| Paneel ID | Bron Velden | Formatting |
|---|---|---|
| #file-overview-contact | 68, 69, 70, 71, 82 | Multiline: bedrijf → naam → email → telefoon |
| #file-overview-address | 17, 52, 19, 20, 21 | 2 regels: straat nr toev / postcode stad |
| #file-overview-date | 50 | Datum string |
| #file-overview-jobs | 5 | Werkzaamheden met line breaks |
| #file-overview-time | 11 | ”Binnen het 1e uur” of “X uur” |
| #file-overview-material | 37 | Materiaal met line breaks |
| #file-overview-employees | 10 | Checked labels, “en”-gescheiden lijst |
| #file-overview-note | 28 | Tekst met line breaks |
Sync Strategie
Section titled “Sync Strategie”- Event-based:
changeeninputevents op alle bronvelden - Polling:
setInterval(300ms)voor programmatische value changes (zonder events) - Change tracking: alleen update als waarde verschilt van laatste render
Verify & Submit
Section titled “Verify & Submit”Bestand: submit-validation.js (8.3KB)
Validatie Flow
Section titled “Validatie Flow”- Gebruiker klikt verify checkbox
- Systeem scant form velden top-to-bottom
- Check per zichtbaar required veld:
- Checkboxes/radios → minstens 1 aangevinkt
- Selects → waarde niet leeg
- File inputs → minstens 1 bestand
- Text inputs → niet leeg
- Speciaal: hidden field #5 (werkzaamheden) leeg EN field #61 zichtbaar → scroll naar #61
Bij Fout
Section titled “Bij Fout”- Checkbox wordt niet aangevinkt
- Foutmelding: “Vul eerst alle verplichte velden in voordat je dit aanvinkt.”
- Scroll naar eerste ongeldige veld (250ms animatie)
- Focus op eerste focusable element in dat veld
Bij Succes
Section titled “Bij Succes”- Checkbox aangevinkt
- Submit knop enabled (
.disabledclass verwijderd)
Confirmation (Smart Tags)
Section titled “Confirmation (Smart Tags)”Bestand: wpforms-confirmation-overview.php
{file_overview}
Section titled “{file_overview}”HTML overzicht na succesvolle submit:
- Contact: bedrijf, naam, email, telefoon
- Adres: straat, nummer, toevoeging, postcode, stad
- Datum, Werkzaamheden, Tijd, Materiaal, Monteur, Notitie
Helper: buildLocationWorkText() — grammaticaal correcte “en”-scheiding van locaties en werkzaamheden.
{file_signature}
Section titled “{file_signature}”- Handtekening afbeelding uit field 64
<img>tag metmax-width: 320px- Leeg als geen handtekening aanwezig
Client-side Modules
Section titled “Client-side Modules”| Module | Bestand | Doel | Key Interactie |
|---|---|---|---|
| prefill-manager.js | Bundel | Element waiting, setValue met lock-respect | MutationObserver + retry logic |
| wpforms-werkbon.js | Bundel | Address sync (select→WP velden), type bepaling | Luistert naar adres + company changes |
| form-field-locks.js | Bundel | Vergrendeling na contact selectie/prefill | 250ms polling + MutationObserver |
| file-overview-sync.js | Bundel | Real-time overzichtspaneel | Event + 300ms polling |
| submit-validation.js | Bundel | Verify checkbox validatie | Checkbox click event |
| modal-search-contact.js | Apart | Contact zoek modal | REST API + AJAX address resolve |
Type Bepaling (wpforms-werkbon.js)
Section titled “Type Bepaling (wpforms-werkbon.js)”Het type wordt automatisch bepaald in deze prioriteit:
- URL prefill parameter (
wpf40_74) → gebruik die waarde - Straat bevat “maasdelta” (uit Select2 source) → type =
maasdelta - Company veld (68) gevuld → type =
zakelijk - Anders → type =
particulier
Address Sync (wpforms-werkbon.js)
Section titled “Address Sync (wpforms-werkbon.js)”Bij elke adreswijziging:
- Als custom address toggle (#22) aangevinkt → gebruik custom velden (2, 15, 14, 13, 4)
- Anders → gebruik select waarden + auto-filled postcode/stad
- Sync naar hidden WP velden: 17, 52, 19, 20, 21
- Deze hidden velden worden opgeslagen naar ACF meta
Zie Adressysteem voor de Select2 chain en AJAX lookups. Zie Contact Systeem voor de zoekmodal en field locking.
Migratie
Section titled “Migratie”In de nieuwe stack wordt Form 40 vervangen door een WorkOrderFormPage React component met:
- React Hook Form + Zod voor validatie (vervangt WPForms + verify checkbox)
WorkItemsEditorcomponent (vervangt werkzaamheden modal + jQuery sortable)MaterialEditorcomponent (vervangt materiaal tabel)AddressAutocompletecomponent (vervangt Select2 chain)ContactSearchcombobox (vervangt Select2 modal)- Direct Supabase insert (vervangt wp_insert_post + ACF)
Zie Migratie naar Beam Stack voor de feature mapping en app structuur.
Bestandsoverzicht
Section titled “Bestandsoverzicht”| Bestand | Locatie | Functie |
|---|---|---|
| page-jobs-form.php | Theme root | Page template |
| wpforms-create-file-post.php | functions/ | FILE CPT aanmaken |
| change-job-status-on-file-complete.php | functions/ | Job → Afgerond |
| wpforms-field-mappings.php | functions/ | Field mapping definities |
| wpforms.php | functions/ | Placeholder filter, value swap |
| wpforms-normalize-phone.php | functions/ | Telefoon E.164 |
| update-employers-after-submit.php | functions/ | Employer array parsing |
| wpforms-confirmation-overview.php | functions/ | Smart tags |
| form-work.php | functions/ | Werkzaamheden modal + tabel |
| form-material.php | functions/ | Materiaal toggle + tabel |
| form-prefill.php | functions/ | PHP prefill logica |
| form-overview.php | functions/ | Overview paneel |
| prefill-manager.js | assets/js/modules/ | Element waiting |
| wpforms-werkbon.js | assets/js/modules/ | Address sync, type detectie |
| form-field-locks.js | assets/js/modules/ | Field locking |
| file-overview-sync.js | assets/js/modules/ | Overview sync |
| submit-validation.js | assets/js/modules/ | Verify validatie |
| modal-search-contact.js | assets/js/ | Contact zoek modal |