Car Documentation

Car Controller Documentation

File: /controllers/carController.php

Purpose: Manages car inventory records, vehicle specifications, and automotive product tracking

Last Updated: December 20, 2024

Total Functions: 4

Lines of Code: ~210

---

๐Ÿ“‹ Overview

The Car Controller manages automotive inventory within the ERP system, handling vehicle records and their associated product data. This controller manages:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**cars**Car master recordsid, productid, brand, carcolor, carmodel, chasisno, cartype, carvalue, carnumber, carmotor, notes, sysdate, userid, del
### Related Tables (Referenced)

Table NamePurposeKey Columns
**product**Product master dataproductid, productName, conditions
**storedetail**Store inventorystoredetailid, productid, productquantity
### System Tables

Table NamePurposeKey Columns
**programsettings**System configurationprogramsettingsid, settingkey, settingvalue
**usergroup**User group permissionsusergroupid, usergroupname
---

๐Ÿ”‘ Key Functions

1. Default Action - Add New Car Form

Location: Lines 24-32

Purpose: Display form for adding new car records

Process Flow:

1. Load all active products for dropdown selection

2. Display car addition form

3. Set template variables for form population

SQL Query:

SELECT productId, productName 
FROM product 
WHERE conditions = 0

Template Variables:

---

2. show - Car Listing with AJAX

Location: Lines 33-47

Purpose: Display car listing interface with filtering capabilities

Process Flow:

1. Load authentication and permission checks

2. Set display mode (show=2 for alternative view)

3. Load product data for filters

4. Display car listing template with AJAX integration

Features:

---

3. edit - Edit Existing Car

Location: Lines 48-65

Purpose: Load and display car data for editing

Function Signature:

// URL: ?do=edit&id={car_id}
$id = filter_input(INPUT_GET, 'id');

Process Flow:

1. Load car record by ID

2. Load associated product information

3. Load all products for dropdown

4. Display edit form with pre-populated data

Template Variables:

---

4. savedata() - Save Car Record

Location: Lines 75-118

Purpose: Create or update car records with complete validation

Function Signature:

function savedata()

Input Parameters:

$productid = filter_input(INPUT_POST, 'productid');
$brand = filter_input(INPUT_POST, 'brand');
$carcolor = filter_input(INPUT_POST, 'carcolor');
$carmodel = filter_input(INPUT_POST, 'carmodel');
$chasisno = filter_input(INPUT_POST, 'chasisno');
$cartype = filter_input(INPUT_POST, 'cartype');
$carvalue = filter_input(INPUT_POST, 'carvalue');
$carnumber = filter_input(INPUT_POST, 'carnumber');
$carmotor = filter_input(INPUT_POST, 'carmotor');
$notes = filter_input(INPUT_POST, 'notes');
$carid = filter_input(INPUT_POST, 'carid');

Process Flow:

