Files
MokoSuiteField/source/packages/com_mokosuitefield/api/src/Controller/FieldEstimatesController.php
T

151 lines
4.8 KiB
PHP
Raw Normal View History

<?php
namespace Moko\Component\MokoSuiteField\Api\Controller;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\Database\DatabaseInterface;
/**
* Estimates + Route API.
*
* GET /estimates — List estimates
* POST /estimates — Create estimate from field
* PATCH /estimates/{id}/status — Update estimate status (approve/reject)
* POST /estimates/{id}/convert— Convert estimate to work order
* GET /route/{techId} — Get optimized daily route
* POST /route/{techId}/optimize — Trigger route optimization
*/
class FieldEstimatesController extends BaseController
{
private function requireAuth(string $action = 'core.manage'): void
{
$user = Factory::getApplication()->getIdentity();
if (!$user || $user->guest || (!$user->authorise('core.admin') && !$user->authorise($action, 'com_mokosuitefield'))) {
http_response_code(403);
echo json_encode(['error' => 'Access denied.']);
Factory::getApplication()->close();
}
}
public function listEstimates(): void
{
$this->requireAuth('core.manage');
$db = Factory::getContainer()->get(DatabaseInterface::class);
$input = Factory::getApplication()->getInput();
$query = $db->getQuery(true)
->select('e.*, cd.name AS customer_name, loc.address')
->from($db->quoteName('#__mokosuitefield_estimates', 'e'))
->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = e.contact_id')
->join('LEFT', $db->quoteName('#__mokosuitefield_locations', 'loc') . ' ON loc.id = e.location_id')
->order('e.created DESC');
$status = $input->getString('status', '');
if ($status) $query->where($db->quoteName('e.status') . ' = ' . $db->quote($status));
$techId = $input->getInt('technician_id', 0);
if ($techId) $query->where('e.technician_id = ' . $techId);
$db->setQuery($query, 0, 100);
$this->sendJson($db->loadObjectList() ?: []);
}
public function createEstimate(): void
{
$this->requireAuth('core.create');
$input = Factory::getApplication()->getInput();
$estimateId = \Moko\Plugin\System\MokoSuiteField\Helper\EstimateHelper::createEstimate(
$input->getInt('contact_id', 0),
$input->getInt('location_id', 0),
$input->getString('trade', 'general'),
$input->getString('description', ''),
json_decode($input->getString('line_items', '[]'), true) ?: []
);
$this->sendJson(['success' => true, 'estimate_id' => $estimateId]);
}
public function updateStatus(): void
{
$this->requireAuth('core.edit');
$input = Factory::getApplication()->getInput();
$id = $input->getInt('id', 0);
$status = $input->getString('status', '');
if (!in_array($status, ['sent', 'approved', 'rejected', 'expired'])) {
http_response_code(400);
$this->sendJson(['error' => 'Invalid status']);
return;
}
$db = Factory::getContainer()->get(DatabaseInterface::class);
$update = (object) [
'id' => $id,
'status' => $status,
];
if ($status === 'approved') {
$update->approved_at = Factory::getDate()->toSql();
}
$db->updateObject('#__mokosuitefield_estimates', $update, 'id');
$this->sendJson(['success' => true]);
}
public function convertToWorkOrder(): void
{
$this->requireAuth('core.create');
$id = Factory::getApplication()->getInput()->getInt('id', 0);
$woId = \Moko\Plugin\System\MokoSuiteField\Helper\EstimateHelper::convertToWorkOrder($id);
if (!$woId) {
http_response_code(400);
$this->sendJson(['error' => 'Could not convert estimate']);
return;
}
$this->sendJson(['success' => true, 'work_order_id' => $woId]);
}
public function getRoute(): void
{
$this->requireAuth('core.manage');
$techId = Factory::getApplication()->getInput()->getInt('tech_id', 0);
$date = Factory::getApplication()->getInput()->getString('date', date('Y-m-d'));
$route = \Moko\Plugin\System\MokoSuiteField\Helper\RouteHelper::getTechRoute($techId, $date);
$metrics = \Moko\Plugin\System\MokoSuiteField\Helper\RouteHelper::estimateRouteMetrics($techId, $date);
$this->sendJson([
'route' => $route,
'metrics' => $metrics,
]);
}
public function optimizeRoute(): void
{
$this->requireAuth('core.manage');
$techId = Factory::getApplication()->getInput()->getInt('tech_id', 0);
$date = Factory::getApplication()->getInput()->getString('date', date('Y-m-d'));
$optimized = \Moko\Plugin\System\MokoSuiteField\Helper\RouteHelper::optimizeRoute($techId, $date);
$metrics = \Moko\Plugin\System\MokoSuiteField\Helper\RouteHelper::estimateRouteMetrics($techId, $date);
$this->sendJson([
'route' => $optimized,
'metrics' => $metrics,
]);
}
private function sendJson(mixed $data): void
{
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);
Factory::getApplication()->close();
}
}