feat: NpoDonorController API #15

Merged
jmiller merged 1 commits from dev into main 2026-06-18 17:47:35 +00:00
@@ -0,0 +1,111 @@
<?php
namespace Moko\Component\MokoSuiteNpo\Api\Controller;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\Database\DatabaseInterface;
/**
* Donor management + Recurring donations API.
*
* GET /donors — List donors with lifetime giving
* GET /donors/{id} — Donor detail with giving history
* GET /donors/{id}/pledges — Active recurring pledges
* POST /donors/{id}/pledges — Create recurring pledge
* DELETE /donors/{id}/pledges/{pid}— Cancel pledge
* GET /recurring/summary — Recurring revenue summary
*/
class NpoDonorController extends BaseController
{
private function requireAuth(string $action = 'core.manage'): void
{
$user = Factory::getApplication()->getIdentity();
if (!$user || $user->guest || (!$user->authorise('core.admin') && !$user->authorise($action, 'com_mokosuitenpo'))) {
http_response_code(403);
echo json_encode(['error' => 'Access denied']);
Factory::getApplication()->close();
}
}
public function listDonors(): void
{
$this->requireAuth('npo.donors');
$input = Factory::getApplication()->getInput();
$model = new \Moko\Component\MokoSuiteNpo\Administrator\Model\DonorsModel();
$donors = $model->getItems(
$input->getString('search', ''),
$input->getString('type', ''),
$input->getString('level', ''),
$input->getInt('limit', 50)
);
$this->sendJson($donors);
}
public function getDonor(): void
{
$this->requireAuth('npo.donors');
$id = Factory::getApplication()->getInput()->getInt('id', 0);
$model = new \Moko\Component\MokoSuiteNpo\Administrator\Model\DonorsModel();
$donor = $model->getDonor($id);
if (!$donor) {
http_response_code(404);
$this->sendJson(['error' => 'Donor not found']);
return;
}
// Get recent donations
$donationsModel = new \Moko\Component\MokoSuiteNpo\Administrator\Model\DonationsModel();
$donor->recent_donations = $donationsModel->getItems('', '', (int) $donor->id, 0, 0, 20);
$this->sendJson($donor);
}
public function donorPledges(): void
{
$this->requireAuth('npo.donors');
$donorId = Factory::getApplication()->getInput()->getInt('id', 0);
$pledges = \Moko\Plugin\System\MokoSuiteNpo\Helper\RecurringDonationHelper::getDonorPledges($donorId);
$this->sendJson($pledges);
}
public function createPledge(): void
{
$this->requireAuth('npo.donors');
$input = Factory::getApplication()->getInput();
$pledgeId = \Moko\Plugin\System\MokoSuiteNpo\Helper\RecurringDonationHelper::createPledge(
$input->getInt('donor_id', 0),
$input->getFloat('amount', 0),
$input->getString('frequency', 'monthly'),
$input->getInt('fund_id', 0),
$input->getInt('saved_payment_id', 0) ?: null
);
$this->sendJson(['success' => true, 'pledge_id' => $pledgeId]);
}
public function cancelPledge(): void
{
$this->requireAuth('npo.donors');
$pledgeId = Factory::getApplication()->getInput()->getInt('pledge_id', 0);
$result = \Moko\Plugin\System\MokoSuiteNpo\Helper\RecurringDonationHelper::cancelPledge($pledgeId);
$this->sendJson(['success' => $result]);
}
public function recurringSummary(): void
{
$this->requireAuth('npo.donors');
$summary = \Moko\Plugin\System\MokoSuiteNpo\Helper\RecurringDonationHelper::getRecurringSummary();
$this->sendJson($summary);
}
private function sendJson(mixed $data): void
{
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);
Factory::getApplication()->close();
}
}