Files
citrus-cms/resources/views/guide/developer-get-started-guide.md
T
2026-04-28 21:15:09 +03:00

16 KiB

DevQMS Developer Get Started Guide

Table of Contents

  1. Project Overview
  2. Architecture Overview
  3. Core Components
  4. Module System
  5. DevExtreme Integration
  6. Admin-AJAX System
  7. Save Trigger System
  8. Batch Excel Operations
  9. Development Workflow
  10. Common Patterns
  11. Troubleshooting

Project Overview

DevQMS is a Quality Management System (QMS) built on Laravel framework with advanced features including:

  • Modular Architecture: Each module (WeldLog, TestPackage, etc.) has its own Model, Controller, and View
  • DevExtreme Integration: Advanced UI components for data grids, forms, and charts
  • Dynamic Form System: Forms are generated dynamically based on database schema
  • Excel Import/Export: Batch operations for data management
  • Role-based Access Control: User permission system with different levels
  • Real-time Data Processing: Save triggers for automatic data synchronization

Architecture Overview

Directory Structure

app/
├── Http/Controllers/
│   ├── AdminController.php          # Main CRUD controller
│   ├── AdminAjaxController.php     # AJAX request handler
│   └── SaveTrigger/                # Automatic data processing
├── DevExtreme/                     # DevExtreme integration classes
├── Models/                         # Eloquent models
└── Functions/                      # Helper functions

resources/views/
├── admin/                          # Admin panel views
│   └── type/                       # Module views
├── admin-ajax/                     # AJAX response views
├── components/                     # Reusable components
│   ├── blocks/                     # Module blocks
│   └── table/                      # DataGrid components
└── guide/                          # Documentation

routes/
└── web.php                         # Route definitions

Core Technologies

  • Backend: Laravel 8+ with PHP 8+
  • Frontend: DevExtreme DataGrid, jQuery, Bootstrap
  • Database: MySQL with InnoDB
  • File Storage: Laravel Storage with local/cloud options
  • Excel Processing: Maatwebsite Excel package

Core Components

1. AdminController.php

The central controller handling all CRUD operations for modules. Key methods:

// Read operations
public function tableToJson(Request $request, string $tableName)
public function getDetail(Request $request, string $tableName, string $columnName, string $value)

// Write operations  
public function insertJson(Request $request, string $tableName)
public function saveJson(Request $request, string $tableName)
public function removeJson(Request $request, string $tableName)

// Excel operations
public function importExcel(Request $request, string $tableName)
public function exportExcel(Request $request, string $tableName, string $fileName)

Important: All modules use this centralized controller - no need to create individual controllers for basic CRUD operations.

2. AdminAjaxController.php

Handles AJAX requests through view-based routing:

public function index(Request $request, string $var) {
    $url = "admin-ajax.$var";
    return view($url, array("request" => $request));
}

AJAX views are located in resources/views/admin-ajax/ and follow the naming pattern {action}.blade.php.

3. DevExtreme Integration

DbSet.php

Custom query builder for DevExtreme DataGrid:

$dbSet = new DbSet($mySQL, 'table_name');
$result = $dbSet->Select(['id', 'name'])
                ->Filter(['status' => 'active'])
                ->OrderBy('name')
                ->SkipTake(0, 10)
                ->AsArray();

Utils.php

Helper functions for data processing and SQL escaping.

Module System

Creating a New Module

  1. Create Model and Migration:
// app/Models/NewModule.php
class NewModule extends Model {
    protected $table = 'new_modules';
    protected $primaryKey = 'id';
    public $timestamps = true;
}
  1. Create View Template:
// resources/views/admin/type/new-module.blade.php
<?php 
use App\Models\NewModule;

$title = "New Module";
$tableName = "new_modules";
$listDatas = NewModule::orderBy("id","DESC")->paginate(setting('row_count'));

$blockGroup = [    
    'General Info' => [
        'name',
        'description',
    ],
    'Details' => [
        'status',
        'created_at',
    ],
];

$relationDatas = [
    'status' => [
        'type' => 'select',
        'datas' => [
            'active' => 'Active',
            'inactive' => 'Inactive'
        ]
    ],
];

$firstUploadFolder = 'NewModule/';
$firstUploadTitle = 'Upload Files';
?>

<div class="content">
    <div class="row">   
        @include("admin.type.document.upload") 
        @include("components.blocks.module-block")     
    </div>
</div>
  1. Add to Types Table: Register the module in the admin panel's Types section with:
  • Title: "New Module"
  • Slug: "new-module"
  • Fields: "name,description,status,created_at"

Module Template Structure

sablon4.blade.php

Base template for modules with these key variables:

