EmployeeHolidays Documentation

Employee Holidays Controller Documentation

File: /controllers/employeeHolidays.php

Purpose: Manages company-wide holiday definitions and employee holiday calendar administration

Last Updated: December 20, 2024

Total Functions: 6+

Lines of Code: ~189

---

๐Ÿ“‹ Overview

The Employee Holidays Controller manages the company holiday calendar system that defines official holidays affecting employee attendance and payroll calculations. It provides:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**employeeholidays**Holiday definitions and calendarid, holiday, holiday_date, userid, today, del
### Reference Tables

Table NamePurposeKey Columns
**user**System users for audit trailuserid, username
---

๐Ÿ”‘ Key Functions

1. Default Action - Holiday Management Interface

Location: Line 26

Purpose: Display holiday creation/management interface with auto-initialization

Process Flow:

1. Auto-Initialize: Check for existing empty holiday record

2. Create if Missing: Create new empty holiday record if none exists

3. Load Existing: Load existing empty record for editing

4. Display Interface: Show holiday management form

Auto-Initialization Logic:

$employeeholidaysnull = R::findOne('employeeholidays',"ISNULL(NULLIF(holiday, ''))");
if(!$employeeholidaysnull->id){
    $employeeholidays = R::dispense('employeeholidays');
    $employeeholidays->holiday = '';         
    $employeeholidays->holiday_date = date("Y-m-d");  
    $employeeholidays->userid = $_SESSION['userid'];
    $employeeholidays->today = $today;
    $employeeholidays->del = 0;
    R::store($employeeholidays);
} else {
    // Update existing empty record with current date/user
    $employeeholidaysnull->holiday_date = date("Y-m-d");  
    $employeeholidaysnull->userid = $_SESSION['userid'];
    $employeeholidaysnull->today = $today;
    R::store($employeeholidaysnull);
}

Features:

---

2. addappend() - Add Additional Holiday Entry

Location: Line 50

Purpose: Create additional blank holiday entry for bulk holiday creation

Process Flow:

1. Create new empty holiday record

2. Set current date as default

3. Track creating user

4. Display in append mode for inline editing

Implementation:

$employeeholidays = R::dispense('employeeholidays');
$employeeholidays->holiday = null;         
$employeeholidays->holiday_date = date("Y-m-d");  
$employeeholidays->userid = $_SESSION['userid'];
$employeeholidays->today = $today;
$employeeholidays->del = 0;
R::store($employeeholidays);

---

3. autosave() - Real-time Auto-save

Location: Line 62

Purpose: Save holiday data automatically as user types (AJAX)

Function Signature:

// Triggered when: do=autosave
$id = filter_input(INPUT_POST, 'id');
$name = filter_input(INPUT_POST, 'name');  // Field name
$val = filter_input(INPUT_POST, 'val');   // Field value

Process Flow:

1. Receive AJAX request with field data

2. Update specific field in database

3. No response needed (silent save)

Implementation:

R::exec("update employeeholidays set $name = '" . $val . "' where id = $id");

Features:

---

4. showajax() - Holiday Listing with DataTables

Location: Line 93

Purpose: Provide AJAX data feed for holiday listing with search, pagination, and filtering

Function Signature:

function showajax() {
    global $allcutsup;  // DataTables configuration
}

Process Flow:

1. Parameter Extraction: Get DataTables parameters (search, pagination, ordering)

2. Query Building: Build dynamic SQL with filters

3. Data Processing: Process records for display

4. JSON Response: Return DataTables-compatible JSON

Search Implementation:

if (isset($_POST['search']['value']) && $_POST['search']['value'] != "") {
    $searchQuery .= "and ( employeeholidays.id LIKE '%" . $_POST["search"]["value"] . "%'
                OR employeeholidays.holiday LIKE '%" . $_POST["search"]["value"] . "%'
                OR employeeholidays.holiday_date LIKE '%" . $_POST["search"]["value"] . "%'
                OR employeeholidays.userid LIKE '%" . $_POST["search"]["value"] . "%'
                OR employeeholidays.today LIKE '%" . $_POST["search"]["value"] . "%'
    )";
}

