app/Http/Resources/* transformers and the shared Support/ApiResponse helper for consistent envelopes.app/ tree is partitioned by bounded context instead of technical type at the top level:| Module | Models | Controllers | Services |
|---|---|---|---|
| Account | User, Role, UserPoint | Auth, AdminUser | UserService |
| Catalog | Country, Region, Destination, Hotel, Flight, Restaurant, Attraction, Category | public + Admin CRUD pairs | per-entity services + Fixtures + AiAttraction |
| Trips | Trip, ItineraryItem, TripDestination, Review, Favourite, AiGeneration, BudgetSnapshot, TripContribution | Trip, AI, Map, Interaction, admin variants | TripService, ForkService, AttachService, ReviewService, AiUsage |
| Commerce | Order, OrderItem, Payment, Plan, Subscription, Address, AgencyAssignment | Checkout, Paymob, Plan, Agency, Analytics | CheckoutService, PaymobGateway/Client, WebhookService, PriceCalculator, strategies |
| Chat | Conversation, Message | ConversationController | — (policy-guarded) |
| System | Setting, Flag, Survey, ContactMessage, NewsletterSubscriber, Notification, Report, PasswordResetToken | Weather, Report, Settings, Survey, Contact, Flags, Dashboard | GenerateReportService (+Excel), OpenMeteo, Newsletter, Survey, Flag |
app/Interfaces/<Module>/ (e.g. PaymentGatewayInterface) and are bound to implementations in AppServiceProvider.app/Repositories/<Module>/ encapsulate Eloquent queries so services stay persistence-agnostic.FormRequest, delegate to one service, return a Resource.InvalidStateTransitionException) funnel through a custom ApiExceptionHandler for uniform error payloads.CheckoutType enum drives factory selection; each strategy builds order lines and pricing before delegating to the single payment gateway. Adding a purchasable product type = one new strategy class.| Event | Listener(s) | Effects |
|---|---|---|
PaymentSucceeded | FulfillOrderListener | mark order paid, fire mail + notification, subscription activation |
PaymentFailed | HandlePaymentFailed | failure mails/notifications, state rollback |
MessageSent | conversation notifications | chat unread counts |
Commerce agency events (AgencyAssignment*) | admin/user notifications | marketplace workflow |
TripBookedMail, WelcomeMail, SubscriptionActivatedMail, …) and database notifications (app/Notifications) keep user-facing messaging decoupled from controllers. Long-running work (report PDF/XLSX generation, destination geocoding) runs on queued jobs: GenerateReportJob, GeocodeDestinationJob.auth:api) + optional verified email gate and custom EnsureUserIsActive middleware.permission:manage hotels, role:admin|super_admin, etc. Permissions are seeded by RoleAndPermissionSeeder; policies exist for fine-grained cases (TripPolicy, ConversationPolicy, FlagPolicy, AgencyAssignmentPolicy).super_admin, admin, user, agency (agency marketplace endpoints under /agency/*).