$title = "Module Title";                    // Page title
$tableName = "table_name";                  // Database table name
$listDatas = Model::paginate(50);          // Data source
$blockGroup = [];                          // Field grouping
$relationDatas = [];                       // Field type definitions
$firstUploadFolder = 'ModuleName/';        // File upload folder
$firstUploadTitle = 'Upload Title';        // Upload section title

module-block.blade.php

Handles the DataGrid integration and includes:

  • Column selection
  • Excel import/export
  • DataGrid component
  • Field type mapping

DevExtreme Integration

DataGrid Configuration

The DataGrid is configured in resources/views/components/table/datagrid.blade.php with:

var dataGrid = $("#dataGrid").dxDataGrid({
    dataSource: dataSource,
    keyExpr: "{{$tableName}}",
    allowColumnResizing: true,
    allowColumnReordering: true,
    showBorders: true,
    filterRow: {
        visible: true
    },
    searchPanel: {
        visible: true
    },
    paging: {
        pageSize: 20
    },
    pager: {
        showPageSizeSelector: true,
        allowedPageSizes: [10, 20, 50, 100]
    },
    editing: {
        mode: "popup",
        allowUpdating: true,
        allowAdding: true,
        allowDeleting: true
    }
});

Field Types

Supported field types in relationDatas:

$relationDatas = [
    'text_field' => ['type' => 'text'],
    'date_field' => ['type' => 'date'],
    'number_field' => ['type' => 'number'],
    'select_field' => [
        'type' => 'select',
        'datas' => ['option1' => 'Label 1', 'option2' => 'Label 2']
    ],
    'link_field' => [
        'type' => 'link-search',
        'html' => '<i class="fa fa-link"></i>'
    ],
    'decimal_field' => ['type' => 'decimal'],
    'checkbox_field' => ['type' => 'checkbox']
];

Custom Validation

Add custom validation in components/table/datagrid/validation-callback/{module}/{field}.blade.php:

function validationCallback_fieldName(e) {
    // Custom validation logic
    if (e.value && e.value.length < 3) {
        return false;
    }
    return true;
}

Admin-AJAX System

Creating AJAX Endpoints

  1. Create AJAX View:
// resources/views/admin-ajax/custom-action.blade.php
@php
$data = db('table_name')->where('condition', $request->input('value'))->get();
echo json_encode([
    'status' => 'success',
    'data' => $data
]);
@endphp
  1. Call from JavaScript:
$.ajax({
    url: '/admin-ajax/custom-action',
    type: 'POST',
    data: {
        value: 'search_value',
        _token: csrf_token
    },
    success: function(response) {
        // Handle response
    }
});

Common AJAX Patterns

Batch Operations

// admin-ajax/batch-operation.blade.php
@php
$ids = $request->input('ids', []);
$operation = $request->input('operation');

foreach($ids as $id) {
    db('table_name')->where('id', $id)->update(['status' => $operation]);
}

echo json_encode(['status' => 'success', 'processed' => count($ids)]);
@endphp

Data Export

// admin-ajax/export-data.blade.php
@php
$query = $request->input('query');
$data = DB::select($query);

$filename = 'export_' . date('Y-m-d_H-i-s') . '.xlsx';
Excel::store(new ExportExcel($data), $filename);

echo json_encode(['status' => 'success', 'file' => $filename]);
@endphp

Save Trigger System

Overview

Save triggers automatically process data changes and maintain data consistency across related tables.

Trigger Structure

// app/Http/Controllers/SaveTrigger/{table_name}.php
<?php
use App\Models\RelatedModel;

$id = $request['key'];
$data = db($tableName)->where("id", $id)->first();

// Detect changed fields
$changedFields = [];
foreach ($data as $key => $value) {
    if (isset($beforeData->$key) && $beforeData->$key != $value) {
        $changedFields[] = $key;
    }
}

// Execute related updates
if (in_array('status', $changedFields)) {
    // Update related records
    RelatedModel::where('parent_id', $id)
               ->update(['status' => $data->status]);
}

Common Trigger Patterns

Status Synchronization

// Update related records when status changes
if (in_array('status', $changedFields)) {
    $newStatus = $data->status;
    
    // Update child records
    db('child_table')->where('parent_id', $id)
                    ->update(['status' => $newStatus]);
    
    // Update summary tables
    $summary = db('summary_table')->where('parent_id', $id)->first();
    if ($summary) {
        $summary->update(['last_status' => $newStatus]);
    }
}

Calculated Fields

// Recalculate totals when related fields change
if (array_intersect(['quantity', 'unit_price'], $changedFields)) {
    $total = $data->quantity * $data->unit_price;
    
    db($tableName)->where('id', $id)
                 ->update(['total' => $total]);
}

Cross-Table Updates

// Update related tables when key fields change
if (in_array('project_id', $changedFields)) {
    $newProjectId = $data->project_id;
    
    // Update all related records
    db('related_table')->where('parent_id', $id)
                      ->update(['project_id' => $newProjectId]);
}

