when($filters['search'] ?? null, fn($q,$s)=>$q->where('name','ILIKE',"%{$s}%")->orWhere('code','ILIKE',"%{$s}%"))->orderBy('service_type')->orderBy('event')->paginate($filters['per_page'] ?? 10); } public function save(array $data, int $userId, ?NasScriptPolicy $policy = null): NasScriptPolicy { $allowedEvents = $data['service_type'] === 'ppp' ? ['on_up', 'on_down'] : ['on_login', 'on_logout']; if (! in_array($data['event'], $allowedEvents, true)) { throw ValidationException::withMessages(['event' => 'Event tidak sesuai dengan tipe layanan Script Policy.']); } preg_match_all('/\{\{\s*([a-z_]+)\s*\}\}/', $data['script_template'], $matches); $invalid = array_diff(array_unique($matches[1]), self::VARIABLES); if ($invalid) throw ValidationException::withMessages(['script_template' => 'Variabel tidak diizinkan: '.implode(', ', $invalid)]); return DB::transaction(function () use ($data,$userId,$policy) { $version = $policy ? $policy->current_version + 1 : 1; $values = collect($data)->except(['script_template','change_notes'])->all(); $values['allowed_variables'] = self::VARIABLES; $values['current_version'] = $version; $values['created_by'] ??= $userId; $policy ? $policy->update($values) : $policy = NasScriptPolicy::create($values); $policy->versions()->create(['version'=>$version,'script_template'=>$data['script_template'],'checksum'=>hash('sha256',$data['script_template']),'change_notes'=>$data['change_notes'] ?? null,'created_by'=>$userId]); return $policy->fresh(['latestVersion','versions']); }); } }