비즈뿌리오 알림톡 UX 개편 후속: - 코어/게시판/이커머스 알림 템플릿 [편집] 모달에 확장 채널 편집 영역 (extension_point 2종 + hidden_template_editor 채널 메타)을 신설하고, 알림톡 템플릿·문자(SMS)·수신자 규칙을 한 창에서 통합 저장하도록 개정 (행 하단은 상태 요약 전용, 승인 여부 2단 배지) - 검수 신청에 검수자 전달 의견(comment) 동봉 — kapi request 로만 전달, 행에는 저장하지 않음 (FormRequest 신설 + API 문서 백필) - 관리 탭 모바일 카드뷰·도구줄 코어 관례 통일, 사이트맵 알림 정의 다국어 라벨 결측 수정 + 코어 정의 라벨 패리티 테스트 신설 언어팩 번역 소실·보존 결함군 (보완 실측 → 커밋 전 점검에서 연쇄 확정, 전부 실패 테스트 선행 후 수정): - [기본값 복원]이 활성 언어팩 번역(ja)을 영구 소실 → 복원 기본값에 시딩과 같은 주입기(SSoT)로 팩 로케일 병합 (notification·identity) - 코어 알림/본인인증 시더의 언어팩 주입 전면 불능 → 주입기가 연관/리스트 양형태 수용 + identity 시더의 config 복합 키 보존 - 실패한 언어팩 업데이트가 active 팩을 installed 로 방치 → 상태 복원 확장 - 병합·제거의 사용자 수정 보존 판정 사문(연관 전제 isset) → dot-path 판정 교정, 팩 주입 저장의 user_overrides 오염 차단(시딩 바인딩), 템플릿 2모델 translatableTrackableFields 선언(beta.4 설계 누락), 같은 프로세스 활성화 시 시더 번역 필터 stale(캡처 인스턴스 캐시) 교정 - 7.0.9 업그레이드 스텝 신설 — 활성 팩 seed 재동기화로 기설치본의 소실 번역 자동 복구 (멱등·운영자 수정 보존·팩별 실패 격리)
126 lines
3.3 KiB
PHP
126 lines
3.3 KiB
PHP
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use App\Models\Concerns\HasUserOverrides;
|
||
use App\Models\Concerns\IdentityMessageContentBehavior;
|
||
use App\Services\IdentityMessageDefinitionService;
|
||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||
use Illuminate\Database\Eloquent\Model;
|
||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||
|
||
/**
|
||
* 본인인증 메시지 템플릿 모델.
|
||
*
|
||
* 정의(IdentityMessageDefinition) 1건 × 채널 N개 구조. 다국어 subject/body + 활성 토글
|
||
* + user_overrides 보존을 제공합니다. NotificationTemplate 와 분리된 IDV 전용 모델.
|
||
*/
|
||
class IdentityMessageTemplate extends Model
|
||
{
|
||
use HasFactory, HasUserOverrides, IdentityMessageContentBehavior;
|
||
|
||
/**
|
||
* 사용자 수정 보존 대상 필드.
|
||
*
|
||
* @var array<int, string>
|
||
*/
|
||
protected array $trackableFields = [
|
||
'subject',
|
||
'body',
|
||
'is_active',
|
||
];
|
||
|
||
/**
|
||
* 다국어 JSON 컬럼 — 운영자 수정을 dot-path(`"subject.ja"` 등) sub-key 단위로 기록.
|
||
* (NotificationTemplate 과 동형 — 미선언의 결과는 그쪽 주석 참조, #597 에서 교정)
|
||
*
|
||
* @var array<int, string>
|
||
*/
|
||
protected array $translatableTrackableFields = [
|
||
'subject',
|
||
'body',
|
||
];
|
||
|
||
/**
|
||
* 활동 로그 추적 필드.
|
||
*
|
||
* @var array<string, array<string, string>>
|
||
*/
|
||
public static array $activityLogFields = [
|
||
'subject' => ['label_key' => 'activity_log.fields.subject', 'type' => 'text'],
|
||
'body' => ['label_key' => 'activity_log.fields.body', 'type' => 'text'],
|
||
'is_active' => ['label_key' => 'activity_log.fields.is_active', 'type' => 'boolean'],
|
||
];
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
protected $table = 'identity_message_templates';
|
||
|
||
/**
|
||
* @var array<int, string>
|
||
*/
|
||
protected $fillable = [
|
||
'definition_id',
|
||
'channel',
|
||
'subject',
|
||
'body',
|
||
'is_active',
|
||
'is_default',
|
||
'user_overrides',
|
||
'updated_by',
|
||
];
|
||
|
||
/**
|
||
* 모델 이벤트 등록 — 변경 시 정의/템플릿 캐시 자동 삭제.
|
||
*/
|
||
protected static function booted(): void
|
||
{
|
||
$invalidate = function () {
|
||
try {
|
||
app(IdentityMessageDefinitionService::class)->invalidateAllCache();
|
||
} catch (\Throwable) {
|
||
// 테스트/마이그레이션 환경에서 서비스 미등록 시 무시
|
||
}
|
||
};
|
||
|
||
static::saved($invalidate);
|
||
static::deleted($invalidate);
|
||
}
|
||
|
||
/**
|
||
* 캐스팅 정의.
|
||
*
|
||
* IdentityMessageContentBehavior trait 가 subject/body/is_active/is_default 를 처리하므로
|
||
* 여기서는 user_overrides 만 추가합니다.
|
||
*
|
||
* @return array<string, string>
|
||
*/
|
||
protected function casts(): array
|
||
{
|
||
return [
|
||
'user_overrides' => 'array',
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 메시지 정의 관계.
|
||
*
|
||
* @return BelongsTo
|
||
*/
|
||
public function definition(): BelongsTo
|
||
{
|
||
return $this->belongsTo(IdentityMessageDefinition::class, 'definition_id');
|
||
}
|
||
|
||
/**
|
||
* 수정자 관계.
|
||
*
|
||
* @return BelongsTo
|
||
*/
|
||
public function updater(): BelongsTo
|
||
{
|
||
return $this->belongsTo(User::class, 'updated_by');
|
||
}
|
||
}
|