CarReview Documentation

Car Review Controller Documentation

File: /controllers/carReviewController.php

Purpose: Manages dual-reviewer approval system for automotive and financial transactions across multiple business processes

Last Updated: December 20, 2024

Total Functions: 2

Lines of Code: ~543

---

๐Ÿ“‹ Overview

The Car Review Controller implements a sophisticated dual-reviewer approval system that ensures financial and operational integrity across multiple business processes. This controller manages:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Review Tables

Table NamePurposeKey Columns
**carreview**Review tracking recordscarreviewid, tablename, modelid, reviewuserid1, reviewuserid2, sysdate1, sysdate2
**carreviewer**Reviewer configurationcarreviewerid, reviewer1, reviewer2
### Monitored Transaction Tables

Table NamePurposeKey Columns
**savedaily**Daily cash operationssavedailyid, savedailychangeamount, savedailychangetype
**sellbill**Sales billssellbillid, sellbillclientid, conditions
**buybill**Purchase billsbuybillid, supplierid, conditions
**importcontract**Import contractsid, del
**carfile**Car documentationid, del
**shippingfile**Shipping filesid
**cartracking**Car tracking recordsid
**dollarearnings**Dollar earningsid, conditions
---

๐Ÿ”‘ Key Functions

1. Default Action - Review Dashboard

Location: Lines 8-327

Purpose: Display comprehensive review dashboard showing pending approvals across all modules

Process Flow:

