Your IP : 216.73.216.224


Current Path : /var/www/html/administrator/components/com_osmembership/model/
Upload File :
Current File : /var/www/html/administrator/components/com_osmembership/model/dashboard.php

<?php
/**
 * @package        Joomla
 * @subpackage     Membership Pro
 * @author         Tuan Pham Ngoc
 * @copyright      Copyright (C) 2012 - 2026 Ossolution Team
 * @license        GNU/GPL, see LICENSE.php
 */

defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Updater\Updater;
use Joomla\Component\Installer\Administrator\Model\UpdateModel;
use Joomla\Database\DatabaseDriver;

class OSMembershipModelDashboard extends MPFModel
{
	/**
	 * Constructor
	 *
	 * @throws Exception
	 */
	public function __construct()
	{
		parent::__construct();

		$this->state->insert('filter_plan_id', 'int', 0)
			->insert('filter_subscription_type', 'string', '')
			->insert('filter_duration', 'string', '');
	}

	/**
	 * Get latest subscriptions
	 *
	 * @return array
	 */
	public function getLatestSubscriptions()
	{
		return MPFModel::getTempInstance('Subscriptions', 'OSMembershipModel')
			->limitstart(0)
			->limit(6)
			->filter_order('tbl.created_date')
			->filter_order_Dir('DESC')
			->plan_id($this->state->get('filter_plan_id', 0))
			->getData();
	}

	/***
	 * Get total revenue
	 *
	 * @return float
	 */
	public function getTotalRevenue()
	{
		[$fromDate, $toDate] = $this->getFromDateAndToDateFromSelectedDuration();

		return $this->getRevenueForDuration(
			$fromDate,
			$toDate,
			$this->state->filter_plan_id,
			$this->state->filter_subscription_type
		);
	}

	/***
	 * Get total revenue
	 *
	 * @return float
	 */
	public function getTotalSubscriptions()
	{
		[$fromDate, $toDate] = $this->getFromDateAndToDateFromSelectedDuration();

		return $this->getTotalSubscriptionsForDuration(
			$fromDate,
			$toDate,
			$this->state->filter_plan_id,
			$this->state->filter_subscription_type
		);
	}

	/**
	 * Get total active subscriptions
	 *
	 * @return int
	 * @throws Exception
	 */
	public function getTotalActiveSubscriptions()
	{
		[$fromDate, $toDate] = $this->getFromDateAndToDateFromSelectedDuration();

		return $this->getTotalActiveSubscriptionsForDuration(
			$fromDate,
			$toDate,
			$this->state->filter_plan_id,
			$this->state->filter_subscription_type
		);
	}

	/**
	 * Get total refund amount
	 *
	 * @return int
	 * @throws Exception
	 */
	public function getTotalRefundAmount()
	{
		[$fromDate, $toDate] = $this->getFromDateAndToDateFromSelectedDuration();

		return $this->getTotalRefundAmountForDuration(
			$fromDate,
			$toDate,
			$this->state->filter_plan_id,
			$this->state->filter_subscription_type
		);
	}

	/**
	 * Method to get last 12 months sales data
	 *
	 * @param   int  $planId
	 *
	 * @return array
	 */
	public function getMonthlyRevenueChartData()
	{
		$today = Factory::getDate('Now', Factory::getApplication()->get('offset'));
		$today->setDate($today->format('Y', true), $today->format('n', true), 1);

		$data = [
			'labels'                => [],
			'total_revenue_dataset' => [],
			'refund_amount_dataset' => [],
		];

		for ($i = 0; $i < 13; $i++)
		{
			if ($i > 0)
			{
				$today->modify('-1 month');
			}

			$month = $today->format('n', true);
			$year  = $today->format('Y', true);

			$startMonth = clone $today;
			$endMonth   = clone $today;

			$startMonth->setTime(0, 0, 0);
			$startMonth->setDate($year, $month, 1);
			$endMonth->setTime(23, 59, 59);
			$endMonth->setDate($year, $month, $today->format('t', true));

			$data['total_revenue_dataset'][] = $this->getRevenueForDuration(
				$startMonth->toSql(),
				$endMonth->toSql(),
				$this->state->filter_plan_id,
				$this->state->filter_subscription_type
			);

			$data['refund_amount_dataset'][] = $this->getTotalRefundAmountForDuration(
				$startMonth->toSql(),
				$endMonth->toSql(),
				$this->state->filter_plan_id,
				$this->state->filter_subscription_type
			);

			$data['labels'][] = $today->format('M') . '/ ' . $year;
		}

		$data['labels']                = array_reverse($data['labels']);
		$data['total_revenue_dataset'] = array_reverse($data['total_revenue_dataset']);
		$data['refund_amount_dataset'] = array_reverse($data['refund_amount_dataset']);

		return $data;
	}

