Passed
Push — task/all-applications-to-pdf ( 4d8a77 )
by Grant
08:54
created

JobPoster::status()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4.016

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 14
ccs 9
cts 10
cp 0.9
rs 9.9332
c 0
b 0
f 0
cc 4
nc 4
nop 0
crap 4.016
1
<?php
2
3
/**
4
 * Created by Reliese Model.
5
 * Date: Thu, 12 Jul 2018 22:39:27 +0000.
6
 */
7
8
namespace App\Models;
9
10
use App\Events\JobSaved;
11
use App\Models\JobApplication;
12
use Illuminate\Notifications\Notifiable;
13
use Illuminate\Support\Facades\App;
14
use Illuminate\Support\Facades\Lang;
15
use Jenssegers\Date\Date;
16
use \Backpack\CRUD\CrudTrait;
17
18
/**
19
 * Class JobPoster
20
 *
21
 * @property int $id
22
 * @property int $job_term_id
23
 * @property int $term_qty
24
 * @property \Jenssegers\Date\Date $open_date_time
25
 * @property \Jenssegers\Date\Date $close_date_time
26
 * @property \Jenssegers\Date\Date $start_date_time
27
 * @property \Jenssegers\Date\Date $review_requested_at
28
 * @property \Jessengers\Date\Date $published_at
29
 * @property int $department_id
30
 * @property int $province_id
31
 * @property int $salary_min
32
 * @property int $salary_max
33
 * @property int $noc
34
 * @property string $classification
35
 * @property int $security_clearance_id
36
 * @property int $language_requirement_id
37
 * @property boolean $remote_work_allowed
38
 * @property int $manager_id
39
 * @property boolean $published
40
 * @property \Jenssegers\Date\Date $created_at
41
 * @property \Jenssegers\Date\Date $updated_at
42
 *
43
 * @property int $submitted_applications_count
44
 *
45
 * @property \App\Models\Lookup\Department $department
46
 * @property \App\Models\Lookup\JobTerm $job_term
47
 * @property \App\Models\Lookup\LanguageRequirement $language_requirement
48
 * @property \App\Models\Manager $manager
49
 * @property \App\Models\Lookup\Province $province
50
 * @property \App\Models\Lookup\SecurityClearance $security_clearance
51
 * @property \Illuminate\Database\Eloquent\Collection $criteria
52
 * @property \Illuminate\Database\Eloquent\Collection $job_applications
53
 * @property \Illuminate\Database\Eloquent\Collection $job_poster_key_tasks
54
 * @property \Illuminate\Database\Eloquent\Collection $job_poster_questions
55
 * @property \Illuminate\Database\Eloquent\Collection $job_poster_translations
56
 * @property \Illuminate\Database\Eloquent\Collection $submitted_applications
57
 * @property \Illuminate\Database\Eloquent\Collection[ScreeningPlan] $screening_plans
58
 *
59
 * Localized Properties:
60
 * @property string $city
61
 * @property string $title
62
 * @property string $impact
63
 * @property string $branch
64
 * @property string $division
65
 * @property string $education
66
 *
67
 * Methods
68
 * @method boolean isOpen()
69
 * @method string timeRemaining()
70
 */
