Guardar cambios consolidar grupos docentes y clave de grupo
This commit is contained in:
@@ -66,15 +66,40 @@ class GrupoController extends Controller
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$nivel = Plan::where('id',$request->plan_id)->first();
|
||||
$plan = Plan::with('nivelRel')->where('id', $request->plan_id)->first();
|
||||
$plantel = Plantel::find($request->plantel);
|
||||
$turno = Turno::find($request->turno);
|
||||
|
||||
$nomenclatura = strtoupper(substr($plantel->nomenclatura, 0, 3));
|
||||
$nivel = strtoupper(substr($plan->nivelRel->name, 0, 1));
|
||||
$turnoLetra = strtoupper(substr($turno->name, 0, 1));
|
||||
$planId = $request->plan_id;
|
||||
$anioMes = now()->format('Ym');
|
||||
|
||||
$claveBase = "{$nomenclatura}-{$nivel}-{$turnoLetra}-{$planId}-{$anioMes}";
|
||||
|
||||
$sufijos = range('A', 'Z');
|
||||
$clave = $claveBase;
|
||||
|
||||
if (Grupo::where('clave', $claveBase)->exists()) {
|
||||
foreach ($sufijos as $sufijo) {
|
||||
$claveConSufijo = "{$claveBase}-{$sufijo}";
|
||||
if (!Grupo::where('clave', $claveConSufijo)->exists()) {
|
||||
$clave = $claveConSufijo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$grupo = Grupo::create([
|
||||
'plan_id' => $request->plan_id,
|
||||
'ciclo' => 1,
|
||||
'nivel' => $nivel->nivel,
|
||||
'plantel' => $request->plantel,
|
||||
'turno' => $request->turno,
|
||||
'status'=>1
|
||||
]);
|
||||
'plan_id' => $request->plan_id,
|
||||
'ciclo' => 1,
|
||||
'nivel' => $plan->nivel,
|
||||
'plantel' => $request->plantel,
|
||||
'turno' => $request->turno,
|
||||
'status' => 1,
|
||||
'clave' => $clave,
|
||||
]);
|
||||
|
||||
return redirect()->route('grupo.edit',$grupo)->with('info','El grupo se creo correctamente');
|
||||
|
||||
@@ -104,6 +129,15 @@ class GrupoController extends Controller
|
||||
});
|
||||
$ciclos = Plan::where('id',$grupo->plan_id)->first();
|
||||
|
||||
$grupo->load(['alumnos' => function ($query) {
|
||||
$query->join('alumno_user', 'alumnos.id', '=', 'alumno_user.alumno_id')
|
||||
->join('users', 'alumno_user.user_id', '=', 'users.id')
|
||||
->orderBy('users.apellidoPaterno')
|
||||
->orderBy('users.apellidoMaterno')
|
||||
->orderBy('users.name')
|
||||
->select('alumnos.*');
|
||||
}]);
|
||||
|
||||
return view('grupo.edit',compact(['grupo','turnos','plans','planteles','ciclos']));
|
||||
}
|
||||
|
||||
@@ -140,6 +174,7 @@ class GrupoController extends Controller
|
||||
return redirect()->route('grupo.edit',$grupo);
|
||||
}else{
|
||||
$grupo->alumnos()->detach();
|
||||
$grupo->docentes()->detach();
|
||||
$grupo->delete();
|
||||
session()->flash('swal',[
|
||||
'icon'=>'success',
|
||||
|
||||
@@ -57,32 +57,21 @@ class GrupoAlumno extends Component
|
||||
$plantelesUsuario = $user->plantelUsuarios->pluck('id');
|
||||
|
||||
$alumnos = Alumno::query()
|
||||
->with(['alumnos.plantelUsuarios', 'statusAlumno', 'plan.carreraRel','nivelRel'])
|
||||
->with(['usuario', 'statusAlumno', 'plan.carreraRel', 'nivelRel'])
|
||||
|
||||
->where('status', 2)
|
||||
// ✅ Cambia el 2 por el status correcto
|
||||
->whereIn('status', [2, 3]) // inscrito o alumno
|
||||
|
||||
->where('nivel', $grupo->nivel)
|
||||
|
||||
->whereDoesntHave('grupos')
|
||||
|
||||
->whereHas('alumnos.plantelUsuarios', function ($q) use ($plantelesUsuario) {
|
||||
$q->whereIn('plantels.id', $plantelesUsuario);
|
||||
})
|
||||
|
||||
->orderByRaw("
|
||||
CASE
|
||||
WHEN plan_id = {$grupo->plan_id} THEN 0
|
||||
ELSE 1
|
||||
END
|
||||
")
|
||||
->orderByRaw("
|
||||
CASE
|
||||
WHEN nivel = {$grupo->nivel} THEN 0
|
||||
ELSE 1
|
||||
END"
|
||||
)
|
||||
|
||||
->get();
|
||||
->where('nivel', $grupo->nivel)
|
||||
->whereDoesntHave('grupos')
|
||||
->whereHas('usuario', function ($q) use ($plantelesUsuario) {
|
||||
$q->whereHas('plantelUsuarios', function ($q2) use ($plantelesUsuario) {
|
||||
$q2->whereIn('plantel_user.plantel_id', $plantelesUsuario);
|
||||
});
|
||||
})
|
||||
->orderByRaw("CASE WHEN plan_id = {$grupo->plan_id} THEN 0 ELSE 1 END")
|
||||
->orderByRaw("CASE WHEN nivel = {$grupo->nivel} THEN 0 ELSE 1 END")
|
||||
->get();
|
||||
|
||||
return view('livewire.grupo-alumno', [
|
||||
'alumnos' => $alumnos,
|
||||
|
||||
@@ -71,25 +71,23 @@ $this->materiasSelect = Material::whereHas('carreraMaterial', function($query) u
|
||||
icon: 'success',
|
||||
title: '¡Listo!',
|
||||
text: 'Docente asignado correctamente',
|
||||
timer: 2000,
|
||||
timer: 3000,
|
||||
confirm: false,
|
||||
closeModal: true,
|
||||
reload: true
|
||||
);
|
||||
}
|
||||
|
||||
public function eliminar($docenteId)
|
||||
public function eliminar($docenteId, $materiaId)
|
||||
{
|
||||
$this->grupo->docentes()->detach($docenteId);
|
||||
$this->grupo->docentes()->wherePivot('materia_id', $materiaId)->detach($docenteId);
|
||||
|
||||
$this->dispatch('swal',
|
||||
icon: 'success',
|
||||
title: '¡Eliminado!',
|
||||
text: 'Docente removido correctamente',
|
||||
title: 'Eliminado',
|
||||
text: 'Docente removido de la materia correctamente',
|
||||
timer: 2000,
|
||||
confirm: false,
|
||||
closeModal: false,
|
||||
reload: true
|
||||
closeModal: true,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Models;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
class Material extends Model
|
||||
class Tarea extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ return new class extends Migration
|
||||
Schema::create('grupos', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('plan_id');
|
||||
$table->string('clave')->unique();
|
||||
$table->unsignedBigInteger('ciclo');
|
||||
$table->unsignedBigInteger('nivel');
|
||||
$table->unsignedBigInteger('plantel');
|
||||
|
||||
@@ -16,6 +16,7 @@ class GrupoSeeder extends Seeder
|
||||
$grupo = Grupo::create([
|
||||
'plan_id'=> 1,
|
||||
'ciclo'=> 1,
|
||||
'clave'=>"WASDWASD",
|
||||
'nivel'=> 1,
|
||||
'plantel'=> 3,
|
||||
'turno'=> 1,
|
||||
@@ -32,6 +33,7 @@ class GrupoSeeder extends Seeder
|
||||
$grupo2 = Grupo::create([
|
||||
'plan_id'=> 2,
|
||||
'ciclo'=> 1,
|
||||
'clave'=>"WASDWASD2",
|
||||
'nivel'=> 2,
|
||||
'plantel'=> 3,
|
||||
'turno'=> 2,
|
||||
|
||||
@@ -37,7 +37,7 @@ class UserSeeder extends Seeder
|
||||
'password' => bcrypt('6686'),
|
||||
'code'=>1,
|
||||
'status'=>1
|
||||
])->assignRole('Promotor');
|
||||
])->assignRole('Control escolar');
|
||||
|
||||
$user1->plantelUsuarios()->sync(3);
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
@method('PUT')
|
||||
@csrf
|
||||
<div class="mb-3">
|
||||
<label>Seleccionar Carrera</label>
|
||||
<select class="form-control" name="plan_id">
|
||||
<label>Carrera</label>
|
||||
<select class="form-control" name="plan_id" disabled>
|
||||
<option value="">Seleccionar plan</option>
|
||||
@foreach ($plans as $nivel => $grupos)
|
||||
<optgroup label="{{ $nivel }}">
|
||||
@@ -43,7 +43,12 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Seleccionar ciclo</label>
|
||||
<label>Clave</label>
|
||||
<input type="text" class="form-control" name="clave" value="{{ $grupo->clave }}" disabled>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>ciclo</label>
|
||||
<select class="form-control" name="ciclo">
|
||||
<option value="0">Seleccionar ciclo</option>
|
||||
@for ($i=1 ; $i <= $ciclos->duracion ; $i++)
|
||||
@@ -53,7 +58,7 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Seleccionar turno</label>
|
||||
<label>turno</label>
|
||||
<select class="form-control" name="turno">
|
||||
<option value="0">Seleccionar turno</option>
|
||||
@foreach ($turnos as $turno)
|
||||
@@ -65,8 +70,8 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Seleccionar plantel</label>
|
||||
<select class="form-control" name="plantel">
|
||||
<label>plantel</label>
|
||||
<select class="form-control" name="plantel" disabled>
|
||||
<option value="0">Seleccionar plantel</option>
|
||||
@foreach ($planteles as $plantel)
|
||||
<option value="{{ $plantel->id }}" {{ $plantel->id == $grupo->plantel ? 'selected' : '' }}>
|
||||
@@ -77,7 +82,7 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Seleccionar status</label>
|
||||
<label>status</label>
|
||||
<select class="form-control" name="status">
|
||||
<option value="1" {{ 1 == $grupo->status ? 'selected' : '' }}>Activo</option>
|
||||
<option value="0" {{ 0 == $grupo->status ? 'selected' : '' }}>Inactivo</option>
|
||||
@@ -113,36 +118,41 @@
|
||||
<div class="card-header py-3">
|
||||
<div class="d-sm-flex align-items-center justify-content-between">
|
||||
<h6 class="m-0 font-weight-bold text-primary">Alumnos</h6>
|
||||
@can('grupo.create')
|
||||
<button onclick="Livewire.dispatch('create-grupo')"
|
||||
class="d-sm-inline-block btn btn-sm btn-success shadow-sm">
|
||||
<i class="fas fa-plus fa-sm text-white-50"></i> Agregar alumno
|
||||
</button>
|
||||
@endcan
|
||||
@hasrole('Control escolar')
|
||||
<button onclick="Livewire.dispatch('create-grupo')"
|
||||
class="d-sm-inline-block btn btn-sm btn-success shadow-sm">
|
||||
<i class="fas fa-plus fa-sm text-white-50"></i> Agregar alumno
|
||||
</button>
|
||||
@endhasrole
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="container-fluid">
|
||||
<table id="tcont2" class="table table-striped table-bordered nowrap table-hover" style="width:100%;">
|
||||
<table id="tcont" class="table table-striped table-bordered nowrap table-hover" style="width:100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
{{-- <th>Id</th> --}}
|
||||
<th>Nombre</th>
|
||||
<th>Opciones</th>
|
||||
@hasrole('Control escolar')
|
||||
<th>Opciones</th>
|
||||
@endhasrole
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($grupo->alumnos as $alumno)
|
||||
<tr>
|
||||
<td>{{$alumno->id}}</td>
|
||||
{{-- <td>{{$alumno->id}}</td> --}}
|
||||
<td>
|
||||
{{$alumno->usuario->first()?->name}}
|
||||
{{$alumno->usuario->first()?->apellidoPaterno}}
|
||||
{{$alumno->usuario->first()?->apellidoMaterno}}
|
||||
{{$alumno->usuario->first()?->name}}
|
||||
</td>
|
||||
|
||||
@hasrole('Control escolar')
|
||||
<td>
|
||||
@can('grupo.destroy')
|
||||
|
||||
<form class="delete-form"
|
||||
action="{{route('grupo.destroy',$grupo->id)}}"
|
||||
method="POST">
|
||||
@@ -150,15 +160,17 @@
|
||||
@method('DELETE')
|
||||
<input class="d-none" name="alumno" value="{{$alumno->id}}">
|
||||
<button type="submit" style="border:none; background:none;">
|
||||
<i class="fa-solid fa-circle-xmark fa-xl"
|
||||
style="color:#e66565;"></i>
|
||||
<i class="fa-regular fa-circle-user-circle-minus fa-2xl" style="color: rgb(255, 0, 0);"></i>
|
||||
</button>
|
||||
</form>
|
||||
@endcan
|
||||
|
||||
</td>
|
||||
@endhasrole
|
||||
|
||||
|
||||
</tr>
|
||||
@empty
|
||||
<tr><td colspan="3">Sin alumnos.</td></tr>
|
||||
<tr>Sin alumnos.</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -185,50 +197,4 @@ document.addEventListener('livewire:init', () => {
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script> new DataTable('#tcont2', {
|
||||
responsive: true,
|
||||
language: {
|
||||
"decimal": "",
|
||||
"emptyTable": "No hay información",
|
||||
"info": "Mostrando _START_ a _END_ de _TOTAL_ Entradas",
|
||||
"infoEmpty": "Mostrando 0 to 0 of 0 Entradas",
|
||||
"infoFiltered": "(Filtrado de _MAX_ total entradas)",
|
||||
"infoPostFix": "",
|
||||
"thousands": ",",
|
||||
"lengthMenu": "Mostrar _MENU_ Entradas",
|
||||
"loadingRecords": "Cargando...",
|
||||
"processing": "Procesando...",
|
||||
"search": "Buscar:",
|
||||
"zeroRecords": "Sin resultados encontrados"
|
||||
},
|
||||
lengthMenu: [
|
||||
[10, 25, 50, -1],
|
||||
['10 filas', '25 filas', '50 filas', 'Todos']
|
||||
],
|
||||
layout: {
|
||||
topStart: {
|
||||
buttons: ['colvis', 'pageLength']
|
||||
},
|
||||
topEnd: ['search'],
|
||||
bottomStart: [{
|
||||
buttons: [{
|
||||
extend: 'excel',
|
||||
title: 'Excel'
|
||||
},
|
||||
{
|
||||
extend: 'pdfHtml5',
|
||||
title: 'PDF'
|
||||
},
|
||||
{
|
||||
extend: 'print'
|
||||
}
|
||||
]
|
||||
}, 'info'],
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$("#tcont2_wrapper").removeClass("form-inline");
|
||||
$("#tcont2_wrapper").addClass("w-100"); </script>
|
||||
@endsection
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Nombre</th>
|
||||
<th>Clave</th>
|
||||
<th>Opciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -35,6 +36,9 @@
|
||||
<td>{{$grupo->id}}</td>
|
||||
<td><a href="{{route('grupo.show',$grupo->id)}}">{{ $grupo->plan->carreraRel->name }}
|
||||
({{ $grupo->plan->name }}-{{ $grupo->plan->rvoe }})</a></td>
|
||||
|
||||
<td>{{$grupo->clave}}</td>
|
||||
|
||||
<td class="row mx-auto">
|
||||
@can('grupo.edit')
|
||||
<div class="col-sm-6 col-md-6"><a class="btn btn-primary" href="{{route('grupo.edit',$grupo->id)}}">Edit</a></div>
|
||||
|
||||
@@ -53,14 +53,17 @@
|
||||
</div>
|
||||
|
||||
{{-- Tabla docentes asignados --}}
|
||||
<table id="tcont" class="table table-striped table-bordered table-hover" style="width:100%;">
|
||||
<table id="tcont2" class="table table-striped table-bordered table-hover" style="width:100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Materia</th>
|
||||
<th>Ciclo</th>
|
||||
<th>Docente asignado</th>
|
||||
@hasrole('Coordinación académica')
|
||||
<th>Opciones</th>
|
||||
@endhasrole
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -80,26 +83,110 @@
|
||||
<span class="badge badge-secondary">Sin docente</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($docenteAsignado)
|
||||
@can('grupo.destroy')
|
||||
<button wire:click="eliminar({{ $docenteAsignado->id }})"
|
||||
style="border:none; background:none;">
|
||||
<i class="fa-solid fa-circle-xmark fa-xl" style="color:#e66565;"></i>
|
||||
</button>
|
||||
@endcan
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
@hasrole('Coordinación académica')
|
||||
<td>
|
||||
@if($docenteAsignado)
|
||||
<button
|
||||
onclick="confirmarEliminar({{ $docenteAsignado->id }}, {{ $materia->id }}, '{{ $usr?->name }} {{ $usr?->apellidoPaterno }}', '{{ $materia->name }}')"
|
||||
style="border:none; background:none;">
|
||||
<i class="fa-regular fa-circle-user-circle-minus fa-2xl" style="color: rgb(255, 0, 0);"></i>
|
||||
</button>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
@endhasrole
|
||||
|
||||
</tr>
|
||||
@empty
|
||||
<tr><td colspan="5">Sin materias en este plan.</td></tr>
|
||||
<tr>Sin materias en este plan.</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', initTable);
|
||||
|
||||
document.addEventListener('livewire:init', () => {
|
||||
// ✅ Este hook es el correcto para Livewire v3
|
||||
Livewire.hook('commit', ({ component, succeed }) => {
|
||||
succeed(() => {
|
||||
setTimeout(() => initTable(), 50);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function confirmarEliminar(docenteId, materiaId, nombreDocente, nombreMateria) {
|
||||
Swal.fire({
|
||||
title: "¿Eliminar docente?",
|
||||
html: `¿Deseas quitar a <b>${nombreDocente}</b> de <b>${nombreMateria}</b>?`,
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Sí, eliminar",
|
||||
cancelButtonText: "Cancelar",
|
||||
confirmButtonColor: '#e74a3b',
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
@this.eliminar(docenteId, materiaId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initTable() {
|
||||
// ✅ Destroy correcto
|
||||
if ($.fn.DataTable.isDataTable('#tcont2')) {
|
||||
$('#tcont2').DataTable().destroy();
|
||||
$('#tcont2').empty(); // limpia el DOM completamente
|
||||
}
|
||||
|
||||
new DataTable('#tcont2', {
|
||||
retrieve: true, // ✅ evita el error de reinicialización
|
||||
responsive: true,
|
||||
order: [],
|
||||
language: {
|
||||
"decimal": "",
|
||||
"emptyTable": "No hay información",
|
||||
"info": "Mostrando _START_ a _END_ de _TOTAL_ Entradas",
|
||||
"infoEmpty": "Mostrando 0 to 0 of 0 Entradas",
|
||||
"infoFiltered": "(Filtrado de _MAX_ total entradas)",
|
||||
"infoPostFix": "",
|
||||
"thousands": ",",
|
||||
"lengthMenu": "Mostrar _MENU_ Entradas",
|
||||
"loadingRecords": "Cargando...",
|
||||
"processing": "Procesando...",
|
||||
"search": "Buscar:",
|
||||
"zeroRecords": "Sin resultados encontrados"
|
||||
},
|
||||
lengthMenu: [
|
||||
[10, 25, 50, -1],
|
||||
['10 filas', '25 filas', '50 filas', 'Todos']
|
||||
],
|
||||
layout: {
|
||||
topStart: {
|
||||
buttons: ['colvis', 'pageLength']
|
||||
},
|
||||
topEnd: ['search'],
|
||||
bottomStart: [{
|
||||
buttons: [
|
||||
{ extend: 'excel', title: 'Excel' },
|
||||
{ extend: 'pdfHtml5', title: 'PDF' },
|
||||
{ extend: 'print' }
|
||||
]
|
||||
}, 'info'],
|
||||
}
|
||||
});
|
||||
|
||||
$("#tcont2_wrapper").removeClass("form-inline");
|
||||
$("#tcont2_wrapper").addClass("w-100");
|
||||
}
|
||||
|
||||
document.addEventListener('livewire:init', () => {
|
||||
Livewire.on('open-modal-docente', () => {
|
||||
$('#modalDocente').modal('show');
|
||||
@@ -108,7 +195,5 @@
|
||||
$('#modalDocente').modal('hide');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
Reference in New Issue
Block a user