Files
MokoSuiteField/source/packages/com_mokosuitefield/site/src/View/EstimateView/HtmlView.php
T
jmiller 885e155c08
Cascade Main -> Dev / Cascade main -> dev (push) Has been cancelled
Sync Workflows to Repos / sync (push) Has been cancelled
Revert "Merge branch 'dev' into main"
This reverts commit 6fea9d8b1b, reversing
changes made to d9f60b4c61.
2026-07-10 16:25:44 -05:00

91 lines
3.1 KiB
PHP

<?php
namespace Moko\Component\MokoSuiteField\Site\View\EstimateView;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
use Joomla\Database\DatabaseInterface;
/**
* Public estimate approval page — customer views and approves/rejects a field service estimate.
*/
class HtmlView extends BaseHtmlView
{
public ?object $estimate = null;
public array $lineItems = [];
public bool $actioned = false;
public string $actionResult = '';
public function display($tpl = null): void
{
$app = Factory::getApplication();
$input = $app->getInput();
$db = Factory::getContainer()->get(DatabaseInterface::class);
$token = $input->getString('token', '');
if (!$token) {
$app->enqueueMessage('Invalid estimate link.', 'warning');
parent::display($tpl);
return;
}
// Load estimate by token
$db->setQuery($db->getQuery(true)
->select('e.*, cd.name AS customer_name, cd.email_to, cd.telephone')
->select('l.address, l.city, l.state, l.zip')
->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', 'l') . ' ON l.id = e.location_id')
->where($db->quoteName('e.approval_token') . ' = ' . $db->quote($token)));
$this->estimate = $db->loadObject();
if (!$this->estimate) {
$app->enqueueMessage('Estimate not found or link expired.', 'warning');
parent::display($tpl);
return;
}
// Load line items
$db->setQuery($db->getQuery(true)
->select('*')
->from('#__mokosuitefield_estimate_items')
->where('estimate_id = ' . (int) $this->estimate->id)
->order('ordering ASC'));
$this->lineItems = $db->loadObjectList() ?: [];
// Handle approval/rejection (CSRF check not required — token-based public page)
if ($input->getMethod() === 'POST' && \Joomla\CMS\Session\Session::checkToken()) {
$action = $input->getString('action', '');
if ($action === 'approve' && $this->estimate->status === 'sent') {
$db->setQuery($db->getQuery(true)
->update('#__mokosuitefield_estimates')
->set($db->quoteName('status') . ' = ' . $db->quote('approved'))
->set($db->quoteName('approved_at') . ' = ' . $db->quote(Factory::getDate()->toSql()))
->set($db->quoteName('customer_signature') . ' = ' . $db->quote($input->getString('signature', '')))
->where('id = ' . (int) $this->estimate->id));
$db->execute();
$this->actioned = true;
$this->actionResult = 'approved';
$this->estimate->status = 'approved';
} elseif ($action === 'reject' && $this->estimate->status === 'sent') {
$db->setQuery($db->getQuery(true)
->update('#__mokosuitefield_estimates')
->set($db->quoteName('status') . ' = ' . $db->quote('rejected'))
->set($db->quoteName('rejection_reason') . ' = ' . $db->quote($input->getString('reason', '')))
->where('id = ' . (int) $this->estimate->id));
$db->execute();
$this->actioned = true;
$this->actionResult = 'rejected';
$this->estimate->status = 'rejected';
}
}
parent::display($tpl);
}
}