# Permission Update Fix Summary

## Issues Fixed

### 1. Module Code Conversion Mismatch (CRITICAL)
**Problem**: The template was using `lower|cut:" "|cut:"&"|cut:"-"` to convert module names to codes, which produced different results than the view's `get_module_code()` function. For example:
- Template: "Reports & Statements" → "reportsstatements" 
- View: "Reports & Statements" → "reports_statements"

This mismatch caused form field names to not match what the view expected, resulting in permissions not being saved.

**Fix**: 
- Updated `users/templatetags/permission_filters.py` to use the same `MODULE_NAME_TO_CODE` mapping as the view
- Updated template to use `module_to_code` filter instead of manual string manipulation
- Both now produce identical module codes

### 2. AJAX Request Handling
**Problem**: If the form was submitted via AJAX (which can happen in production), the view returned HTML redirect instead of JSON, causing "JSON.parse: unexpected character" errors.

**Fix**: 
- Added detection for AJAX requests (checks `X-Requested-With` header and content type)
- Returns `JsonResponse` for AJAX requests, HTML redirect for normal form submissions
- Proper error handling for both cases

### 3. Error Logging
**Problem**: Errors were being silently swallowed, making it hard to debug production issues.

**Fix**:
- Added comprehensive logging at each step:
  - POST request received with field count
  - Fields processed vs matched
  - Permissions created/deleted counts
  - Full exception logging with stack traces
- Logs include admin ID, user ID, and operation details

## How Default Permissions Work

### Permission Hierarchy
1. **UserPermission** (Custom Overrides) - Highest priority
2. **RolePermission** - Role-based permissions
3. **DefaultRolePermission** - Default permissions for the role
4. **System Default** - False (denied) if nothing is set

### How Default Permissions Affect User Permissions

When you set default permissions in the Settings page:
1. They update both `DefaultRolePermission` and `RolePermission` for all users with that role
2. When assigning permissions to a user:
   - The system compares the desired permission against the role default
   - **If desired = role default**: No `UserPermission` is created (user inherits from role)
   - **If desired ≠ role default**: A `UserPermission` is created to override the default

### Example
- Default permission for "loan_officer" → "loans.access" = True
- User wants "loans.access" = True
- Result: No custom permission created, user inherits True from role default
- If you later change the default to False, the user's effective permission becomes False (unless they have a custom override)

## What to Check in Production

### 1. Check Server Logs
Look for these log messages after submitting the form:
```
POST request received: Admin=<id>, User=<id>, Fields count=<n>, Sample fields=[...]
Cleared <n> existing permissions for user <id>
Successfully updated permissions: Admin=<id> updated User=<id>, created=<n>, deleted=<n>, fields_processed=<n>, fields_matched=<n>
```

### 2. Check Database
Verify that `UserPermission` records are being created:
```sql
SELECT COUNT(*) FROM user_permissions WHERE user_id = '<user_id>';
```

### 3. Common Issues
- **No fields matched**: Module code mismatch (should be fixed now)
- **Zero permissions created**: All permissions match role defaults (this is normal)
- **JSON parse error**: Form being submitted via AJAX (should be fixed now)

### 4. Debugging Steps
1. Check browser console for JavaScript errors
2. Check network tab - is the form submitting as POST or AJAX?
3. Check server logs for the log messages above
4. Verify module codes match between template and view:
   - Template field name: `perm_<module_code>_<action_code>`
   - View expects: `perm_<module_code>_<action_code>`
   - Both should use the same `MODULE_NAME_TO_CODE` mapping

## Files Modified

1. `users/templatetags/permission_filters.py`
   - Added `MODULE_NAME_TO_CODE` mapping
   - Updated `module_to_code` filter to match view logic

2. `templates/users/simplified_user_permissions.html`
   - Changed from `lower|cut:" "|cut:"&"|cut:"-"` to `module_to_code` filter

3. `users/simplified_permissions_views.py`
   - Added AJAX request detection
   - Added comprehensive logging
   - Added JSON response for AJAX requests
   - Added `action_name` to permissions dictionary

## Testing Checklist

- [ ] Permissions save correctly in local environment
- [ ] Permissions save correctly in production
- [ ] No JSON parse errors in console
- [ ] Default permissions from settings affect user permissions correctly
- [ ] Logs show proper field matching
- [ ] Custom permissions are created when they differ from defaults
- [ ] No custom permissions are created when they match defaults

