feat: sam_stat 통계 DB 인프라 구축 (Phase 1)
- sam_stat DB 연결 설정 (config/database.php, .env) - 메타 테이블 마이그레이션 (stat_definitions, stat_job_logs) - dim_date 차원 테이블 + DimDateSeeder (2020~2030, 4018건) - 기반 모델: BaseStatModel, StatDefinition, StatJobLog, DimDate - 집계 커맨드: stat:aggregate-daily, stat:aggregate-monthly - StatAggregatorService + StatDomainServiceInterface 골격 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
60
app/Console/Commands/StatAggregateDailyCommand.php
Normal file
60
app/Console/Commands/StatAggregateDailyCommand.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Services\Stats\StatAggregatorService;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class StatAggregateDailyCommand extends Command
|
||||
{
|
||||
protected $signature = 'stat:aggregate-daily
|
||||
{--date= : 집계 대상 날짜 (YYYY-MM-DD, 기본: 전일)}
|
||||
{--domain= : 특정 도메인만 집계 (sales, finance, production)}
|
||||
{--tenant= : 특정 테넌트만 집계}';
|
||||
|
||||
protected $description = '일간 통계 집계 (sam_stat DB)';
|
||||
|
||||
public function handle(StatAggregatorService $aggregator): int
|
||||
{
|
||||
$date = $this->option('date')
|
||||
? Carbon::parse($this->option('date'))
|
||||
: Carbon::yesterday();
|
||||
|
||||
$domain = $this->option('domain');
|
||||
$tenantId = $this->option('tenant') ? (int) $this->option('tenant') : null;
|
||||
|
||||
$this->info("📊 일간 통계 집계 시작: {$date->format('Y-m-d')}");
|
||||
|
||||
if ($domain) {
|
||||
$this->info(" 도메인 필터: {$domain}");
|
||||
}
|
||||
if ($tenantId) {
|
||||
$this->info(" 테넌트 필터: {$tenantId}");
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $aggregator->aggregateDaily($date, $domain, $tenantId);
|
||||
|
||||
$this->info('✅ 일간 집계 완료:');
|
||||
$this->info(" - 처리 테넌트: {$result['tenants_processed']}");
|
||||
$this->info(" - 처리 도메인: {$result['domains_processed']}");
|
||||
$this->info(" - 소요 시간: {$result['duration_ms']}ms");
|
||||
|
||||
if (! empty($result['errors'])) {
|
||||
$this->warn(' ⚠️ 에러 발생: '.count($result['errors']).'건');
|
||||
foreach ($result['errors'] as $error) {
|
||||
$this->error(" - {$error}");
|
||||
}
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
} catch (\Throwable $e) {
|
||||
$this->error("❌ 집계 실패: {$e->getMessage()}");
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
app/Console/Commands/StatAggregateMonthlyCommand.php
Normal file
54
app/Console/Commands/StatAggregateMonthlyCommand.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Services\Stats\StatAggregatorService;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class StatAggregateMonthlyCommand extends Command
|
||||
{
|
||||
protected $signature = 'stat:aggregate-monthly
|
||||
{--year= : 집계 대상 연도 (기본: 전월 기준)}
|
||||
{--month= : 집계 대상 월 (기본: 전월)}
|
||||
{--domain= : 특정 도메인만 집계}
|
||||
{--tenant= : 특정 테넌트만 집계}';
|
||||
|
||||
protected $description = '월간 통계 집계 (sam_stat DB)';
|
||||
|
||||
public function handle(StatAggregatorService $aggregator): int
|
||||
{
|
||||
$lastMonth = Carbon::now()->subMonth();
|
||||
$year = $this->option('year') ? (int) $this->option('year') : $lastMonth->year;
|
||||
$month = $this->option('month') ? (int) $this->option('month') : $lastMonth->month;
|
||||
|
||||
$domain = $this->option('domain');
|
||||
$tenantId = $this->option('tenant') ? (int) $this->option('tenant') : null;
|
||||
|
||||
$this->info("📊 월간 통계 집계 시작: {$year}-".str_pad($month, 2, '0', STR_PAD_LEFT));
|
||||
|
||||
try {
|
||||
$result = $aggregator->aggregateMonthly($year, $month, $domain, $tenantId);
|
||||
|
||||
$this->info('✅ 월간 집계 완료:');
|
||||
$this->info(" - 처리 테넌트: {$result['tenants_processed']}");
|
||||
$this->info(" - 처리 도메인: {$result['domains_processed']}");
|
||||
$this->info(" - 소요 시간: {$result['duration_ms']}ms");
|
||||
|
||||
if (! empty($result['errors'])) {
|
||||
$this->warn(' ⚠️ 에러 발생: '.count($result['errors']).'건');
|
||||
foreach ($result['errors'] as $error) {
|
||||
$this->error(" - {$error}");
|
||||
}
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
} catch (\Throwable $e) {
|
||||
$this->error("❌ 집계 실패: {$e->getMessage()}");
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user