EnrollmentCrudController::show()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 13
nc 1
nop 1
dl 0
loc 20
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
namespace App\Http\Controllers\Admin;
4
5
use App\Models\Course;
6
use App\Models\Enrollment;
7
use App\Models\EnrollmentStatusType;
8
use App\Models\Paymentmethod;
9
use App\Models\Period;
10
use App\Models\PhoneNumber;
11
use App\Models\ScheduledPayment;
12
use App\Models\Scholarship;
13
use Backpack\CRUD\app\Http\Controllers\CrudController;
14
use Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
15
use Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
16
use Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
17
use Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
18
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
19
use Backpack\CRUD\app\Library\Widget;
20
use Illuminate\Support\Facades\Gate;
21
use Illuminate\Support\Facades\Log;
22
23
/**
24
 * Class EnrollmentCrudController
25
 * This controller is used to view enrollments only.
26
 * No enrollments may be created or updated from here.
27
 */
28
class EnrollmentCrudController extends CrudController
29
{
30
    use ListOperation;
0 ignored issues
show
introduced by
The trait Backpack\CRUD\app\Http\C...perations\ListOperation requires some properties which are not provided by App\Http\Controllers\Adm...nrollmentCrudController: $model, $query, $entity_name_plural
Loading history...
31
    use ShowOperation { show as traitShow; }
0 ignored issues
show
introduced by
The trait Backpack\CRUD\app\Http\C...perations\ShowOperation requires some properties which are not provided by App\Http\Controllers\Adm...nrollmentCrudController: $route, $entity_name
Loading history...
32
    use UpdateOperation { update as traitUpdate; }
0 ignored issues
show
introduced by
The trait Backpack\CRUD\app\Http\C...rations\UpdateOperation requires some properties which are not provided by App\Http\Controllers\Adm...nrollmentCrudController: $entity_name, $model
Loading history...
33
    use DeleteOperation;
34
35
    protected string $mode = 'global';
36
37
    protected ?Course $course = null;
38
39
    public function __construct()
40
    {
41
        parent::__construct();
42
        $this->middleware(['permission:enrollments.view']);
43
        $this->middleware('permission:enrollments.delete', ['only' => ['destroy']]);
44
    }
45
46
    public function setup()
47
    {
48
        CRUD::setModel(Enrollment::class);
49
        CRUD::setRoute(config('backpack.base.route_prefix').'/enrollment');
50
        CRUD::setEntityNameStrings(__('enrollment'), __('enrollments'));
51
    }
52
53
    /*
54
    |--------------------------------------------------------------------------
55
    | CrudPanel Configuration
56
    |--------------------------------------------------------------------------
57
    */
58
59
    public function setupListOperation()
60
    {
61
        if ($this->crud->getRequest()->has('course_id')) {
62
            $this->mode = 'course';
63
            $this->course = Course::findOrFail($this->crud->getRequest()->course_id);
64
65
            if (Gate::forUser(backpack_user())->denies('view-course', $this->course)) {
66
                abort(403);
67
            }
68
            CRUD::addClause('course', $this->course->id);
69
        }
70
71
        if ($this->mode === 'course') {
72
            CRUD::denyAccess(['create', 'update', 'delete']);
73
        }
74
75
        CRUD::enableExportButtons();
76
77
        if ($this->mode === 'course') {
78
            Widget::add(['type' => 'view',
79
                'view' => 'partials.course_info',
80
                'course' => $this->course, ])->to('before_content');
81
82
            CRUD::denyAccess(['show']);
83
            CRUD::addButtonFromView('line', 'showStudent', 'showStudentForEnrollment');
84
85
            CRUD::addButtonFromView('top', 'enroll-student-in-course', 'enroll-student-in-course', 'end');
86
            CRUD::addButtonFromView('top', 'switch-to-photo-roster', 'switch-to-photo-roster', 'end');
87
        }
88
89
        if (config('app.currency_position') === 'before') {
90
            $currency = ['prefix' => config('app.currency_symbol')];
91
        } else {
92
            $currency = ['suffix' => config('app.currency_symbol')];
93
        }
94
95
        CRUD::addColumns([['name' => 'id',
96
            'label' => 'ID',
97
            'wrapper' => ['element' => function ($crud, $column, $entry) {
98
                return $entry->status_id > 2 ? 'del' : 'span';
99
            }], ],
100
101
            ['label' => __('ID number'),
102
                'type' => 'text',
103
                'name' => 'student.idnumber',
104
                'wrapper' => ['element' => function ($crud, $column, $entry) {
105
                    return $entry->status_id > 2 ? 'del' : 'span';
106
                }], ],
107
108
            ['name' => 'user',
109
                'key' => 'user_lastname',
110
                'attribute' => 'lastname',
111
                'label' => __('Last Name'),
112
                'type' => 'relationship',
113
                'wrapper' => ['element' => function ($crud, $column, $entry) {
114
                    return $entry->status_id > 2 ? 'del' : 'span';
115
                }],
116
                'orderable' => true,
117
                'orderLogic' => function ($query, $column, $columnDirection) {
118
                    return $query->leftJoin('users', 'enrollments.student_id', '=', 'users.id')
119
                        ->orderBy('users.lastname', $columnDirection)->select('enrollments.*');
120
                },
121
                'searchLogic' => function ($query, $column, $searchTerm) {
122
                    $query->orWhereHas('student', function ($q) use ($searchTerm) {
123
                        $q->whereHas('user', function ($q) use ($searchTerm) {
124
                            $q->where('lastname', 'like', '%'.$searchTerm.'%');
125
                        });
126
                    });
127
                },
128
            ],
129
130
            ['name' => 'user',
131
                'key' => 'user_firstname',
132
                'attribute' => 'firstname',
133
                'label' => __('First Name'),
134
                'type' => 'relationship',
135
                'wrapper' => ['element' => function ($crud, $column, $entry) {
136
                    return $entry->status_id > 2 ? 'del' : 'span';
137
                }],
138
                'searchLogic' => function ($query, $column, $searchTerm) {
139
                    $query->orWhereHas('student', function ($q) use ($searchTerm) {
140
                        $q->whereHas('user', function ($q) use ($searchTerm) {
141
                            $q->where('firstname', 'like', '%'.$searchTerm.'%');
142
                        });
143
                    });
144
                },
145
                'orderLogic' => function ($query, $column, $columnDirection) {
146
                    return $query->leftJoin('users', 'enrollments.student_id', '=', 'users.id')
147
                        ->orderBy('users.firstname', $columnDirection)->select('enrollments.*');
148
                },
149
                'orderable' => true,
150
            ],
151
152
            ['label' => __('Age'),
153
                'name' => 'student_age', ],
154
155
            ['label' => __('Birthdate'),
156
                'name' => 'student_birthdate', ], ]);
157
158
        if ($this->mode === 'global') {
159
            CRUD::addColumns([['label' => __('Course'),
160
                'type' => 'select',
161
                'name' => 'course_id',
162
                'entity' => 'course',
163
                'attribute' => 'name',
164
                'model' => Course::class, ],
165
                ['type' => 'relationship',
166
                    'name' => 'course.period',
167
                    'label' => __('Period'),
168
                    'attribute' => 'name',
169
                    'orderLogic' => function ($query, $column, $columnDirection) {
170
                        return $query->leftJoin('courses', 'enrollments.course_id', '=', 'courses.id')
171
                            ->orderBy('courses.period_id', $columnDirection)->select('enrollments.*');
172
                    },
173
                    'orderable' => true,
174
                ], ]);
175
        }
176
177
        CRUD::addColumns([['label' => __('Status'),
178
            'type' => 'select',
179
            'name' => 'status_id',
180
            'entity' => 'enrollmentStatus',
181
            'attribute' => 'name',
182
            'model' => EnrollmentStatusType::class,
183
            'wrapper' => ['element' => 'span',
184
                'class' => function ($crud, $column, $entry) {
185
                    return 'badge badge-pill badge-'.$entry->enrollmentStatus->styling();
186
                }, ], ]]);
187
188
        if (config('app.books_module') && $this->mode === 'course') {
189
            CRUD::addColumn(['name' => 'hasBook',
190
                'type' => 'model_function',
191
                'function_name' => 'getHasBookForCourseAttribute',
192
                'label' => __('Book'),
193
            ]);
194
        }
195
196
        if (config('invoicing.allow_scheduled_payments')) {
197
            CRUD::addColumn(['name' => 'scheduledPayments',
198
                'type' => 'relationship',
199
                'label' => __('Scheduled Payments'),
200
                // OPTIONAL
201
                'attribute' => 'date',
202
                'model' => ScheduledPayment::class,
203
            ]);
204
        }
205
206
        CRUD::addColumn(array_merge(['name' => 'price',
207
            // The db column name
208
            'label' => __('Price'),
209
            'type' => 'number',
210
        ], $currency));
211
212
        if (config('invoicing.invoices_contain_enrollments_only')) {
213
            CRUD::addColumn(array_merge(['name' => 'balance',
214
                'label' => __('Balance'),
215
                'type' => 'number', ], $currency));
216
        }
217
218
        CRUD::addColumns([
219
220
            ['name' => 'scholarships',
221
                'type' => 'relationship',
222
                'label' => __('Scholarship'),
223
                'attribute' => 'name',
224
                'model' => Scholarship::class, ],
225
226
            ['label' => __('Email'),
227
                'name' => 'user',
228
                'attribute' => 'email',
229
                'type' => 'relationship', ],
230
231
            ['label' => __('Phone Number'),
232
                'type' => 'select_multiple',
233
                'name' => 'student.phone',
234
                'attribute' => 'phone_number',
235
                'model' => PhoneNumber::class, ], ]);
236
237
        if ($this->mode === 'global') {
238
            CRUD::addFilter(['name' => 'status_id',
239
                'type' => 'select2_multiple',
240
                'label' => __('Status'), ], fn () => EnrollmentStatusType::all()->pluck('name', 'id')->toArray(), function ($values) {
241
                    foreach (json_decode($values, null, 512, JSON_THROW_ON_ERROR) as $value) {
242
                        CRUD::addClause('orWhere', 'status_id', $value);
243
                    }
244
                });
245
246
            CRUD::addFilter(['name' => 'period_id',
247
                'type' => 'select2',
248
                'label' => __('Period'), ], fn () => Period::all()->pluck('name', 'id')->toArray(), function ($value) {
249
                    CRUD::addClause('period', $value);
250
                });
251
252
            CRUD::addFilter(['name' => 'scholarship',
253
                'type' => 'select2',
254
                'label' => __('Scholarship'), ], fn () => Scholarship::all()->pluck('name', 'id')->toArray(), function ($value) {
255
                    if ($value == 'all') {
256
                        CRUD::addClause('whereHas', 'scholarships');
257
                    } else {
258
                        CRUD::addClause('whereHas', 'scholarships', function ($q) use ($value) {
259
                            $q->where('scholarships.id', $value);
260
                        });
261
                    }
262
                });
263
        }
264
265
        if ($this->mode === 'global' && $this->crud->getOperation() === 'list' && $this->crud->filters()->where('name', 'status_id')->count() > 0) {
266
            if ($this->crud->filters()->where('name', 'status_id')->first()->currentValue && in_array(1, json_decode($this->crud->filters()->where('name', 'status_id')->first()->currentValue))) {
267
                Widget::add()->type('view')->view('enrollments.total_balance_widget')->to('before_content');
268
            }
269
        }
270
    }
271
272
    public function show($enrollment)
273
    {
274
        $enrollment = Enrollment::findOrFail($enrollment);
275
276
        // then load the page
277
        $commentsIncludingInvoices = $enrollment->comments
278
            ->concat($enrollment->invoices()
279
                ->map(fn($invoice) => $invoice->comments->map(function ($comment) use ($invoice) {
280
                    $comment->prefix = '(' . __('Invoice') . " " . ($invoice->invoice_reference ?? $invoice->id) . ")";
0 ignored issues
show
Bug introduced by
Are you sure __('Invoice') of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

280
                    $comment->prefix = '(' . /** @scrutinizer ignore-type */ __('Invoice') . " " . ($invoice->invoice_reference ?? $invoice->id) . ")";
Loading history...
281
                    return $comment;
282
                }))
283
                ->flatten()
284
            );
285
286
        return view('enrollments.show', [
287
            'enrollment' => $enrollment,
288
            'comments' => $commentsIncludingInvoices,
289
            'scholarships' => Scholarship::all(),
290
            'availablePaymentMethods' => Paymentmethod::all(),
291
            'writeaccess' => $enrollment->status_id !== 2 && backpack_user()->can('enrollments.edit'),
292
        ]);
293
    }
294
295
    protected function setupUpdateOperation()
296
    {
297
        if (config('app.currency_position') === 'before') {
298
            $currency = ['prefix' => config('app.currency_symbol')];
299
        } else {
300
            $currency = ['suffix' => config('app.currency_symbol')];
301
        }
302
303
        CRUD::addField([
304
            'label' => __('Course'),
305
            'type' => 'select2',
306
            'name' => 'course_id',
307
308
            'entity' => 'course',
309
            'model' => Course::class,
310
            'attribute' => 'name',
311
312
            'options' => (fn ($query) => $query->orderBy('level_id', 'ASC')->where('period_id', $this->crud->getCurrentEntry()->course->period_id)->get()),
0 ignored issues
show
Bug introduced by
The property period_id does not seem to exist on Illuminate\Database\Eloquent\Relations\Relation.
Loading history...
313
        ]);
314
315
        CRUD::addField(array_merge([
316
            'name' => 'price',
317
            // The db column name
318
            'label' => __('Price'),
319
            'type' => 'number',
320
        ], $currency));
321
322
        if (config('invoicing.allow_scheduled_payments')) {
323
            CRUD::addField([
324
                'name' => 'scheduledPayments',
325
                'label' => __('Scheduled Payments'),
326
                'type' => 'repeatable',
327
                'fields' => [
328
                    [
329
                        'name' => 'id',
330
                        'type' => 'hidden',
331
                    ],
332
                    [
333
                        'name' => 'date',
334
                        'type' => 'date',
335
                        'label' => __('Date'),
336
                        'wrapper' => ['class' => 'form-group col-md-4'],
337
                    ],
338
                    array_merge([
339
                        'name' => 'value',
340
                        'type' => 'number',
341
                        'attributes' => ['step' => 0.01,
342
                            'min' => 0, ],
343
                        'label' => __('Value'),
344
                        'wrapper' => ['class' => 'form-group col-md-4'],
345
                    ], $currency),
346
                    [
347
                        'name' => 'status',
348
                        'type' => 'radio',
349
                        'label' => __('Status'),
350
                        'wrapper' => ['class' => 'form-group col-md-4'],
351
                        'options' => [
352
                            1 => __('Pending'),
353
                            2 => __('Paid'),
354
                        ],
355
                        'inline' => true,
356
                    ],
357
                ],
358
            ]);
359
        }
360
361
        CRUD::addField([
362
            'label' => __('Status'),
363
            'type' => 'select',
364
            'name' => 'status_id',
365
            'entity' => 'enrollmentStatus',
366
            'model' => EnrollmentStatusType::class,
367
            'attribute' => 'name',
368
        ]);
369
    }
370
371
    public function update()
372
    {
373
        $enrollment = $this->crud->getCurrentEntry();
374
        if ($this->crud->getRequest()->has('scheduledPayments')) {
375
            $newScheduledPayments = collect(json_decode($this->crud->getRequest()->input('scheduledPayments'), null, 512, JSON_THROW_ON_ERROR));
376
            $enrollment->saveScheduledPayments($newScheduledPayments);
377
        }
378
        return $this->traitUpdate();
379
    }
380
381
    public function destroy($enrollment)
382
    {
383
        $enrollment = Enrollment::findOrFail($enrollment);
384
        $enrollment->cancel();
385
386
        Log::notice('Enrollment canceled by user '.backpack_user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
387
    }
388
}
389