Batch Excel Operations

Import Process

  1. File Upload: Users upload Excel files through the interface
  2. Validation: System validates data format and required fields
  3. Processing: Data is processed in batches to handle large files
  4. Save Triggers: Each row triggers the appropriate save triggers
  5. Progress Tracking: Real-time progress updates via AJAX

Export Process

  1. Query Building: Dynamic SQL query based on filters
  2. Data Retrieval: Fetch data with pagination for large datasets
  3. Formatting: Apply formatting and styling
  4. File Generation: Create Excel file with multiple sheets if needed
  5. Download: Provide download link to user

Implementation Example

// Batch Excel Import
public function importExcel(Request $request, string $tableName) {
    $file = $request->file('file');
    $import = new ImportExcel($tableName);
    
    Excel::import($import, $file);
    
    return response()->json([
        'status' => 'success',
        'imported' => $import->getRowCount()
    ]);
}

// Batch Excel Export
public function exportExcel(Request $request, string $tableName, string $fileName = "") {
    $query = $request->input('query');
    $data = DB::select($query);
    
    $fileName = $fileName ?: $tableName . '_' . date('Y-m-d_H-i-s');
    
    return Excel::download(new ExportExcel($data), $fileName . '.xlsx');
}

Development Workflow

1. Environment Setup

# Clone repository
git clone [repository-url]
cd dev

# Install dependencies
composer install
npm install

# Configure environment
cp .env.example .env
php artisan key:generate

# Run migrations
php artisan migrate

# Start development server
php artisan serve

2. Creating New Features

  1. Database Changes:

    php artisan make:migration create_new_table
    php artisan migrate
    
  2. Model Creation:

    php artisan make:model NewModel
    
  3. View Template:

    • Copy sablon4.blade.php as base
    • Customize variables and field groups
    • Add to Types table
  4. Save Triggers (if needed):

    • Create trigger file in SaveTrigger/
    • Define change detection logic
    • Implement cross-table updates

3. Testing

# Run tests
php artisan test

# Test specific module
php artisan test --filter=NewModuleTest

4. Deployment

# Production deployment
composer install --optimize-autoloader --no-dev
php artisan config:cache
php artisan route:cache
php artisan view:cache

Common Patterns

1. Dynamic Field Handling

// Get field types from database
$fieldTypes = [];
foreach($columns as $column) {
    $fieldTypes[$column] = table_column_type($tableName, $column);
}

// Apply custom field types
$relationDatas = [
    'status' => ['type' => 'select', 'datas' => $statusOptions],
    'date_field' => ['type' => 'date'],
];

2. Permission Checking

// Check user permissions
if (!isAuth($tableName, 'write')) {
    return response()->json(['error' => 'Permission denied'], 403);
}

// Role-based access
if (!isAdmin()) {
    // Limited access logic
}

3. Data Validation

// Custom validation in save triggers
$requiredFields = ['name', 'email', 'status'];
foreach($requiredFields as $field) {
    if (empty($data->$field)) {
        throw new Exception("Field $field is required");
    }
}

4. Error Handling

try {
    // Database operation
    DB::transaction(function() use ($data) {
        // Complex operations
    });
} catch (Exception $e) {
    Log::error('Operation failed', [
        'error' => $e->getMessage(),
        'data' => $data
    ]);
    
    return response()->json(['error' => 'Operation failed'], 500);
}

Troubleshooting

Common Issues

  1. DataGrid Not Loading:

    • Check browser console for JavaScript errors
    • Verify AJAX endpoint returns valid JSON
    • Check network tab for failed requests
  2. Save Triggers Not Working:

    • Verify trigger file exists in SaveTrigger/
    • Check database permissions
    • Review error logs
  3. Excel Import Failures:

    • Validate Excel file format
    • Check column mappings
    • Verify required fields are present
  4. Permission Errors:

    • Check user level in database
    • Verify module permissions
    • Review middleware configuration

Debug Tools

  1. Laravel Telescope (if enabled):

    /telescope
    
  2. Database Logging:

    DB::enableQueryLog();
    // ... operations
    dd(DB::getQueryLog());
    
  3. DevExtreme Debug:

    // Enable DevExtreme debug mode
    DevExpress.config({ debug: true });
    

Performance Optimization

  1. Database Indexing:

    CREATE INDEX idx_table_column ON table_name(column_name);
    
  2. Query Optimization:

    // Use eager loading for relationships
    $data = Model::with('relation')->get();
    
  3. Caching:

    // Cache frequently accessed data
    $data = Cache::remember('key', 3600, function() {
        return Model::all();
    });
    

This guide provides a comprehensive overview of the DevQMS system. For specific module documentation, refer to the individual guide files in the guide/ directory. Always test changes in a development environment before deploying to production.