	/**
	 * Get sales statistic for each date in a given duration
	 *
	 * @return array
	 */
	public function getDailyRevenueChartData()
	{
		$fromDate = Factory::getDate('now', Factory::getApplication()->get('offset'))
			->modify('-1 month');

		$toDate = Factory::getDate('now', Factory::getApplication()->get('offset'));

		// Set from date to the beginning of day
		$fromDate->setTime(0, 0, 0);

		// Set to date to the end of days
		$toDate->setTime(23, 59, 59);

		$data = [
			'labels'                => [],
			'total_revenue_dataset' => [],
			'refund_amount_dataset' => [],
		];

		$i = 0;

		while ($fromDate < $toDate)
		{
			$startDay = clone $fromDate;
			$startDay->setTime(0, 0, 0);
			$endDay = clone $fromDate;
			$endDay->setTime(23, 59, 59);

			$data['total_revenue_dataset'][] = $this->getRevenueForDuration(
				$startDay->toSql(),
				$endDay->toSql(),
				$this->state->filter_plan_id,
				$this->state->filter_subscription_type
			);

			$data['refund_amount_dataset'][] = $this->getTotalRefundAmountForDuration(
				$startDay->toSql(),
				$endDay->toSql(),
				$this->state->filter_plan_id,
				$this->state->filter_subscription_type
			);

			if ($i % 3 === 0)
			{
				$data['labels'][] = $fromDate->format('d-M-y', true);
			}
			else
			{
				$data['labels'][] = '';
			}

			$i++;
			$fromDate->modify('+1 day');
		}

		return $data;
	}

	/**
	 * Method to get revenue by payment method chart data
	 *
	 * @return array
	 */
	public function getRevenueByPaymentMethodsChartData(): array
	{
		[$fromDate, $toDate] = $this->getFromDateAndToDateFromSelectedDuration();

		$db = $this->getDbo();

		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from('#__osmembership_plugins')
			->where('published = 1');
		$db->setQuery($query);

		if (!$db->loadResult())
		{
			return [];
		}

		$query->clear()
			->select('name, title')
			->from('#__osmembership_plugins');
		$db->setQuery($query);
		$paymentMethods = $db->loadObjectList('name');

		$query->clear()
			->select('payment_method, IFNULL(SUM(gross_amount), 0) AS payment_method_revenue')
			->from('#__osmembership_subscribers')
			->where('published IN (1,2)')
			->where('CHAR_LENGTH(payment_method) > 0')
			->where('group_admin_id = 0')
			->group('payment_method');

		if ($fromDate)
		{
			$query->where('created_date >= ' . $db->quote($fromDate));
		}

		if ($toDate)
		{
			$query->where('created_date <=' . $db->quote($toDate));
		}

		if ($this->state->filter_subscription_type)
		{
			$query->where('act = ' . $db->quote($this->state->filter_subscription_type));
		}

		if ($this->state->filter_plan_id)
		{
			$query->where('plan_id = ' . (int) $this->state->filter_plan_id);
		}

		$db->setQuery($query);

		$rows = $db->loadObjectList();

		$totalRevenue = 0;

		foreach ($rows as $row)
		{
			$totalRevenue += $row->payment_method_revenue;

			$row->payment_method_title = isset($paymentMethods[$row->payment_method]) ? $paymentMethods[$row->payment_method]->title : $row->payment_method;
		}

		$data   = [];
		$config = OSMembershipHelper::getConfig();

		if ($totalRevenue > 0)
		{
			$totalPercent = 0;
			$label        = '';

			foreach ($rows as $row)
			{
				$percent      = round($row->payment_method_revenue / $totalRevenue * 100, 2);
				$totalPercent += $percent;
				$label        = $row->payment_method_title
					. ' - ' . OSMembershipHelper::formatCurrency($row->payment_method_revenue, $config);
				$data[$label] = $percent;
			}

			// Make sure total percent is 100%
			if ($totalPercent < 100)
			{
				$data[$label] = round(
					($data[$label] + 100 - $totalPercent) / 100,
					2
				);
			}
		}

		return $data;
	}

	/**
	 * Get total subscriptions for given duration
	 *
	 * @param   string  $fromDate
	 * @param   string  $toDate
	 * @param   int     $planId
	 * @param   string  $subscriptionType
	 *
	 * @return int
	 */
	protected function getTotalSubscriptionsForDuration(
		$fromDate = null,
		$toDate = null,
		$planId = null,
		$subscriptionType = null
	) {
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from('#__osmembership_subscribers')
			->where('(published IN (1,2) OR (published = 0 AND payment_method LIKE "os_offline%"))')
			->where('group_admin_id = 0');

		if ($fromDate)
		{
			$query->where('created_date >= ' . $db->quote($fromDate));
		}

		if ($toDate)
		{
			$query->where('created_date <=' . $db->quote($toDate));
		}

		if ($planId)
		{
			$query->where('plan_id = ' . (int) $planId);
		}

		if ($subscriptionType)
		{
			$query->where('act = ' . $db->quote($subscriptionType));
		}

		$db->setQuery($query);

		return (int) $db->loadResult();
	}

