feat: second helper — core business logic for primary feature
Universal: Auto Version Bump / Version Bump (push) Successful in 8s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 11s

This commit is contained in:
Jonathan Miller
2026-06-21 17:30:17 -05:00
parent 615638ab2a
commit 360ff1dcf7
@@ -0,0 +1,101 @@
<?php
namespace Moko\Plugin\System\MokoSuiteAuto\Helper;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\Database\DatabaseInterface;
/**
* Deal management — sales deals, gross profit, F&I products, deal jacket.
*/
class DealHelper
{
/**
* Create a new deal.
*/
public static function create(int $vehicleId, int $buyerContactId, int $salespersonId, float $salePrice): object
{
if ($salePrice <= 0) {
throw new \InvalidArgumentException('Sale price must be positive.');
}
$db = Factory::getContainer()->get(DatabaseInterface::class);
$deal = (object) [
'vehicle_id' => $vehicleId,
'buyer_contact_id'=> $buyerContactId,
'salesperson_id' => $salespersonId,
'sale_price' => round($salePrice, 2),
'status' => 'negotiating',
'created_at' => Factory::getDate()->toSql(),
];
$db->insertObject('#__mokosuiteauto_deals', $deal, 'id');
return (object) ['success' => true, 'deal_id' => (int) $deal->id];
}
/**
* Calculate gross profit for a deal.
*/
public static function getGrossProfit(int $dealId): object
{
$db = Factory::getContainer()->get(DatabaseInterface::class);
$db->setQuery($db->getQuery(true)
->select('d.sale_price, v.invoice_price, v.reconditioning_cost')
->select('COALESCE(ti.appraisal_value, 0) AS trade_allowance')
->from($db->quoteName('#__mokosuiteauto_deals', 'd'))
->join('INNER', $db->quoteName('#__mokosuiteauto_vehicles', 'v') . ' ON v.id = d.vehicle_id')
->join('LEFT', $db->quoteName('#__mokosuiteauto_trade_ins', 'ti') . ' ON ti.id = d.trade_in_id')
->where('d.id = ' . (int) $dealId));
$deal = $db->loadObject();
if (!$deal) {
return (object) ['success' => false, 'error' => 'Deal not found'];
}
$frontGross = (float) $deal->sale_price - (float) $deal->invoice_price
- (float) ($deal->reconditioning_cost ?? 0);
// F&I back-end gross
$db->setQuery($db->getQuery(true)
->select('COALESCE(SUM(profit), 0) AS fi_gross')
->from('#__mokosuiteauto_deal_fi_products')
->where('deal_id = ' . (int) $dealId));
$backGross = (float) $db->loadResult();
return (object) [
'deal_id' => $dealId,
'sale_price' => (float) $deal->sale_price,
'invoice' => (float) $deal->invoice_price,
'recon_cost' => (float) ($deal->reconditioning_cost ?? 0),
'front_gross' => round($frontGross, 2),
'back_gross' => round($backGross, 2),
'total_gross' => round($frontGross + $backGross, 2),
];
}
/**
* Get sales dashboard — deals by status, monthly volume.
*/
public static function getSalesDashboard(): object
{
$db = Factory::getContainer()->get(DatabaseInterface::class);
$db->setQuery($db->getQuery(true)
->select('COUNT(*) AS total_deals')
->select('SUM(CASE WHEN status = ' . $db->quote('delivered') . ' THEN 1 ELSE 0 END) AS delivered')
->select('SUM(CASE WHEN status = ' . $db->quote('negotiating') . ' THEN 1 ELSE 0 END) AS in_negotiation')
->select('SUM(CASE WHEN status = ' . $db->quote('pending_finance') . ' THEN 1 ELSE 0 END) AS pending_finance')
->select('SUM(CASE WHEN status = ' . $db->quote('delivered') . ' AND MONTH(delivered_at) = MONTH(NOW()) AND YEAR(delivered_at) = YEAR(NOW()) THEN sale_price ELSE 0 END) AS mtd_volume')
->select('SUM(CASE WHEN status = ' . $db->quote('delivered') . ' AND MONTH(delivered_at) = MONTH(NOW()) AND YEAR(delivered_at) = YEAR(NOW()) THEN 1 ELSE 0 END) AS mtd_units')
->from('#__mokosuiteauto_deals'));
$stats = $db->loadObject();
$stats->mtd_volume = round((float) ($stats->mtd_volume ?? 0), 0);
return $stats;
}
}