Skip to content

Werkbon Formulier (Form 40)

Form 40 is het hoofdformulier van de applicatie. Het wordt gebruikt om werkbonnen aan te maken, gekoppeld aan een bestaande melding.

Form ID40
Templatepage-jobs-form.php
URL/werkbon-invullen/?job_id=123
CPT outputfile (werkbon)
Gekoppeld aanjob (melding) via file-job relatie

Volledige mapping van alle Form 40 velden naar ACF meta keys:

KeyField IDACF Meta KeyTypeBeschrijving
job_id58file-jobhiddenGekoppelde melding post ID
date49file-datedate (Flatpickr)Datum werkbon
street_select23Select2Straat (adres chain start)
number_select24Select2Huisnummer
addition_select25Select2Toevoeging
zipcode_auto26readonlyAuto-ingevuld postcode
city_auto27readonlyAuto-ingevulde stad
streetname17file-streetnamehiddenSync vanuit select → opgeslagen
number52file-numberhiddenSync vanuit select → opgeslagen
addition19file-additionhiddenSync vanuit select → opgeslagen
zipcode20file-zipcodehiddenSync vanuit select → opgeslagen
city21file-cityhiddenSync vanuit select → opgeslagen
custom_toggle22checkboxSchakel naar vrije tekst adres
street_custom2textVrij straatveld (fallback)
number_custom15textVrij nummerveld
addition_custom14textVrij toevoegingveld
zipcode_custom13textVrij postcodeveld
city_custom4textVrij stadsveld
description5file-descriptiontextareaLeesbare tekst (gegenereerd door JS)
description_json53file-description-jsonhiddenJSON werkzaamheden array
material37file-materialtextareaLeesbaar: “qty x label”
material_json55file-material-jsonhiddenJSON materiaal array
company68file-companytextBedrijfsnaam
firstname69file-firstnametextVoornaam
lastname70file-lastnametextAchternaam
email71file-emailemailEmail adres
phone82file-phonetextTelefoon
contact_id78file-contacthiddenContact post ID
moneybird_id80hiddenMoneybird extern ID
type74file-typeselectmaasdelta / particulier / zakelijk
employer10file-employercheckboxMonteur(s) user IDs
note28file-notetextareaInterne notitie
signature64signatureHandtekening afbeelding
verifycheckboxVerificatie voor submit

Exacte uitvoeringsvolgorde na form submission:

StapPriorityHookCallbackBestandDoel
15wpforms_process_filterwpf_dev_filter_placeholder_valueswpforms.phpFilter placeholder waarden (’…’, ‘Selecteer…‘)
210wpforms_process_filterwpf_dev_process_filter_choices_valueswpforms.phpSwap value ↔ value_raw voor show_values velden
310wpforms_process_filter[phone normalizer]wpforms-normalize-phone.phpTelefoon field 82 → E.164 format
410wpforms_post_submissions_process_meta[employer parser]update-employers-after-submit.phpField 10 (employer) → array[int]
510wpforms_process_complete[file creator]wpforms-create-file-post.phpFILE CPT aanmaken
610wpforms_process_complete_40[status updater]change-job-status-on-file-complete.phpJob status → 2 (Afgerond)

Bestand: wpforms-create-file-post.php

  1. Check form_data['id'] === 40
  2. Laad field map via beam_get_form40_field_map()
  3. Bouw post title: YYYYMMDD: straat nr toevoeging, stad (of YYYYMMDD: Werkbon als adres leeg)
  4. wp_insert_post(['post_type' => 'file', 'post_status' => 'publish'])
  5. beam_save_form_values_to_meta(40, $file_id, $fields, ['contact_id']) — alle velden behalve contact
  6. Link job: field 58 → update_field('file-job', $job_id, $file_id)
  7. 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
  8. Link contact: hra_set_relationship_field($file_id, 'file-contact', $contact_id)
  9. Clear caches: clean_post_cache(), wp_cache_delete(), acf_flush_value_cache()
  10. Trigger: do_action('acf/save_post', $file_id) → Make.com webhook (zie Integraties)

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
ParameterVoorbeeldBeschrijving
job_id?job_id=123Primair — PHP leest alle job ACF velden
wpf40_58?wpf40_58=123Legacy — individueel veld prefill
wpf40_68?wpf40_68=BedrijfLegacy — elk veld via field ID
wpf40_10[]?wpf40_10[]=5&wpf40_10[]=8Team/monteur prefill (meerdere)

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 resolution

Na PHP prefill neemt JavaScript het over:

  1. form-field-locks.js detecteert URL params → vergrendelt alle contact + adres velden
  2. “Bewerk” knop verschijnt boven de vergrendelde velden
  3. BEAM_CONTACT_PREFILL_BUSY = true pauzeert de lock cycle
  4. Team prefill: wpf40_10[] params → checkbox matching op value (ID) of label text

Bestand: form-work.php (847 regels)

ElementTypeBeschrijving
#location_selectMulti-selectLocaties kiezen (Keuken, Badkamer, etc.)
#work_selectSingle-selectType werkzaamheid
#file_time_extraSelectOptionele tijd: 0-8 uur in 0.5 stappen
#file_date_extraFlatpickrOptionele datum
  • 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

Preset knoppen voor veelgebruikte combinaties:

  • “Riool ontstopt met hogedruk” �� vult locatie, werk, tijd in
  • Klik → modal wordt gevuld → gebruiker kan aanpassen → toevoegen
  • Pencil icon: laad rij terug in modal → knoptekst wordt “Bijwerken”
  • Trash icon: verwijder rij uit tabel
  • Na elke wijziging: automatische sync naar form velden