Filtering Options:

Response Format:

$output = array(
    "recordsTotal" => $counts,
    "recordsFiltered" => count($rResult),
    "data" => array()
);

---

5. holidays() - Holiday Search API

Location: Line 175

Purpose: Provide autocomplete search for holiday selection in other modules

Function Signature:

function holidays() {
    $name = $_POST['searchTerm'];  // Search query
}

Process Flow:

1. Receive search term from AJAX request

2. Query holidays with LIKE match

3. Format results for Select2 dropdown

4. Return JSON response

Implementation:

$productsData = R::getAll("SELECT employeeholidays.id, holiday as name
FROM employeeholidays WHERE holiday LIKE '%" . $name . "%' limit 50");

foreach ($productsData as $pro) {
    $row_array['id'] = $pro['id'];
    $row_array['text'] = $pro['name'];
    array_push($return_arr, $row_array);
}
echo json_encode($return_arr);

Features:

---

6. edit() - Holiday Edit Interface

Location: Line 75

Purpose: Load specific holiday for editing

Process Flow:

1. Get holiday ID from URL parameter

2. Load holiday record using RedBean

3. Assign to template for editing

4. Display edit form

---

7. del() - Soft Delete Holiday

Location: Line 83

Purpose: Mark holiday as deleted without removing from database

Process Flow:

1. Get holiday ID from POST data

2. Load holiday record

3. Set del flag to 1

4. Save record

5. Return success indicator

Implementation:

$id = filter_input(INPUT_POST, 'id');
$employeeholidays = R::load('employeeholidays',$id);
$employeeholidays->del = 1;
R::store($employeeholidays);
echo "1";

---

๐Ÿ”„ Workflows

Workflow 1: Holiday Creation Process

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Access Holiday Management
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Check for Working Record
- Query for existing empty holiday record
- If none exists, create new empty record
- If exists, update with current user/date
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Display Holiday Form
- Show holiday name field
- Display date picker pre-filled with current date
- Enable auto-save functionality
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Real-time Auto-save
- User types holiday name
- AJAX auto-save triggers on field change
- Save individual fields without page refresh
- User selects/changes date
- Auto-save date change immediately
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Complete Holiday Creation
- Holiday automatically saved as user works
- No explicit save button needed
- Record marked as complete when both fields filled
- New empty record auto-created for next holiday
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Holiday Management and Search

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Holiday List Management
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Display Holiday DataTable
- Load AJAX-powered holiday listing
- Show search, pagination, and sorting
- Display edit and delete actions
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Search and Filter Operations
- Global search across all fields
- Date range filtering
- User-specific filtering
- Real-time AJAX updates
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Holiday Actions
EDIT Action:
โ†’ Load holiday for editing
โ†’ Display edit form
โ”‚ โ””โ”€โ†’ Use auto-save for updates โ”‚
DELETE Action:
โ†’ Soft delete holiday (set del = 1)
โ†’ Remove from active listings
โ”‚ โ””โ”€โ†’ Preserve for audit trail โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty)Default actionDisplay holiday management interface
`do=addappend`Additional entryCreate new empty holiday for bulk entry
`do=autosave``autosave()`AJAX auto-save field updates
`do=show`List viewDisplay holiday management list
`do=showajax``showajax()`AJAX data feed for DataTables
`do=holidays``holidays()`Holiday search API for autocomplete
`do=edit`Edit formDisplay holiday edit form
`do=del``del()`Soft delete holiday
### Required Parameters by Action

Auto-save (do=autosave):

Holiday Search (do=holidays):

DataTables AJAX (do=showajax):

- search[value] - Global search term

- order[0][column] - Sort column index

- order[0][dir] - Sort direction (asc/desc)

- start - Pagination start

- length - Page size

- fromdate - Start date filter

- todate - End date filter

- data1 - Holiday ID filter

