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);
}
}