|
|
|
@@ -0,0 +1,105 @@
|
|
|
|
|
<?php
|
|
|
|
|
namespace Moko\Plugin\System\MokoSuiteNpo\Helper;
|
|
|
|
|
|
|
|
|
|
defined('_JEXEC') or die;
|
|
|
|
|
|
|
|
|
|
use Joomla\CMS\Factory;
|
|
|
|
|
use Joomla\Database\DatabaseInterface;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Board of directors management — member terms, committees, meeting minutes, attendance.
|
|
|
|
|
*/
|
|
|
|
|
class BoardManagementHelper
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* Get current board members with term status.
|
|
|
|
|
*/
|
|
|
|
|
public static function getCurrentMembers(): array
|
|
|
|
|
{
|
|
|
|
|
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
|
|
|
|
|
|
|
|
|
$db->setQuery($db->getQuery(true)
|
|
|
|
|
->select('bm.*, cd.name, cd.email_to, cd.telephone')
|
|
|
|
|
->select('CASE WHEN bm.term_end < NOW() THEN ' . $db->quote('expired')
|
|
|
|
|
. ' WHEN bm.term_end < DATE_ADD(NOW(), INTERVAL 90 DAY) THEN ' . $db->quote('expiring_soon')
|
|
|
|
|
. ' ELSE ' . $db->quote('active') . ' END AS term_status')
|
|
|
|
|
->from($db->quoteName('#__mokosuitenpo_board_members', 'bm'))
|
|
|
|
|
->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = bm.contact_id')
|
|
|
|
|
->where($db->quoteName('bm.status') . ' = ' . $db->quote('active'))
|
|
|
|
|
->order('bm.role ASC, cd.name ASC'));
|
|
|
|
|
|
|
|
|
|
return $db->loadObjectList() ?: [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get committee assignments.
|
|
|
|
|
*/
|
|
|
|
|
public static function getCommittees(): array
|
|
|
|
|
{
|
|
|
|
|
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
|
|
|
|
|
|
|
|
|
$db->setQuery($db->getQuery(true)
|
|
|
|
|
->select('c.id, c.name AS committee_name, c.description')
|
|
|
|
|
->select('(SELECT COUNT(*) FROM #__mokosuitenpo_committee_members cm WHERE cm.committee_id = c.id AND cm.status = ' . $db->quote('active') . ') AS member_count')
|
|
|
|
|
->select('(SELECT cd2.name FROM #__mokosuitenpo_committee_members cm2'
|
|
|
|
|
. ' JOIN #__contact_details cd2 ON cd2.id = cm2.contact_id'
|
|
|
|
|
. ' WHERE cm2.committee_id = c.id AND cm2.role = ' . $db->quote('chair')
|
|
|
|
|
. ' AND cm2.status = ' . $db->quote('active') . ' LIMIT 1) AS chair_name')
|
|
|
|
|
->from($db->quoteName('#__mokosuitenpo_committees', 'c'))
|
|
|
|
|
->where($db->quoteName('c.status') . ' = ' . $db->quote('active'))
|
|
|
|
|
->order('c.name ASC'));
|
|
|
|
|
|
|
|
|
|
return $db->loadObjectList() ?: [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get meeting attendance rate for a board member.
|
|
|
|
|
*/
|
|
|
|
|
public static function getAttendanceRate(int $contactId, int $months = 12): object
|
|
|
|
|
{
|
|
|
|
|
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
|
|
|
|
$since = date('Y-m-d', strtotime("-{$months} months"));
|
|
|
|
|
|
|
|
|
|
$db->setQuery($db->getQuery(true)
|
|
|
|
|
->select('COUNT(*) AS total_meetings')
|
|
|
|
|
->select('SUM(CASE WHEN ma.status = ' . $db->quote('present') . ' THEN 1 ELSE 0 END) AS attended')
|
|
|
|
|
->select('SUM(CASE WHEN ma.status = ' . $db->quote('absent') . ' THEN 1 ELSE 0 END) AS absent')
|
|
|
|
|
->select('SUM(CASE WHEN ma.status = ' . $db->quote('excused') . ' THEN 1 ELSE 0 END) AS excused')
|
|
|
|
|
->from($db->quoteName('#__mokosuitenpo_meeting_attendance', 'ma'))
|
|
|
|
|
->join('INNER', $db->quoteName('#__mokosuitenpo_meetings', 'm') . ' ON m.id = ma.meeting_id')
|
|
|
|
|
->where('ma.contact_id = ' . (int) $contactId)
|
|
|
|
|
->where('m.meeting_date >= ' . $db->quote($since)));
|
|
|
|
|
|
|
|
|
|
$stats = $db->loadObject();
|
|
|
|
|
$total = (int) ($stats->total_meetings ?? 0);
|
|
|
|
|
|
|
|
|
|
return (object) [
|
|
|
|
|
'contact_id' => $contactId,
|
|
|
|
|
'total_meetings' => $total,
|
|
|
|
|
'attended' => (int) ($stats->attended ?? 0),
|
|
|
|
|
'absent' => (int) ($stats->absent ?? 0),
|
|
|
|
|
'excused' => (int) ($stats->excused ?? 0),
|
|
|
|
|
'attendance_pct' => $total > 0 ? round((int) $stats->attended / $total * 100, 1) : 0,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get terms expiring within N days.
|
|
|
|
|
*/
|
|
|
|
|
public static function getExpiringTerms(int $days = 90): array
|
|
|
|
|
{
|
|
|
|
|
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
|
|
|
|
$cutoff = date('Y-m-d', strtotime("+{$days} days"));
|
|
|
|
|
|
|
|
|
|
$db->setQuery($db->getQuery(true)
|
|
|
|
|
->select('bm.id, bm.role, bm.term_start, bm.term_end')
|
|
|
|
|
->select('cd.name, cd.email_to')
|
|
|
|
|
->from($db->quoteName('#__mokosuitenpo_board_members', 'bm'))
|
|
|
|
|
->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = bm.contact_id')
|
|
|
|
|
->where($db->quoteName('bm.status') . ' = ' . $db->quote('active'))
|
|
|
|
|
->where('bm.term_end BETWEEN ' . $db->quote(date('Y-m-d')) . ' AND ' . $db->quote($cutoff))
|
|
|
|
|
->order('bm.term_end ASC'));
|
|
|
|
|
|
|
|
|
|
return $db->loadObjectList() ?: [];
|
|
|
|
|
}
|
|
|
|
|
}
|