Version 4.0 - December 2025
A comprehensive, secure payroll management system for food service vendors with full Alaska compliance. Built with modern MVC architecture, PDO prepared statements, and enterprise-grade security features.
Designed and Maintained by: Danny Moore Built for: FreshServe Catering
✅ Modern Architecture: Converted from procedural PHP to Model-View-Controller pattern ✅ PDO Prepared Statements: 100% SQL injection proof with parameterized queries ✅ Object-Oriented Design: Clean separation of concerns, maintainable codebase ✅ PSR-4 Autoloading: Automatic class loading, no manual includes ✅ Backward Compatible URLs: All existing bookmarks and links continue to work
✅ Environment Configuration: .env file for sensitive credentials (never committed to git)
✅ Session Hardening: Production-grade session security (HttpOnly, Secure, SameSite)
✅ Authentication Middleware: Centralized auth checks in all controllers
✅ XSS Protection: Proper output escaping throughout views
✅ Error Handling: Production mode hides all error details, logs securely
✅ Clean MVC Structure: app/ directory with Controllers, Models, Services, Helpers
✅ Reusable Components: Base Controller and Model classes with CRUD operations
✅ Service Layer: Business logic separated (TaxCalculator, PayrollProcessor, SickLeaveCalculator)
✅ View Rendering: Consistent layout system with header/footer templates
✅ Documentation: Complete deployment guide, security checklist, environment setup guide
- Employee Management: Full CRUD operations with pay rates, leave balances, tax filing status
- Payroll Processing: Automated tax calculations, sick leave accrual (1 hr/30 hrs), vacation tracking
- Tax Compliance: IRS Form 941 quarterly reporting, Alaska wage reports, federal tax brackets
- Company Settings: Configure business info, sick leave caps, unemployment rates, themes
- User Management: Admin account control, password management
- Time Clock: Employee time tracking with clock in/out and history reports
- Reports: Payment history, paystubs, tax payment reports, Alaska CSV exports
- Payment History: View personal payment records with leave balances
- Paystubs: Access detailed paystubs showing all deductions and leave accruals
- Profile Management: View personal information and current leave balances
- Time Clock: Clock in/out with timestamp verification
- Password Management: Change password securely
- Sick Leave Law (AS 23.10.500): Automatic 1 hr/30 hrs accrual with configurable caps
- Quarterly Wage Reports: Generate CSV files for Alaska Department of Labor
- No State Income Tax: Proper Alaska tax handling
- SUTA Tracking: Alaska State Unemployment Tax Administration
- IRS 2025 Tax Brackets: Automated federal income tax withholding
- Form 941: Quarterly federal tax return generation
- FICA & Medicare: Proper Social Security and Medicare calculations with wage base limits
- Additional Medicare Tax: 0.9% on wages over $200,000
- W-4 Withholding: Support for withholding allowances
payroll/
├── app/ # Application core
│ ├── Controllers/ # Request handlers
│ │ ├── AdminController.php # Admin dashboard, accounts, user management
│ │ ├── AuthController.php # Login, logout, authentication
│ │ ├── CompanyController.php # Company settings
│ │ ├── EmployeeController.php # Employee CRUD operations
│ │ ├── PayrollController.php # Payment processing, paystubs
│ │ ├── TaxController.php # Tax reports, Form 941, Alaska CSV
│ │ ├── TimeClockController.php# Time tracking
│ │ └── ReportController.php # Print reports
│ │
│ ├── Models/ # Database layer
│ │ ├── Admin.php # Admin user model
│ │ ├── Employee.php # Employee model
│ │ ├── History.php # Payment history model
│ │ ├── CompanySettings.php # Company settings model
│ │ ├── FederalTaxBracket.php # Tax bracket model
│ │ ├── PayrollTax.php # Payroll tax rates model
│ │ └── TimeClock.php # Time clock model
│ │
│ ├── Services/ # Business logic
│ │ ├── TaxCalculator.php # Tax calculation service
│ │ ├── PayrollProcessor.php # Payroll processing service
│ │ └── SickLeaveCalculator.php# Alaska sick leave service
│ │
│ ├── Core/ # Framework core
│ │ ├── Database.php # PDO database singleton
│ │ ├── Model.php # Base model with CRUD
│ │ ├── Controller.php # Base controller
│ │ ├── Auth.php # Authentication middleware
│ │ ├── DotEnv.php # Environment variable loader
│ │ └── View.php # View rendering
│ │
│ └── Helpers/ # Helper functions
│ ├── DateHelper.php # Date formatting utilities
│ └── SecurityHelper.php # Security utilities
│
├── views/ # View templates
│ ├── layouts/ # Layout templates
│ │ ├── default.php # Default layout
│ │ ├── header.php # HTML head + navbar
│ │ └── footer.php # Scripts + closing tags
│ ├── admin/ # Admin views
│ ├── employee/ # Employee views
│ ├── payroll/ # Payroll views
│ ├── tax/ # Tax report views
│ ├── timeclock/ # Time clock views
│ ├── company/ # Company settings views
│ ├── auth/ # Login views
│ └── report/ # Print report views
│
├── config/ # Configuration
│ └── config.php # Application config (reads from .env)
│
├── assets/ # Public assets
│ ├── css/ # Stylesheets
│ ├── js/ # JavaScript
│ └── images/ # Images
│
├── downloads/ # Generated files (Alaska CSV)
│
├── bootstrap.php # Application initialization
├── .env # Environment variables (NOT in git)
├── .env.example # Environment template
├── *.php # Route files (backward compatible)
│
└── Documentation/
├── README.md # This file
├── PRODUCTION_DEPLOYMENT.md # Security & deployment guide
├── ENV_SETUP.md # Environment configuration guide
├── REFACTORING_GUIDE.md # MVC refactoring documentation
├── IMPLEMENTATION_GUIDE.md # Alaska sick leave guide
└── TESTING_GUIDE.md # Testing procedures
- PHP: 8.0 or higher (tested on PHP 8.1-8.4)
- MySQL: 5.7+ or MariaDB 10.3+
- Web Server: Apache 2.4+ or Nginx 1.18+
- SSL Certificate: REQUIRED for production (Let's Encrypt recommended)
- pdo_mysql (PDO MySQL driver) ⭐ REQUIRED
- session (Session handling)
- json (JSON processing)
- mbstring (Multi-byte string support)
- openssl (Secure connections)
- CPU: 2+ cores
- RAM: 2GB minimum, 4GB recommended
- Storage: 10GB minimum (for logs and backups)
- HTTPS: SSL/TLS certificate (mandatory for production)
-
Clone Repository
git clone https://github.com/yourusername/payroll.git cd payroll -
Configure Environment
# Copy environment template cp .env.example .env # Edit with your credentials nano .env
-
Set Up Database
# Create database mysql -u root -p -e "CREATE DATABASE payroll CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" # Import schema mysql -u root -p payroll < payroll.sql mysql -u root -p payroll < create_company_settings.sql mysql -u root -p payroll < update_payrate_taxes.sql mysql -u root -p payroll < update_alaska_sick_leave.sql mysql -u root -p payroll < update_alaska_csv_fields.sql
-
Configure .env File
DB_HOST=localhost DB_NAME=payroll DB_USER=root DB_PASS=your_password_here DB_CHARSET=utf8mb4 APP_NAME="Payroll System" APP_URL=http://localhost APP_ENV=development DEBUG_MODE=true SESSION_NAME=pay TIMEZONE=America/Anchorage
-
Access Application
- URL:
http://localhost/payroll - Default Admin:
admin/admin - Change password immediately!
- URL:
Production deployment requires additional security measures:
- HTTPS/SSL certificate (mandatory)
- Secure
.envconfiguration - Production-grade database user (not root)
- File permissions hardening
- Web server security headers
- Automated backups
- Error logging configuration
See PRODUCTION_DEPLOYMENT.md for complete checklist and step-by-step instructions.
The application uses a .env file for all sensitive configuration. This file is never committed to git.
Database Configuration:
DB_HOST=localhost # Database server
DB_NAME=payroll # Database name
DB_USER=payroll_user # Database username
DB_PASS=strong_password # Database password (16+ chars)
DB_CHARSET=utf8mb4 # Character setApplication Configuration:
APP_NAME="Your Company Payroll"
APP_URL=https://yourdomain.com
APP_ENV=production # production, development, or staging
DEBUG_MODE=false # MUST be false in production
SESSION_NAME=pay # PHP session name
TIMEZONE=America/AnchorageSee ENV_SETUP.md for detailed environment configuration guide.
Production Settings (Automatic when APP_ENV=production):
- ✅ Session cookies: HttpOnly, Secure, SameSite=Strict
- ✅ Session ID regeneration on login
- ✅ Error display: OFF (errors logged only)
- ✅ HTTPS-only cookies
- ✅ Strict session mode
Debug Mode:
DEBUG_MODE=true- Shows detailed errors (development only)DEBUG_MODE=false- Hides errors, logs only (production required)
-
Login as Admin
- URL:
https://yourdomain.com/login.php - Default credentials:
admin/admin - IMMEDIATELY change password in Admin Account
- URL:
-
Configure Company Settings
- Navigate to: Settings → Company Setup
- Enter company information
- Set employee count for Alaska sick leave cap
- Configure Alaska unemployment rate
- Select color theme
-
Set Up Employees
- Navigate to: Employees → Employee Setup
- Add all employees with pay rates and tax info
- Configure Alaska fields for quarterly reporting
- Navigate to: Payroll → Payroll Input
- Select employee from dropdown
- Enter hours worked:
- Regular hours (e.g., 80 for bi-weekly)
- Overtime hours (paid at 1.5x)
- Sick hours used (deducted from balance)
- Vacation hours used (deducted from balance)
- System automatically calculates:
- Sick leave accrued (1 hr per 30 worked)
- Vacation accrued (annual / 26 periods)
- Federal tax withholding
- FICA & Medicare taxes
- Net pay
- Click "Record Payment"
Payment Records:
- Payroll → Records → Select Employee
Paystubs:
- Click "View Paystub" from records
- Shows all deductions and leave balances
Tax Reports:
- Tax & Reports → Tax Payment Report (monthly/quarterly employer taxes)
- Tax & Reports → IRS Form 941 (quarterly federal tax return)
- Tax & Reports → Employee Tax Report (individual employee taxes)
Alaska Reports:
- Tax & Reports → Alaska CSV Export (quarterly wage report for state)
Automatic Accrual:
- 1 hour sick leave per 30 hours worked
- Accrues each pay period automatically
- Subject to annual caps
Annual Caps (configured in Company Settings):
- 15+ employees: 56 hours/year maximum
- <15 employees: 40 hours/year maximum
Year-End Handling:
- January 1st: YTD counters reset to zero
- Balance carries over to new year
- Can accrue up to annual cap again
Example:
Employee works 80 hours
Sick leave accrued: 80 ÷ 30 = 2.67 hours
If at cap (40 hrs), no additional accrual
Balance visible on paystub
Required Quarterly (Due end of month following quarter):
- Navigate to: Tax & Reports → Alaska CSV Export
- Enter Alaska Employer Account Number
- Select year and quarter (1-4)
- Click "Generate CSV File"
- Review validation warnings
- Download CSV file
- Upload to Alaska UI Tax & Wage System
Before Generating:
- Ensure employees have: SSN, Occupation Code (SOC), Geographic Code
- Set these in Employee Setup → Edit Employee
- Verify Alaska Employer Account in Company Setup
✅ Centralized Auth: All controllers use requireAdmin(), requireEmployee(), or requireAuth()
✅ Session Management: Secure session handling with production hardening
✅ Password Hashing: MD5+SHA1 for legacy compatibility (recommend bcrypt upgrade)
✅ Access Control: Role-based access (admin vs employee)
✅ PDO Prepared Statements: 100% of database queries use parameterized statements ✅ No String Concatenation: Zero SQL queries with variable concatenation ✅ Input Validation: All user input validated before processing
✅ Output Escaping: htmlspecialchars() on all user-generated content
✅ Input Sanitization: User input cleaned before storage
✅ Safe HTML: Controlled HTML generation in controllers
✅ HttpOnly Cookies: Prevents JavaScript access to session cookies ✅ Secure Cookies: Cookies only sent over HTTPS ✅ SameSite: CSRF protection via SameSite=Strict ✅ Session Regeneration: New session ID after login ✅ Strict Mode: Rejects uninitialized session IDs
✅ Credentials in .env: Never hardcoded in code ✅ .gitignore Protection: .env file never committed to git ✅ Config Separation: config/config.php contains no secrets ✅ Error Logging: Production errors logged, never displayed
✅ 600 Permissions on .env: Readable only by web server ✅ 644 on PHP Files: Secure but readable permissions ✅ 755 on Directories: Proper directory permissions ✅ .htaccess Protection: Blocks access to sensitive files
admin - Administrator accounts
id,username,password,first_name,surname,email
employee - Employee records
- Basic info:
employee_no,title,surname,lastname,ssn - Employment:
dept,position,joined,salary_type,hourly_rate - Tax info:
filing_status,withholding_allowances - Sick leave:
sick_hours_balance,sick_hours_ytd_used,sick_hours_ytd_accrued - Vacation:
vacation_hours_annual,vacation_hours_balance,vacation_hours_ytd_used - Alaska fields:
middle_initial,occupation_code,geographic_code
history - Payment history
- Payment:
date,employee_no,regular_hours,overtime_hours,salary,tips - Taxes:
federal_tax,fica_tax,medicare_tax,net_pay - Leave:
sick_hours_used,sick_hours_accrued,vacation_hours_used,vacation_hours_accrued - Alaska:
reportable_wages
company_settings - Company configuration
- Company:
company_name,company_address,company_phone,company_email,company_ein - Sick leave:
employee_count_threshold,sick_leave_cap_large,sick_leave_cap_small,current_employee_count - Alaska:
alaska_employer_account,alaska_unemployment_rate - UI:
color_theme,pay_period_type
federal_tax_brackets - IRS 2025 tax brackets
filing_status,bracket_min,bracket_max,tax_rate,base_tax
payroll_taxes - Payroll tax rates
tax_name,tax_rate,wage_base_limit(FICA/Medicare/FUTA)
time_clock - Time tracking
employee_no,clock_in,clock_out,status
Database Connection Error
Solution:
1. Check .env file exists and has correct credentials
2. Verify MySQL is running: sudo systemctl status mysql
3. Test connection: mysql -u username -p database_name
4. Check DB_HOST, DB_NAME, DB_USER, DB_PASS in .env
"Class not found" Error
Solution:
1. Ensure bootstrap.php is included in route files
2. Verify PSR-4 autoloader is registered in bootstrap.php
3. Check class namespace matches directory structure
4. Clear any PHP opcode cache
Session Errors in Production
Solution:
1. Verify APP_ENV=production in .env
2. Ensure HTTPS is configured (required for secure cookies)
3. Check session directory is writable
4. Review error logs for specific session errors
"Undefined array key" Errors
Solution:
1. Run all database migrations:
- update_alaska_sick_leave.sql
- update_alaska_csv_fields.sql
2. Verify all required columns exist in tables
3. Check IMPLEMENTATION_GUIDE.md for migration steps
Tax Calculations Incorrect
Solution:
1. Verify federal_tax_brackets table has 2025 data
2. Check payroll_taxes table for current rates
3. Verify employee filing_status is set
4. Check W-4 withholding_allowances value
Alaska CSV Export Fails
Solution:
1. Set Alaska Employer Account in Company Setup
2. Ensure employees have: SSN, occupation_code, geographic_code
3. Verify downloads/ directory exists and is writable (755)
4. Check for payment records in selected quarter
5. Review validation warnings in export results
- Monitor error logs for issues
- Verify automated backups ran successfully
- Review payment records for accuracy
- Check employee leave balances
- Generate tax payment report
- Backup database manually
- Review user access (disable terminated employees)
- File IRS Form 941 (by deadlines: Apr 30, Jul 31, Oct 31, Jan 31)
- File Alaska quarterly wage report (by end of month following quarter)
- Test backup restoration
- Review and update tax rates if changed
- Update IRS tax brackets for new year
- Update FICA wage base limit
- Verify Alaska sick leave caps
- Review employee vacation allocations
- Verify employee count in Company Settings
- Update Alaska SUTA rate (when notified by state)
- Security audit
- Password rotation for database
Automated Daily Backups:
#!/bin/bash
# /usr/local/bin/payroll-backup.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/payroll"
DB_NAME="payroll_production"
DB_USER="payroll_user"
DB_PASS="your_password"
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME | gzip > "$BACKUP_DIR/payroll_$DATE.sql.gz"
find $BACKUP_DIR -type f -name "*.sql.gz" -mtime +30 -deleteSchedule in crontab:
0 2 * * * /usr/local/bin/payroll-backup.shMajor Refactoring:
- ✅ Complete conversion to MVC architecture
- ✅ PDO prepared statements (SQL injection proof)
- ✅ 8 Controllers, 7 Models, 3 Services, 24 Views
- ✅ PSR-4 autoloading
- ✅ Backward-compatible route files
Security Enhancements:
- ✅ .env file configuration for credentials
- ✅ Session hardening (HttpOnly, Secure, SameSite)
- ✅ Centralized authentication middleware
- ✅ Production error handling
- ✅ XSS and CSRF protection
Developer Experience:
- ✅ Clean separation of concerns
- ✅ Reusable base classes
- ✅ Service layer for business logic
- ✅ Comprehensive documentation
Files Changed: 92 files (10,121 insertions, 6,570 deletions)
- ✅ Alaska Quarterly CSV Export
- ✅ Dynamic theme system (5 themes)
- ✅ Enhanced navigation with dropdowns
- ✅ Bug fixes for employee editing and SUTA rate
- ✅ Alaska Sick Leave Law compliance (AS 23.10.500)
- ✅ Vacation tracking system
- ✅ IRS Form 941 quarterly reporting
- ✅ Enhanced paystubs with leave balances
- ✅ YTD tracking with automatic reset
- Food service vendor conversion
- Automated tax calculations (IRS 2025)
- Employee and tax configuration pages
- Alaska tax compliance
- Basic payroll system
- Manual payment entry
AuthController - Authentication
showLogin()- Display login pageadminLogin()- Process admin loginemployeeLogin()- Process employee loginlogout()- Logout current user
AdminController - Admin functions
index()- Admin dashboardaccount()- Account settingsupdateAccount()- Update accountchangePassword()- Change passworduserManagement()- User management page
EmployeeController - Employee management
setup()- Employee listcreate()- Create employeeedit($id)- Edit employeeupdate($id)- Update employeedelete($id)- Delete employeeprofile()- View profilechangePassword()- Change password
PayrollController - Payroll processing
pay()- Payment formprocessPayment()- Process paymentrecords()- Payment recordspaystub($id)- View paystubpaystubArchive()- Paystub archivemyRecords()- Employee records
TaxController - Tax reports
setup()- Tax configurationpaymentReport()- Tax payment reportemployeeTaxReport()- Employee tax reportirsForm941()- IRS Form 941alaskaQuarterlyCSV()- Alaska CSV export
TimeClockController - Time tracking
index()- Clock in/out interfaceaction()- Process clock actionhistory()- View historyadminReport()- Admin report
CompanyController - Company settings
setup()- Settings formupdateSettings()- Save settings
ReportController - Print reports
printProfile()- Print employee profileprintRecord()- Print payment record
All models extend Model base class with:
find($id)- Find by primary keyall($orderBy)- Get all recordswhere($field, $value)- Find by fieldcreate($data)- Create recordupdate($id, $data)- Update recorddelete($id)- Delete record
TaxCalculator - Tax calculations
calculateFederalTax($income, $filingStatus)- Federal taxcalculateFICA($ytdWages, $currentWages)- FICA taxcalculateMedicare($ytdWages, $currentWages)- Medicare taxcalculateTotalTaxes($employeeNo, $grossPay)- All taxes
PayrollProcessor - Payroll logic
processPayment($employeeNo, $data)- Process paymentcalculateGrossPay($employee, $hours)- Calculate grossvalidatePayment($data)- Validate payment data
SickLeaveCalculator - Sick leave logic
calculateAccrual($hoursWorked)- Calculate accrualapplyCap($employee, $accrued)- Apply annual capresetYearlyCounters($employee)- Reset on Jan 1
- README.md (this file) - Complete system overview
- PRODUCTION_DEPLOYMENT.md - Security & deployment checklist
- ENV_SETUP.md - Environment configuration guide
- REFACTORING_GUIDE.md - MVC architecture documentation
- IMPLEMENTATION_GUIDE.md - Alaska sick leave guide
- TESTING_GUIDE.md - Testing procedures
- Alaska Sick Leave Law: https://www.akleg.gov/basis/statutes.asp#23.10.500
- Alaska Department of Labor: https://labor.alaska.gov/
- Alaska UI Tax System: https://www.labor.alaska.gov/estax/
- IRS Form 941: https://www.irs.gov/forms-pubs/about-form-941
- IRS e-file: https://www.irs.gov/efile-for-businesses
- Alaska SOC Codes: https://www.bls.gov/soc/
For issues or questions:
- Check troubleshooting section above
- Review documentation files
- Check error logs:
/var/log/php/error.log - Verify
.envconfiguration - Contact system administrator
Built with:
- PHP 8.x
- MySQL 5.7+ / MariaDB 10.3+
- Bootstrap 3.x
- jQuery 3.x
Compliance:
- ✅ Alaska Sick Leave Law (AS 23.10.500)
- ✅ IRS 2025 Federal Tax Brackets
- ✅ IRS Form 941 Quarterly Reporting
- ✅ Alaska Quarterly Wage Reporting
- ✅ FICA, Medicare, FUTA calculations
Security:
- ✅ OWASP Top 10 protections
- ✅ PCI compliance considerations
- ✅ Data encryption (HTTPS required)
- ✅ Secure session management
Before Production Deployment:
- Read PRODUCTION_DEPLOYMENT.md completely
- Configure HTTPS/SSL (required)
- Set up
.envwith production values - Set
APP_ENV=productionandDEBUG_MODE=false - Create dedicated database user (not root)
- Configure automated backups
- Set secure file permissions
- Test all critical functions
Compliance Requirements:
- Maintain payroll records for minimum 4 years (IRS requirement)
- File IRS Form 941 quarterly by deadlines
- File Alaska quarterly wage reports by deadlines
- Consult tax professional for specific business situations
- Update tax rates and brackets annually
Data Protection:
- Never commit
.envto version control - Use strong passwords (16+ characters)
- Enable HTTPS in production
- Regular security audits
- Monitor access logs
Version: 4.0 Last Updated: December 2025 Maintained by: Danny Moore Built for: FreshServe Catering
For detailed deployment instructions and security checklist, see PRODUCTION_DEPLOYMENT.md