Gå til hovedindhold
Hjem
GrN.dk

Main navigation

  • Artikler
  • Cases
  • Ydelser
  • Din digitale projektleder
  • Om Greg Nowak
  • Billedgalleri
  • Kontakt
User account menu
  • Log ind

Bliv en del af mit community / gratis nyhedsbrev — tilmeld dig her

Brødkrumme

  1. Hjem
  2. Cases

Bordbooking med betaling til et kontorfællesskab

Client
Dansk kontorfællesskab — kundebrief, bygget som fungerende demo
Sector
Kontorfællesskaber og delekontorer
Periode
juli 2026

At a glance

Et dansk kontorfællesskab ville lade medlemmerne booke et bord pr. time og betale for det — for ved 20 kr. i timen pr. bord er en booking, der ikke er betalt, ikke en booking. tableflow.grn.dk er det system, bygget efter kundens brief og kørende live: et timegitter, der viser, hvad der faktisk er ledigt, en betalingsreservation på femten minutter, der frigiver sig selv, og en admin-skærm til dem, der driver stedet. Ren PHP og MariaDB — intet framework, ingen dependencies, 853 linjer i syv filer.

853 linjer i 7 filer — intet framework, ingen dependencies
20 kr. i timen pr. bord — prisen beregnes live, mens du vælger timerne
15 minutters betalingsreservation, der frigiver sig selv — intet cronjob

The challenge

Briefen var kort og usædvanligt klar: PHP og en MySQL-database; vælg en dato, et bord og et fra/til-tidspunkt; kun hele timer og kun inden for åbningstiden; registrér navn, e-mail og telefon; 20 kr. i timen pr. bord — og bordet er først reserveret, når der er betalt. Responsivt, fungerer godt på en telefon. Funktionelt.

Netop den sætning om betaling er det, der forvandler en bookingformular til et lille concurrency-problem. Tiden skal holdes, mens den besøgende betaler, men ikke holdes for evigt, hvis vedkommende forsvinder. To personer, der klikker på den samme time i det samme sekund, må ikke begge gå derfra i den tro, at de har den. Og en udløbet, ubetalt reservation skal frigive sig selv — ingen i et kontorfællesskab kommer til at huske at rydde bordet manuelt.

The solution

TableFlow er en bevidst lille PHP 8.3-applikation på MariaDB, der taler med databasen gennem PDO med prepared statements. Intet framework, ingen Composer, intet build-step: 853 linjer fordelt på syv filer — fire sider, et fælles bibliotek, ét stylesheet og en konfigurationsfil, der ligger uden for web-roden.

Booking. Når man vælger en dato og et bord, gentegnes et timegitter, hvor hver time enten er ledig eller streget over som optaget. Et klik på en ledig time sætter starten, et klik på en senere time udvider intervallet — kun hen over sammenhængende ledige timer — og prisen genberegnes undervejs; og så genberegnes den igen på serveren, for browseren er en bekvemmelighed og aldrig autoriteten. Åbningstiderne er en konfigurationstabel (man-fre 08-20, lør 09-16, søndag lukket), lukkedage siger det i stedet for at tilbyde tider, og timer, der allerede er passeret i dag, kan ikke bookes.

Reservationen — uden cronjob. »Denne tid er blokeret« er defineret ét sted, som én SQL-betingelse: reservationen er betalt, eller den er oprettet inden for de seneste femten minutter. Gitteret, bookingtjekket og betalingstrinnet genbruger alle den ene definition, så en ubetalt reservation simpelthen holder op med at blokere, når den bliver for gammel. Intet skal køre efter en tidsplan, og der er intet oprydningsjob, der kan fejle i stilhed.

Ingen dobbeltbooking. Indsættelsen kører i en transaktion, der først selecter de overlappende reservationer FOR UPDATE. To samtidige bookinger af samme time serialiseres mod hinanden, og den, der taber, får at vide, at tiden lige er blevet taget — i stedet for at få en fantomreservation i hånden. Betalingstrinnet gentager tjekket, i tilfælde af at reservationen udløb, mens den besøgende betalte, og en anden tog tiden i mellemtiden.

