๐Ÿ“š ERP Documentation Viewer

Beautiful, colorful documentation for your ERP system

Real Estate Units Reports Controller Documentation

File: /controllers/realestateunitsreports.php

Purpose: Generates comprehensive financial reports for real estate operations including income, expenses, and inventory consumption

Last Updated: December 20, 2024

Total Functions: 2

Lines of Code: ~120

---

๐Ÿ“‹ Overview

The Real Estate Units Reports Controller is a specialized reporting module that provides comprehensive financial analysis for real estate operations. It consolidates data from multiple sources including rental income (from tenants), ownership expenses (to suppliers), and inventory consumption related to property operations.

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Data Sources

Table NamePurposeKey Columns
**realestateunitspaids**Main payment records (both income & expense)id, supplierid, clientid, realestateid, realestateunitid, totalpaid, payed, addtoday
**realestateunitpaidinstallments**Individual installment recordsid, realestateunitpaidid, totalpaid, payed, del
**expenses**General property-related expensesexpensesid, realestateid, realestateunitid, expensesdate, expensevalue
**restaurantrawdestruction**Inventory consumption by propertyid, realestateid, realestateunitid, quantity, sysdate
### Reference Tables

Table NamePurposeKey Columns
**realestates**Property master dataid, realestatename
**realestatesunits**Property unit detailsid, unitname
**supplier**Property owners/supplierssupplierid, suppliername
**client**Tenants/clientsclientid, clientname
**product**Inventory itemsproductId, productName
**programsettings**System configurationprogramsettingsid, Inventoryevaluation
---

๐Ÿ”‘ Key Functions

1. Default Action - Report Display

Location: Line 6

Purpose: Displays the main report interface template

Function Signature:

// Triggered when: do parameter is empty
if (empty($do))

Process Flow:

1. Display header template

2. Display main report template (realestateunitsreportsview/show.html)

3. Display footer template

Features:

---

2. getdata() - Comprehensive Report Generation

Location: Line 10

Purpose: Generates detailed financial report with supplier expenses, client income, general expenses, and inventory consumption

Function Signature:

// Triggered when: do=getdata
$start_date = filter_input(INPUT_POST, 'start_date');
$end_date = filter_input(INPUT_POST, 'end_date');
$supplierid = filter_input(INPUT_POST, 'supplierid');
$clientid = filter_input(INPUT_POST, 'clientid');
$realestateid = filter_input(INPUT_POST, 'realestateid');
$realestateunitid = filter_input(INPUT_POST, 'realestateunitid');

Process Flow:

1. Parse Input Parameters - Extract date range and filter criteria

2. Build Search Queries - Create dynamic WHERE clauses for each data source

3. Query Supplier Payments - Get paid amounts to property owners

4. Query Client Payments - Get received amounts from tenants

5. Query General Expenses - Get other property-related expenses

6. Query Inventory Consumption - Get consumed inventory items

7. Apply Inventory Valuation - Calculate costs based on system settings

8. Calculate Period Duration - Determine months for analysis

9. Assign Data to Template - Pass all data to display template

Data Sources Queried:

Supplier Payments (Property Purchases/Expenses):

$srealestateunitspaids = R::findAll('realestateunitspaids', 
    "where del < 2 and clientid = 0 and payed > 0 $searchQuery $ssearchQuery");

Client Payments (Rental Income):

$crealestateunitspaids = R::findAll('realestateunitspaids', 
    "where del < 2 and supplierid = 0 and payed > 0 $searchQuery $csearchQuery");

General Expenses:

