A comprehensive, role-based enterprise solution for team-based management, built for partnered client, Oracle Corporation (ORCL), as a college capstone business solution project.
In collaboration with Oracle Corporation, our team was tasked with building a comprehensive project management solution as a capstone business deliverable.
The goal: create a fully functional, production-ready system that Oracle stakeholders could use to reliably perform basic project management.
Over the course of a 4-month agile sprint, we delivered a complete role-based platform with four user tiers, real-time collaboration features, comprehensive reporting, access request hierarchies, and enterprise-grade audit logging. All hosted live with HTTPS enforcement throughout the semester.
While the project was a team effort, my responsibility was the entire backend architecture:
Task viewing, status updates, and task access requests.
Project oversight, task creation, team management, and reporting.
Project ownership, team creation, manager assignment, and reporting.
User lifecycle, archive management, audit logs, and reassignment.
Password hashing with bcrypt/argon2id, session regeneration, prepared statements, and complete XSS prevention
Transaction-safe operations with commit/rollback, foreign key constraints, and soft delete patterns
Database triggers capturing before/after states in JSON with IP, user agent, and request context
Planning deviation metrics, completion rates, average task times, and real-time KPI dashboards
Foundation: Database ERD, login authentication system, role-based access control
Core Features: User dashboard, task management, commenting system
Management Layer: Manager dashboard, team management, reporting, access requests
Enterprise Features: Director controls, admin dashboard, audit logging, archive management
Database Tables: 15+
Database Triggers: 30+
PHP Files: 30+
SQL Queries: 200+ prepared statements
User Roles: 4 (User, Manager, Director, Admin)
Audit Log Entries: Complete history of every action
The system was built on a custom PHP/MySQL foundation with no frameworks. Every component was hand-crafted for performance, security, and maintainability. This approach gave us complete control over the architecture and allowed us to implement enterprise features that frameworks often abstract away.
The database consists of 15+ normalized tables with foreign key constraints ensuring referential integrity at the database level. Key tables include:
Users, Roles, User_Roles
Projects, Project_Members, Project_Comments
Tasks, Task_Members, Task_Comments
Teams, Team_Members
Standard_Questions, User_Secret_Questions
Audit_Log (with JSON storage)
Finalized ERD showing relationships between Users, Roles, Projects, Tasks, and Teams. Exported by our team DBA: Greg San Agustin.
[Full ERD available upon request - 15+ tables with foreign key constraints]
The system implements a four-tier hierarchy with granular permissions at every level:
- Full system control
- User creation/deletion
- Archive management
- Audit log viewing
- Password management
- Owns projects (Project_Owner)
- Creates/manages teams
- Assigns managers to projects
- Add & view project comments
- View task comments
- Approves project access requests
- Manages assigned projects
- Add & view project comments
- Creates/edits tasks
- Assigns users to tasks
- Add & views task comments
- Approves task access requests
- Views assigned tasks
- Updates task status
- Adds & views task comments
- Requests task access
All many-to-many relationships use junction tables with composite keys, enabling clean queries and referential integrity.
Data is never truly deleted, just flagged. This enables recovery and maintains historical integrity.
All operations that modify multiple tables use database transactions to ensure data consistency:
This pattern appears throughout the codebase. User creation, task assignment, project archiving, and hard deletions all use transactions to maintain data integrity.
Building without a framework forced me to gain a deep understanding of every layer, from connection management to cyberattack prevention. This knowledge is directly transferable to any tech stack.
Security was designed with multiple layers of protection, ensuring that even if one control fails, others remain. From authentication to authorization to audit, every aspect was hand-crafted with enterprise requirements in mind.
All passwords are hashed using PHP's password_hash() with the
PASSWORD_DEFAULT algorithm.
After successful login, the session ID is regenerated to prevent session fixation attacks
Every login checks the is_active flag. Deactivated users cannot log in, but
their data remains for historical purposes.
Since email servers were out of scope, I built a multi-level self-service password recovery system using security questions.
Users select 3 unique questions and provide answers, all hashed as a security breach precaution.
All 3 answers must be correct. Otherwise, access will be revoked and the recovery process will be reset.
Every page checks both authentication (logged in) and authorization (correct role):
But roles alone aren't enough! I also added validation for ownership and relationships as our functionality grew:
Directors can only modify projects they own.
Users can only update tasks they're assigned to.
Managers can view teams they belong to; directors can edit them.
Zero raw SQL queries with user input. Every database interaction uses prepared statements:
This pattern appears 200+ times across the codebase. Every query with user input uses prepared statements.
When a user attempts to update a task status, these checks occur:
Security is the foundation of this system. Every line of code was written with the assumption that it would be attacked. Prepared statements, output escaping, session management, and validation work together to create a system that's resilient by design.
Every significant action is logged with before/after states:
This complete audit trail means every change is traceable, which was a critical consideration for standard compliance and future debugging.
The system delivers four distinct experiences for each role in the organizational hierarchy. Every feature is gated by authentication, authorization, and relationship validation.
Building a complete enterprise system from scratch meant solving complex problems daily. Here are five of the most challenging issues I encountered and how I solved them.
In a real organization, managers belong to specific teams, and projects should be managed by a cohesive team. But our initial design didn't enforce this. Managers from different teams could be assigned to the same project, creating organizational chaos and confusion.
PROBLEM: How do we maintain team integrity while giving directors flexibility to assign managers?
I built a team detection and enforcement system that tracks which team each manager belongs to and warns when assignments cross team boundaries.
Result: Directors see clear warnings when cross-team assignments occur, and the system prevents accidental organizational fragmentation. If a project already has managers from Team A, only managers from Team A can be added. If a project needs to be delegated for any reason, Directors can add secondary managers to their teams to assume temporary control over that project.
When users and managers mark tasks and projects as "Complete" or "Abandoned", the system should automatically record the completion date and calculate actual duration. When re-opened, we wanted existing dates to reflect the new status of the task or project. Manual date entry would be error-prone and frustrating, so we needed a way to automate it to avoid errors.
I built an intelligent state machine that automatically manages dates based on status transitions, with validation to prevent invalid states. When a project/tasks status is changed to "Complete" or "Abandoned", the completion date (End_Date) is set to the current date. When an item's status is set to "On Hold/Work in Progress/Pending" any existing End_Date is set to NULL until otherwise completed or abandoned.
Validation Layer: Before any update, I validate date logic:
Result: Users never manually enter completion dates. The system handles it automatically, ensuring data consistency and preventing invalid states.
Project managers needed to understand how accurate their estimates were. Raw numbers don't tell the story. A project that took 10 days vs. estimated 5 days is very different from one that took 5 days vs. estimated 10 days. We needed a metric that showed direction and magnitude of estimation error.
I created a planning deviation percentage with color coding: green for overestimation (completed faster), red for underestimation (took longer), and gray for perfect estimation.
Result: Managers can instantly see estimation accuracy. +25% means they overestimated (completed 25% faster than planned). -25% means they underestimated (took 25% longer). This drives better estimation over time.
Users wanted filter settings to persist across page reloads, but server-side session storage would require constant AJAX calls. We needed a client-side solution that remembered each user's preferences without database overhead.
I used the browser's sessionStorage API with user-specific keys to maintain filter state across page views while ensuring filters from one user don't affect another.
Result: Filters persist across page reloads, are unique per user, and automatically clear on logout. Zero server overhead, instant response.
When an admin permanently deletes a user or project, dozens of related records must be removed in the correct order. Foreign key constraints prevent orphaned data, but also make deletion complex. A single failure could leave the database in an inconsistent state.
I implemented transaction-safe cascade deletion with temporary foreign key disabling and comprehensive error handling.
Result: Admins can permanently remove users with confidence, knowing the system maintains integrity and can recover from any failure.
Each of these challenges required deep understanding of databases, application logic, and user experience. Building without a framework meant I had to solve them at the fundamental level. This fundamental knowledge can transfer directly to countless technology stack.
Building a complete enterprise system from scratch in 4 months was an intense, rewarding experience. Beyond the technical skills, I gained deep insights into software architecture, team collaboration, and what it takes to deliver a production-ready business solution.
Foreign keys, transactions, and soft deletes aren't optional. They're the foundation of a reliable system. Every time I thought about skipping a constraint "just for now," I later discovered why it was essential. The upfront investment in data integrity saved countless hours of debugging and workarounds.
Prepared statements, output escaping, and session management couldn't be afterthoughts. By making security part of every coding decision, the system remained resilient throughout development.
The RBAC hierarchy (User → Manager → Director → Admin) wasn't just a client specification. It shaped the foundation of how we developed the system. Good architecture enables accessible features, but bad architecture limits them. The team integrity enforcement wouldn't have been possible without the team tables designed during Sprint (Month) 3.
Working with a frontend developer who couldn't directly contribute to the codebase taught me to write clean, documented, and predictable backend code. Every function needed clear inputs/outputs, and the API surface had to be intuitive. This discipline will serve me well in any team environment.
Planning deviation metrics helped managers improve estimation accuracy
Completion rate tracking identified high-performing team members
Average completion times informed future project planning
Audit logs provided complete traceability for compliance
1. API-First Design
I built the backend and frontend together, which sometimes
led to tight coupling. Next time, I'd design a clean REST
API first, then build the frontend against it. This would
make testing easier and allow for future mobile apps or
third-party integrations.
2. More Comprehensive Testing
With 15,000+ lines of code, manual testing became time-consuming.
I'd implement unit tests for critical paths (authentication,
authorization, transaction logic) to catch regressions faster.
3. Database Migration System
Schema changes required manual SQL scripts. A simple
migration system would have made updates safer and more
repeatable, especially when working with a DBA.
4. Earlier Performance Optimization
Some complex reports with multiple JOINs could be slow
with large datasets. I'd add query optimization and pagination
earlier in the development cycle.
Originally deemed out-of-scope, email integration would notify users of access request approvals, task assignments, and password changes. This would complete the user experience.
More sophisticated reporting with trend lines, forecasting, and export capabilities (CSV/PDF) would give managers deeper insights into team performance.
Implement WebSocket or polling for live updates and notifications. When a task status changes, all viewers see the update without refreshing.
With 25+ PHP files sharing similar patterns, a component-based approach (even simple PHP includes) would reduce code duplication and ensure consistency.
When I started this project, I was confident in my coding ability but hadn't faced the complexity of a full enterprise system. Four months later, I've learned that building reliable, secure, maintainable software can be quite a difficult task.
The moments I'm most proud of aren't the features that worked on the first try. Those moments were the last few days of rigorous error fixing, seeing my team work with the software, and the constant late nights throughout those 4 months. Every prepared statement, every validation check, every foreign key constraint represents a lesson learned.
Most importantly, I learned that frameworks are tools, not crutches. Building this without one forced me to understand the fundamentals at a depth I never would have achieved otherwise. I'm now beginning to pick up frameworks and learn how to not just use them, but why they are so valuable.
This project proved that I can architect, build, and deliver a complete enterprise system—from database schema to user interface—with security, data integrity, and user experience as first-class concerns. No frameworks, no shortcuts, just 15,000+ lines of carefully crafted code.
Developed by "Team Broncos" at UCCS in collaboration with Oracle Corporation
Team Broncos:
- Teammate: Project Manager
- Noah Ragsdale: Frontend Designer
- Connor Hill: Backend Developer
- Greg San Agustin: Database Administrator
All JavaScript functionality, PHP/SQL backend architecture, and business logic
implemented by me.