run:R W Run
1.7 KB
2026-04-08 19:26:11
R W Run
8.34 KB
2026-04-08 19:26:11
R W Run
3.54 KB
2026-04-08 19:26:10
R W Run
1.8 KB
2026-04-08 19:26:10
R W Run
3.59 KB
2026-04-08 19:26:09
R W Run
3.19 KB
2026-04-08 19:26:10
R W Run
4.85 KB
2026-04-08 19:26:12
R W Run
2.47 KB
2026-04-08 19:26:12
R W Run
11.26 KB
2026-04-08 19:26:10
R W Run
1.34 KB
2026-04-08 19:26:10
R W Run
3.54 KB
2026-04-08 19:26:09
R W Run
4.61 KB
2026-04-08 19:26:10
R W Run
37 By
2026-04-08 19:26:09
R W Run
error_log
📄Overview.php
1<?php
2
3namespace WHMCS\Module\Widget;
4
5use AdminLang;
6use App;
7use WHMCS\Carbon;
8use WHMCS\Database\Capsule;
9use WHMCS\Module\AbstractWidget;
10use WHMCS\Order\Order;
11
12/**
13 * System Overview Widget.
14 *
15 * @copyright Copyright (c) WHMCS Limited 2005-2021
16 * @license https://www.whmcs.com/eula/ WHMCS Eula
17 */
18class Overview extends AbstractWidget
19{
20 protected $title = 'System Overview';
21 protected $description = 'An overview of orders and income.';
22 protected $columns = 2;
23 protected $weight = 10;
24 protected $requiredPermission = 'View Income Totals';
25
26 public function getData()
27 {
28 $today = Carbon::today()->startOfDay()->toDateString();
29 $month = Carbon::today()->subMonth()->startOfDay()->toDateString();
30 $year = Carbon::today()->subYear()->startOfMonth()->startOfDay()->toDateString();
31
32 $dates = [
33 'today' => '%k',
34 'month' => '%e %M',
35 'year' => '%M %Y',
36 ];
37
38 $orderData = $completeOrderData = array();
39 foreach ($dates as $dateType => $format) {
40 $data = Order::where('date', '>', $$dateType)
41 ->select(
42 [
43 Capsule::raw('date_format(date, \'' . $format . '\') as format_date'),
44 Capsule::raw('COUNT(id) as id_count'),
45 'status',
46 ]
47 )
48 ->groupBy('format_date', 'status')
49 ->get();
50
51 $xAxisData = $data->pluck('format_date');
52
53 $todayData = $completedData = [];
54 foreach ($xAxisData as $xAxisDatum) {
55 $todayData[$xAxisDatum] = $data->where('format_date', $xAxisDatum)
56 ->sum('id_count');
57 $completedData[$xAxisDatum] = $data->where('format_date', $xAxisDatum)
58 ->where('status', 'Active')
59 ->sum('id_count');
60 }
61
62 $orderData[$dateType] = $todayData;
63 $completeOrderData[$dateType] = $completedData;
64 }
65
66 $incomeData = array();
67
68 $results = Capsule::table('tblaccounts')
69 ->select(
70 Capsule::raw("DATE_FORMAT(date, '%k') AS dateTime"),
71 Capsule::raw('SUM(amountin/rate) AS amountIn')
72 )
73 ->where('date', '>', $today)
74 ->groupBy(Capsule::raw("DATE_FORMAT(date, '%k')"))
75 ->get()
76 ->all();
77
78 foreach ($results as $result) {
79 $incomeData['today'][$result->dateTime] = $result->amountIn;
80 }
81
82 $results = Capsule::table('tblaccounts')
83 ->select(
84 Capsule::raw("DATE_FORMAT(date, '%e %M') AS dateTime"),
85 Capsule::raw('SUM(amountin/rate) AS amountIn')
86 )
87 ->where('date', '>', $month)
88 ->groupBy(Capsule::raw("DATE_FORMAT(date, '%e %M')"))
89 ->get()
90 ->all();
91 foreach ($results as $result) {
92 $incomeData['month'][$result->dateTime] = $result->amountIn;
93 }
94
95 $results = Capsule::table('tblaccounts')
96 ->select(
97 Capsule::raw("DATE_FORMAT(date, '%M %Y') AS dateTime"),
98 Capsule::raw('SUM(amountin/rate) AS amountIn')
99 )
100 ->where('date', '>', $year)
101 ->groupBy(Capsule::raw("date_format(date, '%M %Y')"))
102 ->get()
103 ->all();
104
105 foreach ($results as $result) {
106 $incomeData['year'][$result->dateTime] = $result->amountIn;
107 }
108
109 return array(
110 'orders' => array(
111 'new' => $orderData,
112 'complete' => $completeOrderData,
113 ),
114 'revenue' => array(
115 'income' => $incomeData,
116 ),
117 );
118 }
119
120 public function generateOutput($data)
121 {
122 $viewPeriod = App::getFromRequest('viewperiod');
123 if (!in_array($viewPeriod, array('today', 'month', 'year'))) {
124 $viewPeriod = 'today';
125 }
126
127 $orderData = (isset($data['orders']['new'][$viewPeriod])) ? $data['orders']['new'][$viewPeriod] : [];
128 $completedOrderData = [];
129 if (isset($data['orders']['complete'][$viewPeriod])) {
130 $completedOrderData = $data['orders']['complete'][$viewPeriod];
131 }
132 $incomeData = (isset($data['revenue']['income'][$viewPeriod]))? $data['revenue']['income'][$viewPeriod] : [];
133
134 $graphLabels = $graphData = $graphData2 = $graphData3 = array();
135 if ($viewPeriod == 'today') {
136 for ($i = 0; $i <= date("H"); $i++) {
137 $graphLabels[] = date("ga", mktime($i, date("i"), date("s"), date("m"), date("d"), date("Y")));
138 $graphData[] = isset($orderData[$i]) ? $orderData[$i] : 0;
139 $graphData2[] = isset($incomeData[$i]) ? $incomeData[$i] : 0;
140 $graphData3[] = isset($completedOrderData[$i]) ? $completedOrderData[$i] : 0;
141 }
142 } elseif ($viewPeriod == 'month') {
143 for ($i = 0; $i < 30; $i++) {
144 $time = mktime(0, 0, 0, date("m"), date("d") - $i, date("Y"));
145 $graphLabels[] = date("jS", $time);
146 $graphData[] = isset($orderData[date("j F", $time)]) ? $orderData[date("j F", $time)] : 0;
147 $graphData2[] = isset($incomeData[date("j F", $time)]) ? $incomeData[date("j F", $time)] : 0;
148 $graphData3[] = isset($completedOrderData[date("j F", $time)])
149 ? $completedOrderData[date("j F", $time)]
150 : 0;
151 }
152
153 $graphLabels = array_reverse($graphLabels);
154 $graphData = array_reverse($graphData);
155 $graphData2 = array_reverse($graphData2);
156 $graphData3 = array_reverse($graphData3);
157 } elseif ($viewPeriod == 'year') {
158 for ($i = 0; $i < 12; $i++) {
159 $time = mktime(0, 0, 0, date("m") - $i, 1, date("Y"));
160 $graphLabels[] = date("F y", $time);
161 $graphData[] = isset($orderData[date("F Y", $time)]) ? $orderData[date("F Y", $time)] : 0;
162 $graphData2[] = isset($incomeData[date("F Y", $time)]) ? $incomeData[date("F Y", $time)] : 0;
163 $graphData3[] = isset($completedOrderData[date("F Y", $time)])
164 ? $completedOrderData[date("F Y", $time)]
165 : 0;
166 }
167
168 $graphLabels = array_reverse($graphLabels);
169 $graphData = array_reverse($graphData);
170 $graphData2 = array_reverse($graphData2);
171 $graphData3 = array_reverse($graphData3);
172 }
173
174 $graphLabels = '"' . implode('","', $graphLabels) . '"';
175 $graphData = implode(',', $graphData);
176 $graphData2 = implode(',', $graphData2);
177 $graphData3 = implode(',', $graphData3);
178
179 $activeToday = ($viewPeriod == 'today') ? ' active' : '';
180 $activeThisMonth = ($viewPeriod == 'month') ? ' active' : '';
181 $activeThisYear = ($viewPeriod == 'year') ? ' active' : '';
182
183 $langToday = AdminLang::trans('billing.incometoday');
184 $langActiveThisMonth = AdminLang::trans('billing.incomethismonth');
185 $langActiveThisYear = AdminLang::trans('billing.incomethisyear');
186
187 $langNewOrders = AdminLang::trans('home.newOrders');
188 $langActivatedOrders = AdminLang::trans('home.activatedOrders');
189 $langIncome = AdminLang::trans('billing.income');
190 $langOrders = AdminLang::trans('orders.title');
191
192 return <<<EOF
193<div style="padding:20px;">
194 <div class="btn-group btn-group-sm btn-period-chooser" role="group" aria-label="...">
195 <button type="button" class="btn btn-default{$activeToday}" data-period="today">{$langToday}</button>
196 <button type="button" class="btn btn-default{$activeThisMonth}" data-period="month">{$langActiveThisMonth}</button>
197 <button type="button" class="btn btn-default{$activeThisYear}" data-period="year">{$langActiveThisYear}</button>
198 </div>
199</div>
200
201<div style="width:100%;height:317px;overflow:hidden">
202 <div id="myChartParent">
203 <canvas id="myChart" height="277"></canvas>
204 </div>
205</div>
206
207<script>
208
209$(document).ready(function() {
210 var chartObject = null;
211 var windowResizeTimeoutId = null;
212
213 $('.btn-period-chooser button').click(function() {
214 $('.btn-period-chooser button').removeClass('active');
215 $(this).addClass('active');
216 refreshWidget('Overview', 'viewperiod=' + $(this).data('period'));
217 });
218
219 $(window).resize(function() {
220 if (windowResizeTimeoutId) {
221 clearTimeout(windowResizeTimeoutId);
222 windowResizeTimeoutId = null;
223 }
224
225 windowResizeTimeoutId = setTimeout(function() {
226 if (typeof chartObject === 'object') {
227 chartObject.resize(false);
228 }
229 }, 250);
230 });
231
232 var lineData = {
233 labels: [{$graphLabels}],
234 datasets: [
235 {
236 label: '{$langNewOrders}',
237 backgroundColor: "rgba(220,220,220,0.5)",
238 borderColor: "rgba(220,220,220,1)",
239 pointBackgroundColor: "rgba(220,220,220,1)",
240 pointBorderColor: "#fff",
241 yAxisID: "y-axis-0",
242 data: [{$graphData}],
243 type: 'line',
244 lineTension: 0
245 },
246 {
247 label: '{$langActivatedOrders}',
248 backgroundColor: "rgba(51,92,249,0.5)",
249 borderColor: "rgba(51,92,249,1)",
250 pointBackgroundColor: "rgba(51,92,249,1)",
251 pointBorderColor: "#fff",
252 yAxisID: "y-axis-0",
253 data: [{$graphData3}]
254 },
255 {
256 label: '{$langIncome}',
257 backgroundColor: "rgba(93,197,96,0.5)",
258 borderColor: "rgba(93,197,96,1)",
259 pointBackgroundColor: "rgba(93,197,96,1)",
260 pointBorderColor: "#fff",
261 yAxisID: "y-axis-1",
262 data: [{$graphData2}],
263 type: 'line'
264 }
265 ]
266 };
267
268 var canvas = document.getElementById("myChart");
269 var parent = document.getElementById('myChartParent');
270
271 canvas.width = parent.offsetWidth;
272 canvas.height = parent.offsetHeight;
273
274 var ctx = $("#myChart");
275 var chartObject = new Chart(ctx, {
276 type: 'bar',
277 data: lineData,
278 options: {
279 responsive: false,
280 maintainAspectRatio: false,
281 responsiveAnimationDuration: 500,
282 scales: {
283 yAxes: [
284 {
285 position: "left",
286 "id": "y-axis-0",
287 scaleLabel: {
288 display: true,
289 labelString: '{$langOrders}'
290 },
291 ticks: {
292 beginAtZero: true
293 }
294 },
295 {
296 position: "right",
297 "id": "y-axis-1",
298 scaleLabel: {
299 display: true,
300 labelString: '{$langIncome}'
301 },
302 ticks: {
303 beginAtZero: true
304 }
305 }
306 ]
307 }
308 }
309 });
310});
311</script>
312EOF;
313 }
314}
315