create service count floor level and retributions

This commit is contained in:
arifal
2025-06-18 18:44:30 +07:00
parent df70a47bd1
commit 59cc102c5a
13 changed files with 1415 additions and 180 deletions

View File

@@ -0,0 +1,110 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BuildingFunctionFormulaConfig extends Model
{
use HasFactory;
protected $fillable = [
'building_function_id',
'formula_id',
'floor_level',
'min_floor',
'max_floor',
'multiplier',
'is_active',
'priority',
'notes',
];
protected $casts = [
'multiplier' => 'decimal:4',
'is_active' => 'boolean',
'min_floor' => 'integer',
'max_floor' => 'integer',
'floor_level' => 'integer',
'priority' => 'integer',
];
/**
* Relationship to BuildingFunction
*/
public function buildingFunction()
{
return $this->belongsTo(BuildingFunction::class, 'building_function_id');
}
/**
* Relationship to MasterFormula
*/
public function formula()
{
return $this->belongsTo(MasterFormula::class, 'formula_id');
}
/**
* Scope untuk konfigurasi aktif
*/
public function scopeActive($query)
{
return $query->where('is_active', true);
}
/**
* Scope untuk mencari berdasarkan building function dan floor level
*/
public function scopeForBuildingAndFloor($query, $buildingFunctionId, $floorLevel)
{
return $query->where('building_function_id', $buildingFunctionId)
->where(function($q) use ($floorLevel) {
$q->where('floor_level', $floorLevel)
->orWhere('floor_level', 0) // 0 = berlaku untuk semua lantai
->orWhere(function($qq) use ($floorLevel) {
$qq->whereNotNull('min_floor')
->whereNotNull('max_floor')
->where('min_floor', '<=', $floorLevel)
->where('max_floor', '>=', $floorLevel);
});
})
->orderBy('priority', 'desc')
->orderBy('floor_level', 'desc'); // Prioritas: spesifik floor > range > semua lantai
}
/**
* Method untuk mendapatkan formula yang tepat untuk building function dan floor tertentu
*/
public static function getFormulaForBuildingAndFloor($buildingFunctionId, $floorLevel)
{
return self::active()
->forBuildingAndFloor($buildingFunctionId, $floorLevel)
->with('formula')
->first();
}
/**
* Method untuk check apakah floor level masuk dalam range
*/
public function isFloorInRange($floorLevel)
{
// Jika floor_level = 0, berlaku untuk semua lantai
if ($this->floor_level == 0) {
return true;
}
// Jika ada specific floor level
if ($this->floor_level == $floorLevel) {
return true;
}
// Jika ada range min-max
if (!is_null($this->min_floor) && !is_null($this->max_floor)) {
return $floorLevel >= $this->min_floor && $floorLevel <= $this->max_floor;
}
return false;
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class FormulaParameter extends Model
{
use HasFactory;
protected $fillable = [
'formula_id',
'parameter_id',
];
/**
* Relationship to MasterFormula
*/
public function formula()
{
return $this->belongsTo(MasterFormula::class, 'formula_id');
}
/**
* Relationship to MasterParameter
*/
public function parameter()
{
return $this->belongsTo(MasterParameter::class, 'parameter_id');
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MasterFormula extends Model
{
use HasFactory;
protected $fillable = [
'formula_code',
'formula_name',
'formula_expression',
'formula_category',
'description',
'usage_notes',
];
/**
* Relationship to FormulaParameter (Many-to-Many dengan MasterParameter)
*/
public function formulaParameters()
{
return $this->hasMany(FormulaParameter::class, 'formula_id');
}
/**
* Relationship to MasterParameter through FormulaParameter
*/
public function parameters()
{
return $this->belongsToMany(MasterParameter::class, 'formula_parameters', 'formula_id', 'parameter_id');
}
/**
* Relationship to BuildingFunctionFormulaConfig
*/
public function buildingConfigs()
{
return $this->hasMany(BuildingFunctionFormulaConfig::class, 'formula_id');
}
/**
* Scope untuk mencari berdasarkan kategori
*/
public function scopeByCategory($query, $category)
{
return $query->where('formula_category', $category);
}
/**
* Method untuk mendapatkan parameter yang diperlukan formula ini
*/
public function getRequiredParameters()
{
return $this->parameters()->get();
}
/**
* Method untuk evaluate formula dengan parameter values
*/
public function evaluateFormula($parameterValues = [])
{
$expression = $this->formula_expression;
// Replace parameter codes dengan nilai actual
foreach ($parameterValues as $parameterCode => $value) {
$expression = str_replace('{' . $parameterCode . '}', $value, $expression);
}
// Evaluasi mathematical expression (hati-hati dengan security!)
// Untuk production, gunakan library yang aman seperti SymfonyExpressionLanguage
try {
return eval("return $expression;");
} catch (Exception $e) {
throw new \Exception("Error evaluating formula: " . $e->getMessage());
}
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MasterParameter extends Model
{
use HasFactory;
protected $fillable = [
'parameter_code',
'parameter_name',
'default_value',
'unit',
'description',
];
protected $casts = [
'default_value' => 'decimal:6',
];
/**
* Relationship to FormulaParameter
*/
public function formulaParameters()
{
return $this->hasMany(FormulaParameter::class, 'parameter_id');
}
/**
* Relationship to MasterFormula through FormulaParameter
*/
public function formulas()
{
return $this->belongsToMany(MasterFormula::class, 'formula_parameters', 'parameter_id', 'formula_id');
}
/**
* Scope untuk mencari berdasarkan parameter code
*/
public function scopeByCode($query, $code)
{
return $query->where('parameter_code', $code);
}
/**
* Method untuk mendapatkan nilai parameter dengan fallback ke default
*/
public function getValue($customValue = null)
{
return $customValue !== null ? $customValue : $this->default_value;
}
}