diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c8a642e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.claude/ +.mcp.json +TODO.md +*.min.css +*.min.js +vendor/ +node_modules/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e8b6077 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,19 @@ + + +# Changelog + +## [Unreleased] + +### Added +- **Repository** -- initial scaffold +- **System Plugin** -- Extension class, service provider +- **SQL Schema** -- 8 tables: locations, services, staff, schedules, availability_overrides, bookings, booking_services, waitlist +- **Admin Component** -- 6 views: dashboard, bookings, services, staff, schedules, locations +- **Webservices Plugin** -- 7 API routes +- **Configuration** -- plugin settings across 4 fieldsets +- **Access Control** -- granular permissions \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..c3d59f0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,30 @@ +# MokoSuitebooking + +Appointment and resource booking for service businesses for Joomla 6. + +## Quick Reference + +| Field | Value | +|---|---| +| **Package** | `pkg_mokosuitebooking` | +| **Layer** | 2 (requires: Client, CRM) | +| **Language** | PHP 8.3+ | +| **Branch** | develop on `dev`, merge to `main` (protected) | + +## Architecture + +Joomla **package** -- Layer 2 add-on. CRM contacts as clients, service catalog with staff scheduling and online booking. + +## Rules + +- **Never commit** `.claude/`, `.mcp.json`, `TODO.md`, `*.min.css`/`*.min.js` +- **Attribution**: `Authored-by: Moko Consulting` +- **Workflow directory**: `.mokogitea/` +- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoCLI/wiki) +- **Changelog**: `[Unreleased]` only -- release system assigns versions + +## Coding Standards + +- PHP 8.3+ / Joomla 6 patterns +- `$this->getDatabase()` in models, `Factory::getContainer()->get(DatabaseInterface::class)` in helpers +- `Factory::getApplication()->getIdentity()` for user \ No newline at end of file diff --git a/README.md b/README.md index 15091a1..73b9b27 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,45 @@ -# MokoSuiteBooking + -MokoSuite Booking — appointment and resource booking for service businesses on Joomla 6 \ No newline at end of file +# MokoSuite booking + +Appointment and resource booking for service businesses for MokoSuite on Joomla 6. + +## Overview + +MokoSuitebooking is a **Layer 2** extension in the MokoSuite platform, building on MokoSuiteClient (Layer 0) and MokoSuiteCRM (Layer 1). + +## Features + +- **Service Catalog** -- services with duration, pricing, staff assignment +- **Online Booking** -- real-time availability with booking widget +- **Staff Scheduling** -- recurring availability patterns with overrides +- **Multi-Location** -- support for multiple business locations +- **Walk-In Queue** -- walk-in queue management +- **Client History** -- CRM contact-linked visit frequency and spend tracking +- **Waitlist** -- automated notification when slots open +- **REST API** -- full CRUD for services, staff, bookings, schedules, locations +- **Access Control** -- granular permissions + +## Requirements + +- Joomla 6.x +- PHP 8.3+ +- MokoSuiteClient (Layer 0) +- MokoSuiteCRM (Layer 1) + +## Installation + +Install via Joomla Extension Manager using the package file `pkg_mokosuitebooking.zip`. + +## License + +GNU General Public License v3.0 or later. + +## Links + +- [Documentation](https://git.mokoconsulting.tech/MokoConsulting/MokoSuitebooking/wiki) +- [Issues](https://git.mokoconsulting.tech/MokoConsulting/MokoSuitebooking/issues) +- [MokoSuite Platform](https://mokoconsulting.tech) \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/access.xml b/source/packages/com_mokosuitebooking/admin/access.xml new file mode 100644 index 0000000..3b7b618 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/access.xml @@ -0,0 +1,17 @@ + + +
+ + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/config.xml b/source/packages/com_mokosuitebooking/admin/config.xml new file mode 100644 index 0000000..4cf87ad --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/config.xml @@ -0,0 +1,6 @@ + + +
+ +
+
\ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/language/en-GB/com_mokosuitebooking.ini b/source/packages/com_mokosuitebooking/admin/language/en-GB/com_mokosuitebooking.ini new file mode 100644 index 0000000..13443bb --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/language/en-GB/com_mokosuitebooking.ini @@ -0,0 +1,9 @@ +; Copyright (C) 2026 Moko Consulting +; SPDX-License-Identifier: GPL-3.0-or-later +COM_MOKOSUITEBOOKING="MokoSuite Booking" +COM_MOKOSUITEBOOKING_DASHBOARD="Dashboard" +COM_MOKOSUITEBOOKING_BOOKINGS="Bookings" +COM_MOKOSUITEBOOKING_SERVICES="Services" +COM_MOKOSUITEBOOKING_STAFF="Staff" +COM_MOKOSUITEBOOKING_SCHEDULES="Schedules" +COM_MOKOSUITEBOOKING_LOCATIONS="Locations" diff --git a/source/packages/com_mokosuitebooking/admin/language/en-GB/com_mokosuitebooking.sys.ini b/source/packages/com_mokosuitebooking/admin/language/en-GB/com_mokosuitebooking.sys.ini new file mode 100644 index 0000000..8efe74e --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/language/en-GB/com_mokosuitebooking.sys.ini @@ -0,0 +1,4 @@ +; Copyright (C) 2026 Moko Consulting +; SPDX-License-Identifier: GPL-3.0-or-later +COM_MOKOSUITEBOOKING="MokoSuite Booking" +COM_MOKOSUITEBOOKING_XML_DESCRIPTION="Appointment and resource booking" diff --git a/source/packages/com_mokosuitebooking/admin/services/provider.php b/source/packages/com_mokosuitebooking/admin/services/provider.php new file mode 100644 index 0000000..cc30d87 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/services/provider.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Extension\ComponentInterface; +use Joomla\CMS\Extension\MVCComponent; +use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface; +use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\CMS\Component\Router\RouterFactoryInterface; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; + +return new class implements ServiceProviderInterface { + public function register(Container $container): void { + $container->set(ComponentInterface::class, function (Container $container) { + $c = new MVCComponent($container->get(ComponentDispatcherFactoryInterface::class)); + $c->setMVCFactory($container->get(MVCFactoryInterface::class)); + $c->setRouterFactory($container->get(RouterFactoryInterface::class)); + return $c; + }); + } +}; \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/src/Controller/DisplayController.php b/source/packages/com_mokosuitebooking/admin/src/Controller/DisplayController.php new file mode 100644 index 0000000..e5303c7 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/src/Controller/DisplayController.php @@ -0,0 +1,18 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Component\MokoSuiteBooking\Administrator\Controller; + +defined('_JEXEC') or die; + +use Joomla\CMS\MVC\Controller\BaseController; + +class DisplayController extends BaseController +{ + protected $default_view = 'bookingdashboard'; +} \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/src/Model/BookingDashboardModel.php b/source/packages/com_mokosuitebooking/admin/src/Model/BookingDashboardModel.php new file mode 100644 index 0000000..09dcebf --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/src/Model/BookingDashboardModel.php @@ -0,0 +1,17 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Component\MokoSuiteBooking\Administrator\Model; + +defined('_JEXEC') or die; + +use Joomla\CMS\MVC\Model\BaseDatabaseModel; + +class BookingDashboardModel extends BaseDatabaseModel +{ +} \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/src/View/BookingBookings/HtmlView.php b/source/packages/com_mokosuitebooking/admin/src/View/BookingBookings/HtmlView.php new file mode 100644 index 0000000..4839094 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/src/View/BookingBookings/HtmlView.php @@ -0,0 +1,23 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Component\MokoSuiteBooking\Administrator\View\BookingBookings; + +defined('_JEXEC') or die; + +use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\Toolbar\ToolbarHelper; + +class HtmlView extends BaseHtmlView +{ + public function display($tpl = null): void + { + ToolbarHelper::title('MokoSuite Booking - Bookings'); + parent::display($tpl); + } +} \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/src/View/BookingDashboard/HtmlView.php b/source/packages/com_mokosuitebooking/admin/src/View/BookingDashboard/HtmlView.php new file mode 100644 index 0000000..fc55501 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/src/View/BookingDashboard/HtmlView.php @@ -0,0 +1,23 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Component\MokoSuiteBooking\Administrator\View\BookingDashboard; + +defined('_JEXEC') or die; + +use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\Toolbar\ToolbarHelper; + +class HtmlView extends BaseHtmlView +{ + public function display($tpl = null): void + { + ToolbarHelper::title('MokoSuite Booking - Dashboard'); + parent::display($tpl); + } +} \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/src/View/BookingLocations/HtmlView.php b/source/packages/com_mokosuitebooking/admin/src/View/BookingLocations/HtmlView.php new file mode 100644 index 0000000..f24cca7 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/src/View/BookingLocations/HtmlView.php @@ -0,0 +1,23 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Component\MokoSuiteBooking\Administrator\View\BookingLocations; + +defined('_JEXEC') or die; + +use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\Toolbar\ToolbarHelper; + +class HtmlView extends BaseHtmlView +{ + public function display($tpl = null): void + { + ToolbarHelper::title('MokoSuite Booking - Locations'); + parent::display($tpl); + } +} \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/src/View/BookingSchedules/HtmlView.php b/source/packages/com_mokosuitebooking/admin/src/View/BookingSchedules/HtmlView.php new file mode 100644 index 0000000..fdf500f --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/src/View/BookingSchedules/HtmlView.php @@ -0,0 +1,23 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Component\MokoSuiteBooking\Administrator\View\BookingSchedules; + +defined('_JEXEC') or die; + +use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\Toolbar\ToolbarHelper; + +class HtmlView extends BaseHtmlView +{ + public function display($tpl = null): void + { + ToolbarHelper::title('MokoSuite Booking - Schedules'); + parent::display($tpl); + } +} \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/src/View/BookingServices/HtmlView.php b/source/packages/com_mokosuitebooking/admin/src/View/BookingServices/HtmlView.php new file mode 100644 index 0000000..1e28e08 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/src/View/BookingServices/HtmlView.php @@ -0,0 +1,23 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Component\MokoSuiteBooking\Administrator\View\BookingServices; + +defined('_JEXEC') or die; + +use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\Toolbar\ToolbarHelper; + +class HtmlView extends BaseHtmlView +{ + public function display($tpl = null): void + { + ToolbarHelper::title('MokoSuite Booking - Services'); + parent::display($tpl); + } +} \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/src/View/BookingStaff/HtmlView.php b/source/packages/com_mokosuitebooking/admin/src/View/BookingStaff/HtmlView.php new file mode 100644 index 0000000..5c9ed61 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/src/View/BookingStaff/HtmlView.php @@ -0,0 +1,23 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Component\MokoSuiteBooking\Administrator\View\BookingStaff; + +defined('_JEXEC') or die; + +use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\Toolbar\ToolbarHelper; + +class HtmlView extends BaseHtmlView +{ + public function display($tpl = null): void + { + ToolbarHelper::title('MokoSuite Booking - Staff'); + parent::display($tpl); + } +} \ No newline at end of file diff --git a/source/packages/com_mokosuitebooking/admin/tmpl/bookingbookings/default.php b/source/packages/com_mokosuitebooking/admin/tmpl/bookingbookings/default.php new file mode 100644 index 0000000..1db369e --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/tmpl/bookingbookings/default.php @@ -0,0 +1,11 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + */ +defined('_JEXEC') or die; +?> +
+

