E-Ticket TNKS: Reviewing a Mountaineering Booking from Route Selection to Check-out
A technical review of the Laravel 11 e-ticketing system for Kerinci Seblat National Park, covering gate capacity, group records, payments, tickets, and its mobile API.
A mountaineering booking is not an online-store checkout. The system must know who enters the park, when the group returns, which gates they use, whether capacity remains, and whom to contact when plans change. E-Ticket TNKS carries that information through one workflow, from reservation to ticket and on-site status.
I reviewed the struktur3 branch at commit 8226ff4, including its web and API routes, controllers, models, migrations, and four supplied screenshots. The captured site still warns that it is under development and that data will be reset at launch. This review covers a work in progress, not a finished service with every issue resolved.
The Home page puts field conditions first
The landing page does more than sell a photograph of Mount Kerinci. Beside the booking action, it shows the number of hikers currently in the area, the weather, and the mountain status. A destination gallery follows, then a breakdown of Indonesian and international visitors. The order works: prospective hikers see that field conditions can affect the trip before choosing a package.
Blade and Bootstrap 5 produce the server-rendered interface. HomepageController gathers destinations, hiker statistics, and weather data before returning the view. The result is easy to follow, although some CSS still lives directly in Blade files and will become harder to maintain as the public site grows.
Booking is built as a sequence of decisions
Users choose a destination and package, then set the dates, Indonesian and international visitor counts, and entry and exit gates. After sign-in, the group leader needs a verified profile and must be at least 17. The system rejects past dates, reversed ranges, bookings more than a month ahead, undersized groups, and schedule conflicts for individual hikers.
After accepting the terms, each group member is linked to a verified profile. Hikers under 17 must attach parental permission before continuing. The form also records emergency numbers and carried equipment, calculates the charge per hiker, and moves the booking to payment inside a database transaction.
| Area | Rule visible in the code |
|---|---|
| Ownership | API booking queries are always scoped to the signed-in user |
| Group leader | Verified profile and a minimum age of 17 |
| Schedule | No past dates, valid date order, and no more than one month ahead |
| Group | The package minimum and gate requirements must be met |
| Capacity | Paid bookings count against each entry date and gate |
| Members | No duplicates or overlapping bookings for the same hiker |
| Payment | An administrator verifies QRIS or bank-transfer evidence before issuing a ticket |
A booking moves through approval, form completion, payment, hike confirmation, check-in, check-out, and completion. An approved payment creates a ticket code and triggers an invoice email. The administrator's scanner finds that code and opens the correct booking record.
Administrators handle the work after a ticket is booked
The admin panel manages destinations, photographs, gates, packages and prices, bookings, payment evidence, visitor profiles, administrator accounts, roles, permissions, calendars, logs, and revenue and visitor reports. Each route checks roles and permissions instead of relying on one admin flag for the entire menu.
- Operators can prioritize bookings that are waiting for payment verification.
- Payments are accepted or rejected manually; the result changes the booking status and is sent by email.
- A ticket code takes field staff to the relevant group details.
- Revenue and visitor reports can be downloaded from permission-protected areas.
The same repository provides an API for a mobile app. Laravel Sanctum protects profiles and bookings, while public endpoints expose destinations, packages, tickets, events, gates, and capacity. Google sign-in and email verification are also available. Sharing one data model across web and mobile is sensible, but duplicating rules across two controllers is already becoming expensive.
What already works well
The project's strength is its grasp of the domain. Bookings use UUIDs, group members have separate records, tickets distinguish Indonesian and international visitors, gates store daily limits, and hike status is separate from payment status. Several form operations run inside database transactions, while API queries ensure users can only read their own bookings.
The strongest work in this repository is not the Hero page. Its value appears when field rules become data, validation, and statuses that staff can use.
Technical debt that should not climb with the hikers
The web booking controller has reached 817 lines, and the API version adds another 475. Both calculate capacity, find scheduling conflicts, manage hikers, and process payments through similar paths. Duplicate rules are manageable while the feature set is small. Once a limit changes on the web and is missed in the API, users get two behaviors for the same booking.
- The gk_bookings migration links id_tiket to gk_tiket_pendakis, while the model, validation, and controller treat it as a gk_paket_tikets ID. The foreign key and application relation should agree before new migrations run elsewhere.
- The capacity check reads bookings first, then creates a draft in a transaction without locking the gate quota. Two concurrent requests can still see the same remaining places.
- MidtransController stores sandbox credentials in source and does not appear connected to an active route. Move those credentials to the environment before reusing the adapter.
- LoggerMiddleware stores almost every request field except the password. Booking forms contain personal data and files, so logging needs an allowlist and sensitive-value redaction.
- The two available tests are still framework examples. Capacity calculations, status transitions, booking ownership, payments, and schedule conflicts have no regression coverage.
- The README is six lines long. Running the app, preparing the database, choosing a branch, and configuring weather, email, OAuth, storage, and payments still depend on team knowledge.
I would start with a BookingService shared by web and API, explicit status enums, and tests for quotas and payments. Blade cleanup, page-level style extraction, and mobile integration can follow. The order matters: a destination-card bug hurts presentation, while a quota bug can admit a group that should have been rejected.
Final assessment
E-Ticket TNKS handles much more than the four screenshots reveal. Destination selection is only the front door. Behind it sit hiker identities, age rules, gate capacity, nationality-based pricing, parental permission, payment evidence, email, ticket codes, and the sequence of field operations.
I would preserve that operational model and pause new public features for now. Unify the booking rules, lock capacity calculations, repair the database relation, redact logs, and write tests that follow a hiker from draft to completion. Once that foundation is stable, the web and mobile apps can grow without drifting apart.
Read next
Articles sharing this post's topics, followed by the latest entries.
Reader notes
Comments
Checking your session...



Loading reader comments...