overview.php
235 lines
| 1 | <?php |
| 2 | /** |
| 3 | * @package VikAppointments - Libraries |
| 4 | * @subpackage dashboard |
| 5 | * @author E4J s.r.l. |
| 6 | * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved. |
| 7 | * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL |
| 8 | * @link https://vikwp.com |
| 9 | */ |
| 10 | |
| 11 | // No direct access |
| 12 | defined('ABSPATH') or die('No script kiddies please!'); |
| 13 | |
| 14 | VAPLoader::import('libraries.statistics.factory'); |
| 15 | VAPLoader::import('libraries.statistics.helpers.finance'); |
| 16 | VAPLoader::import('libraries.statistics.helpers.appointments'); |
| 17 | |
| 18 | /** |
| 19 | * Widget used to display a financial overview within the |
| 20 | * Dashboard of WordPress. |
| 21 | * |
| 22 | * @since 1.2 |
| 23 | */ |
| 24 | class JDashboardWidgetVikAppointmentsOverview extends JDashboardWidget |
| 25 | { |
| 26 | /** |
| 27 | * Keep a reference of the user that needs to access |
| 28 | * this kind of widget. |
| 29 | * |
| 30 | * @var JUser |
| 31 | */ |
| 32 | private $user; |
| 33 | |
| 34 | /** |
| 35 | * Returns the name of the widget. |
| 36 | * |
| 37 | * @return string |
| 38 | */ |
| 39 | public function getName() |
| 40 | { |
| 41 | return __('VikAppointments - Overview', 'vikappointments'); |
| 42 | } |
| 43 | |
| 44 | /** |
| 45 | * Checks whether the specified user is able to access |
| 46 | * this widget. Allow only super users. |
| 47 | * |
| 48 | * @param mixed $user The user to check. |
| 49 | * |
| 50 | * @return boolean |
| 51 | */ |
| 52 | public function canAccess($user = null) |
| 53 | { |
| 54 | if (!$user instanceof JUser) |
| 55 | { |
| 56 | // get user |
| 57 | $user = JFactory::getUser($user); |
| 58 | } |
| 59 | |
| 60 | // keep a reference |
| 61 | $this->user = $user; |
| 62 | |
| 63 | // allow administrators and users that can access the appointments or financial data |
| 64 | return $user->authorise('core.admin', 'com_vikappointments') |
| 65 | || $user->authorise('core.access.reservations', 'com_vikappointments') |
| 66 | || $user->authorise('core.access.analytics.finance', 'com_vikappointments'); |
| 67 | } |
| 68 | |
| 69 | /** |
| 70 | * Renders the HTML to display within the contents of the widget. |
| 71 | * |
| 72 | * @param mixed $args A registry of settings. |
| 73 | * |
| 74 | * @return string The HTML to display. |
| 75 | */ |
| 76 | protected function renderWidget($args) |
| 77 | { |
| 78 | // prepare display data |
| 79 | $data = array( |
| 80 | 'config' => $args, |
| 81 | 'widget' => $this, |
| 82 | 'user' => $this->user ? $this->user : JFactory::getUser(), |
| 83 | ); |
| 84 | |
| 85 | // fetch analytics |
| 86 | $this->fetchMonthTotal($data); |
| 87 | $this->fetchRog($data); |
| 88 | $this->fetchWeeklyChart($data); |
| 89 | $this->fetchPendingCount($data); |
| 90 | $this->fetchPaymentCount($data); |
| 91 | |
| 92 | // create layout file |
| 93 | $layout = new JLayoutFile('html.wpdash.overview.widget', null, array('component' => 'com_vikappointments')); |
| 94 | |
| 95 | // render widget content |
| 96 | return $layout->render($data); |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * Fetches the total earning of the current month. |
| 101 | * |
| 102 | * @param array &$data The display data array to fill. |
| 103 | * |
| 104 | * @return void |
| 105 | */ |
| 106 | private function fetchMonthTotal(&$data) |
| 107 | { |
| 108 | // back to first day of the current month |
| 109 | $from = JFactory::getDate(); |
| 110 | $from->modify($from->format('Y-m-01 00:00:00')); |
| 111 | |
| 112 | // use the current date as delimiter, since there cannot be |
| 113 | // orders in the future |
| 114 | $to = JFactory::getDate(); |
| 115 | |
| 116 | // define the columns to load |
| 117 | $columns = ['total', 'tax', 'net']; |
| 118 | |
| 119 | // fetch revenue |
| 120 | $data['monthtotal'] = VAPStatisticsHelperFinance::getTotalRevenue($from, $to, $columns); |
| 121 | } |
| 122 | |
| 123 | /** |
| 124 | * Fetches the rate of growth between the current month and |
| 125 | * the previous one. |
| 126 | * |
| 127 | * @param array &$data The display data array to fill. |
| 128 | * |
| 129 | * @return void |
| 130 | */ |
| 131 | private function fetchRog(&$data) |
| 132 | { |
| 133 | // use the current month |
| 134 | $m1 = JFactory::getDate(); |
| 135 | $m1 = $m1->format('Y-m'); |
| 136 | |
| 137 | // back to previous month |
| 138 | $m2 = JFactory::getDate(); |
| 139 | $m2->modify('-1 month'); |
| 140 | $m2 = $m2->format('Y-m'); |
| 141 | |
| 142 | // fetch rog |
| 143 | $data['rog'] = VAPStatisticsHelperFinance::getRog($m1, $m2, $proportional = true); |
| 144 | } |
| 145 | |
| 146 | /** |
| 147 | * Instantiates the analytics widget responsible to generating a |
| 148 | * financial revenue chart. |
| 149 | * |
| 150 | * @param array &$data The display data array to fill. |
| 151 | * |
| 152 | * @return void |
| 153 | */ |
| 154 | private function fetchWeeklyChart(&$data) |
| 155 | { |
| 156 | // force "option" in request to allow the plugin to use the correct folder |
| 157 | // from which the layout files should be loaded |
| 158 | JFactory::getApplication()->input->set('option', 'com_vikappointments'); |
| 159 | |
| 160 | // load employee-services revenue chart instance |
| 161 | $data['chart'] = VAPStatisticsFactory::getInstance('finance_revenue_chart', [ |
| 162 | 'range' => '-1 week', |
| 163 | ]); |
| 164 | } |
| 165 | |
| 166 | /** |
| 167 | * Fetches total count of pending appointments. |
| 168 | * |
| 169 | * @param array &$data The display data array to fill. |
| 170 | * |
| 171 | * @return void |
| 172 | */ |
| 173 | private function fetchPendingCount(&$data) |
| 174 | { |
| 175 | // fetch rog |
| 176 | $lookup = VAPStatisticsHelperAppointments::getStatusesCount(); |
| 177 | |
| 178 | $data['pending'] = 0; |
| 179 | |
| 180 | // find all pending status codes |
| 181 | $pending = JHtml::fetch('vaphtml.status.find', 'code', array('appointments' => 1, 'approved' => 0, 'reserved' => 1)); |
| 182 | |
| 183 | foreach($pending as $code) |
| 184 | { |
| 185 | if (isset($lookup[$code])) |
| 186 | { |
| 187 | // increase pending count |
| 188 | $data['pending'] += (int) $lookup[$code]; |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | /** |
| 194 | * Fetches total count of appointments that require a payment. |
| 195 | * |
| 196 | * @param array &$data The display data array to fill. |
| 197 | * |
| 198 | * @return void |
| 199 | */ |
| 200 | private function fetchPaymentCount(&$data) |
| 201 | { |
| 202 | $dbo = JFactory::getDbo(); |
| 203 | |
| 204 | $data['needpay'] = 0; |
| 205 | |
| 206 | // get any approved codes with no payment |
| 207 | $approved = JHtml::fetch('vaphtml.status.find', 'code', array('appointments' => 1, 'approved' => 1, 'paid' => 0)); |
| 208 | |
| 209 | $q = $dbo->getQuery(true); |
| 210 | |
| 211 | // count total number of appointments |
| 212 | $q->select('COUNT(1)'); |
| 213 | $q->from($dbo->qn('#__vikappointments_reservation')); |
| 214 | |
| 215 | // take only the appointments that still have to be paid |
| 216 | $q->where(sprintf('(%s - %s) > 0', $dbo->qn('total_cost'), $dbo->qn('tot_paid'))); |
| 217 | // take only the appointments with check-in in the past |
| 218 | $q->where($dbo->qn('checkin_ts') . ' < ' . $dbo->q(JFactory::getDate()->toSql())); |
| 219 | |
| 220 | if ($approved) |
| 221 | { |
| 222 | // filter by approved status |
| 223 | $q->where($dbo->qn('status') . ' IN (' . implode(',', array_map(array($dbo, 'q'), $approved)) . ')'); |
| 224 | } |
| 225 | |
| 226 | $dbo->setQuery($q); |
| 227 | $dbo->execute(); |
| 228 | |
| 229 | if ($dbo->getNumRows()) |
| 230 | { |
| 231 | $data['needpay'] = (int) $dbo->loadResult(); |
| 232 | } |
| 233 | } |
| 234 | } |
| 235 |