|
|
<?php
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
|
|
class Application extends Model
|
|
|
{
|
|
|
protected $fillable = [
|
|
|
'user_id',
|
|
|
'competition_id',
|
|
|
'status',
|
|
|
'player_name',
|
|
|
'school',
|
|
|
'degree',
|
|
|
'contact_email',
|
|
|
'contact_mobile',
|
|
|
'company_name',
|
|
|
'project_name',
|
|
|
'track',
|
|
|
'location_country',
|
|
|
'location_province',
|
|
|
'location_city',
|
|
|
'oversea_country',
|
|
|
'intro',
|
|
|
'promise_signed_at',
|
|
|
'promise_signature',
|
|
|
'submitted_at',
|
|
|
];
|
|
|
|
|
|
protected $casts = [
|
|
|
'promise_signed_at' => 'datetime',
|
|
|
'submitted_at' => 'datetime',
|
|
|
];
|
|
|
|
|
|
public function user(): BelongsTo
|
|
|
{
|
|
|
return $this->belongsTo(User::class);
|
|
|
}
|
|
|
|
|
|
public function competition(): BelongsTo
|
|
|
{
|
|
|
return $this->belongsTo(Competition::class);
|
|
|
}
|
|
|
|
|
|
public function files(): HasMany
|
|
|
{
|
|
|
return $this->hasMany(ApplicationFile::class);
|
|
|
}
|
|
|
|
|
|
public function reviewRecords(): HasMany
|
|
|
{
|
|
|
return $this->hasMany(ApplicationReviewRecord::class);
|
|
|
}
|
|
|
|
|
|
public function reviewScores(): HasMany
|
|
|
{
|
|
|
return $this->hasMany(ApplicationReviewScore::class);
|
|
|
}
|
|
|
|
|
|
public function isSubmitted(): bool
|
|
|
{
|
|
|
return $this->status === 'submitted';
|
|
|
}
|
|
|
|
|
|
/** 评委已产生评审记录或打分后,选手端不可再修改报名/附件 */
|
|
|
public function isSignupLockedByReview(): bool
|
|
|
{
|
|
|
return $this->reviewRecords()->exists() || $this->reviewScores()->exists();
|
|
|
}
|
|
|
|
|
|
/** 已超过赛事设置的报名截止时间(未设置截止时间则不据此拦截) */
|
|
|
public function isPastSignupCloseForCompetition(): bool
|
|
|
{
|
|
|
$this->loadMissing('competition');
|
|
|
$close = $this->competition?->signup_close_at;
|
|
|
|
|
|
return $close !== null && now()->isAfter($close);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 选手是否仍可编辑报名表:报名截止时间内且评委尚未评审;草稿与已提交均可继续改报直至截止或评审落库。
|
|
|
*/
|
|
|
public function participantMayEditSignup(): bool
|
|
|
{
|
|
|
if ($this->isSignupLockedByReview()) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
return ! $this->isPastSignupCloseForCompetition();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param 'status'|'file' $field 422 时 errors 字段名(报名表用 status,附件接口用 file)
|
|
|
*/
|
|
|
public function assertMayEditSignup(string $field = 'status'): void
|
|
|
{
|
|
|
if ($this->isSignupLockedByReview()) {
|
|
|
$msg = $field === 'file'
|
|
|
? '已有评委评审或打分记录,不可再上传或删除附件'
|
|
|
: '已有评委评审或打分记录,报名内容不可再修改';
|
|
|
|
|
|
throw ValidationException::withMessages([$field => [$msg]]);
|
|
|
}
|
|
|
|
|
|
if ($this->isPastSignupCloseForCompetition()) {
|
|
|
$msg = $field === 'file'
|
|
|
? '报名已截止,不可再上传或删除附件'
|
|
|
: '报名已截止,无法再修改或提交报名';
|
|
|
|
|
|
throw ValidationException::withMessages([$field => [$msg]]);
|
|
|
}
|
|
|
}
|
|
|
}
|