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; + } +}