Save Type Controller Documentation
File: /controllers/saveTypeController.php
Purpose: Manages cash register/safe categories and types for organizational classification
Last Updated: December 20, 2024
Total Functions: 5 operations
Lines of Code: ~74
---
๐ Overview
The Save Type Controller is a simple CRUD (Create, Read, Update, Delete) management system for categorizing different types of cash registers and safes. It provides the foundational classification system that helps organize cash storage locations by their purpose, location, or operational characteristics.
Primary Functions
- โ Create new save type categories
- โ Display all active save types
- โ Edit existing save type information
- โ Soft delete save types
- โ AJAX search functionality for dropdowns
- โ User tracking for all operations
Related Controllers
- โข saveController.php - Cash register management
- โข saveCloseController.php - Cash closing operations
---
๐๏ธ Database Tables
Primary Table (Direct Operations)
| Table Name | Purpose | Key Columns |
|---|---|---|
| **savetype** | Save type definitions | id, name, del, adddate, adduserid, updatedate, updateuserid, deldate, deluserid |
CREATE TABLE savetype (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
del TINYINT DEFAULT 0, -- 0=active, 1=updated, 2=deleted
adddate DATETIME, -- Creation timestamp
adduserid INT, -- User who created
updatedate DATETIME, -- Last update timestamp
updateuserid INT, -- User who last updated
deldate DATETIME, -- Deletion timestamp
deluserid INT -- User who deleted
);
---
๐ Key Functions
1. Default Action - Add Form Display
Location: Lines 7-10
Purpose: Display form for creating new save types
Process Flow:
1. Display header template
2. Show add form template
3. Display footer template
Template: savetypeview/add.html
---
2. show() - Display Save Types List
Location: Lines 11-16
Purpose: Show all active save types with management options
Process Flow:
1. Query all save types with del < 2 (exclude hard-deleted)
2. Assign data to template
3. Display list with edit/delete options
Query:
$savetype = R::findAll('savetype','del < 2');
Template: savetypeview/show.html
---
3. edit() - Edit Form Display
Location: Lines 17-23
Purpose: Display edit form for existing save type
Process Flow:
1. Get save type ID from GET parameter
2. Load save type data by ID
3. Display edit form with current values
Template: savetypeview/edit.html
---
4. savedata() - Save/Update Save Type
Location: Lines 24-46
Purpose: Handle both new creation and updates of save types
Function Logic:
$name = filter_input(INPUT_POST, 'name');
$id = filter_input(INPUT_POST, 'id');
if (!$id) {
// CREATE NEW
$savetype = R::dispense('savetype');
$savetype->del = 0;
$savetype->adddate = date("Y-m-d H:i:s");
$savetype->adduserid = $_SESSION['userid'];
$savetype->deldate = '';
$savetype->deluserid = '';
} else {
// UPDATE EXISTING
$savetype = R::load('savetype', $id);
$savetype->del = 1; // Mark as updated
$savetype->updatedate = date("Y-m-d H:i:s");
$savetype->updateuserid = $_SESSION['userid'];
}
$savetype->name = $name;
R::store($savetype);
Process Flow:
1. Determine Operation: Check if ID provided (update) or not (create)
2. Create New: Dispense new bean with creation metadata
3. Update Existing: Load existing bean and set update metadata
4. Set Data: Assign name and save to database
5. Redirect: Return to show page on success
---
5. delete() - Soft Delete Save Type
Location: Lines 47-54
Purpose: Mark save type as deleted without removing from database
Process Flow:
1. Get save type ID from GET parameter
2. Load save type record
3. Mark as deleted (del = 2)
4. Set deletion metadata
5. Save changes and redirect
Deletion Logic:
$id = filter_input(INPUT_GET, 'id');
$tables = R::load('savetype', $id);
$tables->del = 2; // Soft delete
$tables->deldate = date("Y-m-d H:i:s");
$tables->deluserid = $_SESSION['userid'];
R::store($tables);
---
6. savetype - AJAX Search
Location: Lines 55-70
Purpose: Provide AJAX search functionality for dropdown selection
Function Signature:
// POST parameter
$name = $_POST['searchTerm']; // Search query
Process Flow:
1. Get search term from POST
2. Query save types with LIKE matching
3. Format results for Select2/dropdown
4. Return JSON response
Query & Response:
$allSaveType = R::getAll("SELECT id, name as name
FROM savetype
WHERE del < 2 and name LIKE '%" . $name . "%'
limit 50");
foreach ($allSaveType as $pro) {
$row_array['id'] = $pro['id'];
$row_array['text'] = $pro['name'];
array_push($return_arr, $row_array);
}
echo json_encode($return_arr);
Response Format:
[
{"id": 1, "text": "Main Safe"},
{"id": 2, "text": "Cash Register 1"},
{"id": 3, "text": "Petty Cash"}
]
---
๐ Workflows
Workflow 1: Create New Save Type
---
Workflow 2: Edit Save Type
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description | |
|---|---|---|---|
| (empty) | Default action | Display add form | |
| `do=show` | Show list | Display all save types | |
| `do=edit` | Edit form | Display edit form | |
| `do=savedata` | Save/Update | Process form submission | |
| `do=delete` | Delete | Soft delete save type | |
| `do=savetype` | AJAX search | Return JSON for dropdowns |
Display Form (empty do):
- โข No parameters required
Show List (do=show):
- โข No parameters required
Edit Form (do=edit):
- โข
id- Save type ID (GET parameter)
Save Data (do=savedata):
- โข
name- Save type name (POST, required) - โข
id- Save type ID for updates (POST, optional)
Delete (do=delete):
- โข
id- Save type ID (GET parameter)
AJAX Search (do=savetype):
- โข
searchTerm- Search query (POST parameter)
---
๐งฎ Calculation Methods
Status Flag Logic
// Save type status meanings
$del = 0; // Active/New record
$del = 1; // Updated record
$del = 2; // Soft deleted record
// Query active records
WHERE del < 2 // Shows active and updated records
WHERE del = 0 // Shows only new/unmodified records
WHERE del = 2 // Shows only deleted records
AJAX Search Scoring
// Simple LIKE matching with limit
WHERE name LIKE '%searchterm%' LIMIT 50
---
๐ Security & Permissions
Authentication
- โข No explicit authentication check in this controller
- โข Relies on session-based user tracking
- โข Uses
$_SESSION['userid']for audit trail
Input Validation
$name = filter_input(INPUT_POST, 'name');
$id = filter_input(INPUT_POST, 'id');
Validation Rules:
- โข Name field required for creation/update
- โข ID must be numeric for edit/delete operations
- โข Basic SQL injection prevention via filter_input
Data Integrity
- โข Soft delete preserves historical data
- โข User audit trail for all operations
- โข Timestamp tracking for changes
---
๐ Performance Considerations
Database Optimization
1. Indexes Recommended:
- savetype(del) for filtering active records
- savetype(name) for search functionality
- savetype(id, del) composite for specific lookups
2. Query Efficiency:
- Simple SELECT queries with minimal JOINs
- LIMIT clause on search results
- Proper WHERE clause usage
Memory Management
- โข Minimal data loading
- โข Direct RedBeanPHP operations
- โข Clean result handling
Known Performance Issues
// Potential issue: No input sanitization for LIKE search
WHERE name LIKE '%" . $name . "%'
// Consider: Prepared statements or proper escaping for search terms
---
๐ Common Issues & Troubleshooting
1. Duplicate Save Type Names
Issue: Multiple save types with same name created
Cause: No uniqueness constraint or validation
Fix: Add name uniqueness check before creation
$existing = R::findOne('savetype', 'name = ? AND del < 2', [$name]);
if ($existing) {
// Handle duplicate error
}
2. AJAX Search Not Working
Issue: Dropdown search returns no results
Cause: Incorrect search parameter or query
Debug:
// Add debugging to AJAX function
error_log("Search term: " . $name);
error_log("Query results: " . print_r($allSaveType, true));
3. Soft Delete Confusion
Issue: "Deleted" records still appear in some lists
Cause: Inconsistent use of del flag filtering
Fix: Standardize queries to use WHERE del < 2
4. Session Issues
Issue: User ID not recorded in audit fields
Cause: Session not properly initialized
Debug:
if (!isset($_SESSION['userid'])) {
echo "Session not initialized";
}
---
๐งช Testing Scenarios
Test Case 1: Create Save Type
1. Access save type management
2. Click add new save type
3. Enter descriptive name
4. Submit form
5. Verify record appears in list
6. Check audit fields populated
Test Case 2: Edit Save Type
1. Select existing save type for edit
2. Modify name
3. Submit changes
4. Verify updated name appears
5. Check del flag set to 1
6. Verify update timestamps
Test Case 3: Delete Save Type
1. Select save type for deletion
2. Confirm deletion
3. Verify record no longer in list
4. Check del flag set to 2
5. Verify delete timestamp set
Test Case 4: AJAX Search
1. Access dropdown with save type search
2. Enter partial name
3. Verify matching results appear
4. Check JSON format correct
5. Test with no matches
Test Case 5: Bulk Operations
1. Create multiple save types
2. Edit some records
3. Delete some records
4. Verify list shows correct statuses
5. Check audit trail completeness
Debug Mode Enable
// Add debugging at top of file
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Debug save operations
echo "Name: $name<br>";
echo "ID: $id<br>";
echo "User ID: " . $_SESSION['userid'] . "<br>";
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข saveController.php - Cash register management
- โข Database Schema Documentation - Table relationships
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur