CASE FILE 12/13CLASS: SAMPLE BUILDDATA: REALISTIC, NOT CLIENTTYPE: Websites & scripts

Sample build: realistic data, built to show how I'd handle this work. Not client work.

Sample buildWebsites & scripts

PHP booking form with server-side validation and invoicing

A PHP booking form that prices, invoices and refuses double bookings: 24/24 tests pass

Sample build · realistic data, built to show how I'd handle this work · not client work · every figure is computed from the files in the appendix

  • 24/24tests pass
  • 5PHP files
  • 243lines of PHP
  • 0double bookings allowed

01Summary

  1. A booking form in plain PHP (5 files, 243 lines) validates every field on the server.
  2. Each confirmed booking gets an invoice with net, 10% tax and a due date, and a slot can never be booked twice.
  3. 24 of 24 automated tests pass.

Each confirmed booking gets an invoice with net, 10% tax and a due date, and a slot can never be booked twice.

Key point, computed from the sample files

02The scenario

In this scenario bookings arrive by email, two people sometimes get the same slot, and invoices are typed up later.

Exhibit 1: Current-state process map: 4 manual steps across 3 roles
Current-state swimlaneCustomerOfficeCalendarPhones or emails1Checks the diary2Writes invoice3Double bookingpossible4

Source: sample files

03Issues in the data

Exhibit 2: Issues in the scenario, counted from the sample data
3services priced by hand
15ways a form submission can be wrong (tested)
1slot that two customers could take

Source: sample files

04How I approached it

  • A booking form for 3 services with server-side validation of every field (name, email, weekday date from tomorrow, half-hour slots, quantity, notes).
  • CSRF token and a hidden honeypot field against spam.
  • SQLite storage with a unique rule on service, date and time, so a slot can only be booked once.
  • Invoice numbering (INV-year-0001), 10% tax calculated in cents and a 14-day due date.
  • A test script with 24 tests.
Exhibit 3: Target design for the scenario
Future-state architectureFORMHTML formHoneypotPHPValidatorStore (unique slot)InvoiceOUTPUTConfirmationInvoice recordTESTS24 automated tests

Source: my design and the sample files

05How this applies to your business

  1. Assess and designMap the current process, size the gaps from your own data, agree the design and a written scope.
  2. Build and testBuild in your own tools with the checks built in, then run real cases end to end.
  3. Document and hand overSOPs, a walkthrough and a handover, so your team runs it without me.
Exhibit 4: Responsibilities (R responsible, A accountable, C consulted, I informed)
ActivityBusiness ownerSpecialist (me)Your team
Approve services and pricesACR
Build and testIRI
Host and maintainACR

Source: sample plan

06Controls and checks

Exhibit 5: Control framework: 4 checks, status read from the files
CheckWhat it catchesStatus
Form validation testsBad input reaching the booking15 of 15
Invoice testsWrong tax, totals or due dates5 of 5
Slot testsDouble bookings3 of 3
Sequence testDuplicate invoice numbers1 of 1

Source: sample files (Checks / Controls tab, test output or run log)

07What the files show

Exhibit 6: What the sample files show
  • 24/24tests pass
  • 5PHP files
  • 243lines of PHP
  • 0double bookings allowed

Source: sample files, measured by script. Sample data, not a client result.

  • tests/run_tests.php reports 24 of 24 tests passed (output included in the download).
  • Run locally with php -S and checked in a browser: invalid input, a confirmed booking and a refused second booking (screenshots below).
  • Impossible dates such as 31 November are rejected.

08Risks and how the build handles them

Exhibit 7: Risks and mitigations
RiskMitigation built in
Spam bookingsHoneypot field and validation
Double bookingDatabase rejects a duplicate slot
Price tampering or forged postsPrices are calculated on the server; CSRF token on the form

Source: sample design

09Appendix: files

A. Screenshots of the deliverable

Booking confirmed with invoice INV-2026-0001: line, net, 10% tax and total calculated server-side

Exhibit 8: Booking confirmed with invoice INV-2026-0001: line, net, 10% tax and total calculated server-side

Source: sample files

The same form after an invalid submission, with a message beside each field that failed validation

Exhibit 9: The same form after an invalid submission, with a message beside each field that failed validation

Source: sample files

A second booking for the same service, date and time is refused because the slot is already taken

Exhibit 10: A second booking for the same service, date and time is refused because the slot is already taken

Source: sample files

Exhibit 11: Code excerpt: Invoice.php, from line 10
    public static function fromBooking(array $b, int $seq, DateTimeImmutable $issued): array
    {
        $svc = Validator::SERVICES[$b['service']];
        $unitCents = (int)round($svc['price'] * 100);
        $netCents = $unitCents * (int)$b['qty'];
        $taxCents = (int)round($netCents * self::TAX_RATE);
        return [
            'number' => sprintf('INV-%s-%04d', $issued->format('Y'), $seq),
            'issued' => $issued->format('Y-m-d'),
            'due'    => $issued->modify('+14 days')->format('Y-m-d'),
            'customer' => $b['name'], 'email' => $b['email'],
            'lines'  => [[
                'desc' => $svc['label'] . ' on ' . $b['date'] . ' at ' . $b['time'],
                'qty' => (int)$b['qty'], 'unit' => $unitCents / 100, 'net' => $netCents / 100,
            ]],
            'net' => $netCents / 100, 'tax' => $taxCents / 100, 'gross' => ($netCents + $taxCents) / 100,
        ];
    }

Source: Invoice.php

B. Downloadable files

FileWhat it isSize
php-booking-invoice.zipFull source: public/, src/, tests/ (run with php -S)396.5 KB
test-output.txtTest run output1.2 KB
Validator.phpSource file2.5 KB
Invoice.phpSource file1.2 KB
Store.phpSource file1.5 KB

Sample build: realistic data, built to show how I'd handle this work. Names are placeholders and no client data is used.

Have a similar problem in your business?

Hire me on Upwork (opens in a new tab)