diff --git a/source/packages/com_mokosuitenpo/api/src/Controller/NpoReportsController.php b/source/packages/com_mokosuitenpo/api/src/Controller/NpoReportsController.php new file mode 100644 index 0000000..60d80b8 --- /dev/null +++ b/source/packages/com_mokosuitenpo/api/src/Controller/NpoReportsController.php @@ -0,0 +1,123 @@ +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 annualReport(): void + { + $this->requireAuth(); + $year = Factory::getApplication()->getInput()->getInt('year', (int) date('Y')); + $summary = \Moko\Plugin\System\MokoSuiteNpo\Helper\ImpactReportHelper::getAnnualSummary($year); + $this->sendJson($summary); + } + + public function donorImpact(): void + { + $this->requireAuth(); + $input = Factory::getApplication()->getInput(); + $impact = \Moko\Plugin\System\MokoSuiteNpo\Helper\ImpactReportHelper::getDonorImpact( + $input->getInt('donor_id', 0), + $input->getInt('year', (int) date('Y')) + ); + $this->sendJson($impact); + } + + public function listRecurring(): void + { + $this->requireAuth(); + $db = Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class); + + $db->setQuery($db->getQuery(true) + ->select('p.*, cd.name AS donor_name') + ->from($db->quoteName('#__mokosuitenpo_pledges', 'p')) + ->join('INNER', $db->quoteName('#__mokosuitenpo_donors', 'd') . ' ON d.id = p.donor_id') + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = d.contact_id') + ->where($db->quoteName('p.status') . ' = ' . $db->quote('active')) + ->where('p.saved_payment_id IS NOT NULL') + ->order('p.next_charge_date ASC')); + + $this->sendJson($db->loadObjectList() ?: []); + } + + public function createRecurring(): void + { + $this->requireAuth('npo.donations'); + $input = Factory::getApplication()->getInput(); + + $id = \Moko\Plugin\System\MokoSuiteNpo\Helper\RecurringDonationHelper::createPledge( + $input->getInt('donor_id', 0), + $input->getFloat('amount', 0), + $input->getString('frequency', 'monthly'), + $input->getInt('saved_payment_id', 0), + $input->getInt('fund_id', 0) ?: null + ); + + $this->sendJson(['success' => true, 'pledge_id' => $id]); + } + + public function cancelRecurring(): void + { + $this->requireAuth('npo.donations'); + $id = Factory::getApplication()->getInput()->getInt('id', 0); + + $db = Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class); + + // Verify pledge exists and is active before cancelling + $db->setQuery($db->getQuery(true) + ->select('id, status') + ->from('#__mokosuitenpo_pledges') + ->where('id = ' . (int) $id)); + $pledge = $db->loadObject(); + + if (!$pledge) { + http_response_code(404); + $this->sendJson(['success' => false, 'error' => 'Pledge not found']); + return; + } + if ($pledge->status !== 'active') { + $this->sendJson(['success' => false, 'error' => 'Pledge is not active']); + return; + } + + $db->setQuery($db->getQuery(true) + ->update('#__mokosuitenpo_pledges') + ->set($db->quoteName('status') . ' = ' . $db->quote('cancelled')) + ->set($db->quoteName('cancelled_at') . ' = ' . $db->quote(Factory::getDate()->toSql())) + ->where('id = ' . (int) $id) + ->where($db->quoteName('status') . ' = ' . $db->quote('active'))); + $db->execute(); + + $this->sendJson(['success' => true]); + } + + 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(); + } +} diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 4135fa0..f291a57 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.01.00 + 01.01.01 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index dbef4db..0758b55 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.01.00 + 01.01.01 2026-06-11 Moko Consulting hello@mokoconsulting.tech