Betaling og kvittering. Betalingssiden nås via et tilfældigt token på 32 tegn, så en reservation kun er synlig for den, der lavede den. Selve knappen er en ærlig simulation, markeret i brugerfladen som det sted, hvor MobilePay eller en kortgateway kobles på; en betaling skifter reservationen til Betalt, stempler tidspunktet og forvandler siden til en kvittering.

Admin. En adgangskodebeskyttet skærm viser kommende reservationer (eller dem alle) og lader den, der driver stedet, markere en booking som betalt — for eksempel ved kontant betaling — markere den som ubetalt igen eller slette den. Ubetalte reservationer ud over fristen markeres Udløbet: tiden er ledig igen, men den kan stadig afregnes manuelt, hvis ingen andre har taget den.

Alt det andet. Hver POST bærer et CSRF-token, bookingformularen har en honeypot til bots, og dato, tidsinterval, navn, e-mail og telefon valideres alt sammen på serveren. Brugerfladen er dansk, mobile-first og følger den besøgendes lyse eller mørke systemindstilling.

Leverancen omfattede hostingen: sin egen virtual host under en dedikeret tableflow-systembruger, sit eget git-repository, en databasebruger afgrænset til netop denne applikation, credentials i en fil, web-roden ikke kan servere, et Let's Encrypt-certifikat og en HTTP-til-HTTPS-redirect, bag Cloudflare.

The results

Systemet har været live på tableflow.grn.dk siden 23. juli 2026 og blev verificeret hele vejen igennem før overdragelsen: en booking helt til betaling, en afvist dobbeltbooking, admin-handlingerne og værnet mod lukkedage.

At det fylder 853 linjer uden dependencies er pointen, ikke praleri. Der er intet framework at opgradere, intet plugin-træ at auditere og intet build, der kan knække en tilfældig tirsdag — koden, der kører, er koden, der blev skrevet, og en ændring af åbningstider eller timepris er én linje i en konfigurationsfil.

Det er en demo, og det siger den selv: betalingsknappen simulerer en transaktion, og admin-adgangskoden står trykt på dens egen login-skærm. At gøre det til et produktionssystem for et konkret kontorfællesskab er en afgrænset opgave — en rigtig betalingsgateway, rigtige admin-konti, prøvedata ryddet — ikke en omskrivning.

»Man har først reserveret bordet, når man har betalt.«

Kundebriefen, der bestilte løsningen

Got a project that needs the same kind of hands-on delivery?

Your digital project manager

Anmeld Greg på Google

Greg Nowak Google-anmeldelser

 

Skriftlige anbefalinger fra Trafik og Veje, Aarhus Kommune (2011) og AgroTech (2010) — læs dem på LinkedIn.

Illustreret infografik, der opsummerer: Hvad spørger kunderne om? Lad AI læse mønstrene i supporten
Hvad spørger kunderne om? Lad AI læse mønstrene i supporten
2026-09-04

AI-baseret ticketanalyse kan afsløre gentagne klager, produktfejl og huller i dokumentationen – uden at virksomheden behøver endnu en chatbot.

Illustreret infografik, der opsummerer: OpenSSH 10 ændrer kryptografien: Derfor skal ældre SFTP-integrationer have en oprydningsplan
OpenSSH 10 ændrer kryptografien: Derfor skal ældre SFTP-integrationer have en oprydningsplan
2026-09-02

OpenSSH 10 fjerner DSA og advarer om nøgleudveksling, der ikke er post-kvantesikker. Her får du en metode til at afgrænse SFTP-oprydningen uden at svække alle SSH-forbindelser.