Bookings

+

Coming soon.

+
diff --git a/source/packages/com_mokosuitebooking/admin/tmpl/bookingdashboard/default.php b/source/packages/com_mokosuitebooking/admin/tmpl/bookingdashboard/default.php new file mode 100644 index 0000000..a69f273 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/tmpl/bookingdashboard/default.php @@ -0,0 +1,11 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + */ +defined('_JEXEC') or die; +?> +
+

Dashboard

+

Coming soon.

+
diff --git a/source/packages/com_mokosuitebooking/admin/tmpl/bookinglocations/default.php b/source/packages/com_mokosuitebooking/admin/tmpl/bookinglocations/default.php new file mode 100644 index 0000000..070f7c4 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/tmpl/bookinglocations/default.php @@ -0,0 +1,11 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + */ +defined('_JEXEC') or die; +?> +
+

Locations

+

Coming soon.

+
diff --git a/source/packages/com_mokosuitebooking/admin/tmpl/bookingschedules/default.php b/source/packages/com_mokosuitebooking/admin/tmpl/bookingschedules/default.php new file mode 100644 index 0000000..5c6526d --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/tmpl/bookingschedules/default.php @@ -0,0 +1,11 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + */ +defined('_JEXEC') or die; +?> +
+

Schedules

+

