# 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.