1. Load Reviewer Configuration:

   $reviewersData = R::load('carreviewer',1);
   $reviewersData['reviewer1'] = explode(',', $reviewersData['reviewer1']);
   $reviewersData['reviewer2'] = explode(',', $reviewersData['reviewer2']);
   ```

2. **Verify User Permissions**:
   ```php
   if($_SESSION['userid'] != -1 && 
      !in_array($_SESSION['userid'], $reviewersData['reviewer1']) && 
      !in_array($_SESSION['userid'], $reviewersData['reviewer2'])){
       header("location:index.php");
   }
   ```

3. **Process Each Module for Review Status**:

**Module Processing Pattern** (repeated for each transaction type):
php

// Example: Save Daily Operations

$todaySaveDaily = R::getAll("SELECT DISTINCT savedaily.savedailyid, savedaily.* FROM savedaily

LEFT JOIN carreview ON carreview.tablename = 'savedailyController.php'

and modelid = savedailyid

WHERE reviewuserid1 IS NULL OR reviewuserid2 IS NULL

OR reviewuserid1 = 0 OR reviewuserid2 = 0

order by savedailyid");

foreach ($todaySaveDaily as $value) {

$isExist = R::getAll("SELECT * from carreview where tablename = 'savedailyController.php'

and modelid = ?", [$value['savedailyid']]);

if(count($isExist) == 0){

$saveNotReviewed1++;

$saveNotReviewed2++;

}

else{

if(count($isExist) == 2){

// Both reviewers completed

array_push($saveReviewed1, $value['savedailyid']);

array_push($saveReviewed2, $value['savedailyid']);

}

else{

// One reviewer completed

if($isExist[0]['reviewuserid1'] > 0){

array_push($saveReviewed1, $value['savedailyid']);

$saveNotReviewed2++;

} else {

array_push($saveReviewed2, $value['savedailyid']);

$saveNotReviewed1++;

}

}

}

}

### Modules Monitored for Review:

#### 1. **Save Daily Operations**
- **Table**: `savedaily`
- **Controller**: `savedailyController.php`
- **Purpose**: Daily cash register operations
- **Review Criteria**: All transactions require dual approval

#### 2. **Sales Bills**
- **Table**: `sellbill`
- **Controller**: `sellbillController.php`
- **Purpose**: Customer sales transactions
- **Review Criteria**: Non-cancelled bills (`conditions = 0`)

#### 3. **Purchase Bills**
- **Table**: `buybill`
- **Controller**: `buyBillController.php`
- **Purpose**: Supplier purchase transactions
- **Review Criteria**: Active bills (`conditions = 0`)

#### 4. **Import Contracts**
- **Table**: `importcontract`
- **Controller**: `importContractController.php`
- **Purpose**: Import contract documentation
- **Review Criteria**: Non-deleted contracts (`del < 2`)

#### 5. **Car Files**
- **Table**: `carfile`
- **Controller**: `fileController.php`
- **Purpose**: Car documentation files
- **Review Criteria**: Active files (`del < 2`)

#### 6. **Shipping Files**
- **Table**: `shippingfile`
- **Controller**: `shippingFilesController.php`
- **Purpose**: Shipping documentation
- **Review Criteria**: All shipping files

#### 7. **Car Tracking**
- **Table**: `cartracking`
- **Controller**: `carTrackingController.php`
- **Purpose**: Vehicle movement tracking
- **Review Criteria**: All tracking records

#### 8. **Dollar Earnings**
- **Table**: `dollarearnings`
- **Controller**: `dollarEarningsController.php`
- **Purpose**: Foreign currency earnings
- **Review Criteria**: Active records (`conditions = 0`)

---

### 2. **savedata** - Bulk Review Approval
**Location**: Lines 328-539  
**Purpose**: Process bulk approval submissions from reviewers

**Function Signature**:
php

// Triggered when: do=savedata

// POST data contains comma-separated IDs for each module

**Input Parameters**:
php

$saveDailyIds1 = filter_input(INPUT_POST, 'saveDailyIds1'); // Reviewer 1 approvals

$saveDailyIds2 = filter_input(INPUT_POST, 'saveDailyIds2'); // Reviewer 2 approvals

$billIds1 = filter_input(INPUT_POST, 'billIds1'); // Sales bills reviewer 1

$billIds2 = filter_input(INPUT_POST, 'billIds2'); // Sales bills reviewer 2

$buyBillIds1 = filter_input(INPUT_POST, 'buyBillIds1'); // Purchase bills reviewer 1

$buyBillIds2 = filter_input(INPUT_POST, 'buyBillIds2'); // Purchase bills reviewer 2

// ... similar for other modules

**Process Flow**:
1. **Verify Reviewer Authorization**:
   ```php
   $reviewersData = R::load('carreviewer',1);
   if(in_array($_SESSION['userid'], explode(',', $reviewersData['reviewer1']))) {
       // Process reviewer 1 approvals
   }
   if(in_array($_SESSION['userid'], explode(',', $reviewersData['reviewer2']))) {
       // Process reviewer 2 approvals
   }
   ```

2. **Process Approvals by Module** (pattern for each module):
   ```php
   if (isset($saveDailyIds1)) {
       foreach (explode(",", $saveDailyIds1) as $value) {
           if (!$value) continue;
           $review = R::dispense('carreview');
           $review->tablename = 'savedailyController.php';
           $review->modelid = $value;
           $review->reviewuserid1 = $_SESSION['userid'];
           $review->sysdate1 = date("Y-m-d H:i:s");
           R::store($review);
       }
   }
   ```

3. **Handle Multiple Reviews**:
   - Creates new review record if none exists
   - Updates existing record if partial review exists
   - Maintains separate timestamps for each reviewer

**Approval Logic**:
- Each transaction can have 0, 1, or 2 approvals
- Reviewer 1 sets `reviewuserid1` and `sysdate1`
- Reviewer 2 sets `reviewuserid2` and `sysdate2`
- Both fields populated = fully approved
- Missing fields = pending review

---

## ๐Ÿ”„ Workflows

### Workflow 1: Dual-Review Approval Process

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

โ”‚ START: Transaction Created in System โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 1. Transaction Requires Review โ”‚

โ”‚ - Transaction created in source system โ”‚

โ”‚ - No review record exists in carreview table โ”‚

โ”‚ - Appears on both reviewers' dashboards โ”‚

โ”‚ - Status: Pending both reviews โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 2. First Reviewer Approval โ”‚

โ”‚ - Reviewer 1 or 2 accesses review dashboard โ”‚

โ”‚ - Selects transactions for approval โ”‚

โ”‚ - Submits bulk approval โ”‚

โ”‚ - Creates carreview record with reviewer ID and date โ”‚

โ”‚ - Status: Pending second review โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 3. Second Reviewer Approval โ”‚

โ”‚ - Remaining reviewer sees transaction โ”‚

โ”‚ - Provides second approval โ”‚

โ”‚ - Updates carreview record with second reviewer info โ”‚

โ”‚ - Status: Fully approved โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 4. Transaction Complete โ”‚

โ”‚ - Both reviewuserid1 and reviewuserid2 populated โ”‚

โ”‚ - Transaction no longer appears on review dashboards โ”‚

โ”‚ - Audit trail preserved with reviewer IDs and dates โ”‚

โ”‚ - Transaction considered approved for processing โ”‚

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

---

### Workflow 2: Review Dashboard Loading

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

โ”‚ START: User Accesses Review Dashboard โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 1. Verify User Authorization โ”‚

โ”‚ - Check user ID against reviewer1 and reviewer2 lists โ”‚

โ”‚ - Redirect unauthorized users โ”‚

โ”‚ - Load reviewer configuration โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 2. Query Each Module for Pending Reviews โ”‚

โ”‚ FOR EACH business module: โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Query transactions requiring review โ”‚

โ”‚ โ”‚ (LEFT JOIN with carreview table) โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Categorize by review status: โ”‚

โ”‚ โ”‚ โ”œโ”€ No reviews: Count for both reviewers โ”‚

โ”‚ โ”‚ โ”œโ”€ One review: Count for remaining reviewer โ”‚

โ”‚ โ”‚ โ””โ”€ Two reviews: Mark as completed โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ””โ”€โ†’ Track completed reviews by reviewer โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 3. Display Review Dashboard โ”‚

โ”‚ - Show pending review counts by module โ”‚

โ”‚ - Display transactions awaiting user's review โ”‚

โ”‚ - Highlight completed reviews โ”‚

โ”‚ - Provide bulk selection interface โ”‚

โ”‚ - Enable bulk approval submission โ”‚

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

---

## ๐ŸŒ URL Routes & Actions

| URL Parameter | Function Called | Description |
|---------------|----------------|-------------|
| `do=` (empty) | Default dashboard | Display review dashboard with pending approvals |
| `do=savedata` | Bulk approval | Process selected approvals from reviewers |

### Required Parameters by Action

**Review Dashboard** (`do=` empty):
- No parameters required
- User authentication verified via session
- Reviewer authorization checked against configuration

**Bulk Approval** (`do=savedata`):
- Module-specific ID lists (comma-separated):
  - `saveDailyIds1`, `saveDailyIds2` - Daily operations
  - `billIds1`, `billIds2` - Sales bills
  - `buyBillIds1`, `buyBillIds2` - Purchase bills
  - `contractIds1`, `contractIds2` - Import contracts
  - `fileIds1`, `fileIds2` - Car files
  - `shippingIds1`, `shippingIds2` - Shipping files
  - `trackingIds1`, `trackingIds2` - Car tracking
  - `dollarIds1`, `dollarIds2` - Dollar earnings

---

## ๐Ÿ”’ Security & Access Control

### Reviewer Authorization
php

// Load reviewer configuration

$reviewersData = R::load('carreviewer',1);

$reviewersData['reviewer1'] = explode(',', $reviewersData['reviewer1']);

$reviewersData['reviewer2'] = explode(',', $reviewersData['reviewer2']);

// Verify user authorization

if($_SESSION['userid'] != -1 &&

!in_array($_SESSION['userid'], $reviewersData['reviewer1']) &&

!in_array($_SESSION['userid'], $reviewersData['reviewer2'])){

header("location:index.php");

}

### Role-Based Processing
php

// Separate processing for each reviewer role

if(in_array($_SESSION['userid'], explode(',', $reviewersData['reviewer1']))) {

// Process reviewer 1 approvals

}

if(in_array($_SESSION['userid'], explode(',', $reviewersData['reviewer2']))) {

// Process reviewer 2 approvals

}

### Audit Trail
- Each approval records reviewer ID and timestamp
- Maintains complete review history
- Prevents approval tampering through database constraints
- Supports review reversal tracking

---

## ๐Ÿ“Š Review Analytics

### Dashboard Metrics
For each module, the dashboard tracks:
- **Not Reviewed Count**: Transactions requiring both approvals
- **Reviewer 1 Pending**: Transactions needing first approval
- **Reviewer 2 Pending**: Transactions needing second approval
- **Completed Reviews**: Transactions with both approvals

### Template Variables (per module):
php

// Example for Save Daily

$smarty->assign("saveNotReviewed1", $saveNotReviewed1); // Count pending review 1

$smarty->assign("saveNotReviewed2", $saveNotReviewed2); // Count pending review 2

$smarty->assign("saveReviewed1", $saveReviewed1); // Array of completed by reviewer 1

$smarty->assign("saveReviewed2", $saveReviewed2); // Array of completed by reviewer 2

---

## ๐Ÿงฎ Business Logic

### Review State Logic
php

if(count($isExist) == 0){

// No reviews yet - needs both reviewers

$moduleNotReviewed1++;

$moduleNotReviewed2++;

}

else{

if(count($isExist) == 2){

// Both reviews complete

array_push($moduleReviewed1, $value['id']);

array_push($moduleReviewed2, $value['id']);

}

else{

// One review complete, determine which reviewer remains

if($isExist[0]['reviewuserid1'] > 0){

array_push($moduleReviewed1, $value['id']);

$moduleNotReviewed2++;

} else {

array_push($moduleReviewed2, $value['id']);

$moduleNotReviewed1++;

}

}

}

### Approval Recording
php

// Create new review record

$review = R::dispense('carreview');

$review->tablename = 'savedailyController.php';

$review->modelid = $value;

$review->reviewuserid1 = $_SESSION['userid']; // or reviewuserid2

$review->sysdate1 = date("Y-m-d H:i:s"); // or sysdate2

R::store($review);

---

## ๐Ÿ› Common Issues & Troubleshooting

### 1. **Incomplete Review Records**
**Issue**: Transactions show as partially reviewed but missing reviewer information  
**Cause**: Database inconsistency or failed approval save

**Debug Query**:
sql

-- Find orphaned review records

SELECT cr.*,

CASE WHEN reviewuserid1 = 0 THEN 'Missing Reviewer 1'

WHEN reviewuserid2 = 0 THEN 'Missing Reviewer 2'

ELSE 'Complete' END as status

FROM carreview cr

WHERE (reviewuserid1 = 0 AND reviewuserid2 > 0)

OR (reviewuserid1 > 0 AND reviewuserid2 = 0);

### 2. **Reviewer Configuration Issues**
**Issue**: Users cannot access review dashboard  
**Cause**: Incorrect reviewer1/reviewer2 configuration

**Fix**:
sql

-- Check reviewer configuration

SELECT * FROM carreviewer WHERE carreviewerid = 1;

-- Update reviewer lists (comma-separated user IDs)

UPDATE carreviewer SET

reviewer1 = '1,2,3',

reviewer2 = '4,5,6'

WHERE carreviewerid = 1;

### 3. **Performance Issues with Large Datasets**
**Issue**: Dashboard loads slowly with many pending reviews  
**Solution**: Add database indexes

sql

CREATE INDEX idx_carreview_table_model ON carreview(tablename, modelid);

CREATE INDEX idx_carreview_reviewers ON carreview(reviewuserid1, reviewuserid2);

---

## ๐Ÿงช Testing Scenarios

### Test Case 1: Dual Approval Workflow

1. Create transaction in any monitored module

2. Verify appears on both reviewers' dashboards

3. Login as reviewer 1, approve transaction

4. Verify shows as pending for reviewer 2 only

5. Login as reviewer 2, provide second approval

6. Verify transaction no longer appears on dashboards

7. Confirm both reviewer IDs and dates recorded

### Test Case 2: Bulk Approval Operations

1. Generate multiple transactions across different modules

2. Login as authorized reviewer

3. Select multiple transactions for approval

4. Submit bulk approval

5. Verify all selected transactions processed

6. Confirm review records created correctly

7. Test with second reviewer for completion

### Test Case 3: Unauthorized Access Prevention

1. Login as user not in reviewer1 or reviewer2 lists

2. Attempt to access review dashboard

3. Verify redirected to index.php

4. Test with expired session

5. Verify proper access control enforcement

```

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When reviewer configuration or approval workflow changes