Illustreret infografik, der opsummerer: Bottrafik overstiger nu menneskelig trafik – og crawlerregler er ikke længere valgfrie
Bottrafik overstiger nu menneskelig trafik – og crawlerregler er ikke længere valgfrie
2026-09-01

Botforespørgsler overstiger nu menneskelig webtrafik. Lær at auditere AI-crawlere, fastsætte regler på stiniveau, håndhæve robots.txt og måle det forretningsmæssige afkast.

Illustreret infografik, der opsummerer: Cloudflare Tunnel i 2026: Bedre overblik, sværere spørgsmål
Cloudflare Tunnel i 2026: Bedre overblik, sværere spørgsmål
2026-09-01

Cloudflares Tunnel-opdateringer fra 2026 forbedrer kortlægning, overvågning af replikaer, logstreaming og overdragelse – men synliggør samtidig svagt ejerskab og mangelfuld praksis for failover og logging.

Illustreret infografik, der opsummerer: Fra salgsmøde til CRM: Automatisér opfølgningen uden datarod
Fra salgsmøde til CRM: Automatisér opfølgningen uden datarod
2026-09-01

Sådan bruger du AI til mødenoter og opfølgning, mens faste regler beskytter CRM-data, kundematch og pipeline mod fejl og forhastede ændringer.

Illustreret infografik, der opsummerer: Drupal 10 udfases i december 2026: Begynd med at kortlægge opgraderingen
Drupal 10 udfases i december 2026: Begynd med at kortlægge opgraderingen
2026-08-31

Drupal 10 når end of life den 9. december 2026. Brug denne praktiske kortlægning til at afgrænse arbejdet med Drupal 11-parathed, Composer-efterslæb, moduler og custom code.

Illustreret infografik, der opsummerer: Apache 2.4.67 satte ældre reverse proxies tilbage på risikolisten
Apache 2.4.67 satte ældre reverse proxies tilbage på risikolisten
2026-08-31

Apache 2.4.67 tydeliggjorde risikoen ved overtagne reverse proxies. Læs, hvordan du opgraderer til 2.4.68, gennemgår HTTP/2, AJP og .htaccess og tester ændringerne sikkert.

Illustreret infografik, der opsummerer: WooCommerce Checkout Blocks: Hvornår bør du migrere – og hvornår bør du rulle tilbage?
WooCommerce Checkout Blocks: Hvornår bør du migrere – og hvornår bør du rulle tilbage?
2026-08-30

WooCommerce-blokke er standarden, men ikke alle webshops er klar. Brug denne praktiske gennemgang, testplan og rollback-procedure til at beskytte omsætningen i checkout.

Illustreret infografik, der opsummerer: Cloudflare Service Keys: Gennemgå ældre automatisering inden 30. september
Cloudflare Service Keys: Gennemgå ældre automatisering inden 30. september
2026-08-30

Cloudflare Service Keys holder op med at virke den 30. september 2026. Find ældre scripts, vælg API-tokens med afgrænsede rettigheder, test overgangen, og dokumentér ejerskabet.

Illustreret infografik, der opsummerer: Password-hashing i WordPress 6.8: Den skjulte risiko ved ældre loginintegrationer
Password-hashing i WordPress 6.8: Den skjulte risiko ved ældre loginintegrationer
2026-08-29

WordPress 6.8 ændrede hashing af adgangskoder og tokens. Se, hvor ældre loginintegrationer fejler, hvad du bør gennemgå, og hvordan du tester autentificering sikkert.

Flere artikler
RSS feed

Footer

  • Alle artikler
  • Kontakt

GrN.dk — AI-automatisering, webplatforme, weboptimering, datahåndtering og logistik.

© 2026 GrN.dk · LinkedIn · Kontakt · AI-automatisering på dansk: nowa.dk

Bag GrN.dk: Individual Entrepreneur Codecrafter · Tax ID 305669096 · Bakhtrioni St. 22, 0194 Tbilisi, Georgien · officielt virksomhedsregister