# API Controller Documentation

**File**: `/controllers/api.php`  
**Purpose**: RESTful API endpoints for mobile app and external integrations  
**Last Updated**: December 20, 2024  
**Total Functions**: 14+  
**Lines of Code**: ~455

---

## 📋 Overview

The API Controller provides JSON-based REST API endpoints for mobile applications and third-party integrations. It handles:
- User authentication and session management
- Customer authentication for mobile apps
- Product catalog retrieval with search and pagination
- Sales order creation and management (offer system)
- Customer debt reports and transaction history
- Cross-Origin Resource Sharing (CORS) support
- Multi-language responses (Arabic/English)
- Real-time sales order processing

### Primary Functions
- [x] User login authentication
- [x] Customer login authentication  
- [x] Product catalog API with search
- [x] Sales offer creation and management
- [x] Real-time product addition to offers
- [x] Customer debt reporting
- [x] Barcode collection for POS systems
- [x] Order total calculations with tax
- [x] Order deletion and modification
- [x] CORS headers for web applications

### Related Controllers
- [sellbillController.php](sellbillController.md) - Sales operations
- [clientController.php](#) - Customer management
- [productController.php](productController.md) - Product management
- [clientReportsController.php](clientReportsController.md) - Customer reports

---

## 🗄️ Database Tables

### Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **user** | System user authentication | userid, username, password, employeename, usergroupid, conditions |
| **client** | Customer authentication & data | clientid, clientname, clientphone, password, priceTypeId, conditions |
| **product** | Product catalog | productId, productName, productBuyPrice, productSellAllPrice, productSellHalfPrice, productSellUnitPrice, parcode, productCatId |
| **collectedparcodestemp** | Temporary barcode storage | userid, sellerid, parcodes, sysdate, conditions |

### Sales Offer Tables
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **sellbilloffer** | Sales offers/draft orders | sellbillid, sellbillclientid, sellbillserial, sellbilltotalbill, sellbillaftertotalbill, orderSavedBillId, tax |
| **sellbilldetailoffer** | Sales offer line items | sellbilldetailid, sellbillid, sellbilldetailproductid, sellbilldetailquantity, sellbilldetailprice, sellbilldetailtotalprice |

### Financial Tables (Referenced)
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **clientdebtchange** | Customer debt transactions | clientdebtchangeid, clientid, clientdebtchangeamount, clientdebtchangetype, tablename, clientdebtchangemodelid |
| **sellbill** | Completed sales bills | sellbillid, sellbillclientid, sellbilltotalbill, sellbillaftertotalbill, sellbilltotalpayed |
| **returnsellbill** | Sales return bills | returnsellbillid, returnsellbillclientid, returnsellbilltotalbill, returnsellbillaftertotalbill |
| **sellbillandrutern** | Combined sell/return bills | sellbillid, sellbillclientid, sellbillprice, returnsellbillprice |

### Configuration Tables
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **programsettings** | System settings | programsettingsid, settingkey, settingvalue, vatValue |
| **checkdeposit** | Check deposits | checkdepositid, clientid, bankname, accountname, checkamount |
| **bills** | Service bills | billid, clientid, productstotalprice, finalnetbillvalue |

---

## 🔑 Key Functions

### 1. **User Authentication** - `do=user`
**Location**: Line 49  
**Purpose**: Retrieve user information for mobile app authentication

**Request Parameters**:
```php
$id = $get_request->id;           // Single user ID
$usergroupid = $get_request->group; // User group ID
// No parameters = all users
```

**Response Format**:
```json
// Single user
{"id": 123, "name": "John Doe"}

// Multiple users
[
    {"id": 123, "name": "John Doe"},
    {"id": 124, "name": "Jane Smith"}
]
```

**Process Flow**:
1. Parse request parameters from JSON
2. Query `user` table based on parameters
3. Filter active users (conditions = 0)
4. Return JSON response with user data

---

### 2. **User Login** - `do=login`
**Location**: Line 88  
**Purpose**: Authenticate system users for mobile applications

**Request Parameters**:
```php
$username = $get_request->username;
$password = $get_request->password;
```

**Response Format**:
```json
{
    "status": 1,           // 1=success, 2=error, 3=missing data
    "reason": "success",
    "id": 123,
    "name": "John Doe"
}
```

**Security Features**:
- Direct SQL query with parameter binding
- Active user validation (conditions = 0)
- Password comparison (plain text - legacy system)
- Structured error responses

---

### 3. **Customer Login** - `do=clientlogin`
**Location**: Line 143  
**Purpose**: Authenticate customers for mobile app access

**Request Parameters**:
```php
$phone = $get_request->phone;
$password = $get_request->password;
```

**Response Format**:
```json
{
    "status": 1,
    "reason": "تم تسجيل الدخول",     // Arabic success message
    "clientid": 456,
    "clientname": "Customer Name"
}
```

**Features**:
- Phone-based authentication
- Multi-language responses (Arabic)
- Client status validation
- Mobile-optimized responses

---

### 4. **Product Catalog** - `do=product`
**Location**: Line 162  
**Purpose**: Retrieve product catalog with search and pagination

**Request Parameters**:
```php
$id = $get_request->id;              // Single product ID
$text = $get_request->search;        // Search term
$start_item = $get_request->start_item; // Pagination offset
$page_no = $get_request->page_no;    // Items per page
$show_all = $get_request->show_all;  // Disable pagination
```

**Response Modes**:
```php
// Single product
{"productId": 123, "productName": "Item", "productSellAllPrice": 100.00}

// Search results (paginated)
[
    {"productId": 123, "productName": "Item 1", "productSellAllPrice": 100.00},
    {"productId": 124, "productName": "Item 2", "productSellAllPrice": 150.00}
]
```

**Search Features**:
- LIKE search on product names
- Pagination support (default 20 items)
- Active product filtering (conditions = 0)
- Flexible result formats

---

### 5. **Customer Report** - `do=clientreport`
**Location**: Line 189  
**Purpose**: Generate customer debt and transaction reports

**Request Parameters**:
```php
$clientid = $get_request->clientid;
$startDate = $get_request->from;
$endDate = $get_request->to;
$order = $get_request->order;
```

**Process Flow**:
1. Build dynamic WHERE clause based on filters
2. Join `clientdebtchange` with `client` tables
3. Calculate running debt totals
4. Link transactions to source documents
5. Load additional data based on transaction type
6. Return enriched transaction array

**Transaction Types Handled**:
- `sellbillController.php` - Sales bills
- `returnsellbillController.php` - Sales returns
- `depositcheckController.php` - Check deposits
- `clientPayedDeptController.php` - Customer payments
- `billreceiptController.php` - Bill receipts

---

### 6. **Create Sales Offer** - `do=createsellbillid`
**Location**: Line 301  
**Purpose**: Create new sales order/offer for customer

**Request Parameters**:
```php
$clientid = $get_request->clientid;
```

**Process Flow**:
1. Validate customer exists
2. Generate unique serial number using `uniqid()`
3. Insert new `sellbilloffer` record
4. Set default values (tax = 15%, billnameid = 7)
5. Return new offer ID for subsequent operations

**Response Format**:
```json
{
    "status": 1,
    "reason": "تم بنجاح",
    "sellbillid": 12345
}
```

---

### 7. **Add Product to Offer** - `do=addsellbilloffer`
**Location**: Line 333  
**Purpose**: Add or update product in existing sales offer

**Request Parameters**:
```php
$productid = $get_request->productid;
$quantity = $get_request->quantity;
$sellbillid = $get_request->sellbillid;
```

**Process Flow**:
1. Check if offer is still editable (orderSavedBillId = 0)
2. Load product and customer data
3. Determine price based on customer's price type:
   - `-1` or `0`: All price (wholesale)
   - `2`: Half price  
   - `1`: Unit price (retail)
4. Check if product already exists in offer
5. Insert new or update existing line item
6. Recalculate offer totals with tax
7. Update offer header with new totals

**Tax Calculation**:
```php
$vatValue = R::getCell("SELECT vatValue FROM programsettings WHERE programsettingsid = 1");
$taxPer = $vatValue / 100;
$taxPerPlusOne = $taxPer + 1;
$sellbilltotalbill = $sellbilldetailtotalprice - (($sellbilldetailtotalprice * $taxPer) / $taxPerPlusOne);
```

---

### 8. **Barcode Collection** - `do=collectparcodes`
**Location**: Line 110  
**Purpose**: Store scanned barcodes for later processing

**Request Parameters**:
```php
$userid = $get_request->userid;
$sellerid = $get_request->casherid;
$parcodes = $get_request->parcodes; // "00001,00002,00003"
```

**Use Case**: Mobile app scans multiple product barcodes, stores them temporarily, then processes all at once on main POS system.

**Response Format**:
```json
{
    "status": 1,
    "reason": "sucess",
    "id": 789
}
```

---

## 🔄 Workflows

### Workflow 1: Mobile Sales Order Creation
```
┌─────────────────────────────────────────────────────────────┐
│                START: Mobile Sales Process                 │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Customer Login                                          │
│     POST /api.php?do=clientlogin                           │
│     - Authenticate with phone + password                   │
│     - Return clientid for session                          │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Browse Product Catalog                                  │
│     GET /api.php?do=product&search=term&page_no=1          │
│     - Search products by name                              │
│     - Paginate results                                     │
│     - Display prices based on customer type               │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Create Sales Offer                                     │
│     POST /api.php?do=createsellbillid                      │
│     - Create empty offer for customer                      │
│     - Generate unique serial number                        │
│     - Return sellbillid for adding products               │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Add Products to Offer                                  │
│     FOR EACH selected product:                             │
│       │                                                    │
│       ├─→ POST /api.php?do=addsellbilloffer               │
│       │   - Add product with quantity                     │
│       │   - Apply customer-specific pricing               │
│       │   - Recalculate totals with tax                   │
│       │                                                    │
│       └─→ Update offer running total                      │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  5. Review Order                                           │
│     GET /api.php?do=sellbilldetailoffer                    │
│     - Display offer header and line items                  │
│     - Show calculated totals and tax                       │
│     - Allow modifications before finalizing                │
└─────────────────────────────────────────────────────────────┘
```

---

### Workflow 2: Customer Debt Report Access
```
┌─────────────────────────────────────────────────────────────┐
│              START: Mobile Report Request                  │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Customer Authentication                                 │
│     POST /api.php?do=clientlogin                           │
│     - Verify customer credentials                           │
│     - Establish session context                             │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Request Debt Report                                     │
│     POST /api.php?do=clientreport                          │
│     - Specify date range (optional)                        │
│     - Set sort order preference                             │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Generate Transaction History                            │
│     - Query clientdebtchange for customer                  │
│     - Calculate running debt balance                        │
│     - Link each transaction to source document             │
│     - Load transaction-specific details                     │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Return Enriched Data                                    │
│     - Transaction list with links                           │
│     - Running balance calculations                          │
│     - Source document details                               │
│     - Bank/payment information where applicable             │
└─────────────────────────────────────────────────────────────┘
```

---

## 🌐 URL Routes & Actions

| URL Parameter | Function | Description | HTTP Method |
|---------------|----------|-------------|-------------|
| `do=user` | User lookup | Get user information by ID, group, or all | GET/POST |
| `do=login` | User authentication | System user login | POST |
| `do=clientlogin` | Customer authentication | Customer mobile login | POST |
| `do=product` | Product catalog | Search products with pagination | GET/POST |
| `do=clientreport` | Customer reports | Generate debt/transaction reports | POST |
| `do=createsellbillid` | Create offer | Start new sales offer | POST |
| `do=addsellbilloffer` | Add to offer | Add product to existing offer | POST |
| `do=sellbilloffer` | List offers | Get customer's active offers | GET/POST |
| `do=sellbilldetailoffer` | Offer details | Get offer header and line items | GET/POST |
| `do=deletesellbilloffer` | Delete offer | Remove entire offer | POST |
| `do=deletesellbilldetailoffer` | Delete line | Remove product from offer | POST |
| `do=collectparcodes` | Store barcodes | Temporary barcode storage | POST |

---

## 🧮 Calculation Methods

### Customer Pricing Logic
```php
// Price determination based on customer type
if ($client['priceTypeId'] == -1 || $client['priceTypeId'] == 0) {
    $price = $product['productSellAllPrice'];  // Wholesale
    $pricetype = 0;
} elseif ($client['priceTypeId'] == 2) {
    $price = $product['productSellHalfPrice']; // Half price
    $pricetype = 2;
} else {
    $price = $product['productSellUnitPrice']; // Retail
    $pricetype = 1;
}
```

### Tax Calculation (VAT)
```php
$vatValue = R::getCell("SELECT vatValue FROM programsettings WHERE programsettingsid = 1");
$taxPer = $vatValue / 100;
$taxPerPlusOne = $taxPer + 1;

// Calculate price excluding tax
$sellbilltotalbill = $sellbilldetailtotalprice - (($sellbilldetailtotalprice * $taxPer) / $taxPerPlusOne);
```

### Debt Balance Calculation
```php
$total = 0;
foreach ($send_data as $data) {
    if ($data->clientdebtchangetype == 0) {
        $total = $total + $data->clientdebtchangeamount; // Debt increase
    } else {
        $total = $total - $data->clientdebtchangeamount; // Payment/decrease
    }
}
```

---

## 🔒 Security & Permissions

### CORS Configuration
```php
if (isset($_SERVER['HTTP_ORIGIN'])) {
    header("Access-Control-Allow-Origin: *");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day
}

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);
}
```

### Input Handling
```php
// Multi-platform request parsing
$post_data = file_get_contents("php://input");
if (empty($post_data)) {
    $get_request = json_decode(json_encode($_POST)); // iOS
} else {
    $get_request = json_decode($post_data);          // Android
}
```

### Authentication Methods
- **Users**: Username + password validation
- **Customers**: Phone + password validation
- **Active Status**: All queries filter `conditions = 0`
- **SQL Injection**: Uses RedBeanPHP parameterized queries

---

## 📊 Performance Considerations

### Database Optimization
1. **Indexes Required**:
   - `user(username, conditions)`
   - `client(clientphone, conditions)`
   - `product(productName, conditions)`
   - `clientdebtchange(clientid, clientdebtchangedate)`

2. **Query Efficiency**:
   - Product search uses LIKE with leading wildcard (slower)
   - Pagination implemented for large result sets
   - Active record filtering on all queries

3. **Memory Management**:
   - JSON responses can be large for full catalogs
   - Debt reports may return extensive transaction histories
   - Consider implementing result limits for mobile apps

### API Response Times
```sql
-- Fast queries (< 10ms)
SELECT * FROM user WHERE userid = ? AND conditions = 0;

-- Moderate queries (10-100ms)  
SELECT * FROM product WHERE productName LIKE '%term%' AND conditions = 0 LIMIT 20;

-- Slower queries (100ms+)
SELECT clientdebtchange.*, client.clientname FROM clientdebtchange 
JOIN client ON client.clientid = clientdebtchange.clientid 
WHERE clientdebtchange.clientid = ? ORDER BY clientdebtchangedate DESC;
```

---

## 🐛 Common Issues & Troubleshooting

### 1. **CORS Errors in Web Applications**
**Issue**: Browser blocks API requests from different domains  
**Cause**: Missing or incorrect CORS headers

**Fix**: Headers are already configured for `*` origin, but check:
```php
// Verify these headers are sent
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Credentials: true
```

### 2. **Empty API Responses**
**Issue**: API returns empty arrays or null responses  
**Cause**: Database connection issues or incorrect table filtering

**Debug**:
```sql
-- Check table data exists
SELECT COUNT(*) FROM user WHERE conditions = 0;
SELECT COUNT(*) FROM product WHERE conditions = 0;
SELECT COUNT(*) FROM client WHERE conditions = 0;
```

### 3. **Tax Calculation Errors**
**Issue**: Incorrect price calculations in offers  
**Cause**: VAT setting missing or misconfigured

**Fix**:
```sql
-- Verify VAT setting exists
SELECT vatValue FROM programsettings WHERE programsettingsid = 1;

-- Should return value like 15.00 for 15% VAT
INSERT INTO programsettings (programsettingsid, vatValue) VALUES (1, 15.00) 
ON DUPLICATE KEY UPDATE vatValue = 15.00;
```

### 4. **Mobile Authentication Failures**
**Issue**: Login always returns status = 2  
**Cause**: Password encoding mismatch or inactive accounts

**Debug**:
```sql
-- Check user exists and is active
SELECT userid, username, conditions FROM user WHERE username = 'testuser';

-- Check client exists and is active  
SELECT clientid, clientphone, conditions FROM client WHERE clientphone = '1234567890';
```

---

## 🧪 Testing Scenarios

### API Endpoint Testing

**Test User Authentication**:
```bash
curl -X POST http://localhost/erp19/controllers/api.php?do=login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"123456"}'
```

**Test Product Search**:
```bash
curl -X GET "http://localhost/erp19/controllers/api.php?do=product&search=laptop&page_no=10"
```

**Test Sales Offer Creation**:
```bash
curl -X POST http://localhost/erp19/controllers/api.php?do=createsellbillid \
  -H "Content-Type: application/json" \
  -d '{"clientid":123}'
```

### Integration Testing
1. **Complete Sales Flow**: Login → Browse → Create Offer → Add Products → Review
2. **Customer Report Flow**: Customer Login → Request Report → Process Results
3. **Error Handling**: Invalid credentials, missing parameters, database errors

---

## 📚 Related Documentation

- [CLAUDE.md](/Applications/AMPPS/www/erp19/CLAUDE.md) - PHP 8.2 migration guide
- [sellbillController.md](sellbillController.md) - Sales operations
- [clientReportsController.md](clientReportsController.md) - Customer reporting
- [productController.md](productController.md) - Product management

---

**Documented By**: AI Assistant  
**Review Status**: ✅ Complete  
**Next Review**: When API endpoints change or new mobile features added