/home/edulekha/crm.edulekha.com/modules/appointly/controllers/Reports.php
<?php
defined('BASEPATH') or exit('No direct script access allowed');
class Reports extends AdminController
{
public function __construct()
{
parent::__construct();
$this->load->model('appointly/reports_model');
}
public function index()
{
if (!staff_can('view_reports', 'appointments')) {
access_denied('view_reports');
}
// Set default date range (current month)
$data['date_from'] = date('Y-m-01'); // First day of current month
$data['date_to'] = date('Y-m-t'); // Last day of current month
// Check if dates are passed via GET
if ($this->input->get('date_from') && $this->input->get('date_to')) {
$data['date_from'] = $this->try_parse_date($this->input->get('date_from'));
$data['date_to'] = $this->try_parse_date($this->input->get('date_to'));
}
// Load report data
$this->load_report_data($data, $data['date_from'], $data['date_to']);
// title and load the view
$data['title'] = _l('appointly_reports_dashboard');
$this->load->view('reports/dashboard', $data);
}
public function filter_data()
{
// Check if user has permission
if (!staff_can('view_reports', 'appointments')) {
ajax_access_denied();
}
// Validate date inputs
$date_from = $this->input->post('date_from');
$date_to = $this->input->post('date_to');
// Try to parse dates or use defaults
$date_from = $this->try_parse_date($date_from);
$date_to = $this->try_parse_date($date_to);
// Load required data
$data = [];
$this->load_report_data($data, $date_from, $date_to);
// Return JSON response
echo json_encode([
'success' => true,
'data' => $data
]);
}
public function get_date_range()
{
// Check permission
if (!staff_can('view_reports', 'appointments')) {
echo json_encode([
'success' => false,
'message' => _l('access_denied')
]);
return;
}
// Get range param
$range = $this->input->post('range');
if (!$range) {
echo json_encode([
'success' => false,
'message' => 'Range parameter is required'
]);
return;
}
// Get current year
$current_year = date('Y');
// Get date range
$dates = [];
switch ($range) {
case 'today':
$dates['date_from'] = date('Y-m-d');
$dates['date_to'] = date('Y-m-d');
break;
case 'this_week':
$dates['date_from'] = date('Y-m-d', strtotime('monday this week'));
$dates['date_to'] = date('Y-m-d', strtotime('sunday this week'));
break;
case 'this_month':
$dates['date_from'] = date('Y-m-01');
$dates['date_to'] = date('Y-m-t');
break;
case 'this_year':
$dates['date_from'] = $current_year . '-01-01';
$dates['date_to'] = $current_year . '-12-31';
break;
case 'last_month':
$dates['date_from'] = date('Y-m-01', strtotime('first day of last month'));
$dates['date_to'] = date('Y-m-t', strtotime('last day of last month'));
break;
case 'last_year':
$previous_year = $current_year - 1;
$dates['date_from'] = $previous_year . '-01-01';
$dates['date_to'] = $previous_year . '-12-31';
break;
default:
$dates['date_from'] = date('Y-m-01');
$dates['date_to'] = date('Y-m-t');
break;
}
// Return as JSON with display format
echo json_encode([
'success' => true,
'date_from' => $dates['date_from'],
'date_to' => $dates['date_to'],
'date_from_display' => _d($dates['date_from']),
'date_to_display' => _d($dates['date_to'])
]);
}
public function refresh_stats()
{
// Check if user has permission
if (!staff_can('view_reports', 'appointments')) {
ajax_access_denied();
}
// Validate date inputs
$date_from = $this->input->post('date_from');
$date_to = $this->input->post('date_to');
if (!$date_from || !$date_to) {
echo json_encode([
'success' => false,
'message' => _l('appointly_date_range_required')
]);
return;
}
// Try to parse dates or use defaults
$date_from = $this->try_parse_date($date_from);
$date_to = $this->try_parse_date($date_to);
// Load required data
$data = [];
$this->load_report_data($data, $date_from, $date_to);
// Return JSON response
echo json_encode([
'success' => true,
'data' => $data,
'formatted_date_from' => _d($date_from),
'formatted_date_to' => _d($date_to)
]);
}
private function load_report_data(&$data, $date_from = null, $date_to = null)
{
// If no dates provided, use current month
if (!$date_from) {
$date_from = date('Y-m-01');
}
if (!$date_to) {
$date_to = date('Y-m-t');
}
// Load Reports model
$this->load->model('appointly/reports_model');
// Calculate total appointments in date range
$total_appointments = $this->reports_model->get_total_appointments($date_from, $date_to);
$data['total_appointments'] = $total_appointments;
// Calculate completed appointments in date range
$completed_appointments = $this->reports_model->get_completed_appointments($date_from, $date_to);
$data['completed_appointments'] = $completed_appointments;
// Calculate cancelled appointments in date range
$cancelled_appointments = $this->reports_model->get_cancelled_appointments($date_from, $date_to);
$data['cancelled_appointments'] = $cancelled_appointments;
// Calculate staff performance
$staff_performance = $this->reports_model->get_staff_performance($date_from, $date_to);
$data['staff_performance'] = $staff_performance;
// Calculate monthly statistics for the period
$monthly_stats = $this->reports_model->get_monthly_appointments_stats($date_from, $date_to);
// Prepare data for charts - extract dates for labels
$labels = [];
$totals = [];
$completed = [];
$cancelled = [];
foreach ($monthly_stats as $day_stat) {
// Format the date for display (e.g., Apr 01, Apr 02, etc.)
$labels[] = date('M d', strtotime($day_stat['date']));
$totals[] = (int)$day_stat['total'];
$completed[] = (int)$day_stat['completed'];
$cancelled[] = (int)$day_stat['cancelled'];
}
$data['monthly_stats'] = [
'labels' => $labels,
'total' => $totals,
'completed' => $completed,
'cancelled' => $cancelled
];
// Get popular services
$popular_services = $this->reports_model->get_popular_services($date_from, $date_to);
$data['popular_services'] = [
'labels' => array_column($popular_services, 'name'),
'counts' => array_column($popular_services, 'count')
];
// formatted dates for display
$data['formatted_date_from'] = _d($date_from);
$data['formatted_date_to'] = _d($date_to);
}
/**
* Helper function to try parsing date from different formats
* @param string $date_string Date string to parse
* @return string Date in SQL format (Y-m-d)
*/
private function try_parse_date($date_string)
{
// Return today if no date provided
if (empty($date_string)) {
return date('Y-m-d');
}
// Already in SQL format
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date_string)) {
return $date_string;
}
// Try parsing with DateTime
try {
// Check if we have app date format from settings
$app_date_format = get_option('dateformat');
$app_date_format = str_replace('Y', 'y', $app_date_format);
$app_date_format = str_replace('m', 'M', $app_date_format);
$app_date_format = str_replace('d', 'd', $app_date_format);
$date = DateTime::createFromFormat($app_date_format, $date_string);
// If failed with app format, try common formats
if (!$date) {
// Try common formats
$formats = [
'd/m/Y',
'm/d/Y',
'Y/m/d',
'd-m-Y',
'm-d-Y',
'Y-m-d',
'd.m.Y',
'm.d.Y',
'Y.m.d',
];
foreach ($formats as $format) {
$date = DateTime::createFromFormat($format, $date_string);
if ($date) {
break;
}
}
}
// If still no valid date, try strtotime as last resort
if (!$date && strtotime($date_string)) {
$date = new DateTime($date_string);
}
// If we have a valid date, format it for SQL
if ($date) {
return $date->format('Y-m-d');
}
} catch (Exception $e) {
log_message('error', 'Date parsing error: ' . $e->getMessage());
}
// Default to today if all else fails
return date('Y-m-d');
}
/**
* Get appointment stats table data
*/
public function table()
{
if (!staff_can('view_reports', 'appointments')) {
ajax_access_denied();
}
// Get date range from POST
$date_from = $this->input->post('date_from');
$date_to = $this->input->post('date_to');
// Default to current month if no dates provided
if (!$date_from) {
$date_from = date('Y-m-01');
}
if (!$date_to) {
$date_to = date('Y-m-t');
}
// Try to parse dates
$date_from = $this->try_parse_date($date_from);
$date_to = $this->try_parse_date($date_to);
$total_appointments = $this->reports_model->get_total_appointments($date_from, $date_to);
// Pass date parameters to the view
$this->app->get_table_data(
module_views_path('appointly', 'tables/appointments_stats'),
[
'date_from' => $date_from,
'date_to' => $date_to,
'total_appointments' => $total_appointments
]
);
}
}