giftcon_dev/app/Services/Admin/Sms/AdminSmsTemplateService.php
2026-02-12 15:13:55 +09:00

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