- Add UNIQUE constraint on membership_application.user_id (one app per user) - Add UNIQUE constraint on membership_fees.user_id (one fee record per user) - Add validation checks in process_application.php before inserting - Improve error messages for duplicate submission attempts - Add migration script to clean up existing duplicates before constraints - Update checkMembershipApplication to set session message on redirect - Add comprehensive documentation of duplicate prevention architecture Individual payments/EFTs are tracked separately in payments table
3.5 KiB
3.5 KiB
Membership Application Duplicate Prevention
Overview
Implemented comprehensive validation to prevent users from submitting multiple membership applications or creating multiple membership fee records. Each user can have exactly one application and one membership fee record. Individual payments are tracked separately in the payments/efts table.
Architecture
User (1) ---> Membership Application (1) ---> Membership Fee (1) ---> Multiple Payments/EFTs
- Membership Application: Stores user details and application information (one per user)
- Membership Fee: Stores the total fee amount and dates (one per user, linked to application)
- Payments/EFTs: Tracks individual payment transactions for the membership fee (many per fee)
Changes Made
1. Database Level Protection
File: docs/migrations/002_add_unique_constraints_membership.sql
- Added
UNIQUEconstraint onmembership_application.user_id- ensures each user can only have one application - Added
UNIQUEconstraint onmembership_fees.user_id- ensures each user can only have one membership fee record - Cleans up any duplicate records before adding constraints
2. Application Level Validation
File: src/processors/process_application.php
Added pre-submission checks:
- Check if user already has a membership application in the database
- Check if user already has a membership fee record
- Return clear error message if either check fails
- Catch database constraint violations and provide user-friendly message
File: src/config/functions.php
- Improved
checkMembershipApplication()to set session message before redirecting - Message displayed: "You have already submitted a membership application."
3. Error Handling
If a user somehow bypasses checks:
- Server validates before processing
- Returns HTTP 400 error with JSON response
- User sees clear message directing them to support or check email
- Database constraints prevent data corruption (duplicate key violation)
User Flow
-
First Visit to Application Page:
checkMembershipApplication()checks database- If no application exists, shows form
- If application exists, redirects to
membership_details.php
-
Form Submission:
- Server checks for existing application
- Server checks for existing membership fee
- If checks pass, inserts application and fee in transaction
- On success, redirects to indemnity page
- On error, returns JSON error response
-
Payment Process:
- Individual payment records are created in payments/efts table
- Multiple payments can be made against the single membership_fee record
- Payment status is tracked independently from application
Testing Recommendations
- Test creating a membership application - should succeed
- Try applying again - should be redirected to membership_details
- Try submitting the form multiple times rapidly - should fail on 2nd attempt
- Verify payments can be made against the single membership fee record
- Check database constraints:
SHOW INDEX FROM membership_application;andSHOW INDEX FROM membership_fees;
Database Constraints
-- One application per user
ALTER TABLE membership_application
ADD CONSTRAINT uk_membership_application_user_id UNIQUE (user_id);
-- One membership fee record per user
ALTER TABLE membership_fees
ADD CONSTRAINT uk_membership_fees_user_id UNIQUE (user_id);
Backwards Compatibility
The migration script cleans up any existing duplicate records before adding constraints, ensuring no data loss.