	/**
	 * Get total active subscriptions for given duration
	 *
	 * @param   string  $fromDate
	 * @param   string  $toDate
	 * @param   int     $planId
	 *
	 * @return int
	 */
	protected function getTotalActiveSubscriptionsForDuration(
		$fromDate = null,
		$toDate = null,
		$planId = null,
		$subscriptionType = null
	) {
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from('#__osmembership_subscribers')
			->where('published = 1')
			->where('group_admin_id = 0');

		if ($fromDate)
		{
			$query->where('created_date >= ' . $db->quote($fromDate));
		}

		if ($toDate)
		{
			$query->where('created_date <=' . $db->quote($toDate));
		}

		if ($planId)
		{
			$query->where('plan_id = ' . (int) $planId);
		}

		if ($subscriptionType)
		{
			$query->where('act = ' . $db->quote($subscriptionType));
		}

		$db->setQuery($query);

		return (int) $db->loadResult();
	}

	/**
	 * Get total refund amount for given duration
	 *
	 * @param   string  $fromDate
	 * @param   string  $toDate
	 * @param   int     $planId
	 * @param   string  $subscriptionType
	 *
	 * @return int
	 */
	protected function getTotalRefundAmountForDuration(
		$fromDate = null,
		$toDate = null,
		$planId = null,
		$subscriptionType = null
	) {
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('IFNULL(SUM(gross_amount), 0)')
			->from('#__osmembership_subscribers')
			->where('published = 4')
			->where('group_admin_id = 0');

		if ($fromDate)
		{
			$query->where('created_date >= ' . $db->quote($fromDate));
		}

		if ($toDate)
		{
			$query->where('created_date <=' . $db->quote($toDate));
		}

		if ($planId)
		{
			$query->where('plan_id = ' . (int) $planId);
		}

		if ($subscriptionType)
		{
			$query->where('act = ' . $db->quote($subscriptionType));
		}

		$db->setQuery($query);

		return (int) $db->loadResult();
	}

	/**
	 * @param   string  $fromDate
	 * @param   string  $toDate
	 * @param   int     $planId
	 * @param   string  $subscriptionType
	 *
	 * @return float
	 */
	protected function getRevenueForDuration($fromDate = null, $toDate = null, $planId = null, $subscriptionType = null)
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('IFNULL(SUM(gross_amount), 0)')
			->from('#__osmembership_subscribers')
			->where('published IN (1,2)')
			->where('group_admin_id = 0');

		if ($fromDate)
		{
			$query->where('created_date >= ' . $db->quote($fromDate));
		}

		if ($toDate)
		{
			$query->where('created_date <=' . $db->quote($toDate));
		}

		if ($subscriptionType)
		{
			$query->where('act = ' . $db->quote($subscriptionType));
		}

		if ($planId)
		{
			$query->where('plan_id = ' . (int) $planId);
		}

		$db->setQuery($query);

		return (float) $db->loadResult();
	}

	/**
	 * Method to get from date and to date from selected duration
	 *
	 * @return array|null[]
	 *
	 * @throws Exception
	 */
	protected function getFromDateAndToDateFromSelectedDuration()
	{
		if ($this->state->filter_duration)
		{
			return OSMembershipHelper::getDateDuration($this->state->filter_duration);
		}

		return [null, null];
	}

	/**
	 * Check update result
	 *
	 * @return array
	 */
	public function checkUpdate()
	{
		// Get the caching duration.
		$component     = ComponentHelper::getComponent('com_installer');
		$params        = $component->params;
		$cache_timeout = $params->get('cachetimeout', 6);
		$cache_timeout = 3600 * $cache_timeout;

		// Get the minimum stability.
		$minimum_stability = $params->get('minimum_stability', Updater::STABILITY_STABLE);

		/* @var UpdateModel $model */
		$model = Factory::getApplication()->bootComponent('com_installer')->getMVCFactory()
			->createModel('Update', 'Administrator', ['ignore_request' => true]);

		$model->purge();

		/* @var DatabaseDriver $db */
		$db    = Factory::getContainer()->get('db');
		$query = $db->getQuery(true)
			->select('extension_id')
			->from('#__extensions')
			->where('`type` = "package"')
			->where('`element` = "pkg_osmembership"');
		$db->setQuery($query);
		$eid = (int) $db->loadResult();

		$result['status'] = 0;

		if ($eid)
		{
			$ret = Updater::getInstance()->findUpdates($eid, $cache_timeout, $minimum_stability);

			if ($ret)
			{
				$model->setState('list.start', 0);
				$model->setState('list.limit', 0);
				$model->setState('filter.extension_id', $eid);
				$updates           = $model->getItems();
				$result['status']  = 2;
				$result['version'] = '';

				if (count($updates))
				{
					$result['message'] = Text::sprintf('OSM_UPDATE_CHECKING_UPDATEFOUND', $updates[0]->version);
					$result['version'] = $updates[0]->version;
				}
				else
				{
					$result['message'] = Text::sprintf('OSM_UPDATE_CHECKING_UPDATEFOUND', null);
				}
			}
			else
			{
				$result['status']  = 1;
				$result['message'] = Text::_('OSM_UPDATE_CHECKING_UPTODATE');
			}
		}

		return $result;
	}
}