Add GrantReportingHelper — spending reports, funder compliance, deadline tracking
Universal: Auto Version Bump / Version Bump (push) Successful in 10s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 28s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
Universal: Auto Version Bump / Version Bump (push) Successful in 10s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 28s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
namespace Moko\Plugin\System\MokoSuiteNpo\Helper;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
|
||||
/**
|
||||
* Grant reporting — deliverable tracking, spending reports, funder compliance.
|
||||
*/
|
||||
class GrantReportingHelper
|
||||
{
|
||||
/**
|
||||
* Get grant spending report — budgeted vs actual by category.
|
||||
*/
|
||||
public static function getSpendingReport(int $grantId): object
|
||||
{
|
||||
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
||||
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('g.*, cd.name AS funder_name')
|
||||
->from($db->quoteName('#__mokosuitenpo_grants', 'g'))
|
||||
->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = g.funder_contact_id')
|
||||
->where('g.id = ' . (int) $grantId));
|
||||
$grant = $db->loadObject();
|
||||
|
||||
if (!$grant) return (object) ['found' => false];
|
||||
|
||||
// Get expenses charged to this grant's fund
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('category, COUNT(*) AS count, COALESCE(SUM(amount), 0) AS spent')
|
||||
->from('#__mokosuitenpo_fund_expenses')
|
||||
->where('fund_id = ' . (int) ($grant->fund_id ?? 0))
|
||||
->group('category')
|
||||
->order('spent DESC'));
|
||||
$grant->spending_by_category = $db->loadObjectList() ?: [];
|
||||
|
||||
$grant->total_spent = array_sum(array_column($grant->spending_by_category, 'spent'));
|
||||
$grant->remaining = max(0, (float) ($grant->amount ?? 0) - (float) $grant->total_spent);
|
||||
$grant->utilization_pct = (float) ($grant->amount ?? 0) > 0
|
||||
? round((float) $grant->total_spent / (float) $grant->amount * 100, 1) : 0;
|
||||
|
||||
return $grant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get grants requiring reports soon.
|
||||
*/
|
||||
public static function getUpcomingReportDeadlines(int $days = 30): array
|
||||
{
|
||||
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
||||
|
||||
$db->setQuery($db->getQuery(true)
|
||||
->select('g.id, g.title, g.funder, g.report_due_date, g.amount')
|
||||
->select('DATEDIFF(g.report_due_date, CURDATE()) AS days_until_due')
|
||||
->from($db->quoteName('#__mokosuitenpo_grants', 'g'))
|
||||
->where($db->quoteName('g.status') . ' IN (' . $db->quote('active') . ',' . $db->quote('reporting') . ')')
|
||||
->where($db->quoteName('g.report_due_date') . ' IS NOT NULL')
|
||||
->where($db->quoteName('g.report_due_date') . ' BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL ' . (int) $days . ' DAY)')
|
||||
->order('g.report_due_date ASC'));
|
||||
|
||||
return $db->loadObjectList() ?: [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user