Coming soon.

+
diff --git a/source/packages/com_mokosuitebooking/admin/tmpl/bookingservices/default.php b/source/packages/com_mokosuitebooking/admin/tmpl/bookingservices/default.php new file mode 100644 index 0000000..9ae829b --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/tmpl/bookingservices/default.php @@ -0,0 +1,11 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + */ +defined('_JEXEC') or die; +?> +
+

Services

+

Coming soon.

+
diff --git a/source/packages/com_mokosuitebooking/admin/tmpl/bookingstaff/default.php b/source/packages/com_mokosuitebooking/admin/tmpl/bookingstaff/default.php new file mode 100644 index 0000000..2ca1ab2 --- /dev/null +++ b/source/packages/com_mokosuitebooking/admin/tmpl/bookingstaff/default.php @@ -0,0 +1,11 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + */ +defined('_JEXEC') or die; +?> +
+

Staff

+

Coming soon.

+
diff --git a/source/packages/com_mokosuitebooking/mokosuitebooking.xml b/source/packages/com_mokosuitebooking/mokosuitebooking.xml new file mode 100644 index 0000000..859c553 --- /dev/null +++ b/source/packages/com_mokosuitebooking/mokosuitebooking.xml @@ -0,0 +1,36 @@ + + + MokoSuite Booking + Moko Consulting + hello@mokoconsulting.tech + https://mokoconsulting.tech + 2026-06-27 + Copyright (C) 2026 Moko Consulting. + GPL-3.0-or-later + 06.00.00 + Appointment and resource booking + Moko\Component\MokoSuiteBooking + + + access.xml + config.xml + language + services + src + tmpl + + + en-GB/com_mokosuitebooking.ini + en-GB/com_mokosuitebooking.sys.ini + + COM_MOKOSUITEBOOKING + + COM_MOKOSUITEBOOKING_DASHBOARD + COM_MOKOSUITEBOOKING_BOOKINGS + COM_MOKOSUITEBOOKING_SERVICES + COM_MOKOSUITEBOOKING_STAFF + COM_MOKOSUITEBOOKING_SCHEDULES + COM_MOKOSUITEBOOKING_LOCATIONS + + + \ No newline at end of file diff --git a/source/packages/plg_system_mokosuitebooking/language/en-GB/plg_system_mokosuitebooking.ini b/source/packages/plg_system_mokosuitebooking/language/en-GB/plg_system_mokosuitebooking.ini new file mode 100644 index 0000000..764b0bb --- /dev/null +++ b/source/packages/plg_system_mokosuitebooking/language/en-GB/plg_system_mokosuitebooking.ini @@ -0,0 +1,4 @@ +; Copyright (C) 2026 Moko Consulting +; SPDX-License-Identifier: GPL-3.0-or-later +PLG_SYSTEM_MOKOSUITEBOOKING="System - MokoSuite Booking" +PLG_SYSTEM_MOKOSUITEBOOKING_DESC="Appointment booking helpers and schema" diff --git a/source/packages/plg_system_mokosuitebooking/language/en-GB/plg_system_mokosuitebooking.sys.ini b/source/packages/plg_system_mokosuitebooking/language/en-GB/plg_system_mokosuitebooking.sys.ini new file mode 100644 index 0000000..764b0bb --- /dev/null +++ b/source/packages/plg_system_mokosuitebooking/language/en-GB/plg_system_mokosuitebooking.sys.ini @@ -0,0 +1,4 @@ +; Copyright (C) 2026 Moko Consulting +; SPDX-License-Identifier: GPL-3.0-or-later +PLG_SYSTEM_MOKOSUITEBOOKING="System - MokoSuite Booking" +PLG_SYSTEM_MOKOSUITEBOOKING_DESC="Appointment booking helpers and schema" diff --git a/source/packages/plg_system_mokosuitebooking/mokosuitebooking.xml b/source/packages/plg_system_mokosuitebooking/mokosuitebooking.xml new file mode 100644 index 0000000..dd0be81 --- /dev/null +++ b/source/packages/plg_system_mokosuitebooking/mokosuitebooking.xml @@ -0,0 +1,59 @@ + + + System - MokoSuite Booking + mokosuitebooking + Moko Consulting + 2026-06-27 + Copyright (C) 2026 Moko Consulting. All rights reserved. + GPL-3.0-or-later + hello@mokoconsulting.tech + https://mokoconsulting.tech + 06.00.00 + 8.3 + PLG_SYSTEM_MOKOSUITEBOOKING_DESC + Moko\Plugin\System\MokoSuiteBooking + + src + services + language + sql + + + en-GB/plg_system_mokosuitebooking.ini + en-GB/plg_system_mokosuitebooking.sys.ini + + sql/install.mysql.sql + sql/uninstall.mysql.sql + + +
+ + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + +
+
+
+
\ No newline at end of file diff --git a/source/packages/plg_system_mokosuitebooking/services/provider.php b/source/packages/plg_system_mokosuitebooking/services/provider.php new file mode 100644 index 0000000..f210625 --- /dev/null +++ b/source/packages/plg_system_mokosuitebooking/services/provider.php @@ -0,0 +1,27 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Extension\PluginInterface; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; +use Moko\Plugin\System\MokoSuiteBooking\Extension\Booking; + +return new class implements ServiceProviderInterface { + public function register(Container $container): void { + $container->set(PluginInterface::class, function (Container $container) { + $dispatcher = $container->get(DispatcherInterface::class); + $plugin = new Booking($dispatcher, (array) PluginHelper::getPlugin('system', 'mokosuitebooking')); + $plugin->setApplication(\Joomla\CMS\Factory::getApplication()); + return $plugin; + }); + } +}; \ No newline at end of file diff --git a/source/packages/plg_system_mokosuitebooking/sql/install.mysql.sql b/source/packages/plg_system_mokosuitebooking/sql/install.mysql.sql new file mode 100644 index 0000000..3b479af --- /dev/null +++ b/source/packages/plg_system_mokosuitebooking/sql/install.mysql.sql @@ -0,0 +1,163 @@ +-- +-- MokoSuite Booking Tables +-- + +CREATE TABLE IF NOT EXISTS `#__mokosuitebooking_locations` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `address` VARCHAR(500) NOT NULL DEFAULT '', + `city` VARCHAR(100) NOT NULL DEFAULT '', + `state` VARCHAR(100) NOT NULL DEFAULT '', + `postal_code` VARCHAR(20) NOT NULL DEFAULT '', + `country` VARCHAR(100) NOT NULL DEFAULT '', + `timezone` VARCHAR(50) NOT NULL DEFAULT 'America/New_York', + `phone` VARCHAR(50) NOT NULL DEFAULT '', + `email` VARCHAR(255) NOT NULL DEFAULT '', + `photo` VARCHAR(500) NOT NULL DEFAULT '', + `notes` TEXT, + `published` TINYINT NOT NULL DEFAULT 1, + `ordering` INT NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL, + `created_by` INT NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `#__mokosuitebooking_services` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `description` TEXT, + `category` VARCHAR(100) NOT NULL DEFAULT '', + `duration_minutes` SMALLINT UNSIGNED NOT NULL DEFAULT 30, + `buffer_minutes` SMALLINT UNSIGNED NOT NULL DEFAULT 0, + `price` DECIMAL(10,2) NOT NULL DEFAULT 0.00, + `currency` VARCHAR(3) NOT NULL DEFAULT 'USD', + `max_attendees` SMALLINT UNSIGNED NOT NULL DEFAULT 1, + `requires_deposit` TINYINT NOT NULL DEFAULT 0, + `deposit_amount` DECIMAL(10,2) NOT NULL DEFAULT 0.00, + `color` VARCHAR(7) NOT NULL DEFAULT '#3788d8', + `photo` VARCHAR(500) NOT NULL DEFAULT '', + `published` TINYINT NOT NULL DEFAULT 1, + `ordering` INT NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL, + `created_by` INT NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_category` (`category`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `#__mokosuitebooking_staff` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `contact_id` INT DEFAULT NULL, + `user_id` INT DEFAULT NULL, + `display_name` VARCHAR(255) NOT NULL, + `title` VARCHAR(255) NOT NULL DEFAULT '', + `email` VARCHAR(255) NOT NULL DEFAULT '', + `phone` VARCHAR(50) NOT NULL DEFAULT '', + `bio` TEXT, + `photo` VARCHAR(500) NOT NULL DEFAULT '', + `color` VARCHAR(7) NOT NULL DEFAULT '#3788d8', + `services_json` JSON DEFAULT NULL, + `locations_json` JSON DEFAULT NULL, + `published` TINYINT NOT NULL DEFAULT 1, + `ordering` INT NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL, + PRIMARY KEY (`id`), + KEY `idx_contact` (`contact_id`), + KEY `idx_user` (`user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `#__mokosuitebooking_schedules` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `staff_id` INT UNSIGNED NOT NULL, + `location_id` INT UNSIGNED DEFAULT NULL, + `day_of_week` TINYINT UNSIGNED NOT NULL, + `start_time` TIME NOT NULL, + `end_time` TIME NOT NULL, + `effective_from` DATE DEFAULT NULL, + `effective_until` DATE DEFAULT NULL, + `published` TINYINT NOT NULL DEFAULT 1, + PRIMARY KEY (`id`), + KEY `idx_staff` (`staff_id`), + KEY `idx_location` (`location_id`), + KEY `idx_day` (`day_of_week`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `#__mokosuitebooking_availability_overrides` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `staff_id` INT UNSIGNED NOT NULL, + `override_date` DATE NOT NULL, + `available` TINYINT NOT NULL DEFAULT 0, + `start_time` TIME DEFAULT NULL, + `end_time` TIME DEFAULT NULL, + `reason` VARCHAR(255) NOT NULL DEFAULT '', + `created` DATETIME NOT NULL, + PRIMARY KEY (`id`), + KEY `idx_staff_date` (`staff_id`, `override_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `#__mokosuitebooking_bookings` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `booking_ref` VARCHAR(20) NOT NULL, + `contact_id` INT DEFAULT NULL, + `staff_id` INT UNSIGNED DEFAULT NULL, + `location_id` INT UNSIGNED DEFAULT NULL, + `customer_name` VARCHAR(255) NOT NULL, + `customer_email` VARCHAR(255) NOT NULL DEFAULT '', + `customer_phone` VARCHAR(50) NOT NULL DEFAULT '', + `booking_date` DATE NOT NULL, + `start_time` TIME NOT NULL, + `end_time` TIME NOT NULL, + `status` ENUM('pending','confirmed','in_progress','completed','cancelled','no_show') NOT NULL DEFAULT 'pending', + `total_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00, + `deposit_paid` DECIMAL(10,2) NOT NULL DEFAULT 0.00, + `payment_status` ENUM('unpaid','partial','paid','refunded') NOT NULL DEFAULT 'unpaid', + `notes` TEXT, + `internal_notes` TEXT, + `source` ENUM('admin','website','api','walk_in') NOT NULL DEFAULT 'admin', + `cancelled_at` DATETIME DEFAULT NULL, + `cancellation_reason` VARCHAR(500) NOT NULL DEFAULT '', + `reminder_sent` TINYINT NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL, + `created_by` INT NOT NULL DEFAULT 0, + `modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_ref` (`booking_ref`), + KEY `idx_contact` (`contact_id`), + KEY `idx_staff` (`staff_id`), + KEY `idx_location` (`location_id`), + KEY `idx_date` (`booking_date`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `#__mokosuitebooking_booking_services` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `booking_id` INT UNSIGNED NOT NULL, + `service_id` INT UNSIGNED NOT NULL, + `staff_id` INT UNSIGNED DEFAULT NULL, + `price` DECIMAL(10,2) NOT NULL DEFAULT 0.00, + `duration_minutes` SMALLINT UNSIGNED NOT NULL DEFAULT 30, + PRIMARY KEY (`id`), + KEY `idx_booking` (`booking_id`), + KEY `idx_service` (`service_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `#__mokosuitebooking_waitlist` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `contact_id` INT DEFAULT NULL, + `service_id` INT UNSIGNED NOT NULL, + `staff_id` INT UNSIGNED DEFAULT NULL, + `location_id` INT UNSIGNED DEFAULT NULL, + `customer_name` VARCHAR(255) NOT NULL, + `customer_email` VARCHAR(255) NOT NULL DEFAULT '', + `customer_phone` VARCHAR(50) NOT NULL DEFAULT '', + `preferred_date_start` DATE DEFAULT NULL, + `preferred_date_end` DATE DEFAULT NULL, + `preferred_time_start` TIME DEFAULT NULL, + `preferred_time_end` TIME DEFAULT NULL, + `status` ENUM('waiting','notified','booked','expired','cancelled') NOT NULL DEFAULT 'waiting', + `notified_at` DATETIME DEFAULT NULL, + `notes` TEXT, + `created` DATETIME NOT NULL, + PRIMARY KEY (`id`), + KEY `idx_service` (`service_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/source/packages/plg_system_mokosuitebooking/sql/uninstall.mysql.sql b/source/packages/plg_system_mokosuitebooking/sql/uninstall.mysql.sql new file mode 100644 index 0000000..1b1d773 --- /dev/null +++ b/source/packages/plg_system_mokosuitebooking/sql/uninstall.mysql.sql @@ -0,0 +1,12 @@ +-- +-- MokoSuite Booking — Uninstall +-- + +DROP TABLE IF EXISTS `#__mokosuitebooking_waitlist`; +DROP TABLE IF EXISTS `#__mokosuitebooking_booking_services`; +DROP TABLE IF EXISTS `#__mokosuitebooking_bookings`; +DROP TABLE IF EXISTS `#__mokosuitebooking_availability_overrides`; +DROP TABLE IF EXISTS `#__mokosuitebooking_schedules`; +DROP TABLE IF EXISTS `#__mokosuitebooking_staff`; +DROP TABLE IF EXISTS `#__mokosuitebooking_services`; +DROP TABLE IF EXISTS `#__mokosuitebooking_locations`; \ No newline at end of file diff --git a/source/packages/plg_system_mokosuitebooking/src/Extension/Booking.php b/source/packages/plg_system_mokosuitebooking/src/Extension/Booking.php new file mode 100644 index 0000000..a49c2d9 --- /dev/null +++ b/source/packages/plg_system_mokosuitebooking/src/Extension/Booking.php @@ -0,0 +1,22 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Plugin\System\MokoSuiteBooking\Extension; + +defined('_JEXEC') or die; + +use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\Event\SubscriberInterface; + +class Booking extends CMSPlugin implements SubscriberInterface +{ + public static function getSubscribedEvents(): array + { + return []; + } +} \ No newline at end of file diff --git a/source/packages/plg_webservices_mokosuitebooking/mokosuitebooking.xml b/source/packages/plg_webservices_mokosuitebooking/mokosuitebooking.xml new file mode 100644 index 0000000..45c2880 --- /dev/null +++ b/source/packages/plg_webservices_mokosuitebooking/mokosuitebooking.xml @@ -0,0 +1,15 @@ + + + Web Services - MokoSuite Booking + mokosuitebooking + Moko Consulting + hello@mokoconsulting.tech + https://mokoconsulting.tech + 2026-06-27 + Copyright (C) 2026 Moko Consulting. + 06.00.00 + GPL-3.0-or-later + REST API routes for MokoSuite Booking operations + Moko\Plugin\WebServices\MokoSuiteBooking + srcservices + \ No newline at end of file diff --git a/source/packages/plg_webservices_mokosuitebooking/services/provider.php b/source/packages/plg_webservices_mokosuitebooking/services/provider.php new file mode 100644 index 0000000..6be452f --- /dev/null +++ b/source/packages/plg_webservices_mokosuitebooking/services/provider.php @@ -0,0 +1,25 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Extension\PluginInterface; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; +use Moko\Plugin\WebServices\MokoSuiteBooking\Extension\MokoSuiteBooking; + +return new class implements ServiceProviderInterface { + public function register(Container $container): void { + $container->set(PluginInterface::class, function (Container $container) { + $dispatcher = $container->get(DispatcherInterface::class); + return new MokoSuiteBooking($dispatcher, (array) PluginHelper::getPlugin('webservices', 'mokosuitebooking')); + }); + } +}; \ No newline at end of file diff --git a/source/packages/plg_webservices_mokosuitebooking/src/Extension/MokoSuiteBooking.php b/source/packages/plg_webservices_mokosuitebooking/src/Extension/MokoSuiteBooking.php new file mode 100644 index 0000000..4d2ce96 --- /dev/null +++ b/source/packages/plg_webservices_mokosuitebooking/src/Extension/MokoSuiteBooking.php @@ -0,0 +1,43 @@ + + * SPDX-License-Identifier: GPL-3.0-or-later + * Authored-by: Moko Consulting + */ + +namespace Moko\Plugin\WebServices\MokoSuiteBooking\Extension; + +defined('_JEXEC') or die; + +use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\CMS\Router\ApiRouter; +use Joomla\Event\SubscriberInterface; + +class MokoSuiteBooking extends CMSPlugin implements SubscriberInterface +{ + public static function getSubscribedEvents(): array + { + return [ + 'onBeforeApiRoute' => 'onBeforeApiRoute', + ]; + } + + public function onBeforeApiRoute($event): void + { + $router = $event->getArgument('router'); + + $routes = [ + 'services', 'staff', 'bookings', 'schedules', + 'locations', 'availability', 'waitlist', + ]; + + foreach ($routes as $route) { + $router->createCRUDRoutes( + "v1/booking/{$route}", + $route, + ['component' => 'com_mokosuitebooking'] + ); + } + } +} \ No newline at end of file diff --git a/source/pkg_mokosuitebooking.xml b/source/pkg_mokosuitebooking.xml new file mode 100644 index 0000000..cd945f3 --- /dev/null +++ b/source/pkg_mokosuitebooking.xml @@ -0,0 +1,24 @@ + + + Package - MokoSuite Booking + mokosuitebooking + 06.00.00 + 2026-06-27 + Moko Consulting + hello@mokoconsulting.tech + https://mokoconsulting.tech + Copyright (C) 2026 Moko Consulting. All rights reserved. + GNU General Public License version 3 or later; see LICENSE + Appointment and resource booking for service businesses + 8.3 + + true + + plg_system_mokosuitebooking.zip + com_mokosuitebooking.zip + plg_webservices_mokosuitebooking.zip + + + https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteBooking/updates.xml + + \ No newline at end of file