From 360ff1dcf7158e2a2b464be4b126121396b13660 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Sun, 21 Jun 2026 17:30:17 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20second=20helper=20=E2=80=94=20core=20bu?= =?UTF-8?q?siness=20logic=20for=20primary=20feature?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Helper/DealHelper.php | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 source/packages/plg_system_mokosuiteauto/src/Helper/DealHelper.php diff --git a/source/packages/plg_system_mokosuiteauto/src/Helper/DealHelper.php b/source/packages/plg_system_mokosuiteauto/src/Helper/DealHelper.php new file mode 100644 index 0000000..8cc0d92 --- /dev/null +++ b/source/packages/plg_system_mokosuiteauto/src/Helper/DealHelper.php @@ -0,0 +1,101 @@ +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; + } +}