feat: 통합 감사 로그 도입 및 조회 API/스케줄러 추가
- DB: 감사 로그 테이블(audit_logs) 마이그레이션 및 인덱스 추가 - Config: audit.php 추가(AUDIT_RETENTION_DAYS, AUDIT_LOG_READS 토글) - Model/Service: AuditLog 모델, AuditLogger 서비스 생성 - 도메인 훅: ModelVersion.release(released), BomTemplate upsert/update/delete/replaceItems/clone 기록, diff 조회는 설정 기반 기록 - API: GET /api/v1/design/audit-logs 추가(FormRequest/Service/Controller, 필터 page/size/target_type/target_id/action/actor_id/from/to/sort/order) - Swagger: 감사 로그 조회 문서 추가(Design Audit 태그) - Console: audit:prune 커맨드 추가 및 스케줄러 매일 03:10 실행 등록(시스템 크론 schedule:run 필요) - Fix: PruneAuditLogs import 충돌 제거(Google ServiceControl AuditLog 제거)
This commit is contained in:
@@ -51,6 +51,9 @@ public function upsertTemplate(int $modelVersionId, string $name = 'Main', bool
|
||||
->where('name', $name)
|
||||
->first();
|
||||
|
||||
$action = 'created';
|
||||
$before = null;
|
||||
|
||||
if (!$tpl) {
|
||||
$tpl = BomTemplate::create([
|
||||
'tenant_id' => $tenantId,
|
||||
@@ -60,6 +63,8 @@ public function upsertTemplate(int $modelVersionId, string $name = 'Main', bool
|
||||
'notes' => $notes,
|
||||
]);
|
||||
} else {
|
||||
$action = 'updated';
|
||||
$before = $tpl->toArray();
|
||||
$tpl->fill(['is_primary' => $isPrimary, 'notes' => $notes])->save();
|
||||
}
|
||||
|
||||
@@ -70,6 +75,16 @@ public function upsertTemplate(int $modelVersionId, string $name = 'Main', bool
|
||||
->update(['is_primary' => false]);
|
||||
}
|
||||
|
||||
// 감사 로그
|
||||
app(\App\Services\Audit\AuditLogger::class)->log(
|
||||
tenantId: $tenantId,
|
||||
targetType: 'bom_template',
|
||||
targetId: $tpl->id,
|
||||
action: $action,
|
||||
before: $before,
|
||||
after: $tpl->toArray()
|
||||
);
|
||||
|
||||
return $tpl;
|
||||
});
|
||||
}
|
||||
@@ -99,6 +114,7 @@ public function updateTemplate(int $templateId, array $data): BomTemplate
|
||||
}
|
||||
}
|
||||
|
||||
$before = $tpl->toArray();
|
||||
$tpl->fill($data)->save();
|
||||
|
||||
if (array_key_exists('is_primary', $data) && $data['is_primary']) {
|
||||
@@ -109,6 +125,16 @@ public function updateTemplate(int $templateId, array $data): BomTemplate
|
||||
->update(['is_primary' => false]);
|
||||
}
|
||||
|
||||
// 감사 로그
|
||||
app(\App\Services\Audit\AuditLogger::class)->log(
|
||||
tenantId: $tenantId,
|
||||
targetType: 'bom_template',
|
||||
targetId: $tpl->id,
|
||||
action: 'updated',
|
||||
before: $before,
|
||||
after: $tpl->toArray()
|
||||
);
|
||||
|
||||
return $tpl;
|
||||
}
|
||||
|
||||
@@ -125,7 +151,18 @@ public function deleteTemplate(int $templateId): void
|
||||
throw new NotFoundHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
$before = $tpl->toArray();
|
||||
$tpl->delete();
|
||||
|
||||
// 감사 로그
|
||||
app(\App\Services\Audit\AuditLogger::class)->log(
|
||||
tenantId: $tenantId,
|
||||
targetType: 'bom_template',
|
||||
targetId: $tpl->id,
|
||||
action: 'deleted',
|
||||
before: $before,
|
||||
after: null
|
||||
);
|
||||
}
|
||||
|
||||
/** 템플릿 상세 (옵션: 항목 포함) */
|
||||
@@ -214,6 +251,26 @@ public function replaceItems(int $templateId, array $items): void
|
||||
if (!empty($payloads)) {
|
||||
BomTemplateItem::insert($payloads);
|
||||
}
|
||||
|
||||
// 감사 로그
|
||||
app(\App\Services\Audit\AuditLogger::class)->log(
|
||||
tenantId: $tenantId,
|
||||
targetType: 'bom_template',
|
||||
targetId: $tpl->id,
|
||||
action: 'items_replaced',
|
||||
before: ['items' => $beforeItems],
|
||||
after: ['items' => array_map(function ($p) {
|
||||
return [
|
||||
'ref_type' => $p['ref_type'],
|
||||
'ref_id' => $p['ref_id'],
|
||||
'qty' => (float) $p['qty'],
|
||||
'waste_rate' => (float) $p['waste_rate'],
|
||||
'uom_id' => $p['uom_id'],
|
||||
'notes' => $p['notes'],
|
||||
'sort_order' => $p['sort_order'],
|
||||
];
|
||||
}, $payloads)]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -309,7 +366,7 @@ public function diffTemplates(int $leftTemplateId, int $rightTemplateId): array
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
$result = [
|
||||
'left_template_id' => $left->id,
|
||||
'right_template_id' => $right->id,
|
||||
'summary' => [
|
||||
@@ -321,6 +378,19 @@ public function diffTemplates(int $leftTemplateId, int $rightTemplateId): array
|
||||
'removed' => $removed,
|
||||
'changed' => $changed,
|
||||
];
|
||||
|
||||
if (config('audit.log_reads', false)) {
|
||||
app(\App\Services\Audit\AuditLogger::class)->log(
|
||||
tenantId: $tenantId,
|
||||
targetType: 'bom_template',
|
||||
targetId: $left->id,
|
||||
action: 'diff_viewed',
|
||||
before: ['left' => $left->id, 'right' => $right->id],
|
||||
after: ['summary' => $result['summary']]
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** 템플릿 복제(깊은 복사) */
|
||||
@@ -394,6 +464,16 @@ public function cloneTemplate(int $templateId, ?int $targetVersionId = null, ?st
|
||||
->update(['is_primary' => false]);
|
||||
}
|
||||
|
||||
// 감사 로그
|
||||
app(\App\Services\Audit\AuditLogger::class)->log(
|
||||
tenantId: $tenantId,
|
||||
targetType: 'bom_template',
|
||||
targetId: $dest->id,
|
||||
action: 'cloned',
|
||||
before: ['source_template_id' => $src->id],
|
||||
after: $dest->toArray()
|
||||
);
|
||||
|
||||
return $dest;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user