Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9dda79f
Add finance module Slim 4 MVC structure
DawoudIO Dec 2, 2025
4aa0bbe
Add finance module SCSS styles
DawoudIO Dec 2, 2025
ffd5500
Add dashboard methods to FinancialService
DawoudIO Dec 2, 2025
1a2b750
Update menu from Deposit to Finance with Dashboard link
DawoudIO Dec 2, 2025
a83a452
Allow admins to access finance routes via middleware
DawoudIO Dec 2, 2025
1e4e04b
Improve PledgeEditor UX to distinguish Pledge vs Payment mode
DawoudIO Dec 2, 2025
bd0645a
Add reusable system-settings-panel webpack component
DawoudIO Dec 2, 2025
f9c2d99
Add Cypress tests for finance dashboard and reports index
DawoudIO Dec 2, 2025
6ff142a
Add nofinance test user for access control testing
DawoudIO Dec 2, 2025
bf9ab00
Add integration tests for finance dashboard navigation
DawoudIO Dec 2, 2025
b24e2c6
Potential fix for pull request finding 'Unused variable, import, func…
DawoudIO Dec 2, 2025
dceda75
Update webpack/system-settings-panel.js
DawoudIO Dec 2, 2025
133e8ef
Update copilot-instructions.md
DawoudIO Dec 2, 2025
a3c77ff
Merge branch 'feature/finance-dashboard-module' of https://github.com…
DawoudIO Dec 2, 2025
679921c
Update index.php
DawoudIO Dec 2, 2025
207a805
Update messages.po
DawoudIO Dec 2, 2025
d823d5b
Update system-settings-panel.scss
DawoudIO Dec 2, 2025
0f4a629
settingsHtml
DawoudIO Dec 2, 2025
44975d4
fixed test by adding a new user
DawoudIO Dec 2, 2025
83aced1
Merge branch 'master' into feature/finance-dashboard-module
DawoudIO Dec 2, 2025
425ca1a
Fix: delegate MakeFYString to FinancialService::formatFiscalYear and …
DawoudIO Dec 2, 2025
d9473f3
Merge branch 'master' into feature/finance-dashboard-module
DawoudIO Dec 2, 2025
874e8a0
Update private.admin.user.settings.spec.js
DawoudIO Dec 2, 2025
39c5b5b
Merge branch 'master' into feature/finance-dashboard-module
DawoudIO Dec 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ Routing & middleware
- Routes are prefixed with `/admin/api/` when accessed from frontend
- Use kebab-case for endpoint names (e.g., `/delete-all`)
- AdminRoleAuthMiddleware is applied at the router level
- **Finance Module** (consolidated at `/finance/`):
- Entry point: `src/finance/index.php` with Slim 4 app
- Routes in `src/finance/routes/` (dashboard.php, reports.php)
- Views in `src/finance/views/` with PhpRenderer
- Examples: `/finance/` (dashboard), `/finance/reports`
- Use FinanceRoleAuthMiddleware for security (allows admin OR finance permission)
- Menu entry in `src/ChurchCRM/Config/Menu/Menu.php` under "Finance"
- **Deprecated locations** (DO NOT USE):
- `src/v2/routes/admin/` - REMOVED (admin routes consolidated to `/admin/system/`)
- `src/api/routes/system/` - Legacy admin APIs (no new files here)
Expand Down Expand Up @@ -464,6 +471,7 @@ describe('Feature X', () => {
**Available Commands:**
- `cy.setupAdminSession()` - Authenticates as admin (reads `admin.username`, `admin.password` from config)
- `cy.setupStandardSession()` - Authenticates as standard user (reads `standard.username`, `standard.password` from config)
- `cy.setupNoFinanceSession()` - Authenticates as user without finance permission (reads `nofinance.username`, `nofinance.password` from config)
- `cy.typeInQuill()` - Rich text editor input

**Credentials Configuration:**
Expand All @@ -474,6 +482,8 @@ env: {
'admin.password': 'changeme',
'standard.username': 'tony.wade@example.com',
'standard.password': 'basicjoe',
'nofinance.username': 'judith.matthews@example.com',
'nofinance.password': 'noMoney$',
}
```
- DO NOT hardcode credentials in test files
Expand Down Expand Up @@ -598,6 +608,7 @@ Before committing code changes, verify:
| `src/ChurchCRM/model/ChurchCRM/` | Propel ORM generated classes (don't edit) |
| `src/api/` | REST API entry point + routes |
| `src/admin/routes/api/` | Admin-only API endpoints (NEW - use this for admin APIs) |
| `src/finance/` | Finance module (Slim 4 MVC) - dashboard, reports |
| `src/Include/` | Utility functions, helpers, Config.php |
| `src/locale/` | i18n/translation strings |
| `src/skin/v2/` | Compiled CSS/JS from Webpack |
Expand Down Expand Up @@ -765,6 +776,6 @@ This ensures security vulnerabilities are not publicly disclosed and directs rep

---

Last updated: November 9, 2025
Last updated: December 1, 2025

```
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/// <reference types="cypress" />

// Use user 99 (amanda.black) for these tests to avoid conflicts with
// user 95 (judith.matthews) which is used for nofinance session tests
describe("API Private Admin User", () => {
it("Reset User failed logins", () => {
cy.makePrivateAdminAPICall(
"POST",
"/api/user/95/login/reset",
"/api/user/99/login/reset",
null,
200,
);
Expand All @@ -13,7 +15,7 @@ describe("API Private Admin User", () => {
it("Reset User Password", () => {
cy.makePrivateAdminAPICall(
"POST",
"/api/user/95/password/reset",
"/api/user/99/password/reset",
null,
200,
);
Expand All @@ -22,7 +24,7 @@ describe("API Private Admin User", () => {
it("DisableTwoFactor", () => {
cy.makePrivateAdminAPICall(
"POST",
"/api/user/95/disableTwoFactor",
"/api/user/99/disableTwoFactor",
null,
200,
);
Expand Down
6 changes: 3 additions & 3 deletions cypress/e2e/ui/admin/admin.user.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ describe("Admin User Password", () => {
});

it("Admin Change password", () => {
cy.visit("v2/user/95/changePassword");
cy.contains("Change Password: Judith Kennedy");
cy.visit("v2/user/99/changePassword");
cy.contains("Change Password: Amanda Black");
cy.get("#NewPassword1").type("new-user-password");
cy.get("#NewPassword2").type("new-user-password");
cy.get("form:nth-child(2)").submit();
cy.url().should("contain", "v2/user/95/changePassword");
cy.url().should("contain", "v2/user/99/changePassword");
cy.contains("Password Change Successful");
});

Expand Down
179 changes: 179 additions & 0 deletions cypress/e2e/ui/finance/finance.dashboard.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/// <reference types="cypress" />

/**
* Finance Dashboard Tests
*
* Tests for the new /finance/ module with Slim 4 MVC structure.
* The finance dashboard provides:
* - YTD payment and pledge metrics
* - Tax year reporting checklist
* - Quick actions for deposits and reports
* - Recent deposits list
* - Donation funds overview
*/

describe("Finance Dashboard", () => {
beforeEach(() => {
cy.setupAdminSession();
});

it("should load the finance dashboard", () => {
cy.visit("/finance/");
cy.contains("Finance Dashboard");
cy.contains("Fiscal Year");
});

it("should display YTD metrics cards", () => {
cy.visit("/finance/");

// Check for the 4 metric cards
cy.contains("YTD Payments");
cy.contains("YTD Pledges");
cy.contains("Donor Families");
cy.contains("Total Payments");
});

it("should display Quick Actions section", () => {
cy.visit("/finance/");

cy.contains("Quick Actions");
cy.contains("Create Deposit");
cy.contains("Add Payment");
cy.contains("Generate Reports");
});

it("should navigate to deposits page from Create Deposit button", () => {
cy.visit("/finance/");

// Find and click the Create Deposit button
cy.contains("a", "Create Deposit").click();
cy.url().should("contain", "FindDepositSlip.php");
cy.contains("Deposit Listing");
});

it("should navigate to reports page from Generate Reports button", () => {
cy.visit("/finance/");

// Find and click the Generate Reports button
cy.contains("a", "Generate Reports").click();
cy.url().should("contain", "/finance/reports");
cy.contains("Financial Reports");
});

it("should display Tax Year Reporting Checklist", () => {
cy.visit("/finance/");

cy.contains("Tax Year Reporting Checklist");
cy.contains("Close All Deposits");
cy.contains("Review Donation Funds");
cy.contains("Church Information");
cy.contains("Tax Report Verbiage");
cy.contains("Generate Tax Statements");
});

it("should display Recent Deposits section", () => {
cy.visit("/finance/");

cy.contains("Recent Deposits");
cy.contains("View All");

// Check table headers if deposits exist
cy.get("body").then(($body) => {
if ($body.find("table.table-hover").length > 0) {
cy.contains("th", "ID");
cy.contains("th", "Date");
cy.contains("th", "Type");
cy.contains("th", "Status");
}
});
});

it("should display Deposit Statistics sidebar", () => {
cy.visit("/finance/");

cy.contains("Deposit Statistics");
cy.contains("Total Deposits:");
cy.contains("Open Deposits:");
cy.contains("Closed Deposits:");
});

it("should display Donation Funds sidebar", () => {
cy.visit("/finance/");

cy.contains("Donation Funds");
});

it("should link to Donation Fund Editor from Manage Funds button", () => {
cy.visit("/finance/");

// Admin should see Manage Funds link
cy.contains("a", "Manage Funds").click();
cy.url().should("contain", "DonationFundEditor.php");
});

it("should navigate to settings from Church Information checklist item", () => {
cy.visit("/finance/");

// Find the Settings button in the Church Information row
cy.contains("Church Information")
.parents(".list-group-item")
.find("a")
.contains("Settings")
.click();

cy.url().should("contain", "SystemSettings.php");
});

it("should link deposits checklist to FindDepositSlip", () => {
cy.visit("/finance/");

// Find the View button in the Close All Deposits row
cy.contains("Close All Deposits")
.parents(".list-group-item")
.find("a")
.contains("View")
.click();

cy.url().should("contain", "FindDepositSlip.php");
});
});

describe("Finance Dashboard - Standard User Access", () => {
beforeEach(() => {
cy.setupStandardSession();
});

it("should allow standard users with finance permission to access the dashboard", () => {
// The standard test user (tony.wade) has finance permissions enabled in demo database
cy.visit("/finance/");

// Should be able to see the dashboard
cy.get("h1").should("contain", "Finance Dashboard");

// Metrics should be visible
cy.get(".finance-metric-card").should("have.length.at.least", 3);
});
});

describe("Finance Dashboard - No Finance Permission", () => {
beforeEach(() => {
cy.setupNoFinanceSession();
});

it("should deny access to users without finance permission", () => {
// User judith.matthews has no finance permission
cy.visit("/finance/", { failOnStatusCode: false });

// Should be redirected to access-denied page
cy.url().should("include", "/v2/access-denied");
cy.url().should("include", "role=Finance");
});

it("should deny access to finance reports for users without finance permission", () => {
cy.visit("/finance/reports", { failOnStatusCode: false });

// Should be redirected to access-denied page
cy.url().should("include", "/v2/access-denied");
cy.url().should("include", "role=Finance");
});
});
24 changes: 24 additions & 0 deletions cypress/e2e/ui/finance/finance.deposits.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,30 @@ describe("Finance Deposits", () => {
cy.contains("Envelope Manager");
});

it("Navigate to deposits from Finance Dashboard", () => {
cy.visit("/finance/");
cy.contains("Finance Dashboard");

// Click Create Deposit from Quick Actions
cy.contains("a", "Create Deposit").click();
cy.url().should("contain", "FindDepositSlip.php");
cy.contains("Deposit Listing");
});

it("Navigate to deposits from Finance Menu", () => {
cy.visit("/finance/");

// Use the View All link in Recent Deposits section
cy.contains("Recent Deposits")
.parents(".card")
.find("a")
.contains("View All")
.click();

cy.url().should("contain", "FindDepositSlip.php");
cy.contains("Deposit Listing");
});

it("Create a new Deposit without comment", () => {
cy.visit("/FindDepositSlip.php");
cy.get("#depositComment").clear();
Expand Down
Loading
Loading