0 ignored issues
show
Documentation Bug introduced by
The doc comment \Illuminate\Database\Elo...llection[ScreeningPlan] at position 1 could not be parsed: Expected ']' at position 1, but found '['.
Loading history...
71
class JobPoster extends BaseModel
72
{
73
    use CrudTrait;
0 ignored issues
show
introduced by
The trait Backpack\CRUD\CrudTrait requires some properties which are not provided by App\Models\JobPoster: $Type, $fakeColumns
Loading history...
74
    use \Dimsav\Translatable\Translatable;
0 ignored issues
show
introduced by
The trait Dimsav\Translatable\Translatable requires some properties which are not provided by App\Models\JobPoster: $translations, $useTranslationFallback, $translationModel, $localeKey, $translationForeignKey
Loading history...
75
    use Notifiable;
0 ignored issues
show
introduced by
The trait Illuminate\Notifications\Notifiable requires some properties which are not provided by App\Models\JobPoster: $email, $phone_number
Loading history...
76
77
    const DATE_FORMAT = [
78
        'en' => 'M jS, Y',
79
        'fr' => 'd M Y',
80
    ];
81
    const TIME_FORMAT = [
82
        'en' => 'h:i A T',
83
        'fr' => 'H \h i T',
84
    ];
85
    const TIMEZONE = 'America/Toronto';
86
87
    /**
88
     * @var string[] $translatedAttributes
89
     */
90
    public $translatedAttributes = [
91
        'city',
92
        'title',
93
        'impact',
94
        'branch',
95
        'division',
96
        'education'
97
    ];
98
99
    /**
100
     * @var string[] $casts
101
     */
102
    protected $casts = [
103
        'job_term_id' => 'int',
104
        'department_id' => 'int',
105
        'province_id' => 'int',
106
        'salary_min' => 'int',
107
        'salary_max' => 'int',
108
        'noc' => 'int',
109
        'security_clearance_id' => 'int',
110
        'language_requirement_id' => 'int',
111
        'remote_work_allowed' => 'boolean',
112
        'manager_id' => 'int',
113
        'published' => 'boolean'
114
    ];
115
116
    /**
117
     * @var string[] $dates
118
     */
119
    protected $dates = [
120
        'open_date_time',
121
        'close_date_time',
122
        'start_date_time',
123
        'review_requested_at',
124
        'published_at'
125
    ];
126
127
    /**
128
     * @var string[] $fillable
129
     */
130
    protected $fillable = [
131
        'job_term_id',
132
        'term_qty',
133
        'open_date_time',
134
        'close_date_time',
135
        'start_date_time',
136
        'department_id',
137
        'province_id',
138
        'salary_min',
139
        'salary_max',
140
        'noc',
141
        'classification',
142
        'security_clearance_id',
143
        'language_requirement_id',
144
        'remote_work_allowed',
145
        'published'
146
    ];
147
148
    /**
149
     * @var mixed[] $dispatchesEvents
150
     */
151
    protected $dispatchesEvents = [
152
        'saved' => JobSaved::class,
153
    ];
154
155
    // @codeCoverageIgnoreStart
156
157
    public function department() // phpcs:ignore
158
    {
159
        return $this->belongsTo(\App\Models\Lookup\Department::class);
160
    }
161
162
    public function job_term() // phpcs:ignore
163
    {
164
        return $this->belongsTo(\App\Models\Lookup\JobTerm::class);
165
    }
166
167
    public function language_requirement() // phpcs:ignore
168
    {
169
        return $this->belongsTo(\App\Models\Lookup\LanguageRequirement::class);
170
    }
171
172
    public function manager() // phpcs:ignore
173
    {
174
        return $this->belongsTo(\App\Models\Manager::class);
175
    }
176
177
    public function province() // phpcs:ignore
178
    {
179
        return $this->belongsTo(\App\Models\Lookup\Province::class);
180
    }
181
182
    public function security_clearance() // phpcs:ignore
183
    {
184
        return $this->belongsTo(\App\Models\Lookup\SecurityClearance::class);
185
    }
186
187
    public function criteria() // phpcs:ignore
188
    {
189
        return $this->hasMany(\App\Models\Criteria::class);
190
    }
191
192
    public function job_applications() // phpcs:ignore
193
    {
194
        return $this->hasMany(\App\Models\JobApplication::class);
195
    }
196
197
    public function job_poster_key_tasks() // phpcs:ignore
198
    {
199
        return $this->hasMany(\App\Models\JobPosterKeyTask::class);
200
    }
201
202
    public function job_poster_questions() // phpcs:ignore
203
    {
204
        return $this->hasMany(\App\Models\JobPosterQuestion::class);
205
    }
206
207
    public function job_poster_translations() // phpcs:ignore
208
    {
209
        return $this->hasMany(\App\Models\JobPosterTranslation::class);
210
    }
211
212
    public function screening_plans() // phpcs:ignore
213
    {
214
        return $this->hasMany(\App\Models\ScreeningPlan::class);
215
    }
216
217
    // Artificial Relations
218
219
    /**
220
     * Get all of the Job Applications submitted to this
221
     * Job Poster.
222
     *
223
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
224
     */
225
    public function submitted_applications() // phpcs:ignore
226
    {
227
        return $this->hasMany(\App\Models\JobApplication::class)->whereDoesntHave('application_status', function ($query) : void {
228
            $query->where('name', 'draft');
229
        });
230
    }
231
232
    // Overrides
233
234
    /**
235
     * Retrieve the model for a bound value.
236
     * Seems to be a useful workaround for providing submitted_applications_count
237
     * to any bound routes that receive a jobPoster instance without using the
238
     * withCount property on the model itself.
239
     * See https://github.com/laravel/framework/issues/23957 for more info.
240
     *
241
     * @param mixed $value Value used to retrieve the model instance.
242
     *
243
     * @return \Illuminate\Database\Eloquent\Model|null
244
     */
245
    public function resolveRouteBinding($value) // phpcs:ignore
246
    {
247
        return $this->withCount('submitted_applications')->where('id', $value)->first() ?? abort(404);
248
    }
249
250
    // @codeCoverageIgnoreEnd
251
252
    // Accessors
253
254
    // Mutators
255
256
    /**
257
     * Intercept setting the "published" attribute, and set the
258
     * "published_at" timestamp if true.
259
     *
260
     * @param mixed $value Incoming value for the 'published' attribute.
261
     *
262
     * @return void
263
     */
264 28
    public function setPublishedAttribute($value) : void
265
    {
266 28
        if ($value && $this->open_date_time->isPast()) {
267 19
            $this->attributes['published_at'] = new Date();
268 25
        } elseif ($value && $this->open_date_time->isFuture()) {
269 1
            $this->attributes['published_at'] = $this->open_date_time;
270
        }
271 28
        $this->attributes['published'] = $value;
272 28
    }
273
274
    // Methods
275
276 4
    public function submitted_applications_count()
1 ignored issue
show
Coding Style introduced by
Method name "JobPoster::submitted_applications_count" is not in camel caps format
Loading history...
introduced by
Method \App\Models\JobPoster::submitted_applications_count() does not have return type hint nor @return annotation for its return value.
Loading history...
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
277
    {
278 4
        return $this->submitted_applications()->count();
279
    }
280
281
    /**
282
     * Formatted and localized date and time the Job Poster closes.
283
     *
284
     * @return string[]
285
     */
286 1
    public function applyBy() : array
287
    {
288 1
        $localCloseDate = new Date($this->close_date_time); // This initializes the date object in UTC time
289 1
        $localCloseDate->setTimezone(new \DateTimeZone(self::TIMEZONE)); // Then set the time zone for display
290
        $displayDate = [
291 1
            'date' => $localCloseDate->format(self::DATE_FORMAT[App::getLocale()]),
292 1
            'time' => $localCloseDate->format(self::TIME_FORMAT[App::getLocale()])
293
        ];
294
295 1
        if (App::isLocale('fr')) {
296
            $displayDate['time'] = str_replace(['EST', 'EDT'], ['HNE', 'HAE'], $displayDate['time']);
297
        }
298
299 1
        return $displayDate;
300
    }
301
302
    /**
303
     * Return whether the Job is Open or Closed.
304
     * Used by the Admin Portal JobPosterCrudController.
305
     *
306
     * @return string
307
     */
308
    public function displayStatus() : string
309
    {
310
        return $this->isOpen() ? 'Open' : 'Closed';
311
    }
312
313
    /**
314
     * Check if a Job Poster is open for applications.
315
     *
316
     * @return boolean
317
     */
318 6
    public function isOpen() : bool
319
    {
320 6
        return $this->published
321 6
            && $this->open_date_time->isPast()
322 6
            && $this->close_date_time->isFuture();
323
    }
324
325
    /**
326
     * Check if a Job Poster is closed for applications.
327
     *
328
     * @return boolean
329
     */
330 4
    public function isClosed() : bool
331
    {
332 4
        return $this->published
333 4
            && $this->open_date_time->isPast()
334 4
            && $this->close_date_time->isPast();
335
    }
336
337
    /**
338
     * Calculate the remaining time a Job Poster is open.
339
     *
340
     * @return string
341
     */
342 1
    public function timeRemaining() : string
343
    {
344 1
        $interval = $this->close_date_time->diff(Date::now());
345
346 1
        $d = $interval->d;
347 1
        $h = $interval->h;
348 1
        $m = $interval->i;
349 1
        $s = $interval->s;
350
351 1
        if ($d > 0) {
352 1
            $unit = 'day';
353 1
            $count = $d;
354 1
        } elseif ($h > 0) {
355 1
            $unit = 'hour';
356 1
            $count = $h;
357 1
        } elseif ($m > 0) {
358 1
            $unit = 'minute';
359 1
            $count = $m;
360
        } else {
361
            $unit = 'second';
362
            $count = $s;
363
        }
364
365 1
        $key = "common/time.$unit";
366
367 1
        return Lang::choice($key, $count);
368
    }
369
370
    /**
371
     * Return the current status for the Job Poster.
372
     * Possible values are "draft", "submitted", "published" and "closed".
373
     *
374
     * @return string
375
     */
376 3
    public function status() : string
377
    {
378 3
        $status = 'draft';
379 3
        if ($this->isOpen()) {
380 1
            $status = 'published';
381 3
        } elseif ($this->isClosed()) {
382
            $status = 'closed';
383 3
        } elseif ($this->review_requested_at !== null) {
384 2
            $status = 'submitted';
385
        } else {
386 1
            $status = 'draft';
387
        }
388
389 3
        return $status;
390
    }
391
}
392