# DevQMS Developer Get Started Guide ## Table of Contents 1. [Project Overview](#project-overview) 2. [Architecture Overview](#architecture-overview) 3. [Core Components](#core-components) 4. [Module System](#module-system) 5. [DevExtreme Integration](#devextreme-integration) 6. [Admin-AJAX System](#admin-ajax-system) 7. [Save Trigger System](#save-trigger-system) 8. [Batch Excel Operations](#batch-excel-operations) 9. [Development Workflow](#development-workflow) 10. [Common Patterns](#common-patterns) 11. [Troubleshooting](#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: ```php // 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: ```php 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: ```php $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**: ```php // app/Models/NewModule.php class NewModule extends Model { protected $table = 'new_modules'; protected $primaryKey = 'id'; public $timestamps = true; } ``` 2. **Create View Template**: ```php // resources/views/admin/type/new-module.blade.php 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'; ?>
@include("admin.type.document.upload") @include("components.blocks.module-block")
``` 3. **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: ```php $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: ```javascript 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`: ```php $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' => '' ], 'decimal_field' => ['type' => 'decimal'], 'checkbox_field' => ['type' => 'checkbox'] ]; ``` ### Custom Validation Add custom validation in `components/table/datagrid/validation-callback/{module}/{field}.blade.php`: ```javascript 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**: ```php // 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 ``` 2. **Call from JavaScript**: ```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 ```php // 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 ```php // 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 ```php // app/Http/Controllers/SaveTrigger/{table_name}.php 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 ```php // 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 ```php // 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 ```php // 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 ```php // 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 ```bash # 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**: ```bash php artisan make:migration create_new_table php artisan migrate ``` 2. **Model Creation**: ```bash 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 ```bash # Run tests php artisan test # Test specific module php artisan test --filter=NewModuleTest ``` ### 4. Deployment ```bash # 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 ```php // 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 ```php // 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 ```php // 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 ```php 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**: ```php DB::enableQueryLog(); // ... operations dd(DB::getQueryLog()); ``` 3. **DevExtreme Debug**: ```javascript // Enable DevExtreme debug mode DevExpress.config({ debug: true }); ``` ### Performance Optimization 1. **Database Indexing**: ```sql CREATE INDEX idx_table_column ON table_name(column_name); ``` 2. **Query Optimization**: ```php // Use eager loading for relationships $data = Model::with('relation')->get(); ``` 3. **Caching**: ```php // 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.