Tijdregistratie naar factuur-app: van urenregistraties naar merkgebonden PDF's
Bouw een tijdregistratie-naar-factuur-app die projecturen vastlegt, omzet in facturen en merkgebonden PDF-bestanden genereert voor klanten.

Wat je bouwt en waarom het belangrijk is
Een tijdregistratie-naar-factuur app lost een veelvoorkomende rommel op: uren raken verspreid over agenda's, chats en notities. Als het factuurmoment daar is, moet iemand de maand handmatig reconstrueren. Daar ontstaan fouten: gemiste factureerbare uren, verkeerde tarieven, dubbele regels of totalen die niet kloppen.
Deze app is voor iedereen die op uurbasis factureert en een herhaalbaar proces wil: freelancers met meerdere klanten, bureaus waar meerdere mensen tijd op hetzelfde project boeken en interne teams die uren terugrekenen naar klanten of afdelingen.
Het doel is praktisch: tijdregistraties per project vastleggen, ze samenvoegen in een factuurrecord en een merkgebonden PDF genereren die de klant begrijpt. Als die workflow betrouwbaar is, stopt factureren met een maandelijkse chaos.
“Eerst simpel” betekent meestal:
- Eén manier om tijd te registreren (datum, project, uren, notitie)
- Eén tariefregel (per project of per persoon)
- Eén factuur per klant per periode
- Eén PDF-layout met je logo en bedrijfsgegevens
- Duidelijke statussen (Draft, Sent, Paid)
Een klein scenario: een studio van twee personen registreert tijd voor “Client A - Website Updates.” Iedereen logt gedurende de week uren. Op vrijdag maak je een factuur voor dat project en dat datumbereik, de app zet entries om in factuurregels en de PDF is klaar om te versturen zonder opnieuw te typen.
Als je een no-code platform gebruikt zoals AppMaster, zorg dat data en workflow kloppen voordat je extras toevoegt zoals bonnetjes, multi-valuta, kortingen of goedkeuringen. Dat zijn later makkelijker toe te voegen als de kernflow snel, accuraat en robuust is.
Kernfuncties om in te bouwen (en wat je eerst kunt weglaten)
Een kleine eerste versie brengt je sneller naar “verzendbare facturen”. Focus op drie dingen: tijd vastleggen, tijd omzetten naar heldere factuurregels en een leesbare PDF produceren.
Begin met een paar kernrecords (je kunt ze later hernoemen, maar de structuur telt): Client, Project, Time Entry, Invoice en Invoice Line.
Houd je factuurworkflow simpel met één statusveld op de Invoice-record. Draft, Sent en Paid dekt de meeste teams lange tijd.
Je must-have acties moeten overeenkomen met wat er wekelijks gebeurt:
- Tijd registreren (handmatige invoer is vaak het snelst te bouwen en het makkelijkst te corrigeren)
- Tijd goedkeuren (zelfs als dat alleen een “Approved”-status is)
- Factuur maken van goedgekeurde tijd
- PDF exporteren
“Merkgebonden” betekent niet duur. Het betekent consistent en betrouwbaar: logo, bedrijfsgegevens, factuurnummer en -datums, duidelijke totalen en betalingsinstructies.
Wat je eerst kunt weglaten: belastingen, kortingen, meerdere valuta en bijlagen. Die zijn nuttig, maar ze introduceren randgevallen (afronding, jurisdictieregels, wisselkoersen, bestandsopslag) die de eerste release vertragen.
Datamodel: de records die je nodig hebt en velden die ertoe doen
Een tijdregistratie-naar-factuur app leeft of sterft met zijn datamodel. Houd het klein en voorspelbaar zodat totalen altijd overeenkomen met wat je de klant hebt beloofd.
Een minimaal setje tabellen ziet er meestal zo uit:
- Client: naam, factuur-e-mail, factuuradres, standaardvaluta, betalingstermijn (bijv. Net 14)
- Project: client_id, projectnaam, standaard uurtarief (optioneel), actief-vlag
- Time entry: project_id, persoon (naam of user_id), datum, duur (uren), omschrijving, rate_at_time, factureerbaar (ja/nee), invoiced_invoice_id (leeg totdat gefactureerd)
- Invoice: client_id, project_id (optie), factuurnummer, uitgiftedatum, vervaldatum, status, subtotaal, belasting, totaal
Tarieven zijn waar apps rommelig worden. Kies één aanpak en houd je eraan: per project tarief, per persoon tarief, of vaste tarieven per taak/service.
Zelfs als je een standaardtarief op het project of de persoon opslaat, kopieer het werkelijke tarief naar elke tijdregistratie als rate_at_time wanneer de entry wordt gemaakt (of goedgekeurd). Dat voorkomt verrassingen wanneer tarieven later veranderen. Facturen moeten weergeven wat waar was toen het werk plaatsvond.
Voor tijdregistraties kun je vaak een aparte status overslaan en vertrouwen op of invoiced_invoice_id leeg is of niet. Voor facturen: houd statussen strak: Draft, Ready, Sent, Paid (en voeg Void toe als je een schone annuleringsstatus nodig hebt).
In AppMaster past dit netjes als de Data Designer naar PostgreSQL en houdt relaties duidelijk zonder overal velden te dupliceren.
Tijdregistraties per project vastleggen (eenvoudige UX)
Tijdregistratie is waar de app of moeiteloos voelt of genegeerd wordt. Houd de eerste versie saai en snel: één scherm, één primaire actie en zo min mogelijk keuzes.
Kies één vastlegmethode om mee te starten. Handmatige invoer wint meestal vroeg omdat het voor iedereen werkt en makkelijk te reviewen is. Een timer kan later komen wanneer je weet hoe mensen daadwerkelijk hun dag bijhouden. Als je een timer toevoegt, laat dan nog steeds handmatige aanpassingen toe voor gemiste stops.
Maak de velden die factureringskwaliteit beschermen verplicht:
- Project (of klant + project)
- Datum
- Duur (uren en minuten)
- Korte omschrijving (iets dat de klant zal herkennen)
- Persoon (als meerdere teamleden uren registreren)
Bepaal afrondingsregels vroeg want die beïnvloeden vertrouwen en totalen. Een gebruikelijke aanpak is 6-minuten increments (0,1 uur). Wees duidelijk of je per registratie afrondt of per dagtotaal. Per registratie afronden is eenvoudiger uit te leggen en te auditen.
Als meer dan één persoon bij facturatie betrokken is, voeg een lichte goedkeuringsstap toe. Een praktische regel: eenmaal goedgekeurd zijn entries standaard vergrendeld voor bewerking. Als iets moet veranderen, laat dan een manager-rol het opnieuw openen en leg vast wie het veranderde en waarom.
Tijd omzetten naar factuurregels (roll-up regels)
De roll-up is waar ruwe logs factuurregels worden die de klant kan begrijpen. Houd de regels simpel en voorspelbaar zodat je elke gegenereerde factuur vertrouwt.
Begin met één actie: kies een klant en een datumbereik, en haal alleen ongefactureerde tijdregistraties die matchen. Die filter is de beveiliging tegen dubbel factureren. Als een entry een ontbrekende klant of project heeft, behandel het als “nog niet klaar om te factureren” en laat het buiten de roll-up totdat het is gecorrigeerd.
Hoe entries te groeperen tot factuurregels
Groeperen bepaalt hoeveel regels je creëert en hoe makkelijk het is voor de klant om te reviewen. Kies een standaard en voeg één optionele schakel toe als je flexibiliteit wilt.
Veelgebruikte groeperingsopties:
- Per project
- Per persoon (nuttig als tarieven verschillen)
- Per dag of week
- Per taak/categorie (Design vs Development)
Wat je ook kiest, elke regel moet tonen: een duidelijke label, totaal uren, tarief en regelbedrag. Als tarieven kunnen wijzigen, gebruik dan de rate_at_time opgeslagen op elke entry (of een tarieftabel met “effective from”-datums), niet één “huidig tarief”.
Markeren als gefactureerd (zonder jezelf vast te zetten)
Wanneer je entries aan een factuur toevoegt, sla het factuurnummer op in de tijdregistratie. Dat creëert een audittrail en voorkomt dat dezelfde entry opnieuw wordt opgehaald.
Correcties komen voor. Als je een regel uit een factuur verwijdert, verwijder dan niet de historie. Maak de betreffende tijdregistraties los (wis de invoice ID), herbereken totalen en bewaar een korte notitie zoals “Removed 2.0h, wrong project.”
In AppMaster past dit goed als één business process: query ongefactureerde entries, groepeer ze, maak factuurregels, en update vervolgens elke entry met de factuurreferentie.
Factuurrecords: totalen, nummering en status
De factuurrecord is de container die je later kunt sturen, volgen en auditen. Die moet stabiel blijven, ook als iemand een projectnaam wijzigt of een standaardtarief aanpast.
Een praktisch factuurkopje bevat:
- Factuurnummer (uniek, mensvriendelijk)
- Uitgiftedatum en vervaldatum
- Bill-to details (klantnaam, factuuradres, btw-nummer indien nodig)
- Notities (betalingsinstructies, een korte bedankregel)
- Valuta (en optioneel een opgeslagen wisselkoers als je internationaal factureert)
Houd totalen voorspelbaar. Subtotaal is de som van factuurregels. Pas daarna korting toe (vast bedrag of procent), bereken belasting (vaak over het gereduceerde subtotaal) en sla het eindtotaal op. Bewaar het exacte belastingpercentage en kortingswaarden zodat je de factuur later kunt reproduceren.
Factuurnummering hoeft niet ingewikkeld te zijn. Kies een patroon en houd je eraan: sequentieel (000123), per jaar (2026-00123) of klantprefix plus volgnummer (ACME-014). Consistentie is belangrijker dan perfectie.
Status moet gericht blijven op communicatie en interne controle:
- Draft (bewerkbaar, niet verzonden)
- Ready (totalen vergrendeld)
- Sent (gedeeld met de klant)
- Paid (betaling bevestigd)
- Overdue (boven de vervaldatum)
- Void (geannuleerd, bewaard voor historie)
Een merkgebonden PDF genereren die de klant kan lezen
Een goede factuur-PDF beantwoordt twee vragen snel: wat wordt gefactureerd, en hoe te betalen. Genereer de PDF vanuit de factuurrecord (niet vanuit ruwe tijdregistraties) zodat het document altijd overeenkomt met factuurnummer, totalen en status.
De meeste klanten verwachten steeds dezelfde blokken:
- Kop met je bedrijfsnaam, factuurnummer en factuurdatum
- Klantgegevens (bedrijf, contactpersoon, factuuradres, btw-nummer indien nodig)
- Regels (omschrijving, hoeveelheid of uren, tarief, regelbedrag)
- Totalen (subtotaal, belasting, korting, eindtotaal)
- Betalingsvoorwaarden (vervaldatum, geaccepteerde betaalmethoden, eventuele incassokosten)
Branding doet ertoe, maar leesbaarheid nog meer. Houd één accentkleur, gebruik een eenvoudige letter, en maak totalen makkelijk scanbaar.
Layoutproblemen verschijnen met echte data. Test met lange omschrijvingen en 30+ regels. Zorg dat kolomkoppen op volgende pagina's herhaald worden en dat het totaalblok bij elkaar blijft.
Als je PDF's genereert in AppMaster, behandel de PDF als een artefact van de factuur: sla het bestand (of opslagreferentie) op in de factuurrecord met een gegenereerde timestamp en versie. Dat maakt het makkelijk om exact het document opnieuw te sturen dat de klant heeft ontvangen.
Stapsgewijs bouwplan (no-code workflow)
Bepaal wat de “source of truth” is. Tijdregistraties zijn ruwe feiten. Facturen zijn een snapshot die je kunt versturen en later auditen.
1) Model eerst de data
Maak de tabellen en relaties aan, voeg daarna een paar kwaliteitsvelden toe zodra de basis stabiel is:
- Clients
- Projects
- Time Entries
- Invoices
- Invoice Lines
2) Bouw twee eenvoudige schermen
Houd de UI minimaal:
- Tijdinvoerformulier: project, datum, duur, notities, opslaan
- Factuurreview: klant, periode, regels, totalen, status
Een web-UI is meestal genoeg voor administratie en reviews. Voeg mobiele schermen later toe als mensen onderweg tijd registreren.
3) Automatiseer de roll-up-logica
Bouw een flow zoals: selecteer klant + datumbereik, haal ongefactureerde entries, groepeer ze, maak factuurregels. Markeer entries als gefactureerd pas nadat de factuur is goedgekeurd of op Ready is gezet.
4) Genereer en sla de PDF op
Voeg een “Generate PDF”-actie toe die factuurkop, klantgegevens en regels in een template stopt en het resultaat op de factuurrecord opslaat.
Voorbeeld: van wekelijkse tijdlogs naar een klantklare factuur
Een bureau van 3 personen heeft één klant, Northstar Co, en factureert voor twee projecten over twee weken: Website Refresh en Monthly Support. Het team bestaat uit Alex (design), Priya (dev) en Sam (PM). Iedereen logt dagelijks tijd, kiest de klant, het project, datum en een korte notitie.
Elke dag worden entries als Draft opgeslagen. Op vrijdagmiddag opent Sam een reviewscherm gefilterd op “Deze week, Northstar Co”. Hij corrigeert twee notities (“Homepage hero” in plaats van “Hero”), bevestigt factureerbaar vs niet-factureerbaar en lockt de week.
Hier is een voorbeeld van entries die week:
| Datum | Persoon | Project | Uren | Notitie |
|---|---|---|---|---|
| Ma | Priya | Website Refresh | 2.5 | Header layout fixes |
| Di | Alex | Website Refresh | 3.0 | New homepage mock |
| Di | Sam | Monthly Support | 1.0 | Client call |
| Wo | Priya | Website Refresh | 4.0 | Contact form logic |
| Do | Alex | Monthly Support | 1.5 | Banner update |
| Do | Priya | Monthly Support | 2.0 | Email template tweak |
| Vr | Sam | Website Refresh | 1.0 | QA en overdracht |
Wanneer Sam op “Create invoice” klikt, rolt de app entries in factuurregels met eenvoudige regels: groepeer per project en factureerbaar tarief, sommeer uren en kopieer een korte omschrijving. De factuur bevat dan 3 regels:
| Regel | Omschrijving | Aantal | Tarief | Bedrag |
|---|---|---|---|---|
| 1 | Website Refresh (Design) | 3.0 hrs | $120 | $360 |
| 2 | Website Refresh (Development/PM) | 7.5 hrs | $140 | $1,050 |
| 3 | Monthly Support | 4.5 hrs | $110 | $495 |
Het systeem kent een factuurnummer toe (bijv. NS-2026-014), berekent subtotaal en belasting en zet status op Ready. Nog één klik genereert een merkgebonden PDF (logo, klantadres, regeldetails, totalen, betalingsnotities). Na verzending verandert status naar Sent en worden de onderliggende tijdregistraties gemarkeerd als gefactureerd zodat ze niet nogmaals in rekening worden gebracht.
Veelvoorkomende fouten en hoe ze te vermijden
De meeste problemen zijn geen rekenfouten. Het zijn workflowproblemen.
Geen vergrendeling van gefactureerde tijd. Als mensen entries kunnen bewerken of opnieuw selecteren voor een nieuwe factuur, ontstaat dubbel factureren. Los dit op met een factuurreferentie op elke tijdregistratie en verberg gefactureerde entries uit de “klaar om te factureren”-weergave.
Geschiedenis herschrijven bij tariefwijziging. Als je alleen met een “huidig” project- of gebruikers tarief rekent, verandert een tariefwijziging oude facturen. Kopieer het effectieve tarief naar rate_at_time op elke entry.
Goedgekeurde tijd bewerken zonder audittrail. Voeg “Approved by”, “Approved at” en een korte change note toe voor bewerkingen na goedkeuring.
PDF's die breken met echte data. Lange omschrijvingen, veel regels en grote cijfers zetten je template onder druk.
Snelle oplossingen die de meeste layoutproblemen voorkomen:
- Stel een maximale omschrijvingslengte in en verplaats overflow naar een notitiesectie
- Sta wrapping toe en test met 30+ rijen
- Houd de header compact zodat de tabel ruimte heeft
- Gebruik consistente nummerformaten (valuta, decimalen)
Een vage statusflow. Zonder duidelijke regels worden facturen dubbel verzonden of nooit verzonden.
Een simpele, veilige flow is: Draft -> Ready -> Sent -> Paid. Sta roll-ups alleen toe in Draft en PDF-generatie alleen wanneer totalen vergrendeld zijn.
Een korte checklist en praktische vervolgstappen
Voordat je een factuur verzendt, doe een snelle controle. Dat voorkomt de meest voorkomende issues: verkeerde totalen, ontbrekende details en PDF's die op het scherm prima lijken maar bij printen breken.
Pre-send checklist:
- Klantgegevens zijn compleet (juridische naam, factuuradres, juiste contactpersoon)
- Factuurperiode klopt (start- en einddatum komen overeen met het werk)
- Totalen zijn consistent (subtotaal, belasting, eindtotaal komen overeen met entries, tarieven en afronding)
- Geen tijd is gemist of gedupliceerd (niets ongefactureerd, niets dubbel opgenomen)
- Operationele velden kloppen (uniek factuurnummer, juiste status, PDF opgeslagen op de factuur)
Bekijk daarna de PDF met “printerogen”. Controleer logo-positie, lange adressen, tabel-wrapping en pagina-einden. Test zowel een korte factuur (1–2 regels) als een lange (20+ regels).
Vervolgstappen zodra de basis stabiel is:
- Verstuur facturen per e-mail met een consistent template
- Voeg Stripe-betalingen toe en markeer facturen automatisch als Paid
- Voeg permissies toe zodat alleen de juiste rollen tarieven kunnen wijzigen, tijd kunnen goedkeuren of statussen kunnen aanpassen
Als je snel wilt bouwen en itereren zonder alles vanaf nul te schrijven, is AppMaster (appmaster.io) een praktische optie om een no-code facturatie-app te maken met een echte database, businesslogica en PDF-generatie, en daarna schone broncode te regenereren wanneer vereisten veranderen.
Als je deze week maar één ding verbetert: zorg dat “ongefactureerde tijd” onmogelijk te missen is. Dat bespaart al uren en beschermt je inkomen.
FAQ
Begin met te zorgen dat iedere tijdregistratie een project, datum, duur en korte omschrijving heeft. Maak vervolgens een factuur door een klant en datumreeks te kiezen, alleen ongefactureerde items te halen, ze te groeperen tot factuurregels en de PDF te genereren vanuit de factuursnapshot.
Gebruik vijf records: Client, Project, Time Entry, Invoice en Invoice Line. Houd velden minimaal maar voeg rate_at_time toe op elke tijdregistratie en een invoiced_invoice_id-referentie zodat de factuurhistorie consistent blijft en dubbel factureren wordt voorkomen.
Sla het gebruikte tarief op het moment van het werk op in elke tijdregistratie (bijvoorbeeld rate_at_time). Standaardwaarden mogen op een project of persoon staan, maar facturen moeten altijd rekenen vanuit het opgeslagen tarief zodat oude facturen niet veranderen als tarieven later worden aangepast.
Kies één afrondingsregel en houd je eraan, en maak die zichtbaar in je proces. Een gebruikelijke aanpak is afronden per invoer naar 6-minuten stappen (0,1 uur) omdat dat makkelijk te auditen is en factuurtotalen voorspelbaar houdt.
Gebruik één statusveld op facturen en houd het strak: Draft, Ready, Sent, Paid (voeg Void alleen toe als je annuleringen nodig hebt). Stel duidelijke regels in zoals “roll-up alleen in Draft” en “lock totals in Ready” zodat mensen niet per ongeluk iets wijzigen dat al verzonden is.
Filter factuurcreatie om alleen tijdregistraties te halen waar invoiced_invoice_id leeg is, en zet dat veld zodra de entries aan een factuur gekoppeld worden. Verberg gefactureerde items ook uit de “klaar om te factureren”-weergave zodat dezelfde uren niet opnieuw geselecteerd kunnen worden.
Genereer de PDF vanuit de factuurrecord, niet vanuit ruwe tijdregistraties, zodat deze altijd overeenkomt met het factuurnummer, de totalen en de status. Voeg een duidelijk kopblok, klantgegevens, regels, totalen en betalingsinstructies toe en test met lange omschrijvingen en 30+ regels om layout-breuken te vinden.
Verwijder geen historie. Koppel de betreffende tijdregistraties los van de factuur (wis de factuurreferentie), genereer de factuurregels en totalen opnieuw en bewaar een korte correctienota zodat je later kunt uitleggen wat er veranderd is zonder de audittrail te verliezen.
Begin met handmatige tijdregistratie omdat het snel te bouwen is en makkelijk te corrigeren. Een timer voegt extra randgevallen toe (gemiste stops, bewerkingen, apparaatproblemen), dus voeg die pas toe nadat je kernworkflow betrouwbaar nauwkeurige facturen oplevert.
Bouw eerst de kernflow: tijdinvoer, goedkeuring/lock, factuurcreatie vanuit ongefactureerde tijd en PDF-generatie. Sla belastingen, multi-valuta, kortingen en bijlagen initieel over omdat ze randgevallen toevoegen die je vertragen en berekeningen gecompliceerd maken.


