181 lines
5.0 KiB
PHP
181 lines
5.0 KiB
PHP
<?php
|
|
|
|
namespace App\Models\Member;
|
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
|
use Illuminate\Support\Carbon;
|
|
|
|
class MemInfo extends Model
|
|
{
|
|
protected $table = 'mem_info';
|
|
protected $primaryKey = 'mem_no';
|
|
protected $keyType = 'int';
|
|
public $incrementing = true;
|
|
public $timestamps = false;
|
|
|
|
/**
|
|
* ✅ 보안: guarded=[](전부 허용) 는 위험하니,
|
|
* 기존 App\Models\MemInfo 의 allowlist(fillable) 방식 유지.
|
|
*/
|
|
protected $fillable = [
|
|
'stat_1','stat_2','stat_3','stat_4','stat_5',
|
|
'name','name_first','name_mid','name_last',
|
|
'birth','gender','native',
|
|
'cell_corp','cell_phone','email','pv_sns',
|
|
'bank_code','bank_name','bank_act_num','bank_vact_num',
|
|
'rcv_email','rcv_sms','rcv_push',
|
|
'login_fail_cnt',
|
|
'dt_login','dt_reg','dt_mod',
|
|
'dt_rcv_email','dt_rcv_sms','dt_rcv_push',
|
|
'dt_stat_1','dt_stat_2','dt_stat_3','dt_stat_4','dt_stat_5',
|
|
'ip_reg','ci_v','ci','di',
|
|
'country_code','country_name',
|
|
'admin_memo','modify_log',
|
|
];
|
|
|
|
/**
|
|
* ✅ 레거시 zero-date(0000-00-00 ...)가 있으면 datetime/date cast는 예외/오작동 가능.
|
|
* 안전하게 JSON 컬럼만 cast (나머지는 safe accessor로 뽑아 쓰자)
|
|
*/
|
|
protected $casts = [
|
|
'admin_memo' => 'array',
|
|
'modify_log' => 'array',
|
|
];
|
|
|
|
/* =====================
|
|
* Relationships
|
|
* ===================== */
|
|
|
|
public function authInfo(): HasOne
|
|
{
|
|
return $this->hasOne(MemAuthInfo::class, 'mem_no', 'mem_no');
|
|
}
|
|
|
|
public function authRows(): HasMany
|
|
{
|
|
// mem_auth 복합키 테이블이어도 조회 관계는 가능
|
|
return $this->hasMany(MemAuth::class, 'mem_no', 'mem_no');
|
|
}
|
|
|
|
public function authLogs(): HasMany
|
|
{
|
|
return $this->hasMany(MemAuthLog::class, 'mem_no', 'mem_no');
|
|
}
|
|
|
|
public function addresses(): HasMany
|
|
{
|
|
return $this->hasMany(MemAddress::class, 'mem_no', 'mem_no');
|
|
}
|
|
|
|
public function joinLogs(): HasMany
|
|
{
|
|
return $this->hasMany(MemJoinLog::class, 'mem_no', 'mem_no');
|
|
}
|
|
|
|
public function stRing(): HasOne
|
|
{
|
|
return $this->hasOne(MemStRing::class, 'mem_no', 'mem_no');
|
|
}
|
|
|
|
public function loginRecents(): HasMany
|
|
{
|
|
return $this->hasMany(MemLoginRecent::class, 'mem_no', 'mem_no');
|
|
}
|
|
|
|
public function modLogs(): HasMany
|
|
{
|
|
return $this->hasMany(MemModLog::class, 'mem_no', 'mem_no');
|
|
}
|
|
|
|
/* =====================
|
|
* Scopes (기존 App\Models\MemInfo에서 가져옴)
|
|
* ===================== */
|
|
|
|
public function scopeActive(Builder $q): Builder
|
|
{
|
|
// CI에서 stat_3 == 3 접근금지 / 4 탈퇴신청 / 5 탈퇴완료
|
|
return $q->whereNotIn('stat_3', ['3','4','5']);
|
|
}
|
|
|
|
public function scopeByEmail(Builder $q, string $email): Builder
|
|
{
|
|
return $q->where('email', strtolower($email));
|
|
}
|
|
|
|
public function scopeByPhoneLookup(Builder $q, string $phoneNormalized): Builder
|
|
{
|
|
// TODO: cell_phone이 암호화면 단순 where 비교 불가
|
|
// 추천: cell_phone_hash 같은 정규화+해시 컬럼 만들어 lookup
|
|
return $q;
|
|
}
|
|
|
|
/* =====================
|
|
* Helpers (둘 모델 통합)
|
|
* ===================== */
|
|
|
|
public function isBlocked(): bool
|
|
{
|
|
return (string) $this->stat_3 === '3';
|
|
}
|
|
|
|
public function isWithdrawnOrRequested(): bool
|
|
{
|
|
return in_array((string) $this->stat_3, ['4','5'], true);
|
|
}
|
|
|
|
public function isWithdrawn(): bool
|
|
{
|
|
// legacy: dt_out 기본값이 0000-00-00 00:00:00 일 수 있음
|
|
$v = $this->attributes['dt_out'] ?? null;
|
|
return !empty($v) && $v !== '0000-00-00 00:00:00';
|
|
}
|
|
|
|
public function hasEmail(): bool
|
|
{
|
|
return !empty($this->attributes['email']);
|
|
}
|
|
|
|
public function isFirstLogin(): bool
|
|
{
|
|
$dtLogin = $this->dt_login_at();
|
|
$dtReg = $this->dt_reg_at();
|
|
|
|
if (!$dtLogin || !$dtReg) return false;
|
|
return $dtLogin->equalTo($dtReg);
|
|
}
|
|
|
|
/* =====================
|
|
* Safe datetime accessors
|
|
* ===================== */
|
|
|
|
private function safeCarbon(?string $value): ?Carbon
|
|
{
|
|
if (!$value) return null;
|
|
if ($value === '0000-00-00 00:00:00' || $value === '0000-00-00') return null;
|
|
|
|
try {
|
|
return Carbon::parse($value);
|
|
} catch (\Throwable $e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function dt_login_at(): ?Carbon
|
|
{
|
|
return $this->safeCarbon($this->attributes['dt_login'] ?? null);
|
|
}
|
|
|
|
public function dt_reg_at(): ?Carbon
|
|
{
|
|
return $this->safeCarbon($this->attributes['dt_reg'] ?? null);
|
|
}
|
|
|
|
public function dt_mod_at(): ?Carbon
|
|
{
|
|
return $this->safeCarbon($this->attributes['dt_mod'] ?? null);
|
|
}
|
|
}
|