diff --git a/app/Http/Controllers/Admin/LegalOpinionCategoryController.php b/app/Http/Controllers/Admin/LegalOpinionCategoryController.php new file mode 100644 index 0000000..b0941f1 --- /dev/null +++ b/app/Http/Controllers/Admin/LegalOpinionCategoryController.php @@ -0,0 +1,69 @@ +filled('q')) { + $q = $request->q; + $query->where('name', 'like', "%{$q}%"); + } + + $perPage = min(max((int) $request->input('per_page', 15), 10), 100); + $categories = $query->paginate($perPage)->withQueryString(); + + return view('admin.legal-opinion-category.index', compact('categories')); + } + + public function create() + { + return view('admin.legal-opinion-category.create'); + } + + public function store(Request $request) + { + $validated = $request->validate([ + 'name' => 'required|string|unique:legal_opinion_categories,name', + ]); + + LegalOpinionCategory::create($validated); + + return redirect(route('legal-opinion-category.index')); + } + + public function edit(LegalOpinionCategory $legalOpinionCategory) + { + return view('admin.legal-opinion-category.update', compact('legalOpinionCategory')); + } + + public function show(LegalOpinionCategory $legalOpinionCategory) + { + return redirect(route('legal-opinion-category.edit', $legalOpinionCategory->id)); + } + + public function update(Request $request, LegalOpinionCategory $legalOpinionCategory) + { + $validated = $request->validate([ + 'name' => 'required|string|unique:legal_opinion_categories,name,' . $legalOpinionCategory->id, + ]); + + $legalOpinionCategory->update($validated); + + return redirect(route('legal-opinion-category.edit', $legalOpinionCategory->id)); + } + + public function destroy(LegalOpinionCategory $legalOpinionCategory) + { + $legalOpinionCategory->delete(); + + return redirect(route('legal-opinion-category.index')); + } +} diff --git a/app/Http/Controllers/Admin/LegalOpinionController.php b/app/Http/Controllers/Admin/LegalOpinionController.php new file mode 100644 index 0000000..efa9b46 --- /dev/null +++ b/app/Http/Controllers/Admin/LegalOpinionController.php @@ -0,0 +1,126 @@ +filled('q')) { + $q = $request->q; + $query->where(function ($qry) use ($q) { + $qry->where('opinion_number', 'like', "%{$q}%") + ->orWhere('subject', 'like', "%{$q}%") + ->orWhere('full_text', 'like', "%{$q}%") + ->orWhere('issuing_authority', 'like', "%{$q}%"); + }); + } + + $perPage = min(max((int) $request->input('per_page', 15), 10), 100); + $legalOpinions = $query->latest()->paginate($perPage)->withQueryString(); + + return view('admin.legal-opinion.index', compact('legalOpinions')); + } + + public function create() + { + $arts = Art::all(); + $categories = LegalOpinionCategory::all(); + + return view('admin.legal-opinion.create', compact('arts', 'categories')); + } + + public function store(Request $request) + { + $validated = $request->validate([ + 'opinion_number' => [ + 'required', + Rule::unique('legal_opinions', 'opinion_number')->where('category_id', $request->input('category_id')), + ], + 'opinion_date' => 'nullable|date', + 'subject' => 'nullable|string|max:1000', + 'full_text' => 'required|string', + 'issuing_authority' => 'nullable|string', + 'category_id' => 'required|exists:legal_opinion_categories,id', + 'art_ids' => 'nullable|array', + 'art_ids.*' => 'exists:art,id', + ]); + + $legalOpinion = LegalOpinion::create([ + 'opinion_number' => $validated['opinion_number'], + 'opinion_date' => $validated['opinion_date'] ?? null, + 'subject' => $validated['subject'] ?? null, + 'full_text' => $validated['full_text'], + 'issuing_authority' => $validated['issuing_authority'] ?? null, + 'category_id' => $validated['category_id'], + ]); + + if (!empty($validated['art_ids'])) { + $legalOpinion->arts()->attach($validated['art_ids']); + } + + return redirect(route('legal-opinion.index')); + } + + public function edit(LegalOpinion $legalOpinion) + { + $arts = Art::all(); + $categories = LegalOpinionCategory::all(); + $selectedArtIds = $legalOpinion->arts->pluck('id')->toArray(); + + return view('admin.legal-opinion.update', compact('legalOpinion', 'arts', 'categories', 'selectedArtIds')); + } + + public function show(LegalOpinion $legalOpinion) + { + return redirect(route('legal-opinion.edit', $legalOpinion->id)); + } + + public function update(Request $request, LegalOpinion $legalOpinion) + { + $validated = $request->validate([ + 'opinion_number' => [ + 'required', + Rule::unique('legal_opinions', 'opinion_number') + ->where('category_id', $request->input('category_id')) + ->ignore($legalOpinion->id), + ], + 'opinion_date' => 'nullable|date', + 'subject' => 'nullable|string|max:1000', + 'full_text' => 'required|string', + 'issuing_authority' => 'nullable|string', + 'category_id' => 'required|exists:legal_opinion_categories,id', + 'art_ids' => 'nullable|array', + 'art_ids.*' => 'exists:art,id', + ]); + + $legalOpinion->update([ + 'opinion_number' => $validated['opinion_number'], + 'opinion_date' => $validated['opinion_date'] ?? null, + 'subject' => $validated['subject'] ?? null, + 'full_text' => $validated['full_text'], + 'issuing_authority' => $validated['issuing_authority'] ?? null, + 'category_id' => $validated['category_id'], + ]); + + $legalOpinion->arts()->sync($validated['art_ids'] ?? []); + + return redirect(route('legal-opinion.edit', $legalOpinion->id)); + } + + public function destroy(LegalOpinion $legalOpinion) + { + $legalOpinion->delete(); + + return redirect(route('legal-opinion.index')); + } +} diff --git a/app/Models/Art.php b/app/Models/Art.php index 350f7e3..44d4e28 100644 --- a/app/Models/Art.php +++ b/app/Models/Art.php @@ -53,6 +53,11 @@ class Art extends Model return $this->belongsToMany(JudicialPrecedent::class, 'art_judicial_precedent'); } + public function legalOpinions() + { + return $this->belongsToMany(LegalOpinion::class, 'art_legal_opinion'); + } + public static function search($searchTerm) { return self::where('title', 'LIKE', "%{$searchTerm}%") diff --git a/app/Models/LegalOpinion.php b/app/Models/LegalOpinion.php new file mode 100644 index 0000000..4422f24 --- /dev/null +++ b/app/Models/LegalOpinion.php @@ -0,0 +1,32 @@ +belongsToMany(Art::class, 'art_legal_opinion'); + } + + public function category() + { + return $this->belongsTo(LegalOpinionCategory::class, 'category_id'); + } +} diff --git a/app/Models/LegalOpinionCategory.php b/app/Models/LegalOpinionCategory.php new file mode 100644 index 0000000..bff3d06 --- /dev/null +++ b/app/Models/LegalOpinionCategory.php @@ -0,0 +1,18 @@ +hasMany(LegalOpinion::class, 'category_id'); + } +} diff --git a/database/migrations/2026_05_08_000001_create_legal_opinion_categories_table.php b/database/migrations/2026_05_08_000001_create_legal_opinion_categories_table.php new file mode 100644 index 0000000..bb6463f --- /dev/null +++ b/database/migrations/2026_05_08_000001_create_legal_opinion_categories_table.php @@ -0,0 +1,28 @@ +id(); + $table->string('name')->unique()->comment('نام دستهبندی'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('legal_opinion_categories'); + } +}; diff --git a/database/migrations/2026_05_08_000002_create_legal_opinions_table.php b/database/migrations/2026_05_08_000002_create_legal_opinions_table.php new file mode 100644 index 0000000..1d76b47 --- /dev/null +++ b/database/migrations/2026_05_08_000002_create_legal_opinions_table.php @@ -0,0 +1,35 @@ +id(); + $table->string('opinion_number')->comment('شماره نظریه'); + $table->date('opinion_date')->nullable()->comment('تاریخ نظریه'); + $table->string('subject', 1000)->nullable()->comment('موضوع استعلام یا نظریه'); + $table->longText('full_text')->comment('متن کامل نظریه و استعلام'); + $table->string('issuing_authority')->nullable()->comment('مرجع صدور'); + $table->foreignId('category_id')->constrained('legal_opinion_categories')->onDelete('cascade')->comment('شناسه دستهبندی'); + $table->timestamps(); + + $table->unique(['opinion_number', 'category_id'], 'unique_opinion_category'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('legal_opinions'); + } +}; diff --git a/database/migrations/2026_05_08_000003_create_art_legal_opinion_table.php b/database/migrations/2026_05_08_000003_create_art_legal_opinion_table.php new file mode 100644 index 0000000..3655369 --- /dev/null +++ b/database/migrations/2026_05_08_000003_create_art_legal_opinion_table.php @@ -0,0 +1,31 @@ +id(); + $table->foreignId('art_id')->constrained('art')->onDelete('cascade'); + $table->foreignId('legal_opinion_id')->constrained('legal_opinions')->onDelete('cascade'); + $table->timestamps(); + + $table->unique(['art_id', 'legal_opinion_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('art_legal_opinion'); + } +}; diff --git a/resources/views/admin/legal-opinion-category/create.blade.php b/resources/views/admin/legal-opinion-category/create.blade.php new file mode 100644 index 0000000..38b7b85 --- /dev/null +++ b/resources/views/admin/legal-opinion-category/create.blade.php @@ -0,0 +1,25 @@ +@extends('admin.layouts.app') +@section('content') +