Field #5 — leesbare tekst (file-description):

Keuken, Badkamer: Riool ontstopt met hogedruk (05-04-2026 - 1,5 uur)
Badkamer: Lekkage verholpen

Grammatica: 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"
}
]

Bestand: form-material.php (409 regels)

  • Checkbox: “Is er materiaal gebruikt?”
  • Multi-select verschijnt bij aanvinken
  • Conditional logic: observer checkt .wpforms-conditional-hide class
  • Categorieën als optgroups (alfabetisch gesorteerd, “Overig” altijd laatst)
  • Materialen alfabetisch binnen categorie
  • Quantity tabel met +/- knoppen per materiaal

Field #37 — leesbare tekst (file-material):

2 x PVC Buis 110mm
1 x Ontstopperveer 16mm

Field #55 — JSON (file-material-json):

[
{"id": "mat_001", "label": "PVC Buis 110mm", "qty": 2},
{"id": "mat_042", "label": "Ontstopperveer 16mm", "qty": 1}
]

Bestand: file-overview-sync.js (8.1KB)

8 secties die real-time synchroniseren met form velden:

Paneel IDBron VeldenFormatting
#file-overview-contact68, 69, 70, 71, 82Multiline: bedrijf → naam → email → telefoon
#file-overview-address17, 52, 19, 20, 212 regels: straat nr toev / postcode stad
#file-overview-date50Datum string
#file-overview-jobs5Werkzaamheden met line breaks
#file-overview-time11”Binnen het 1e uur” of “X uur”
#file-overview-material37Materiaal met line breaks
#file-overview-employees10Checked labels, “en”-gescheiden lijst
#file-overview-note28Tekst met line breaks
  • Event-based: change en input events op alle bronvelden
  • Polling: setInterval(300ms) voor programmatische value changes (zonder events)
  • Change tracking: alleen update als waarde verschilt van laatste render

Bestand: submit-validation.js (8.3KB)

  1. Gebruiker klikt verify checkbox
  2. Systeem scant form velden top-to-bottom
  3. Check per zichtbaar required veld:
    • Checkboxes/radios → minstens 1 aangevinkt
    • Selects → waarde niet leeg
    • File inputs → minstens 1 bestand
    • Text inputs → niet leeg
  4. Speciaal: hidden field #5 (werkzaamheden) leeg EN field #61 zichtbaar → scroll naar #61
  • 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
  • Checkbox aangevinkt
  • Submit knop enabled (.disabled class verwijderd)

Bestand: wpforms-confirmation-overview.php

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.

  • Handtekening afbeelding uit field 64
  • <img> tag met max-width: 320px
  • Leeg als geen handtekening aanwezig
ModuleBestandDoelKey Interactie
prefill-manager.jsBundelElement waiting, setValue met lock-respectMutationObserver + retry logic
wpforms-werkbon.jsBundelAddress sync (select→WP velden), type bepalingLuistert naar adres + company changes
form-field-locks.jsBundelVergrendeling na contact selectie/prefill250ms polling + MutationObserver
file-overview-sync.jsBundelReal-time overzichtspaneelEvent + 300ms polling
submit-validation.jsBundelVerify checkbox validatieCheckbox click event
modal-search-contact.jsApartContact zoek modalREST API + AJAX address resolve

Het type wordt automatisch bepaald in deze prioriteit:

  1. URL prefill parameter (wpf40_74) → gebruik die waarde
  2. Straat bevat “maasdelta” (uit Select2 source) → type = maasdelta
  3. Company veld (68) gevuld → type = zakelijk
  4. Anders → type = particulier

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.

In de nieuwe stack wordt Form 40 vervangen door een WorkOrderFormPage React component met:

  • React Hook Form + Zod voor validatie (vervangt WPForms + verify checkbox)
  • WorkItemsEditor component (vervangt werkzaamheden modal + jQuery sortable)
  • MaterialEditor component (vervangt materiaal tabel)
  • AddressAutocomplete component (vervangt Select2 chain)
  • ContactSearch combobox (vervangt Select2 modal)
  • Direct Supabase insert (vervangt wp_insert_post + ACF)

Zie Migratie naar Beam Stack voor de feature mapping en app structuur.

BestandLocatieFunctie
page-jobs-form.phpTheme rootPage template
wpforms-create-file-post.phpfunctions/FILE CPT aanmaken
change-job-status-on-file-complete.phpfunctions/Job → Afgerond
wpforms-field-mappings.phpfunctions/Field mapping definities
wpforms.phpfunctions/Placeholder filter, value swap
wpforms-normalize-phone.phpfunctions/Telefoon E.164
update-employers-after-submit.phpfunctions/Employer array parsing
wpforms-confirmation-overview.phpfunctions/Smart tags
form-work.phpfunctions/Werkzaamheden modal + tabel
form-material.phpfunctions/Materiaal toggle + tabel
form-prefill.phpfunctions/PHP prefill logica
form-overview.phpfunctions/Overview paneel
prefill-manager.jsassets/js/modules/Element waiting
wpforms-werkbon.jsassets/js/modules/Address sync, type detectie
form-field-locks.jsassets/js/modules/Field locking
file-overview-sync.jsassets/js/modules/Overview sync
submit-validation.jsassets/js/modules/Verify validatie
modal-search-contact.jsassets/js/Contact zoek modal