Api_web Documentation

Web API Controller Documentation

File: /controllers/api_web.php

Purpose: RESTful API endpoints for web client registration, authentication, and project data access

Last Updated: December 20, 2024

Total Functions: 8+

Lines of Code: ~410

---

๐Ÿ“‹ Overview

The Web API Controller provides RESTful endpoints for external web clients to interact with the ERP system. It handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**webclients**Web client usersid, name, mobile, user_name, password, device_id, is_active
**project**Project master dataid, clientid, costcenterid, image, filepdf, expenses, income
**webclientprojects**Client-project access controlwebclientid, projectid
### Project Data Tables

Table NamePurposeKey Columns
**projectstages**Project stage definitionsid, name
**projectstagechosse**Selected project stagesprojectid, projectstageid, projectstageimages, projectstagefiles
**projecttimetableitems**Project timeline itemsprojectid, clause, amount, duration, startdate, enddate
### Financial Tables

Table NamePurposeKey Columns
**expenseexchange**Project expensesprojectid, expensetype, thevalue, finalsupervision
**projectexchmaterial**Material exchangesid, projectid
**projectexchmaterialdetail**Material exchange detailsprojectexchid, expensestypeid, totalbuyprice, finalsupervision
**clientdebtchange**Client payment historyclientid, clientdebtchangeamount, clientdebtchangedate, paySerialNo
**income**Project income recordscostcenterid, incomeName, incomeValue
**expensestype**Expense type definitionsexpensestypeid, expensestypename
---

๐Ÿ”‘ Key Functions

1. register - Web Client Registration

Location: Line 68

Purpose: Register new web client with validation and duplicate checking

Function Signature:

// POST data expected
{
    "name": "Client Name",
    "mobile": "1234567890", 
    "user_name": "username",
    "password": "password",
    "device_id": "device_identifier"
}

Process Flow:

1. Input Validation:

   if (!$name || !$mobile || !$user_name || !$password) {
       return ['status' => 2, 'reason' => '๏บ‘๏ปŒ๏บพ ุง๏ปŸ๏บค๏ป˜๏ปฎ๏ป ุง๏ปŸ๏ปค๏ป„๏ป ๏ปฎ๏บ‘๏บ” ๏ป“๏บŽ๏บญ๏ป๏บ”'];
   }
   ```

2. **Duplicate Checks**:
   ```php
   $check_username = R::count('webclients','user_name = ? AND is_active = 1', [$user_name]);
   $check_mobile = R::count('webclients','mobile = ? AND is_active = 1', [$mobile]);
   ```

3. **Account Creation**:
   ```php
   $row = R::dispense('webclients');
   $row->name = $name;
   $row->is_active = 1;
   $row->addtoday = date('Y-m-d H:i:s');
   $id = R::store($row);
   ```

**Response Format**:
json

{

"status": 1,

"reason": "ุชู… ุฅู†ุดุงุก ุงู„ุญุณุงุจ ุจู†ุฌุงุญ",

"webclient_id": 123,

"name": "Client Name",

"mobile": "1234567890",

"user_name": "username"

}

---

### 2. **login** - User Authentication
**Location**: Line 129  
**Purpose**: Authenticate web client using username/mobile and password

**Function Signature**:
php

// POST data expected

{

"username": "username_or_mobile",

"password": "password"

}

**Authentication Logic**:
php

$user = R::findOne('webclients', " (user_name = '" . $username . "' or mobile = '" . $mobile . "') and password = '" . $password . "' ");

if ($user->id > 0 && $user->is_active == 0) {

// Account exists but not activated

return ['status' => 1, 'reason' => '๏ป‹๏ป”๏ปฎุง ๏ปŸ๏ปข ๏ปณ๏บ˜๏ปข ๏บ—๏ป”๏ปŒ๏ปด๏ปž ๏บฃ๏บด๏บŽ๏บ‘๏ปš ๏บ‘๏ปŒ๏บช'];

} elseif ($user->id > 0) {

// Successful login

return ['status' => 1, 'reason' => '๏บ—๏ปข ุง๏ปŸ๏บช๏บง๏ปฎ๏ป ๏บ‘๏ปจ๏บ ๏บŽ๏บก'];

}

**Security Note**: โš ๏ธ This implementation has security vulnerabilities:
- Passwords stored in plain text
- SQL injection potential in concatenated query
- No rate limiting or brute force protection

---

### 3. **projectReport** - Comprehensive Project Report
**Location**: Line 177  
**Purpose**: Generate detailed project report with financial calculations and file attachments

**Function Signature**:
php

// GET parameter: id (project ID)

**Report Components**:

**A. Project Basic Data**:
php

$project = R::getRow("select *, CONCAT('$src', project.image) as image,

CONCAT('$src', project.filepdf) as filepdf

from project where id = ? ", [$projectid]);

**B. Project Stages** (if enabled):
php

if ($project['projectstagesdata'] == 1) {

$projectstages = R::getAll("select * from projectstagechosse

where projectid = ? ", [$projectid]);

// Process stage images and files

foreach ($projectstages as $key => $stage) {

$projectstageimages = explode(',', $stage['projectstageimages']);

$images = [];

foreach ($projectstageimages as $image) {

$images[] = $src . $image;

}

$projectstages[$key]['images'] = $images;

}

}

**C. Financial Calculations**:

**Expense Calculation Logic**:
php

// Get material expenses

$projectexchmaterialdetails = R::getAll("

select *, sum(totalbuyprice) as totals, sum(finalsupervision) as finalsupervisions

from projectexchmaterialdetail JOIN projectexchmaterial

ON projectexchmaterialdetail.projectexchid = projectexchmaterial.id

WHERE projectexchmaterial.projectid = ?

group by projectexchmaterialdetail.expensestypeid", [$projectid]);

// Get direct expenses

$expenseexchange = R::getROW("

select sum(thevalue) as totals, sum(finalsupervision) as finalsupervisions

from expenseexchange

where del = 0 and projectid = ? and expensetype = ?", [$projectid, $expensetype]);

// Calculate supervision based on type

if ($project['supervision_type'] == 1) {

$finalsupervisions = $project['supervision_amount']; // Fixed amount

} else {

$finalsupervisions = $calculated_supervisions; // Calculated percentage

}

**Income Calculation**:
php

if ($project['income'] == 1) {

// Client payments

$project['allclientdebtchange'] = R::getCell("

SELECT sum(clientdebtchangeamount)

FROM clientdebtchange

WHERE clientid = ? and paySerialNo > 0 and del = 0", [$project['clientid']]);

// Other income

$project['allincomeValue'] = R::getCell("

SELECT sum(incomeValue)

FROM income

WHERE costcenterid = ? and conditions = 0", [$project['costcenterid']]);

$project['alltotalsincome'] = $project['allclientdebtchange'] + $project['allincomeValue'];

}

**Final Calculation**:
php

$project['endtotals'] = ($project['alltotals'] + $project['alltotalvalues']) - $project['alltotalsincome'];

---

### 4. **projects** - Project List for Client
**Location**: Line 162  
**Purpose**: Retrieve projects accessible to a specific web client

**Function Signature**:
php

// POST data: {"webclientid": 123}

**Access Control Logic**:
php

$webclient = R::findOne('webclients', " id = ? ", [$webclientid]);

if ($webclient->clientids != 0) {

// Restricted access - only assigned projects

$projectclients = R::getAll("

select *,project.id as id, CONCAT('$src', project.image) as image

from project LEFT JOIN webclientprojects ON project.id = webclientprojects.projectid

where webclientprojects.webclientid = ? ", [$webclientid]);

} else {

// Full access - all projects

$projectclients = R::getAll("

select *, project.id as id, CONCAT('$src', project.image) as image

from project");

}

---

### 5. **updateProfile** - Client Profile Update
**Location**: Line 329  
**Purpose**: Update web client profile information with validation

**Function Signature**:
php

// POST data

{

"id": 123,

"name": "Updated Name",

"mobile": "New Mobile",

"user_name": "new_username",

"password": "new_password",

"device_id": "device_id"

}

**Update Process**:
1. Validate required fields
2. Check username/mobile uniqueness (excluding current user)
3. Update record with new data
4. Set update timestamp and user

---

## ๐Ÿ”„ Workflows

### Workflow 1: Client Registration Process

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

โ”‚ START: New Client Registration โ”‚

โ”‚ POST: api_web.php?do=register โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 1. Parse Request Data โ”‚

โ”‚ - Check request method and headers โ”‚

โ”‚ - Parse JSON from php://input or $_POST โ”‚

โ”‚ - Extract: name, mobile, user_name, password, device_idโ”‚

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

โ”‚

โ–ผ

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

โ”‚ 2. Input Validation โ”‚

โ”‚ IF any required field empty: โ”‚

โ”‚ - Return error: "๏บ‘๏ปŒ๏บพ ุง๏ปŸ๏บค๏ป˜๏ปฎ๏ป ุง๏ปŸ๏ปค๏ป„๏ป ๏ปฎ๏บ‘๏บ” ๏ป“๏บŽ๏บญ๏ป๏บ”" โ”‚

โ”‚ - Status: 2 โ”‚

โ”‚ - Exit process โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 3. Duplicate Username Check โ”‚

โ”‚ Query: COUNT(webclients) WHERE user_name = ? AND is_active = 1 โ”‚

โ”‚ IF count > 0: โ”‚

โ”‚ - Return error: "ุง๏บณ๏ปข ุง๏ปŸ๏ปค๏บด๏บ˜๏บจ๏บช๏ปก ๏ปฃ๏ปœ๏บฎ๏บญ" โ”‚

โ”‚ - Status: 2 โ”‚

โ”‚ - Exit process โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 4. Duplicate Mobile Check โ”‚

โ”‚ Query: COUNT(webclients) WHERE mobile = ? AND is_active = 1 โ”‚

โ”‚ IF count > 0: โ”‚

โ”‚ - Return error: "๏บญ๏ป—๏ปข ุง๏ปŸ๏ปค๏ปฎ๏บ‘๏บŽ๏ปณ๏ปž ๏ปฃ๏ปœ๏บฎ๏บญ" โ”‚

โ”‚ - Status: 2 โ”‚

โ”‚ - Exit process โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 5. Create New Account โ”‚

โ”‚ - Create new webclients record โ”‚

โ”‚ - Set is_active = 1 โ”‚

โ”‚ - Set addtoday = current timestamp โ”‚

โ”‚ - Set adduserid = 0 (system created) โ”‚

โ”‚ - Store record and get new ID โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 6. Return Success Response โ”‚

โ”‚ JSON Response: โ”‚

โ”‚ { โ”‚

โ”‚ "status": 1, โ”‚

โ”‚ "reason": "ุชู… ุฅู†ุดุงุก ุงู„ุญุณุงุจ ุจู†ุฌุงุญ", โ”‚

โ”‚ "webclient_id": {new_id}, โ”‚

โ”‚ "name": "{name}", โ”‚

โ”‚ "mobile": "{mobile}", โ”‚

โ”‚ "user_name": "{user_name}" โ”‚

โ”‚ } โ”‚

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

---

### Workflow 2: Project Financial Report Generation

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

โ”‚ START: Generate Project Report โ”‚

โ”‚ GET: api_web.php?do=projectReport&id={projectid} โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 1. Load Project Basic Data โ”‚

โ”‚ - Get project master record โ”‚

โ”‚ - Build image and PDF URLs with host โ”‚

โ”‚ - Initialize financial totals โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 2. Process Project Stages (if enabled) โ”‚

โ”‚ IF project.projectstagesdata = 1: โ”‚

โ”‚ FOR EACH stage in projectstagechosse: โ”‚

โ”‚ โ”œโ”€โ†’ Load stage definition from projectstages โ”‚

โ”‚ โ”œโ”€โ†’ Process stage images: โ”‚

โ”‚ โ”‚ - Split comma-separated image names โ”‚

โ”‚ โ”‚ - Build full URLs with host prefix โ”‚

โ”‚ โ””โ”€โ†’ Process stage files: โ”‚

โ”‚ - Split comma-separated file names โ”‚

โ”‚ - Combine with original names โ”‚

โ”‚ - Build download URLs โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 3. Process Timeline Items (if enabled) โ”‚

โ”‚ IF project.projecttimetableitems = 1: โ”‚

โ”‚ - Query projecttimetableitems for project โ”‚

โ”‚ - Include: clause, amount, duration, dates โ”‚

โ”‚ ELSE: โ”‚

โ”‚ - Set empty array โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 4. Calculate Project Expenses (if enabled) โ”‚

โ”‚ IF project.expenses = 1: โ”‚

โ”‚ A. Material Exchange Expenses: โ”‚

โ”‚ - Group by expense type โ”‚

โ”‚ - Sum totalbuyprice and finalsupervision โ”‚

โ”‚ - Handle material returns (subtract) โ”‚

โ”‚ โ”‚

โ”‚ B. Direct Expenses: โ”‚

โ”‚ - Query expenseexchange by project โ”‚

โ”‚ - Group by expense type โ”‚

โ”‚ - Sum thevalue and finalsupervision โ”‚

โ”‚ โ”‚

โ”‚ C. Calculate Supervision: โ”‚

โ”‚ IF supervision_type = 1: โ”‚

โ”‚ - Use fixed supervision_amount โ”‚

โ”‚ ELSE: โ”‚

โ”‚ - Calculate based on percentages โ”‚

โ”‚ โ”‚

โ”‚ D. Build Expense Type Summary: โ”‚

โ”‚ FOR EACH expense type: โ”‚

โ”‚ - Load expense type name โ”‚

โ”‚ - Sum all related expenses โ”‚

โ”‚ - Calculate supervision amounts โ”‚

โ”‚ - Add to summary array โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 5. Calculate Project Income (if enabled) โ”‚

โ”‚ IF project.income = 1: โ”‚

โ”‚ A. Client Payments: โ”‚

โ”‚ - Query clientdebtchange for project client โ”‚

โ”‚ - Filter by paySerialNo > 0 (actual payments) โ”‚

โ”‚ - Sum clientdebtchangeamount โ”‚

โ”‚ โ”‚

โ”‚ B. Other Income: โ”‚

โ”‚ - Query income by project cost center โ”‚

โ”‚ - Sum incomeValue where conditions = 0 โ”‚

โ”‚ โ”‚

โ”‚ C. Total Income: โ”‚

โ”‚ - alltotalsincome = client payments + other income โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 6. Calculate Final Project Totals โ”‚

โ”‚ - Total Costs = alltotals + alltotalvalues โ”‚

โ”‚ - Net Result = Total Costs - Total Income โ”‚

โ”‚ - endtotals = (expenses + supervision) - income โ”‚

โ”‚ โ”‚

โ”‚ Positive endtotals = Project Loss โ”‚

โ”‚ Negative endtotals = Project Profit โ”‚

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

โ”‚

โ–ผ

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

โ”‚ 7. Build & Return Complete Report โ”‚

โ”‚ JSON Response: โ”‚

โ”‚ { โ”‚

โ”‚ "project": {project_data_with_totals}, โ”‚

โ”‚ "projectstages": [stage_data_with_files], โ”‚

โ”‚ "projecttimetableitems": [timeline_items], โ”‚

โ”‚ "expenses": [expense_type_summaries], โ”‚

โ”‚ "clientdebtchange": [payment_history], โ”‚

โ”‚ "incomes": [income_records] โ”‚

โ”‚ } โ”‚

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

---

## ๐ŸŒ API Endpoints

| Endpoint | Method | Purpose | Request Body |
|----------|---------|---------|--------------|
| `?do=register` | POST | Register new web client | `{name, mobile, user_name, password, device_id}` |
| `?do=login` | POST | Authenticate user | `{username, password}` |
| `?do=profile` | POST | Get user profile | `{id}` |
| `?do=projects` | POST | Get user's projects | `{webclientid}` |
| `?do=projectReport` | GET | Get detailed project report | `?id={projectid}` |
| `?do=updateProfile` | POST | Update user profile | `{id, name, mobile, user_name, password, device_id}` |
| `?do=getProjects` | POST | Alternative project list | `{webclient_id}` |
| `?do=getProject` | POST | Alternative project detail | `{projectid}` |

---

## ๐Ÿ“ฑ CORS & Cross-Platform Support

### CORS Headers Configuration
php

if (isset($_SERVER['HTTP_ORIGIN'])) {

header("Access-Control-Allow-Origin: *");

header('Access-Control-Allow-Credentials: true');

header('Access-Control-Max-Age: 86400');

}

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))

header("Access-Control-Allow-Methods: GET, POST, OPTIONS");

if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))

header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

exit(0);

}

### Multi-Platform Request Handling
php

$post_data = file_get_contents("php://input");

if (empty($post_data)) {

// iOS compatibility

$get_request = json_decode(json_encode($_POST));

} else {

// Android compatibility

$get_request = json_decode($post_data);

}

---

## ๐Ÿ”’ Security Issues & Recommendations

### Critical Security Vulnerabilities

**1. Plain Text Passwords**
php

// CURRENT (INSECURE)

$row->password = $password;

// RECOMMENDED

$row->password = password_hash($password, PASSWORD_DEFAULT);

// For authentication

if (password_verify($password, $stored_hash)) {

// Valid login

}

**2. SQL Injection Risk**
php

// CURRENT (VULNERABLE)

$user = R::findOne('webclients', " (user_name = '" . $username . "' or mobile = '" . $mobile . "') and password = '" . $password . "' ");

// RECOMMENDED

$user = R::findOne('webclients', " (user_name = ? or mobile = ?) and password = ?", [$username, $username, $password_hash]);

**3. No Rate Limiting**
- Add login attempt limiting
- Implement IP-based throttling
- Add CAPTCHA for repeated failures

**4. Missing Input Sanitization**
- Validate email format
- Sanitize mobile number format
- Escape special characters in user input

---

## ๐Ÿ“Š Performance Considerations

### Database Optimization
1. **Critical Indexes**:
   - `webclients(user_name, is_active)`
   - `webclients(mobile, is_active)`
   - `webclientprojects(webclientid)`
   - `project(clientid)`
   - `expenseexchange(projectid, expensetype)`

2. **Query Optimization**:
   - Use prepared statements for security and performance
   - Limit result sets for large projects
   - Cache frequently accessed project data

### File Handling Performance
- Image and PDF concatenation should be cached
- Consider CDN for file delivery
- Implement file compression for mobile apps

---

## ๐Ÿ› Common Issues & Troubleshooting

### 1. **CORS Preflight Issues**
**Issue**: Browser blocks API requests from web applications  
**Cause**: Missing or incorrect CORS headers

**Fix**:
php

// Ensure all required headers are sent

header("Access-Control-Allow-Origin: *");

header("Access-Control-Allow-Methods: GET, POST, OPTIONS");

header("Access-Control-Allow-Headers: Content-Type, Authorization");

### 2. **Empty Response Data**
**Issue**: API returns empty or null data  
**Cause**: Database connection issues or missing foreign key relationships

**Debug**:
php

// Add debugging output

error_log("Project ID: " . $projectid);

error_log("Query result: " . print_r($project, true));

### 3. **Authentication Failures**
**Issue**: Valid credentials rejected  
**Cause**: Case sensitivity or character encoding issues

**Debug**:
php

// Check exact values being compared

error_log("Input username: " . $username);

error_log("Stored username: " . $user->user_name);

error_log("Password match: " . ($password === $user->password ? 'YES' : 'NO'));

---

## ๐Ÿงช Testing Scenarios

### Test Case 1: User Registration Flow

1. POST valid registration data

2. Verify success response with user ID

3. Attempt duplicate username registration

4. Verify error response for duplicate

5. Test missing required fields

6. Verify appropriate error messages

### Test Case 2: Project Report Generation

1. Request report for valid project ID

2. Verify all financial calculations

3. Test with project having no expenses

4. Test with project having no income

5. Verify file URL generation

6. Test with invalid project ID

### Test Case 3: CORS Functionality

1. Send OPTIONS preflight request

2. Verify CORS headers in response

3. Send actual POST request from browser

4. Verify request not blocked by CORS

5. Test with different origins

```

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โš ๏ธ Security review needed

Next Review: Implement security fixes before production use