- data2 - User ID filter

Edit (do=edit):

Delete (do=del):

---

๐Ÿงฎ Calculation Methods

Date Formatting and Validation

$today = date("Y-m-d H:i:s");  // Full timestamp for audit
$holiday_date = date("Y-m-d");  // Date only for holiday

Auto-save Field Updates

// Dynamic field update
R::exec("update employeeholidays set $name = '" . $val . "' where id = $id");

Search Query Building

$searchQuery = " ";
if ($id != '') {
    $searchQuery .= " and employeeholidays.id = " . $id . " ";
}
if ($userid != '') {
    $searchQuery .= " and employeeholidays.userid = " . $userid . " ";
}
if ($fromdate != '' && $todate != '') {
    $searchQuery .='and employeeholidays.today >= "' . $fromdate . ' 00-00-00" 
                     and employeeholidays.today <= "' . $todate . ' 23-59-55" ';
}

---

๐Ÿ”’ Security & Permissions

Input Validation

Authentication

Data Integrity

---

๐Ÿ“Š Performance Considerations

Database Optimization

1. Efficient Queries:

- Simple LIKE queries for search

- Indexed fields for common searches

- Limited result sets (LIMIT 50 for autocomplete)

2. RedBean ORM:

- Automatic query optimization

- Built-in caching for repeated queries

- Lazy loading for better performance

AJAX Optimization

1. Auto-save Throttling: Consider implementing debouncing for frequent updates

2. Search Limits: Autocomplete limited to 50 results

3. DataTables Pagination: Server-side processing for large datasets

Known Performance Issues

---

๐Ÿ› Common Issues & Troubleshooting

1. Auto-save Not Working

Issue: Changes not saved automatically

Causes:

Debug:

// Check browser console for AJAX errors
console.log('Auto-save request:', {id: id, name: name, val: val});

2. DataTables Not Loading

Issue: Holiday list shows empty or error

Causes:

Debug:

// Add to showajax() function
error_log("DataTables query: " . $searchQuery);
error_log("Result count: " . count($rResult));

3. Holiday Search Empty Results

Issue: Autocomplete returns no holidays

Causes:

Fix:

-- Check for active holidays
SELECT COUNT(*) FROM employeeholidays WHERE del = 0 AND holiday != '';

-- Check for partial matches
SELECT * FROM employeeholidays WHERE holiday LIKE '%search%' AND del = 0;

4. Empty Records Created

Issue: Multiple empty holiday records in database

Cause: Auto-initialization creating duplicates

Prevention:

// Improved check for existing empty record
$existingEmpty = R::findOne('employeeholidays', 
    'holiday IS NULL OR holiday = "" AND del = 0');

---

๐Ÿงช Testing Scenarios

Test Case 1: Holiday Creation Workflow

1. Access holiday management (empty do parameter)
2. Verify auto-creation of empty record
3. Type holiday name and verify auto-save
4. Select date and verify auto-save
5. Check database for completed holiday record
6. Verify new empty record auto-created

Test Case 2: Auto-save Functionality

1. Create holiday with partial information
2. Test auto-save on holiday name field
3. Test auto-save on date field
4. Verify immediate database updates
5. Test with special characters and dates
6. Check for race conditions with rapid typing

Test Case 3: Holiday Search and Selection

1. Create multiple test holidays
2. Test autocomplete search with partial names
3. Verify Select2 dropdown functionality
4. Test with special characters and Unicode
5. Verify search result limits (50 max)
6. Test empty search handling

Test Case 4: DataTables Integration

1. Create holidays with various dates and users
2. Test global search across all fields
3. Test date range filtering
4. Test user-specific filtering
5. Verify pagination with large datasets
6. Test sorting by different columns

Test Case 5: Soft Delete and Recovery

1. Create test holidays
2. Soft delete holidays via del action
3. Verify holidays removed from listings
4. Check holidays still exist in database
5. Test recovery by updating del flag
6. Verify audit trail preservation

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur