123 lines
4.1 KiB
PHP
123 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Admin\Sms;
|
|
|
|
use App\Repositories\Admin\Sms\AdminSmsTemplateRepository;
|
|
use App\Services\Admin\AdminAuditService;
|
|
|
|
final class AdminSmsTemplateService
|
|
{
|
|
public function __construct(
|
|
private readonly AdminSmsTemplateRepository $repo,
|
|
private readonly AdminAuditService $audit,
|
|
) {}
|
|
|
|
public function list(array $filters, int $perPage = 30)
|
|
{
|
|
return $this->repo->paginate($filters, $perPage);
|
|
}
|
|
|
|
public function get(int $id): ?object
|
|
{
|
|
return $this->repo->find($id);
|
|
}
|
|
|
|
public function create(int $adminId, array $data): array
|
|
{
|
|
$code = strtolower(trim((string)($data['code'] ?? '')));
|
|
if ($code === '' || !preg_match('/^[a-z0-9\-_]{3,60}$/', $code)) {
|
|
return ['ok'=>false, 'message'=>'code는 영문/숫자/대시/언더바 3~60자로 입력하세요.'];
|
|
}
|
|
|
|
// 감사로그용: before/after 구성 (민감정보 없음)
|
|
$after = [
|
|
'code' => $code,
|
|
'title' => trim((string)($data['title'] ?? '')),
|
|
'body' => (string)($data['body'] ?? ''),
|
|
'description' => trim((string)($data['description'] ?? '')) ?: null,
|
|
'is_active' => (int)($data['is_active'] ?? 1),
|
|
'created_by' => $adminId,
|
|
];
|
|
|
|
$id = $this->repo->insert($after);
|
|
|
|
// ✅ 성공시에만 감사로그 (id가 0/음수면 기록 안 함)
|
|
if ($id > 0) {
|
|
$req = request();
|
|
$this->audit->log(
|
|
actorAdminId: $adminId,
|
|
action: 'admin.template.create', // 네 컨벤션에 맞게 수정 가능
|
|
targetType: 'template', // 실제 리소스명에 맞게
|
|
targetId: (int)$id,
|
|
before: null,
|
|
after: array_merge(['id' => (int)$id], $after),
|
|
ip: (string)($req?->ip() ?? ''),
|
|
ua: (string)($req?->userAgent() ?? ''),
|
|
);
|
|
}
|
|
|
|
return ['ok'=>true, 'id'=>$id];
|
|
}
|
|
|
|
|
|
public function update(int $id, array $data): array
|
|
{
|
|
// ✅ before 스냅샷(가능하면) — repo에 find/get이 없으면 lockForUpdate 같은 걸로 맞춰야 함
|
|
// 여기서는 "repo->find($id)"가 있다고 가정하지 않고, 안전하게 try로 감쌈.
|
|
$before = null;
|
|
try {
|
|
if (method_exists($this->repo, 'find')) {
|
|
$before = $this->repo->find($id);
|
|
} elseif (method_exists($this->repo, 'get')) {
|
|
$before = $this->repo->get($id);
|
|
}
|
|
} catch (\Throwable $ignored) {
|
|
$before = null;
|
|
}
|
|
|
|
$payload = [
|
|
'title' => trim((string)($data['title'] ?? '')),
|
|
'body' => (string)($data['body'] ?? ''),
|
|
'description' => trim((string)($data['description'] ?? '')) ?: null,
|
|
'is_active' => (int)($data['is_active'] ?? 1),
|
|
];
|
|
|
|
$affected = $this->repo->update($id, $payload);
|
|
|
|
// ✅ 기존 리턴 정책 유지
|
|
$ok = ($affected >= 0);
|
|
|
|
// ✅ 성공시에만 감사로그
|
|
if ($ok) {
|
|
$req = request();
|
|
$actorAdminId = (int)(auth('admin')->id() ?? 0);
|
|
|
|
// actorAdminId를 못 구하면 로그 생략(기존 프로그램 방해 X)
|
|
if ($actorAdminId > 0) {
|
|
$beforeAudit = $before ? (array)$before : ['id' => $id];
|
|
$afterAudit = array_merge($beforeAudit, $payload);
|
|
|
|
$this->audit->log(
|
|
actorAdminId: $actorAdminId,
|
|
action: 'admin.template.update', // 네 컨벤션에 맞게
|
|
targetType: 'template',
|
|
targetId: (int)$id,
|
|
before: $beforeAudit,
|
|
after: $afterAudit,
|
|
ip: (string)($req?->ip() ?? ''),
|
|
ua: (string)($req?->userAgent() ?? ''),
|
|
);
|
|
}
|
|
}
|
|
|
|
return ['ok'=>$ok];
|
|
}
|
|
|
|
|
|
public function activeForSend(int $limit = 200): array
|
|
{
|
|
return $this->repo->listActive($limit);
|
|
}
|
|
|
|
}
|