$expenses = R::getAll("SELECT * FROM expenses 
    left join realestates on expenses.realestateid = realestates.id
    left join realestatesunits on expenses.realestateunitid = realestatesunits.id
    where expenses.conditions = 0 $esearchQuery");

Inventory Consumption:

$restaurantrawdestruction = R::getAll("SELECT *, $buyprice as buypricenew, quantity as quantitynew 
    FROM restaurantrawdestruction 
    left join product on restaurantrawdestruction.productid = product.productId
    left join realestates on restaurantrawdestruction.realestateid = realestates.id
    left join realestatesunits on restaurantrawdestruction.realestateunitid = realestatesunits.id
    where restaurantrawdestruction.conditions = 0 $rsearchQuery");

---

๐Ÿ”„ Workflows

Workflow 1: Comprehensive Financial Report Generation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Generate Financial Report
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Parse Report Parameters
- Start and end dates
- Property/unit filters
- Supplier/client filters
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Build Dynamic Search Queries
FOR EACH data source:
โ†’ Add date range filter
โ†’ Add property/unit filter
โ”‚ โ””โ”€โ†’ Add entity-specific filters โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Query Supplier Payment Data
- Get all paid amounts to suppliers
- Include advance payments
- Include installment payments
- Load related supplier and property data
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Query Client Income Data
- Get all received amounts from clients
- Include advance payments
- Include installment payments
- Load related client and property data
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Query General Expenses
- Get property-related expenses
- Join with property and unit data
- Filter by date and location
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Query Inventory Consumption
- Get inventory items consumed
- Apply inventory valuation method
- Calculate costs based on system settings
- Join with product data
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
7Calculate Summary Metrics
- Total income from rentals
- Total expenses to suppliers
- General operational expenses
- Inventory consumption costs
- Net profit/loss calculation
- Period duration in months
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
8Generate Report Output
- Assign all data to template
- Display via getdata.html template
- Include charts and summaries
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty)Default displayShow report interface
`do=getdata`Data generationGenerate comprehensive report
### Required Parameters for getdata

Date Range (Optional - defaults to current date):

Filters (All Optional):

---

๐Ÿงฎ Calculation Methods

Date Range Handling

if($start_date != '' && $end_date != '') {
    $searchQuery .= ' and realestateunitspaids.addtoday >= "' . $start_date . ' 00-00-00" 
                     and realestateunitspaids.addtoday <= "' . $end_date . ' 23-59-55" ';
} else {
    // Default to current date
    $searchQuery .= ' and realestateunitspaids.addtoday >= "' . $date . ' 00-00-00" 
                     and realestateunitspaids.addtoday <= "' . $date . ' 23-59-55" ';
}

Inventory Valuation Method Selection

$programsettings = R::getRow('select * from programsettings WHERE programsettingsid = 1');
switch ($programsettings['Inventoryevaluation']) {
    case "first":
        $buyprice = 'restaurantrawdestruction.productBuyPrice';
        break;
    case "last":
        $buyprice = 'restaurantrawdestruction.lastbuyprice';
        break;
    case "mean":
    case "generalPrice":
        $buyprice = 'restaurantrawdestruction.meanbuyprice';
        break;
    case "last_discount":
        $buyprice = 'restaurantrawdestruction.lastbuyprice_withDiscount';
        break;
    case "mean_discount":
        $buyprice = 'restaurantrawdestruction.meanbuyprice_withDiscount';
        break;
}

Period Duration Calculation

$months = (int)abs((strtotime($end_date) - strtotime($start_date))/(60*60*24*30));

Data Enhancement for Display

// Enhance supplier payment data
foreach($srealestateunitspaids as $srealestateunitspaid) {
    $realestate = R::load('realestates', $srealestateunitspaid->realestateid);
    $supplier = R::getRow('select * from supplier WHERE supplierid = ? ', [$srealestateunitspaid->supplierid]);
    $realestateunitpaidinstallments = R::findAll('realestateunitpaidinstallments',
        'realestateunitpaidid = ? and del < 2 and payed > 0', [$srealestateunitspaid->id]);
    
    $srealestateunitspaid->realestate = $realestate;
    $srealestateunitspaid->supplier = $supplier;
    $srealestateunitspaid->realestateunitpaidinstallments = $realestateunitpaidinstallments;
}

---

๐Ÿ”’ Security & Permissions

Input Sanitization

$start_date = filter_input(INPUT_POST, 'start_date');
$end_date = filter_input(INPUT_POST, 'end_date');
$supplierid = filter_input(INPUT_POST, 'supplierid');
$clientid = filter_input(INPUT_POST, 'clientid');
$realestateid = filter_input(INPUT_POST, 'realestateid');
$realestateunitid = filter_input(INPUT_POST, 'realestateunitid');

Data Access Control

SQL Injection Prevention

---

๐Ÿ“Š Performance Considerations

Database Optimization Tips

1. Critical Indexes Needed:

   -- For date range queries
   CREATE INDEX idx_realestateunitspaids_date ON realestateunitspaids(addtoday, del);
   CREATE INDEX idx_expenses_date ON expenses(expensesdate, conditions);
   CREATE INDEX idx_restaurantraw_date ON restaurantrawdestruction(sysdate, conditions);
   
   -- For property filtering
   CREATE INDEX idx_realestateunitspaids_property ON realestateunitspaids(realestateid, realestateunitid);
   CREATE INDEX idx_expenses_property ON expenses(realestateid, realestateunitid);
   
   -- For entity filtering
   CREATE INDEX idx_realestateunitspaids_entities ON realestateunitspaids(supplierid, clientid, del);
   ```

2. **Query Optimization**:
   - Date range queries with proper timestamp formatting
   - Efficient joins with LEFT JOIN strategy
   - Proper use of WHERE conditions to filter early
   - Separate queries for different data sources

3. **Memory Considerations**:
   - Large date ranges may return significant data
   - Consider pagination for very large result sets
   - Multiple data arrays loaded simultaneously

### Performance Issues to Watch

**Potential Bottlenecks**:
sql

-- This pattern may be slow for large datasets

SELECT * FROM realestateunitspaids WHERE del < 2 AND payed > 0 AND addtoday BETWEEN ... ;

-- Solution: Ensure composite indexes

CREATE INDEX idx_performance ON realestateunitspaids(del, payed, addtoday);

---

## ๐Ÿ› Common Issues & Troubleshooting

### 1. **Missing Data in Reports**
**Issue**: Some transactions don't appear in report despite being in database  
**Cause**: Filtering conditions too restrictive

**Debug**:
sql

-- Check filtering conditions

SELECT COUNT(*) FROM realestateunitspaids WHERE del < 2; -- All active records

SELECT COUNT(*) FROM realestateunitspaids WHERE del < 2 AND payed > 0; -- Paid only

SELECT COUNT(*) FROM realestateunitspaids WHERE del < 2 AND clientid = 0; -- Supplier payments

SELECT COUNT(*) FROM realestateunitspaids WHERE del < 2 AND supplierid = 0; -- Client payments

### 2. **Incorrect Inventory Valuation**
**Issue**: Inventory costs showing incorrect amounts  
**Cause**: Wrong valuation method selected or missing price data

**Debug**:
sql

-- Check available price fields

SELECT productid, productBuyPrice, lastbuyprice, meanbuyprice,

lastbuyprice_withDiscount, meanbuyprice_withDiscount

FROM restaurantrawdestruction

WHERE realestateid = [ID] LIMIT 10;

-- Check system setting

SELECT Inventoryevaluation FROM programsettings WHERE programsettingsid = 1;

### 3. **Date Range Issues**
**Issue**: Reports showing no data for valid date ranges  
**Cause**: Date format mismatch or timezone issues

**Debug**:
sql

-- Check actual date formats in database

SELECT MIN(addtoday), MAX(addtoday) FROM realestateunitspaids WHERE del < 2;

SELECT MIN(expensesdate), MAX(expensesdate) FROM expenses WHERE conditions = 0;

SELECT MIN(sysdate), MAX(sysdate) FROM restaurantrawdestruction WHERE conditions = 0;

### 4. **Missing Related Data**
**Issue**: Reports show main records but missing supplier/client names  
**Cause**: Broken foreign key relationships

**Fix**:
sql

-- Find orphaned records

SELECT p.id, p.supplierid, s.supplierid as supplier_exists

FROM realestateunitspaids p

LEFT JOIN supplier s ON p.supplierid = s.supplierid

WHERE p.supplierid > 0 AND s.supplierid IS NULL;

-- Find missing client relationships

SELECT p.id, p.clientid, c.clientid as client_exists

FROM realestateunitspaids p

LEFT JOIN client c ON p.clientid = c.clientid

WHERE p.clientid > 0 AND c.clientid IS NULL;

---

## ๐Ÿงช Testing Scenarios

### Test Case 1: Basic Report Generation

1. Set date range covering known transactions

2. Run report without filters

3. Verify all 4 data sections populate

4. Check totals match individual records

5. Validate period calculation is correct

### Test Case 2: Property-Specific Filtering

1. Select specific property from dropdown

2. Run report for date range

3. Verify only that property's transactions appear

4. Check both supplier and client data filtered correctly

5. Validate expenses and inventory filtered to property

### Test Case 3: Unit-Level Analysis

1. Select specific property and unit

2. Run detailed report

3. Verify unit-level filtering works across all data sources

4. Check that property-level expenses still appear

5. Validate inventory consumption specific to unit

### Test Case 4: Edge Cases

1. Test with empty date ranges (current date default)

2. Test with future date ranges (should return empty)

3. Test with very large date ranges (performance)

4. Test with filters returning no results

5. Test inventory valuation method changes

```

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When reporting requirements change

โ†‘