1. Create or Load Record:

   if (!$carid) {
       $cars = R::dispense('cars');
       $cars->del = 0;  // Not deleted
   } else {
       $cars = R::load('cars', $carid);
   }
   ```

2. **Set Record Properties**:
   ```php
   $cars->sysdate = $today;
   $cars->userid = $_SESSION['userid'];
   $cars->productid = $productid;
   $cars->brand = $brand;
   $cars->carcolor = $carcolor;
   // ... etc for all fields
   ```

3. **Store Record and Update Inventory**:
   ```php
   $carid = R::store($cars);
   R::exec('UPDATE storedetail SET productquantity = 0 WHERE productid = ?', [$productid]);
   ```

**Special Behavior**:
- When car is registered, product quantity in store is set to 0
- This indicates the product is now a specific car unit
- Maintains link between product and car for tracking

---

### 5. **showajax()** - AJAX Data Provider
**Location**: Lines 119-191  
**Purpose**: Provide paginated, filtered car data for DataTables

**Function Signature**:
php

function showajax()

**Input Parameters**:
php

$start_date = $_POST['start_date']; // Filter start date

$end_date = $_POST['end_date']; // Filter end date

$del = $_POST['del']; // Include deleted records

$data1 = $_POST['data1']; // Product filter

$_POST['search']['value'] // Search term

$_POST['order'] // Sort specification

$_POST['start'], $_POST['length'] // Pagination

**Process Flow**:
1. **Build Dynamic Query**:
   ```php
   $searchQuery = " ";
   if ($del == '') {
       $searchQuery .= " and cars.del = 0 ";
   }
   if ($data1 != '') {
       $searchQuery .= " and cars.productid = " . $data1 . " ";
   }
   ```

2. **Apply Date Filters**:
   ```php
   if ($start_date != '') {
       $searchQuery .= 'and DATE(cars.sysdate) >= "' . $start_date . '"';
   }
   ```

3. **Apply Search and Sorting**:
   ```php
   if (isset($_POST['search']['value']) && $_POST['search']['value'] != "") {
       $searchQuery .= 'and (cars.id LIKE "%' . $_POST["search"]["value"] . '%" 
                       OR product.productName like "%' . $_POST["search"]["value"] . '%")';
   }
   ```

4. **Return DataTables JSON**:
   ```php
   $output = array(
       "draw" => intval($_POST["draw"]),
       "recordsTotal" => intval($apps),
       "recordsFiltered" => $totals ? $totals : 0,
       "data" => array()
   );
   ```

**Return Format**:
json

{

"draw": 1,

"recordsTotal": 150,

"recordsFiltered": 25,

"data": [

[id, productName, sysdate, editButton, deleteButton],

// ... more rows

]

}

---

### 6. **removecontroller()** - Soft Delete
**Location**: Lines 194-209  
**Purpose**: Soft delete car records (set del=1 instead of physical deletion)

**Function Signature**:
php

function removecontroller()

**Process Flow**:
1. Get car ID from POST data
2. Load car record
3. Set del=1 (soft delete flag)
4. Update system date and user
5. Store changes

php

$tables = R::load('cars', $id);

$tables->del = 1;

$tables->sysdate = $today;

$tables->userid = $userid;

R::store($tables);

---

## ๐Ÿ”„ Workflows

### Workflow 1: Car Registration Process

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ START: Register New Car โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 1. Load Product Selection โ”‚

โ”‚ - Query all active products โ”‚

โ”‚ - Display product dropdown โ”‚

โ”‚ - Show car registration form โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 2. Capture Car Specifications โ”‚

โ”‚ - Product association โ”‚

โ”‚ - Brand and model information โ”‚

โ”‚ - Color and type specification โ”‚

โ”‚ - Chassis number (unique identifier) โ”‚

โ”‚ - Motor details and car number โ”‚

โ”‚ - Value estimation and notes โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 3. Save Car Record โ”‚

โ”‚ - Create new cars table record โ”‚

โ”‚ - Link to product via productid โ”‚

โ”‚ - Set creation timestamp and user โ”‚

โ”‚ - Set del=0 (active record) โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 4. Update Store Inventory โ”‚

โ”‚ - Set product quantity to 0 in storedetail โ”‚

โ”‚ - Indicates product now exists as specific car โ”‚

โ”‚ - Maintains product-car tracking relationship โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

### Workflow 2: Car Search and Management

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ START: Search Cars โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 1. Apply Search Filters โ”‚

โ”‚ - Date range filter (creation date) โ”‚

โ”‚ - Product type filter โ”‚

โ”‚ - Include/exclude deleted records โ”‚

โ”‚ - Free text search (ID, product name) โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 2. Execute Dynamic Query โ”‚

โ”‚ - Build WHERE clause based on filters โ”‚

โ”‚ - Join cars table with product table โ”‚

โ”‚ - Apply sorting and pagination โ”‚

โ”‚ - Count total matching records โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 3. Display Results โ”‚

โ”‚ - DataTables AJAX format โ”‚

โ”‚ - Car ID and product name โ”‚

โ”‚ - Creation date โ”‚

โ”‚ - Edit and delete action buttons โ”‚

โ”‚ - Pagination and sorting controls โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

## ๐ŸŒ URL Routes & Actions

| URL Parameter | Function Called | Description |
|---------------|----------------|-------------|
| `do=` (empty) | Default display | Show add car form |
| `do=show` | Car listing | Display car list with AJAX |
| `do=edit` | Edit form | Show edit form for specific car |
| `do=savedata` | `savedata()` | Save new or updated car record |
| `do=showajax` | `showajax()` | AJAX data provider for listing |
| `do=removecontroller` | `removecontroller()` | Soft delete car record |

### Required Parameters by Action

**Add New Car** (`do=` empty):
- No parameters required

**Show Car List** (`do=show`):
- `show` - Optional display mode (2 for alternative view)

**Edit Car** (`do=edit`):
- `id` - Car ID to edit (required)

**Save Car** (`do=savedata`):
- `productid` - Associated product ID
- `brand` - Car brand name
- `carcolor` - Car color
- `carmodel` - Car model
- `chasisno` - Chassis number (unique)
- `cartype` - Vehicle type
- `carvalue` - Car value/price
- `carnumber` - Car registration/plate number
- `carmotor` - Motor specifications
- `notes` - Additional notes
- `carid` - Car ID (for updates, empty for new)

---

## ๐Ÿงฎ Business Logic

### Product-Car Relationship
php

// When car is registered, product becomes unavailable in general inventory

R::exec('UPDATE storedetail SET productquantity = 0 WHERE productid = ?', [$productid]);

This design pattern indicates:
- Each car is associated with a product type
- Once registered as specific car, product is no longer available as general inventory
- Maintains traceability from product to specific vehicle

### Soft Delete Pattern
php

// Instead of DELETE, set flag

$tables->del = 1;

$tables->sysdate = $today;

$tables->userid = $userid;

Benefits:
- Data preservation for historical reporting
- Audit trail maintenance  
- Ability to restore records
- Referential integrity preservation

---

## ๐Ÿ”’ Security & Permissions

### Authentication
php

include_once("../public/authentication.php");

- Required for show and edit operations
- Missing for add operation (potential security gap)

### Input Sanitization
php

$id = filter_input(INPUT_GET, 'id');

$productid = filter_input(INPUT_POST, 'productid');

// Proper input filtering implemented

### Permission Management
- Uses `programsettings` and `usergroup` tables
- Assigns user group data to templates
- Individual function permissions not explicitly checked

---

## ๐Ÿ“Š Performance Considerations

### Database Optimization
1. **Indexes Recommended**:
   ```sql
   CREATE INDEX idx_cars_del_sysdate ON cars(del, sysdate);
   CREATE INDEX idx_cars_productid ON cars(productid);
   CREATE INDEX idx_cars_chasisno ON cars(chasisno);
   ```

2. **Query Optimization**:
   - AJAX queries use proper LIMIT for pagination
   - JOINs with product table for display
   - Dynamic WHERE clause building

### AJAX Performance
- Pagination implemented (`LIMIT` with `start` and `length`)
- Server-side processing for large datasets
- Efficient search across relevant fields

---

## ๐Ÿ› Common Issues & Troubleshooting

### 1. **Product Quantity Reset**
**Issue**: Product quantity always set to 0 when car registered  
**Behavior**: By design - indicates product now exists as specific car

**Verification**:
sql

SELECT c.id, c.chasisno, p.productName, s.productquantity

FROM cars c

JOIN product p ON p.productid = c.productid

JOIN storedetail s ON s.productid = c.productid

WHERE c.del = 0;

### 2. **Duplicate Chassis Numbers**
**Issue**: No validation prevents duplicate chassis numbers  
**Risk**: Data integrity issues with car identification

**Fix**: Add validation in `savedata()`:
php

// Check for existing chassis number

$existingCar = R::findOne('cars', 'chasisno = ? AND del = 0 AND id != ?', [$chasisno, $carid ?: 0]);

if ($existingCar) {

throw new Exception('Chassis number already exists');

}

### 3. **Search Performance**
**Issue**: LIKE queries without proper indexes can be slow  
**Solution**: Add full-text indexes or optimize search patterns

---

## ๐Ÿงช Testing Scenarios

### Test Case 1: Car Registration

1. Access car addition form

2. Select product from dropdown

3. Fill all car specifications

4. Submit form

5. Verify car record created

6. Confirm product quantity set to 0

7. Check car appears in listing

### Test Case 2: Car Search and Filter

1. Access car listing page

2. Apply date range filter

3. Apply product type filter

4. Use text search

5. Verify results match filters

6. Test pagination

7. Test sorting by different columns

### Test Case 3: Car Edit and Delete

1. Select car from listing

2. Click edit button

3. Modify specifications

4. Save changes

5. Verify updates in database

6. Test soft delete functionality

7. Verify deleted cars excluded from default view

```

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur