feat: initial scaffold
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
# MokoSuite standard ignores
|
||||
.claude/
|
||||
.mcp.json
|
||||
TODO.md
|
||||
vendor/
|
||||
node_modules/
|
||||
.env
|
||||
*.min.css
|
||||
*.min.js
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.ppk
|
||||
|
||||
+8
-7
@@ -11,10 +11,11 @@
|
||||
|
||||
### Added
|
||||
- **Repository** -- initial repo creation with scaffolding
|
||||
- **System Plugin** -- Extension class, service provider
|
||||
- **SQL Schema** -- 8 tables
|
||||
- **Admin Component** -- 6 views: Dashboard, Shipments, Routes, Carriers, Warehouses, Packages
|
||||
- **Webservices Plugin** -- 6 API routes
|
||||
- **Configuration** -- basic settings fieldset
|
||||
- **Access Control** -- core permissions
|
||||
- **Language Files** -- en-GB translations
|
||||
- **System Plugin** -- Extension class, service provider, LogisticsHelper
|
||||
- **SQL Schema** -- 8 tables: orders, deliveries, routes, route_stops, delivery_proofs, pricing_rules, drivers, warehouses
|
||||
- **Admin Component** -- 8 views with ListModels: dashboard, orders, deliveries, routes, warehouses, pricing rules, drivers, proofs
|
||||
- **Admin Templates** -- functional Joomla 6 list views with pagination and status badges
|
||||
- **Webservices Plugin** -- 7 API routes: orders, deliveries, routes, warehouses, pricing rules, drivers, proofs
|
||||
- **Configuration** -- 11 settings across basic, delivery, pricing, notifications
|
||||
- **Access Control** -- 15 permissions for granular role-based access
|
||||
- **Component Language Files** -- en-GB translations for menu, submenu, and extension manager
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# MokoSuiteLogistics
|
||||
|
||||
Layer 2 — Fleet logistics, shipment tracking, route planning, warehouse management
|
||||
Delivery management, route optimization, courier dispatch, and proof of delivery for Joomla 6.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
@@ -10,10 +10,11 @@ Layer 2 — Fleet logistics, shipment tracking, route planning, warehouse m
|
||||
| **Layer** | 2 (requires: Client, CRM) |
|
||||
| **Language** | PHP 8.3+ |
|
||||
| **Branch** | develop on `dev`, merge to `main` (protected) |
|
||||
| **Wiki** | [MokoSuiteLogistics Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteLogistics/wiki) |
|
||||
|
||||
## Architecture
|
||||
|
||||
Joomla **package** -- Layer 2 add-on. CRM contacts as shippers/consignees, shipment tracking with multi-stop routes, warehouse zone management.
|
||||
Joomla **package** -- Layer 2 add-on. CRM contacts as customers/drivers, route-based dispatch with proof of delivery.
|
||||
|
||||
## Rules
|
||||
|
||||
|
||||
@@ -1,3 +1,90 @@
|
||||
# MokoSuiteLogistics
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
|
||||
MokoSuite Logistics — delivery management, route optimization, courier dispatch, proof of delivery for Joomla 6
|
||||
# MokoSuite Logistics
|
||||
|
||||
Delivery management, route optimization, courier dispatch, and proof of delivery for MokoSuite on Joomla 6.
|
||||
|
||||
## Overview
|
||||
|
||||
MokoSuiteLogistics is a **Layer 2** extension in the MokoSuite platform, building on MokoSuiteClient (Layer 0) and MokoSuiteCRM (Layer 1) to provide complete logistics and delivery operations management. Customers and drivers are CRM contacts -- no duplicate user tables.
|
||||
|
||||
## Package Contents
|
||||
|
||||
| Extension | Type | Description |
|
||||
|---|---|---|
|
||||
| `plg_system_mokosuitelogistics` | System Plugin | Core helpers, SQL schema, service classes |
|
||||
| `com_mokosuitelogistics` | Component | Admin dashboard, list views, configuration |
|
||||
| `plg_webservices_mokosuitelogistics` | Webservices Plugin | REST API endpoints |
|
||||
|
||||
## Features
|
||||
|
||||
- **Order Management** -- standard, express, same-day, scheduled, and bulk delivery types with full status lifecycle
|
||||
- **Delivery Tracking** -- real-time delivery status with attempt tracking and failure reasons
|
||||
- **Route Optimization** -- planned routes with sequenced stops, distance tracking, and completion status
|
||||
- **Warehouse Management** -- multiple warehouse locations with manager assignments
|
||||
- **Driver Management** -- CRM contact-linked profiles, vehicle descriptions, rating aggregation
|
||||
- **Pricing Rules** -- configurable per order type with base fees, per-km/kg rates, express multipliers
|
||||
- **Proof of Delivery** -- signature capture, photo proof, geolocation verification
|
||||
- **REST API** -- full CRUD for orders, deliveries, routes, warehouses, pricing rules, drivers, and proofs
|
||||
|
||||
## Database Schema
|
||||
|
||||
8 tables covering the full logistics domain:
|
||||
|
||||
| Table | Purpose |
|
||||
|---|---|
|
||||
| `#__mokosuitelogistics_orders` | Order lifecycle with customer, address, package, payment details |
|
||||
| `#__mokosuitelogistics_deliveries` | Delivery assignments with driver, route, timestamps, attempts |
|
||||
| `#__mokosuitelogistics_routes` | Planned delivery routes with distance and stop counts |
|
||||
| `#__mokosuitelogistics_route_stops` | Sequenced stops within routes with arrival tracking |
|
||||
| `#__mokosuitelogistics_delivery_proofs` | Signature, photo, and geolocation proof of delivery |
|
||||
| `#__mokosuitelogistics_pricing_rules` | Fee structures per order type |
|
||||
| `#__mokosuitelogistics_drivers` | Driver profiles linked to CRM contacts |
|
||||
| `#__mokosuitelogistics_warehouses` | Warehouse locations with manager contacts |
|
||||
|
||||
## Order Status Flow
|
||||
|
||||
```
|
||||
pending --> confirmed --> assigned --> picked_up --> in_transit --> delivered
|
||||
| | | | |
|
||||
+--> cancelled +--> cancelled +--> failed +--> failed +--> failed
|
||||
|
|
||||
+--> returned
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- Joomla 6.x
|
||||
- PHP 8.3+
|
||||
- MokoSuiteClient (Layer 0)
|
||||
- MokoSuiteCRM (Layer 1)
|
||||
|
||||
## Installation
|
||||
|
||||
Install via Joomla Extension Manager using the package file `pkg_mokosuitelogistics.zip`. The package installs all three extensions (system plugin, component, webservices plugin) in the correct order.
|
||||
|
||||
Updates are delivered automatically via the [MokoGitea update server](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteLogistics/updates.xml).
|
||||
|
||||
## Configuration
|
||||
|
||||
Settings are managed via the system plugin parameters:
|
||||
|
||||
| Fieldset | Key Settings |
|
||||
|---|---|
|
||||
| **Basic** | Company name, default currency, timezone, distance unit |
|
||||
| **Delivery** | Max delivery radius, default time window, auto-assign |
|
||||
| **Pricing** | Base delivery fee, per-distance rate, express multiplier, minimum charge |
|
||||
| **Notifications** | Order confirmation, dispatch notification, delivery proof |
|
||||
|
||||
## License
|
||||
|
||||
GNU General Public License v3.0 or later.
|
||||
|
||||
## Links
|
||||
|
||||
- [Documentation](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteLogistics/wiki)
|
||||
- [Issues](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteLogistics/issues)
|
||||
- [MokoSuite Platform](https://mokoconsulting.tech)
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<access component="com_mokosuitelogistics">
|
||||
<section name="component">
|
||||
<action name="core.admin" title="JACTION_ADMIN" />
|
||||
<action name="core.manage" title="JACTION_MANAGE" />
|
||||
<action name="core.create" title="JACTION_CREATE" />
|
||||
<action name="core.delete" title="JACTION_DELETE" />
|
||||
<action name="core.edit" title="JACTION_EDIT" />
|
||||
<action name="core.edit.state" title="JACTION_EDITSTATE" />
|
||||
</section>
|
||||
<section name="component">
|
||||
<action name="core.admin" title="JACTION_ADMIN" />
|
||||
<action name="core.options" title="JACTION_OPTIONS" />
|
||||
<action name="core.manage" title="JACTION_MANAGE" />
|
||||
<action name="core.create" title="JACTION_CREATE" />
|
||||
<action name="core.delete" title="JACTION_DELETE" />
|
||||
<action name="core.edit" title="JACTION_EDIT" />
|
||||
<action name="logistics.orders.manage" title="Manage Orders" />
|
||||
<action name="logistics.deliveries.manage" title="Manage Deliveries" />
|
||||
<action name="logistics.routes.manage" title="Manage Routes" />
|
||||
<action name="logistics.drivers.manage" title="Manage Drivers" />
|
||||
<action name="logistics.warehouses.manage" title="Manage Warehouses" />
|
||||
<action name="logistics.pricing.manage" title="Manage Pricing Rules" />
|
||||
<action name="logistics.proofs.view" title="View Delivery Proofs" />
|
||||
<action name="logistics.reports" title="View Reports" />
|
||||
<action name="logistics.settings" title="Manage Settings" />
|
||||
</section>
|
||||
</access>
|
||||
|
||||
@@ -1,6 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<config>
|
||||
<fieldset name="component" label="COM_MOKOSUITELOGISTICS_CONFIG">
|
||||
<field name="items_per_page" type="number" default="20" label="Items Per Page" min="5" max="100" />
|
||||
</fieldset>
|
||||
<fieldset name="basic" label="Logistics Defaults">
|
||||
<field name="company_name" type="text" default="" label="Company Name" />
|
||||
<field name="default_currency" type="text" default="USD" label="Default Currency" />
|
||||
<field name="timezone" type="text" default="UTC" label="Operating Timezone" />
|
||||
<field name="distance_unit" type="list" default="mi" label="Distance Unit">
|
||||
<option value="mi">Miles</option>
|
||||
<option value="km">Kilometres</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
<fieldset name="delivery" label="Delivery Settings">
|
||||
<field name="max_delivery_radius" type="number" default="50" label="Max Delivery Radius" hint="In distance units" />
|
||||
<field name="default_time_window" type="number" default="4" label="Default Time Window (hours)" />
|
||||
<field name="auto_assign" type="radio" default="1" label="Auto-Assign Drivers" class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
<fieldset name="pricing" label="Pricing">
|
||||
<field name="base_delivery_fee" type="number" default="5.00" step="0.01" label="Base Delivery Fee" />
|
||||
<field name="per_distance_rate" type="number" default="1.00" step="0.01" label="Per Distance Unit Rate" />
|
||||
<field name="express_multiplier" type="number" default="1.50" step="0.1" label="Express Multiplier" />
|
||||
<field name="minimum_charge" type="number" default="5.00" step="0.01" label="Minimum Charge" />
|
||||
</fieldset>
|
||||
<fieldset name="notifications" label="Notifications">
|
||||
<field name="order_confirmation" type="radio" default="1" label="Order Confirmation" class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="dispatch_notification" type="radio" default="1" label="Dispatch Notification" class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="delivery_proof" type="radio" default="1" label="Delivery Proof" class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</config>
|
||||
|
||||
+11
-8
@@ -1,8 +1,11 @@
|
||||
COM_MOKOSUITELOGISTICS="MokoSuiteLogistics"
|
||||
COM_MOKOSUITELOGISTICS_DESCRIPTION="Layer 2 — Fleet logistics, shipment tracking, route planning, warehouse management"
|
||||
COM_MOKOSUITELOGISTICS_LOGISTICSDASHBOARD="Dashboard"
|
||||
COM_MOKOSUITELOGISTICS_LOGISTICSSHIPMENTS="Shipments"
|
||||
COM_MOKOSUITELOGISTICS_LOGISTICSROUTES="Routes"
|
||||
COM_MOKOSUITELOGISTICS_LOGISTICSCARRIERS="Carriers"
|
||||
COM_MOKOSUITELOGISTICS_LOGISTICSWAREHOUSES="Warehouses"
|
||||
COM_MOKOSUITELOGISTICS_LOGISTICSPACKAGES="Packages"
|
||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
COM_MOKOSUITELOGISTICS="MokoSuite Logistics"
|
||||
COM_MOKOSUITELOGISTICS_DASHBOARD="Dashboard"
|
||||
COM_MOKOSUITELOGISTICS_ORDERS="Orders"
|
||||
COM_MOKOSUITELOGISTICS_DELIVERIES="Deliveries"
|
||||
COM_MOKOSUITELOGISTICS_ROUTES="Routes"
|
||||
COM_MOKOSUITELOGISTICS_WAREHOUSES="Warehouses"
|
||||
COM_MOKOSUITELOGISTICS_PRICING="Pricing"
|
||||
COM_MOKOSUITELOGISTICS_DRIVERS="Drivers"
|
||||
COM_MOKOSUITELOGISTICS_PROOFS="Proof of Delivery"
|
||||
|
||||
+4
-2
@@ -1,2 +1,4 @@
|
||||
COM_MOKOSUITELOGISTICS="MokoSuiteLogistics"
|
||||
COM_MOKOSUITELOGISTICS_DESCRIPTION="Layer 2 — Fleet logistics, shipment tracking, route planning, warehouse management"
|
||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
COM_MOKOSUITELOGISTICS="MokoSuite Logistics"
|
||||
COM_MOKOSUITELOGISTICS_XML_DESCRIPTION="Delivery management, route optimization, courier dispatch, proof of delivery"
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright (C) 2026 Moko Consulting
|
||||
* @license GPL-3.0-or-later
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
|
||||
use Joomla\CMS\Extension\ComponentInterface;
|
||||
use Joomla\CMS\Extension\MVCComponent;
|
||||
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\Router\ApiRouter;
|
||||
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) {
|
||||
$component = new MVCComponent($container->get(ComponentDispatcherFactoryInterface::class));
|
||||
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
|
||||
return $component;
|
||||
}
|
||||
);
|
||||
}
|
||||
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;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright (C) 2026 Moko Consulting
|
||||
* @license GPL-3.0-or-later
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace MokoConsulting\Component\MokoSuiteLogistics\Administrator\Controller;
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\Controller;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
@@ -12,5 +14,5 @@ use Joomla\CMS\MVC\Controller\BaseController;
|
||||
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
protected $default_view = 'logisticsdashboard';
|
||||
protected $default_view = 'logisticsdashboard';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
class DeliveriesModel extends ListModel
|
||||
{
|
||||
protected function getListQuery(): QueryInterface
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('a.*')
|
||||
->from($db->quoteName('#__mokosuitelogistics_deliveries', 'a'))
|
||||
->order($db->escape($this->getState('list.ordering', 'a.created'))
|
||||
. ' ' . $db->escape($this->getState('list.direction', 'DESC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function populateState($ordering = 'a.created', $direction = 'DESC'): void
|
||||
{
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
class DriversModel extends ListModel
|
||||
{
|
||||
protected function getListQuery(): QueryInterface
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('a.*')
|
||||
->from($db->quoteName('#__mokosuitelogistics_drivers', 'a'))
|
||||
->order($db->escape($this->getState('list.ordering', 'a.name'))
|
||||
. ' ' . $db->escape($this->getState('list.direction', 'ASC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function populateState($ordering = 'a.name', $direction = 'ASC'): void
|
||||
{
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright (C) 2026 Moko Consulting
|
||||
* @license GPL-3.0-or-later
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace MokoConsulting\Component\MokoSuiteLogistics\Administrator\Model;
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
|
||||
use Moko\Plugin\System\MokoSuiteLogistics\Helper\LogisticsHelper;
|
||||
|
||||
class LogisticsDashboardModel extends BaseDatabaseModel
|
||||
{
|
||||
public function getDashboard(): object
|
||||
{
|
||||
return LogisticsHelper::getDashboard();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
class OrdersModel extends ListModel
|
||||
{
|
||||
protected function getListQuery(): QueryInterface
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select([
|
||||
'o.*',
|
||||
'd.name AS driver_name',
|
||||
])
|
||||
->from($db->quoteName('#__mokosuitelogistics_orders', 'o'))
|
||||
->join('LEFT', $db->quoteName('#__mokosuitelogistics_deliveries', 'del') . ' ON del.order_id = o.id')
|
||||
->join('LEFT', $db->quoteName('#__mokosuitelogistics_drivers', 'd') . ' ON d.id = del.driver_id');
|
||||
|
||||
$search = $this->getState('filter.search');
|
||||
if ($search) {
|
||||
$search = $db->quote('%' . $db->escape($search, true) . '%');
|
||||
$query->where('(o.order_ref LIKE ' . $search . ' OR o.customer_name LIKE ' . $search . ')');
|
||||
}
|
||||
|
||||
$status = $this->getState('filter.status');
|
||||
if ($status) {
|
||||
$query->where($db->quoteName('o.status') . ' = ' . $db->quote($status));
|
||||
}
|
||||
|
||||
$query->order($db->escape($this->getState('list.ordering', 'o.created'))
|
||||
. ' ' . $db->escape($this->getState('list.direction', 'DESC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function populateState($ordering = 'o.created', $direction = 'DESC'): void
|
||||
{
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
class PricingRulesModel extends ListModel
|
||||
{
|
||||
protected function getListQuery(): QueryInterface
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('a.*')
|
||||
->from($db->quoteName('#__mokosuitelogistics_pricing_rules', 'a'))
|
||||
->order($db->escape($this->getState('list.ordering', 'a.name'))
|
||||
. ' ' . $db->escape($this->getState('list.direction', 'ASC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function populateState($ordering = 'a.name', $direction = 'ASC'): void
|
||||
{
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
class ProofsModel extends ListModel
|
||||
{
|
||||
protected function getListQuery(): QueryInterface
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('a.*')
|
||||
->from($db->quoteName('#__mokosuitelogistics_delivery_proofs', 'a'))
|
||||
->order($db->escape($this->getState('list.ordering', 'a.created'))
|
||||
. ' ' . $db->escape($this->getState('list.direction', 'DESC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function populateState($ordering = 'a.created', $direction = 'DESC'): void
|
||||
{
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
class RoutesModel extends ListModel
|
||||
{
|
||||
protected function getListQuery(): QueryInterface
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('a.*')
|
||||
->from($db->quoteName('#__mokosuitelogistics_routes', 'a'))
|
||||
->order($db->escape($this->getState('list.ordering', 'a.created'))
|
||||
. ' ' . $db->escape($this->getState('list.direction', 'DESC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function populateState($ordering = 'a.created', $direction = 'DESC'): void
|
||||
{
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
class WarehousesModel extends ListModel
|
||||
{
|
||||
protected function getListQuery(): QueryInterface
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('a.*')
|
||||
->from($db->quoteName('#__mokosuitelogistics_warehouses', 'a'))
|
||||
->order($db->escape($this->getState('list.ordering', 'a.name'))
|
||||
. ' ' . $db->escape($this->getState('list.direction', 'ASC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function populateState($ordering = 'a.name', $direction = 'ASC'): void
|
||||
{
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\View\Deliveries;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
protected array $items = [];
|
||||
protected mixed $pagination = null;
|
||||
protected mixed $state = null;
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->items = $this->get('Items') ?: [];
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
|
||||
ToolbarHelper::title('MokoSuite Logistics - Deliveries');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\View\Drivers;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
protected array $items = [];
|
||||
protected mixed $pagination = null;
|
||||
protected mixed $state = null;
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->items = $this->get('Items') ?: [];
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
|
||||
ToolbarHelper::title('MokoSuite Logistics - Drivers');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
+16
-8
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright (C) 2026 Moko Consulting
|
||||
* @license GPL-3.0-or-later
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace MokoConsulting\Component\MokoSuiteLogistics\Administrator\View\LogisticsDashboard;
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\View\LogisticsDashboard;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
@@ -13,9 +15,15 @@ use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
ToolbarHelper::title('Dashboard', 'generic');
|
||||
parent::display($tpl);
|
||||
}
|
||||
protected object $dashboard;
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->dashboard = $this->get('Dashboard');
|
||||
|
||||
ToolbarHelper::title('MokoSuite Logistics - Dashboard');
|
||||
ToolbarHelper::preferences('com_mokosuitelogistics');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\View\Orders;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
protected array $items = [];
|
||||
protected mixed $pagination = null;
|
||||
protected mixed $state = null;
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->items = $this->get('Items') ?: [];
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
|
||||
ToolbarHelper::title('MokoSuite Logistics - Orders');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\View\PricingRules;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
protected array $items = [];
|
||||
protected mixed $pagination = null;
|
||||
protected mixed $state = null;
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->items = $this->get('Items') ?: [];
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
|
||||
ToolbarHelper::title('MokoSuite Logistics - Pricing Rules');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\View\Proofs;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
protected array $items = [];
|
||||
protected mixed $pagination = null;
|
||||
protected mixed $state = null;
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->items = $this->get('Items') ?: [];
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
|
||||
ToolbarHelper::title('MokoSuite Logistics - Proof of Delivery');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\View\Routes;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
protected array $items = [];
|
||||
protected mixed $pagination = null;
|
||||
protected mixed $state = null;
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->items = $this->get('Items') ?: [];
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
|
||||
ToolbarHelper::title('MokoSuite Logistics - Routes');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoSuiteLogistics\Administrator\View\Warehouses;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
protected array $items = [];
|
||||
protected mixed $pagination = null;
|
||||
protected mixed $state = null;
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->items = $this->get('Items') ?: [];
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
|
||||
ToolbarHelper::title('MokoSuite Logistics - Warehouses');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
?>
|
||||
<div class="alert alert-info">
|
||||
<h4>Deliveries</h4>
|
||||
<p>Coming soon.</p>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
?>
|
||||
<div class="alert alert-info">
|
||||
<h4>Drivers</h4>
|
||||
<p>Coming soon.</p>
|
||||
</div>
|
||||
@@ -1,15 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright (C) 2026 Moko Consulting
|
||||
* @license GPL-3.0-or-later
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
$d = $this->dashboard;
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>Dashboard</h2>
|
||||
<p>Manage dashboard here.</p>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-4">
|
||||
<div class="card text-bg-primary">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Orders</h5>
|
||||
<p class="display-6"><?php echo (int) $d->total_orders; ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card text-bg-success">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Active Deliveries</h5>
|
||||
<p class="display-6"><?php echo (int) $d->active_deliveries; ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card text-bg-info">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Available Drivers</h5>
|
||||
<p class="display-6"><?php echo (int) $d->available_drivers; ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Drivers</h5>
|
||||
<p class="display-6"><?php echo (int) $d->total_drivers; ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Warehouses</h5>
|
||||
<p class="display-6"><?php echo (int) $d->total_warehouses; ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card text-bg-warning">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Today's Revenue</h5>
|
||||
<p class="display-6"><?php echo number_format((float) $d->today_revenue, 2); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
|
||||
$statusBadges = [
|
||||
'pending' => 'secondary',
|
||||
'confirmed' => 'info',
|
||||
'assigned' => 'warning',
|
||||
'picked_up' => 'primary',
|
||||
'in_transit' => 'primary',
|
||||
'delivered' => 'success',
|
||||
'failed' => 'danger',
|
||||
'cancelled' => 'danger',
|
||||
'returned' => 'dark',
|
||||
];
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_mokosuitelogistics&view=orders'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div id="j-main-container">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:1%">#</th>
|
||||
<th><?php echo HTMLHelper::_('searchtools.sort', 'Order Ref', 'o.order_ref', $listDirn, $listOrder); ?></th>
|
||||
<th>Status</th>
|
||||
<th>Customer</th>
|
||||
<th>Driver</th>
|
||||
<th>Pickup</th>
|
||||
<th><?php echo HTMLHelper::_('searchtools.sort', 'Delivery Fee', 'o.delivery_fee', $listDirn, $listOrder); ?></th>
|
||||
<th><?php echo HTMLHelper::_('searchtools.sort', 'Created', 'o.created', $listDirn, $listOrder); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->items as $i => $item) :
|
||||
$badge = $statusBadges[$item->status] ?? 'secondary';
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo $this->pagination->getRowOffset($i); ?></td>
|
||||
<td><strong><?php echo $this->escape($item->order_ref); ?></strong></td>
|
||||
<td><span class="badge bg-<?php echo $badge; ?>"><?php echo $this->escape($item->status); ?></span></td>
|
||||
<td><?php echo $this->escape($item->customer_name); ?></td>
|
||||
<td><?php echo $this->escape($item->driver_name ?? ''); ?></td>
|
||||
<td><?php echo $this->escape($item->pickup_address); ?></td>
|
||||
<td><?php echo $item->delivery_fee ? number_format((float) $item->delivery_fee, 2) : '-'; ?></td>
|
||||
<td><?php echo HTMLHelper::_('date', $item->created, 'Y-m-d H:i'); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
?>
|
||||
<div class="alert alert-info">
|
||||
<h4>Pricing Rules</h4>
|
||||
<p>Coming soon.</p>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
?>
|
||||
<div class="alert alert-info">
|
||||
<h4>Proof of Delivery</h4>
|
||||
<p>Coming soon.</p>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
?>
|
||||
<div class="alert alert-info">
|
||||
<h4>Routes</h4>
|
||||
<p>Coming soon.</p>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
?>
|
||||
<div class="alert alert-info">
|
||||
<h4>Warehouses</h4>
|
||||
<p>Coming soon.</p>
|
||||
</div>
|
||||
@@ -1,32 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension type="component" method="upgrade">
|
||||
<name>com_mokosuitelogistics</name>
|
||||
<version>0.0.0</version>
|
||||
<creationDate>2026-06</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>(C) 2026 Moko Consulting</copyright>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<description>Layer 2 — Fleet logistics, shipment tracking, route planning, warehouse management</description>
|
||||
<namespace path="src">MokoConsulting\Component\MokoSuiteLogistics</namespace>
|
||||
<administration>
|
||||
<files folder="admin">
|
||||
<folder>services</folder>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
<folder>language</folder>
|
||||
<filename>access.xml</filename>
|
||||
<filename>config.xml</filename>
|
||||
</files>
|
||||
<menu>MokoSuiteLogistics</menu>
|
||||
<submenu>
|
||||
<menu link="option=com_mokosuitelogistics&view=logisticsdashboard">Dashboard</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=logisticsshipments">Shipments</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=logisticsroutes">Routes</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=logisticscarriers">Carriers</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=logisticswarehouses">Warehouses</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=logisticspackages">Packages</menu>
|
||||
</submenu>
|
||||
</administration>
|
||||
<name>MokoSuite Logistics</name>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<creationDate>2026-06-27</creationDate>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting.</copyright>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<version>06.00.00</version>
|
||||
<description>Delivery management, route optimization, courier dispatch, proof of delivery</description>
|
||||
<namespace path="src">Moko\Component\MokoSuiteLogistics</namespace>
|
||||
<administration>
|
||||
<files folder="admin">
|
||||
<filename>access.xml</filename>
|
||||
<filename>config.xml</filename>
|
||||
<folder>language</folder>
|
||||
<folder>services</folder>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
</files>
|
||||
<languages folder="admin/language">
|
||||
<language tag="en-GB">en-GB/com_mokosuitelogistics.ini</language>
|
||||
<language tag="en-GB">en-GB/com_mokosuitelogistics.sys.ini</language>
|
||||
</languages>
|
||||
<menu>COM_MOKOSUITELOGISTICS</menu>
|
||||
<submenu>
|
||||
<menu link="option=com_mokosuitelogistics&view=logisticsdashboard">COM_MOKOSUITELOGISTICS_DASHBOARD</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=orders">COM_MOKOSUITELOGISTICS_ORDERS</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=deliveries">COM_MOKOSUITELOGISTICS_DELIVERIES</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=routes">COM_MOKOSUITELOGISTICS_ROUTES</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=warehouses">COM_MOKOSUITELOGISTICS_WAREHOUSES</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=pricingrules">COM_MOKOSUITELOGISTICS_PRICING</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=drivers">COM_MOKOSUITELOGISTICS_DRIVERS</menu>
|
||||
<menu link="option=com_mokosuitelogistics&view=proofs">COM_MOKOSUITELOGISTICS_PROOFS</menu>
|
||||
</submenu>
|
||||
</administration>
|
||||
</extension>
|
||||
|
||||
+2
-3
@@ -1,3 +1,2 @@
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS="Logistics"
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS_DESCRIPTION="MokoSuiteLogistics system plugin"
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS_ENABLED="Enable MokoSuiteLogistics"
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS="System - MokoSuite Logistics"
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS_DESC="Delivery management, route optimization, courier dispatch, proof of delivery"
|
||||
|
||||
+2
-3
@@ -1,3 +1,2 @@
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS="Logistics"
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS_DESCRIPTION="MokoSuiteLogistics system plugin"
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS_ENABLED="Enable MokoSuiteLogistics"
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS="System - MokoSuite Logistics"
|
||||
PLG_SYSTEM_MOKOSUITELOGISTICS_DESC="Delivery management, route optimization, courier dispatch, proof of delivery"
|
||||
|
||||
@@ -1,43 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension type="plugin" group="system" method="upgrade">
|
||||
<name>plg_system_mokosuitelogistics</name>
|
||||
<version>0.0.0</version>
|
||||
<creationDate>2026-06</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>(C) 2026 Moko Consulting</copyright>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<description>MokoSuiteLogistics system plugin -- schema owner and bootstrap</description>
|
||||
<namespace path="src">MokoConsulting\Plugin\System\MokoSuiteLogistics</namespace>
|
||||
<files>
|
||||
<folder>src</folder>
|
||||
<folder>services</folder>
|
||||
<folder>sql</folder>
|
||||
<folder>language</folder>
|
||||
</files>
|
||||
<install>
|
||||
<sql>
|
||||
<file driver="mysql" charset="utf8mb4">sql/install.mysql.sql</file>
|
||||
</sql>
|
||||
</install>
|
||||
<uninstall>
|
||||
<sql>
|
||||
<file driver="mysql" charset="utf8mb4">sql/uninstall.mysql.sql</file>
|
||||
</sql>
|
||||
</uninstall>
|
||||
<languages folder="language">
|
||||
<language tag="en-GB">en-GB/plg_system_mokosuitelogistics.ini</language>
|
||||
<language tag="en-GB">en-GB/plg_system_mokosuitelogistics.sys.ini</language>
|
||||
</languages>
|
||||
<config>
|
||||
<fields name="params">
|
||||
<fieldset name="basic">
|
||||
<field name="enabled" type="radio" label="PLG_SYSTEM_MOKOSUITELOGISTICS_ENABLED" default="1" class="btn-group">
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
<name>System - MokoSuite Logistics</name>
|
||||
<element>mokosuitelogistics</element>
|
||||
<author>Moko Consulting</author>
|
||||
<creationDate>2026-06-27</creationDate>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<version>06.00.00</version>
|
||||
<php_minimum>8.3</php_minimum>
|
||||
<description>PLG_SYSTEM_MOKOSUITELOGISTICS_DESC</description>
|
||||
<namespace path="src">Moko\Plugin\System\MokoSuiteLogistics</namespace>
|
||||
<files>
|
||||
<folder>src</folder>
|
||||
<folder>services</folder>
|
||||
<folder>language</folder>
|
||||
<folder>sql</folder>
|
||||
</files>
|
||||
<languages folder="language">
|
||||
<language tag="en-GB">en-GB/plg_system_mokosuitelogistics.ini</language>
|
||||
<language tag="en-GB">en-GB/plg_system_mokosuitelogistics.sys.ini</language>
|
||||
</languages>
|
||||
<install><sql><file driver="mysql" charset="utf8">sql/install.mysql.sql</file></sql></install>
|
||||
<uninstall><sql><file driver="mysql" charset="utf8">sql/uninstall.mysql.sql</file></sql></uninstall>
|
||||
<config>
|
||||
<fields name="params">
|
||||
<fieldset name="basic" label="Logistics Defaults">
|
||||
<field name="company_name" type="text" default="" label="Company Name" />
|
||||
<field name="default_currency" type="text" default="USD" label="Default Currency" />
|
||||
<field name="timezone" type="text" default="UTC" label="Operating Timezone" />
|
||||
<field name="distance_unit" type="list" default="mi" label="Distance Unit">
|
||||
<option value="mi">Miles</option>
|
||||
<option value="km">Kilometres</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
<fieldset name="delivery" label="Delivery Settings">
|
||||
<field name="max_delivery_radius" type="number" default="50" label="Max Delivery Radius" hint="In distance units" />
|
||||
<field name="default_time_window" type="number" default="4" label="Default Time Window (hours)" />
|
||||
<field name="auto_assign" type="radio" default="1" label="Auto-Assign Drivers" class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
<fieldset name="pricing" label="Pricing">
|
||||
<field name="base_delivery_fee" type="number" default="5.00" step="0.01" label="Base Delivery Fee" />
|
||||
<field name="per_distance_rate" type="number" default="1.00" step="0.01" label="Per Distance Unit Rate" />
|
||||
<field name="express_multiplier" type="number" default="1.50" step="0.1" label="Express Multiplier" />
|
||||
<field name="minimum_charge" type="number" default="5.00" step="0.01" label="Minimum Charge" />
|
||||
</fieldset>
|
||||
<fieldset name="notifications" label="Notifications">
|
||||
<field name="order_confirmation" type="radio" default="1" label="Order Confirmation" class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="dispatch_notification" type="radio" default="1" label="Dispatch Notification" class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="delivery_proof" type="radio" default="1" label="Delivery Proof" class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
</extension>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright (C) 2026 Moko Consulting
|
||||
* @license GPL-3.0-or-later
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
@@ -12,20 +14,20 @@ use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use MokoConsulting\Plugin\System\MokoSuiteLogistics\Extension\Logistics;
|
||||
use Moko\Plugin\System\MokoSuiteLogistics\Extension\Logistics;
|
||||
|
||||
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 Logistics($dispatcher, (array) PluginHelper::getPlugin('system', 'mokosuitelogistics'));
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
public function register(Container $container): void
|
||||
{
|
||||
$container->set(
|
||||
PluginInterface::class,
|
||||
function (Container $container) {
|
||||
$dispatcher = $container->get(DispatcherInterface::class);
|
||||
$plugin = new Logistics($dispatcher, (array) PluginHelper::getPlugin('system', 'mokosuitelogistics'));
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,172 +1,155 @@
|
||||
-- MokoSuiteLogistics Schema
|
||||
-- Copyright (C) 2026 Moko Consulting
|
||||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_orders` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`order_ref` VARCHAR(20) NOT NULL,
|
||||
`customer_contact_id` INT DEFAULT NULL,
|
||||
`customer_name` VARCHAR(255) NOT NULL,
|
||||
`customer_phone` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`customer_email` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`status` ENUM('pending','confirmed','assigned','picked_up','in_transit','delivered','failed','cancelled','returned') NOT NULL DEFAULT 'pending',
|
||||
`order_type` ENUM('standard','express','same_day','scheduled','bulk') NOT NULL DEFAULT 'standard',
|
||||
`pickup_address` VARCHAR(500) NOT NULL,
|
||||
`pickup_lat` DECIMAL(10,7) DEFAULT NULL,
|
||||
`pickup_lng` DECIMAL(10,7) DEFAULT NULL,
|
||||
`delivery_address` VARCHAR(500) NOT NULL,
|
||||
`delivery_lat` DECIMAL(10,7) DEFAULT NULL,
|
||||
`delivery_lng` DECIMAL(10,7) DEFAULT NULL,
|
||||
`package_type` ENUM('envelope','small_box','medium_box','large_box','pallet','fragile','perishable','custom') NOT NULL DEFAULT 'small_box',
|
||||
`weight_kg` DECIMAL(8,2) DEFAULT NULL,
|
||||
`estimated_distance_km` DECIMAL(10,2) DEFAULT NULL,
|
||||
`delivery_fee` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
`total_charge` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
`payment_method` ENUM('cash','card','account','prepaid','cod') NOT NULL DEFAULT 'card',
|
||||
`payment_status` ENUM('pending','paid','refunded','failed') NOT NULL DEFAULT 'pending',
|
||||
`notes` TEXT,
|
||||
`created` DATETIME NOT NULL,
|
||||
`created_by` INT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_ref` (`order_ref`),
|
||||
KEY `idx_customer` (`customer_contact_id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_type` (`order_type`),
|
||||
KEY `idx_created` (`created`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_carriers` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`contact_id` INT UNSIGNED NULL COMMENT 'FK to CRM contacts',
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`code` VARCHAR(50) NOT NULL,
|
||||
`carrier_type` ENUM('ground','air','sea','rail','courier') NOT NULL DEFAULT 'ground',
|
||||
`tracking_url_template` VARCHAR(500) NULL,
|
||||
`phone` VARCHAR(50) NULL,
|
||||
`email` VARCHAR(255) NULL,
|
||||
`status` ENUM('active','inactive','suspended') NOT NULL DEFAULT 'active',
|
||||
`notes` TEXT NULL,
|
||||
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_code` (`code`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_contact` (`contact_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_warehouses` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`code` VARCHAR(50) NOT NULL,
|
||||
`address` TEXT NULL,
|
||||
`city` VARCHAR(100) NULL,
|
||||
`state` VARCHAR(100) NULL,
|
||||
`postal_code` VARCHAR(20) NULL,
|
||||
`country` VARCHAR(100) NULL,
|
||||
`capacity_sqft` DECIMAL(12,2) NULL,
|
||||
`manager_contact_id` INT UNSIGNED NULL COMMENT 'FK to CRM contacts',
|
||||
`status` ENUM('active','inactive','maintenance') NOT NULL DEFAULT 'active',
|
||||
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_code` (`code`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_manager_contact` (`manager_contact_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_warehouse_zones` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`warehouse_id` INT UNSIGNED NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`zone_type` ENUM('receiving','storage','picking','packing','shipping','cold','hazmat') NOT NULL DEFAULT 'storage',
|
||||
`capacity` INT UNSIGNED NULL,
|
||||
`current_utilization` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`ordering` INT NOT NULL DEFAULT 0,
|
||||
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_warehouse` (`warehouse_id`),
|
||||
KEY `idx_zone_type` (`zone_type`),
|
||||
CONSTRAINT `fk_zone_warehouse` FOREIGN KEY (`warehouse_id`) REFERENCES `#__mokosuitelogistics_warehouses`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_shipments` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`shipment_number` VARCHAR(50) NOT NULL,
|
||||
`shipper_contact_id` INT UNSIGNED NULL COMMENT 'FK to CRM contacts',
|
||||
`consignee_contact_id` INT UNSIGNED NULL COMMENT 'FK to CRM contacts',
|
||||
`carrier_id` INT UNSIGNED NULL,
|
||||
`warehouse_id` INT UNSIGNED NULL,
|
||||
`origin_address` TEXT NULL,
|
||||
`destination_address` TEXT NULL,
|
||||
`shipment_type` ENUM('inbound','outbound','transfer','return') NOT NULL DEFAULT 'outbound',
|
||||
`status` ENUM('draft','booked','picked_up','in_transit','out_for_delivery','delivered','cancelled','returned') NOT NULL DEFAULT 'draft',
|
||||
`priority` ENUM('standard','express','overnight','freight') NOT NULL DEFAULT 'standard',
|
||||
`weight_kg` DECIMAL(10,3) NULL,
|
||||
`volume_cbm` DECIMAL(10,4) NULL,
|
||||
`estimated_pickup` DATETIME NULL,
|
||||
`estimated_delivery` DATETIME NULL,
|
||||
`actual_pickup` DATETIME NULL,
|
||||
`actual_delivery` DATETIME NULL,
|
||||
`tracking_number` VARCHAR(255) NULL,
|
||||
`shipping_cost` DECIMAL(10,2) NULL,
|
||||
`insurance_value` DECIMAL(10,2) NULL,
|
||||
`notes` TEXT NULL,
|
||||
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_shipment_number` (`shipment_number`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_shipper_contact` (`shipper_contact_id`),
|
||||
KEY `idx_consignee_contact` (`consignee_contact_id`),
|
||||
KEY `idx_carrier` (`carrier_id`),
|
||||
KEY `idx_warehouse` (`warehouse_id`),
|
||||
KEY `idx_estimated_delivery` (`estimated_delivery`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_deliveries` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`order_id` INT UNSIGNED NOT NULL,
|
||||
`driver_id` INT UNSIGNED DEFAULT NULL,
|
||||
`route_id` INT UNSIGNED DEFAULT NULL,
|
||||
`status` ENUM('assigned','en_route_pickup','picked_up','en_route_delivery','delivered','failed','returned') NOT NULL DEFAULT 'assigned',
|
||||
`assigned_at` DATETIME DEFAULT NULL,
|
||||
`picked_up_at` DATETIME DEFAULT NULL,
|
||||
`delivered_at` DATETIME DEFAULT NULL,
|
||||
`failed_at` DATETIME DEFAULT NULL,
|
||||
`failure_reason` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
`attempt_number` TINYINT UNSIGNED NOT NULL DEFAULT 1,
|
||||
`actual_distance_km` DECIMAL(10,2) DEFAULT NULL,
|
||||
`driver_notes` TEXT,
|
||||
`created` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_order` (`order_id`),
|
||||
KEY `idx_driver` (`driver_id`),
|
||||
KEY `idx_route` (`route_id`),
|
||||
KEY `idx_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_routes` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`carrier_id` INT UNSIGNED NULL,
|
||||
`route_type` ENUM('scheduled','on_demand','dedicated') NOT NULL DEFAULT 'scheduled',
|
||||
`status` ENUM('active','inactive','planned') NOT NULL DEFAULT 'planned',
|
||||
`distance_km` DECIMAL(10,2) NULL,
|
||||
`estimated_duration_hours` DECIMAL(6,2) NULL,
|
||||
`notes` TEXT NULL,
|
||||
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_carrier` (`carrier_id`),
|
||||
KEY `idx_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`route_ref` VARCHAR(20) NOT NULL,
|
||||
`driver_id` INT UNSIGNED DEFAULT NULL,
|
||||
`status` ENUM('planned','active','completed','cancelled') NOT NULL DEFAULT 'planned',
|
||||
`planned_date` DATE NOT NULL,
|
||||
`started_at` DATETIME DEFAULT NULL,
|
||||
`completed_at` DATETIME DEFAULT NULL,
|
||||
`total_stops` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`total_distance_km` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
`notes` TEXT,
|
||||
`created` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_ref` (`route_ref`),
|
||||
KEY `idx_driver` (`driver_id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_date` (`planned_date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_route_stops` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`route_id` INT UNSIGNED NOT NULL,
|
||||
`stop_number` INT UNSIGNED NOT NULL,
|
||||
`location_name` VARCHAR(255) NOT NULL,
|
||||
`address` TEXT NULL,
|
||||
`latitude` DECIMAL(10,7) NULL,
|
||||
`longitude` DECIMAL(10,7) NULL,
|
||||
`stop_type` ENUM('pickup','dropoff','waypoint','rest') NOT NULL DEFAULT 'dropoff',
|
||||
`estimated_arrival` DATETIME NULL,
|
||||
`estimated_departure` DATETIME NULL,
|
||||
`actual_arrival` DATETIME NULL,
|
||||
`actual_departure` DATETIME NULL,
|
||||
`notes` TEXT NULL,
|
||||
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_route` (`route_id`),
|
||||
KEY `idx_stop_number` (`route_id`, `stop_number`),
|
||||
CONSTRAINT `fk_stop_route` FOREIGN KEY (`route_id`) REFERENCES `#__mokosuitelogistics_routes`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`route_id` INT UNSIGNED NOT NULL,
|
||||
`order_id` INT UNSIGNED DEFAULT NULL,
|
||||
`stop_type` ENUM('pickup','delivery','warehouse','return') NOT NULL DEFAULT 'delivery',
|
||||
`address` VARCHAR(500) NOT NULL,
|
||||
`lat` DECIMAL(10,7) DEFAULT NULL,
|
||||
`lng` DECIMAL(10,7) DEFAULT NULL,
|
||||
`sequence_order` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`estimated_arrival` DATETIME DEFAULT NULL,
|
||||
`actual_arrival` DATETIME DEFAULT NULL,
|
||||
`status` ENUM('pending','arrived','completed','skipped') NOT NULL DEFAULT 'pending',
|
||||
`notes` TEXT,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_route` (`route_id`),
|
||||
KEY `idx_order` (`order_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_packages` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`shipment_id` INT UNSIGNED NOT NULL,
|
||||
`package_number` VARCHAR(50) NOT NULL,
|
||||
`description` VARCHAR(255) NULL,
|
||||
`weight_kg` DECIMAL(10,3) NULL,
|
||||
`length_cm` DECIMAL(8,2) NULL,
|
||||
`width_cm` DECIMAL(8,2) NULL,
|
||||
`height_cm` DECIMAL(8,2) NULL,
|
||||
`declared_value` DECIMAL(10,2) NULL,
|
||||
`is_fragile` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`is_hazmat` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`barcode` VARCHAR(255) NULL,
|
||||
`status` ENUM('created','labeled','in_transit','delivered','damaged','lost') NOT NULL DEFAULT 'created',
|
||||
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_package_number` (`package_number`),
|
||||
KEY `idx_shipment` (`shipment_id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_barcode` (`barcode`),
|
||||
CONSTRAINT `fk_package_shipment` FOREIGN KEY (`shipment_id`) REFERENCES `#__mokosuitelogistics_shipments`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_delivery_proofs` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`delivery_id` INT UNSIGNED NOT NULL,
|
||||
`proof_type` ENUM('signature','photo','both') NOT NULL DEFAULT 'photo',
|
||||
`recipient_name` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`signature_data` TEXT,
|
||||
`photo_path` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
`geolocation_lat` DECIMAL(10,7) DEFAULT NULL,
|
||||
`geolocation_lng` DECIMAL(10,7) DEFAULT NULL,
|
||||
`notes` TEXT,
|
||||
`created` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_delivery` (`delivery_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_tracking_events` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`shipment_id` INT UNSIGNED NOT NULL,
|
||||
`package_id` INT UNSIGNED NULL,
|
||||
`event_type` ENUM('created','picked_up','in_transit','at_hub','out_for_delivery','delivered','exception','returned') NOT NULL,
|
||||
`location` VARCHAR(255) NULL,
|
||||
`latitude` DECIMAL(10,7) NULL,
|
||||
`longitude` DECIMAL(10,7) NULL,
|
||||
`description` TEXT NULL,
|
||||
`event_time` DATETIME NOT NULL,
|
||||
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_shipment` (`shipment_id`),
|
||||
KEY `idx_package` (`package_id`),
|
||||
KEY `idx_event_type` (`event_type`),
|
||||
KEY `idx_event_time` (`event_time`),
|
||||
CONSTRAINT `fk_tracking_shipment` FOREIGN KEY (`shipment_id`) REFERENCES `#__mokosuitelogistics_shipments`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_pricing_rules` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`order_type` ENUM('standard','express','same_day','scheduled','bulk','all') NOT NULL DEFAULT 'all',
|
||||
`base_fee` DECIMAL(10,2) NOT NULL DEFAULT 5.00,
|
||||
`per_km` DECIMAL(10,2) NOT NULL DEFAULT 1.00,
|
||||
`per_kg` DECIMAL(10,2) NOT NULL DEFAULT 0.50,
|
||||
`minimum_charge` DECIMAL(10,2) NOT NULL DEFAULT 5.00,
|
||||
`express_multiplier` DECIMAL(4,2) NOT NULL DEFAULT 1.50,
|
||||
`published` TINYINT NOT NULL DEFAULT 1,
|
||||
`created` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_order_type` (`order_type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_drivers` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`contact_id` INT DEFAULT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`phone` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`email` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`license_number` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`vehicle_description` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`status` ENUM('available','on_delivery','off_duty','inactive') NOT NULL DEFAULT 'available',
|
||||
`current_lat` DECIMAL(10,7) DEFAULT NULL,
|
||||
`current_lng` DECIMAL(10,7) DEFAULT NULL,
|
||||
`rating` DECIMAL(3,2) NOT NULL DEFAULT 5.00,
|
||||
`total_deliveries` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`published` TINYINT NOT NULL DEFAULT 1,
|
||||
`created` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_contact` (`contact_id`),
|
||||
KEY `idx_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_warehouses` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`address` VARCHAR(500) NOT NULL,
|
||||
`lat` DECIMAL(10,7) DEFAULT NULL,
|
||||
`lng` DECIMAL(10,7) DEFAULT NULL,
|
||||
`manager_contact_id` INT DEFAULT NULL,
|
||||
`phone` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`published` TINYINT NOT NULL DEFAULT 1,
|
||||
`created` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_manager` (`manager_contact_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_tracking_events`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_packages`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_warehouses`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_drivers`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_pricing_rules`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_delivery_proofs`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_route_stops`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_routes`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_shipments`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_warehouse_zones`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_warehouses`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_carriers`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_deliveries`;
|
||||
DROP TABLE IF EXISTS `#__mokosuitelogistics_orders`;
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright (C) 2026 Moko Consulting
|
||||
* @license GPL-3.0-or-later
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace MokoConsulting\Plugin\System\MokoSuiteLogistics\Extension;
|
||||
namespace Moko\Plugin\System\MokoSuiteLogistics\Extension;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\Event\SubscriberInterface;
|
||||
|
||||
final class Logistics extends CMSPlugin implements SubscriberInterface
|
||||
class Logistics extends CMSPlugin implements SubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
protected $autoloadLanguage = true;
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Moko\Plugin\System\MokoSuiteLogistics\Helper;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
|
||||
class LogisticsHelper
|
||||
{
|
||||
public static function getDashboard(): object
|
||||
{
|
||||
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
||||
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('COUNT(*)')
|
||||
->from('#__mokosuitelogistics_orders'));
|
||||
$totalOrders = (int) $db->loadResult();
|
||||
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('COUNT(*)')
|
||||
->from('#__mokosuitelogistics_deliveries')
|
||||
->where($db->quoteName('status') . ' IN (' . implode(',', array_map([$db, 'quote'], ['assigned', 'en_route_pickup', 'picked_up', 'en_route_delivery'])) . ')'));
|
||||
$activeDeliveries = (int) $db->loadResult();
|
||||
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('COUNT(*)')
|
||||
->from('#__mokosuitelogistics_drivers')
|
||||
->where($db->quoteName('status') . ' = ' . $db->quote('available'))
|
||||
->where($db->quoteName('published') . ' = 1'));
|
||||
$availableDrivers = (int) $db->loadResult();
|
||||
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('COUNT(*)')
|
||||
->from('#__mokosuitelogistics_drivers')
|
||||
->where($db->quoteName('published') . ' = 1'));
|
||||
$totalDrivers = (int) $db->loadResult();
|
||||
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('COUNT(*)')
|
||||
->from('#__mokosuitelogistics_warehouses')
|
||||
->where($db->quoteName('published') . ' = 1'));
|
||||
$totalWarehouses = (int) $db->loadResult();
|
||||
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('COALESCE(SUM(' . $db->quoteName('total_charge') . '), 0)')
|
||||
->from('#__mokosuitelogistics_orders')
|
||||
->where($db->quoteName('status') . ' = ' . $db->quote('delivered'))
|
||||
->where($db->quoteName('payment_status') . ' = ' . $db->quote('paid'))
|
||||
->where('DATE(' . $db->quoteName('created') . ') = CURDATE()'));
|
||||
$todayRevenue = (float) $db->loadResult();
|
||||
|
||||
return (object) [
|
||||
'total_orders' => $totalOrders,
|
||||
'active_deliveries' => $activeDeliveries,
|
||||
'available_drivers' => $availableDrivers,
|
||||
'total_drivers' => $totalDrivers,
|
||||
'total_warehouses' => $totalWarehouses,
|
||||
'today_revenue' => $todayRevenue,
|
||||
];
|
||||
}
|
||||
|
||||
public static function generateOrderRef(): string
|
||||
{
|
||||
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
||||
$prefix = 'LG';
|
||||
|
||||
do {
|
||||
$ref = $prefix . strtoupper(bin2hex(random_bytes(4)));
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('COUNT(*)')
|
||||
->from('#__mokosuitelogistics_orders')
|
||||
->where($db->quoteName('order_ref') . ' = ' . $db->quote($ref)));
|
||||
} while ((int) $db->loadResult() > 0);
|
||||
|
||||
return $ref;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0"?>
|
||||
<extension type="plugin" group="webservices" method="upgrade">
|
||||
<name>plg_webservices_mokosuitelogistics</name>
|
||||
<version>0.0.0</version>
|
||||
<creationDate>2026-06</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>(C) 2026 Moko Consulting</copyright>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<description>MokoSuiteLogistics webservices plugin</description>
|
||||
<namespace path="src">MokoConsulting\Plugin\WebServices\MokoSuiteLogistics</namespace>
|
||||
<files>
|
||||
<folder>src</folder>
|
||||
<folder>services</folder>
|
||||
</files>
|
||||
<name>Web Services - MokoSuite Logistics</name>
|
||||
<element>mokosuitelogistics</element>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<creationDate>2026-06-27</creationDate>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting.</copyright>
|
||||
<version>06.00.00</version>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<description>REST API routes for MokoSuite Logistics delivery operations</description>
|
||||
<namespace path="src">Moko\Plugin\WebServices\MokoSuiteLogistics</namespace>
|
||||
<files><folder>src</folder><folder>services</folder></files>
|
||||
</extension>
|
||||
|
||||
@@ -1,31 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright (C) 2026 Moko Consulting
|
||||
* @license GPL-3.0-or-later
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Extension\PluginInterface;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use MokoConsulting\Plugin\WebServices\MokoSuiteLogistics\Extension\MokoSuiteLogistics;
|
||||
use Moko\Plugin\WebServices\MokoSuiteLogistics\Extension\MokoSuiteLogistics;
|
||||
|
||||
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 MokoSuiteLogistics($dispatcher, (array) PluginHelper::getPlugin('webservices', 'mokosuitelogistics'));
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
return new class implements ServiceProviderInterface {
|
||||
public function register(Container $container): void {
|
||||
$container->set(PluginInterface::class, function (Container $container) {
|
||||
return new MokoSuiteLogistics($container->get(DispatcherInterface::class), (array) PluginHelper::getPlugin('webservices', 'mokosuitelogistics'));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
+23
-21
@@ -1,34 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright (C) 2026 Moko Consulting
|
||||
* @license GPL-3.0-or-later
|
||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Authored-by: Moko Consulting
|
||||
*/
|
||||
|
||||
namespace MokoConsulting\Plugin\WebServices\MokoSuiteLogistics\Extension;
|
||||
namespace Moko\Plugin\WebServices\MokoSuiteLogistics\Extension;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\CMS\Router\ApiRouter;
|
||||
use Joomla\Event\SubscriberInterface;
|
||||
use Joomla\Router\Route;
|
||||
|
||||
final class MokoSuiteLogistics extends CMSPlugin implements SubscriberInterface
|
||||
class MokoSuiteLogistics extends CMSPlugin implements SubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'onBeforeApiRoute' => 'onBeforeApiRoute',
|
||||
];
|
||||
}
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return ['onBeforeApiRoute' => 'onBeforeApiRoute'];
|
||||
}
|
||||
|
||||
public function onBeforeApiRoute(&$router): void
|
||||
{
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/shipments', 'shipments');
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/routes', 'routes');
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/carriers', 'carriers');
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/warehouses', 'warehouses');
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/packages', 'packages');
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/tracking', 'tracking');
|
||||
}
|
||||
public function onBeforeApiRoute(&$event): void
|
||||
{
|
||||
$router = $event->getArgument('router');
|
||||
$opts = ['component' => 'com_mokosuitelogistics'];
|
||||
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/orders', 'orders', $opts);
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/deliveries', 'deliveries', $opts);
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/routes', 'routes', $opts);
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/warehouses', 'warehouses', $opts);
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/pricingrules', 'pricingrules', $opts);
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/drivers', 'drivers', $opts);
|
||||
$router->createCRUDRoutes('v1/mokosuitelogistics/proofs', 'proofs', $opts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension type="package" method="upgrade">
|
||||
<name>MokoSuiteLogistics</name>
|
||||
<name>Package - MokoSuite Logistics</name>
|
||||
<packagename>mokosuitelogistics</packagename>
|
||||
<version>0.0.0</version>
|
||||
<creationDate>2026-06</creationDate>
|
||||
<version>06.00.00</version>
|
||||
<creationDate>2026-06-27</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>(C) 2026 Moko Consulting</copyright>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<description>Layer 2 — Fleet logistics, shipment tracking, route planning, warehouse management</description>
|
||||
<files>
|
||||
<file type="plugin" id="mokosuitelogistics" group="system">plg_system_mokosuitelogistics.zip</file>
|
||||
<file type="component" id="mokosuitelogistics">com_mokosuitelogistics.zip</file>
|
||||
<file type="plugin" id="mokosuitelogistics" group="webservices">plg_webservices_mokosuitelogistics.zip</file>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
||||
<description>Delivery management, route optimization, courier dispatch, proof of delivery</description>
|
||||
<php_minimum>8.3</php_minimum>
|
||||
<dlid prefix="dlid=" suffix=""/>
|
||||
<blockChildUninstall>true</blockChildUninstall>
|
||||
<files folder="packages">
|
||||
<file type="plugin" id="plg_system_mokosuitelogistics" group="system">plg_system_mokosuitelogistics.zip</file>
|
||||
<file type="component" id="com_mokosuitelogistics">com_mokosuitelogistics.zip</file>
|
||||
<file type="plugin" id="plg_webservices_mokosuitelogistics" group="webservices">plg_webservices_mokosuitelogistics.zip</file>
|
||||
</files>
|
||||
<updateservers>
|
||||
<server type="extension" name="MokoSuiteLogistics Updates">https://git.mokoconsulting.tech/api/packages/MokoConsulting/generic/updates/mokosuitelogistics/updates.xml</server>
|
||||
<server type="extension" priority="1" name="Package - MokoSuite Logistics">https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteLogistics/updates.xml</server>
|
||||
</updateservers>
|
||||
</extension>
|
||||
|
||||
Reference in New Issue
Block a user