tenantId(); $size = (int) ($params['size'] ?? 20); $targetTable = $params['target_table'] ?? null; $isCritical = $params['is_critical'] ?? null; $aggregationType = $params['aggregation_type'] ?? null; $query = TenantStatField::query() ->where('tenant_id', $tenantId); // 필터: 대상 테이블 if ($targetTable) { $query->forTable($targetTable); } // 필터: 중요 필드만 if ($isCritical !== null && $isCritical !== '') { $query->critical(); } // 필터: 특정 집계 함수 포함 if ($aggregationType) { $query->withAggregation($aggregationType); } // 정렬: display_order, field_name $query->ordered(); return $query->paginate($size); } public function store(array $data) { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); // FormRequest에서 이미 검증됨 $payload = $data; // tenant_id + target_table + field_key 유니크 검증 $exists = TenantStatField::query() ->where('tenant_id', $tenantId) ->where('target_table', $payload['target_table']) ->where('field_key', $payload['field_key']) ->exists(); if ($exists) { throw new BadRequestHttpException(__('error.duplicate_key')); } $payload['tenant_id'] = $tenantId; $payload['is_critical'] = $payload['is_critical'] ?? false; $payload['display_order'] = $payload['display_order'] ?? 0; $payload['created_by'] = $userId; return TenantStatField::create($payload); } public function show(int $id) { $tenantId = $this->tenantId(); $field = TenantStatField::query() ->where('tenant_id', $tenantId) ->find($id); if (! $field) { throw new BadRequestHttpException(__('error.not_found')); } return $field; } public function update(int $id, array $data) { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $field = TenantStatField::query() ->where('tenant_id', $tenantId) ->find($id); if (! $field) { throw new BadRequestHttpException(__('error.not_found')); } // FormRequest에서 이미 검증됨 $payload = $data; // target_table 또는 field_key 변경 시 유니크 검증 $targetTableChanged = isset($payload['target_table']) && $payload['target_table'] !== $field->target_table; $fieldKeyChanged = isset($payload['field_key']) && $payload['field_key'] !== $field->field_key; if ($targetTableChanged || $fieldKeyChanged) { $newTargetTable = $payload['target_table'] ?? $field->target_table; $newFieldKey = $payload['field_key'] ?? $field->field_key; $dup = TenantStatField::query() ->where('tenant_id', $tenantId) ->where('target_table', $newTargetTable) ->where('field_key', $newFieldKey) ->where('id', '!=', $id) ->exists(); if ($dup) { throw new BadRequestHttpException(__('error.duplicate_key')); } } $payload['updated_by'] = $userId; $field->update($payload); return $field->refresh(); } public function destroy(int $id): void { $tenantId = $this->tenantId(); $field = TenantStatField::query() ->where('tenant_id', $tenantId) ->find($id); if (! $field) { throw new BadRequestHttpException(__('error.not_found')); } $field->delete(); } public function reorder(array $items): void { $tenantId = $this->tenantId(); $rows = $items['items'] ?? $items; if (! is_array($rows)) { throw new BadRequestHttpException(__('error.invalid_payload')); } DB::transaction(function () use ($tenantId, $rows) { foreach ($rows as $row) { if (! isset($row['id'], $row['display_order'])) { continue; } TenantStatField::query() ->where('tenant_id', $tenantId) ->where('id', $row['id']) ->update(['display_order' => (int) $row['display_order']]); } }); } public function bulkUpsert(array $items): array { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); if (! is_array($items) || empty($items)) { throw new BadRequestHttpException(__('error.empty_items')); } $result = ['created' => 0, 'updated' => 0]; DB::transaction(function () use ($tenantId, $userId, $items, &$result) { foreach ($items as $payload) { // 기본 검증 if (! isset($payload['target_table'], $payload['field_key'], $payload['field_name'], $payload['field_type'])) { throw new BadRequestHttpException(__('error.invalid_payload')); } if (! empty($payload['id'])) { // 수정 $model = TenantStatField::query() ->where('tenant_id', $tenantId) ->find($payload['id']); if (! $model) { throw new BadRequestHttpException(__('error.not_found')); } // target_table 또는 field_key 변경 시 유니크 검증 $targetTableChanged = isset($payload['target_table']) && $payload['target_table'] !== $model->target_table; $fieldKeyChanged = isset($payload['field_key']) && $payload['field_key'] !== $model->field_key; if ($targetTableChanged || $fieldKeyChanged) { $newTargetTable = $payload['target_table'] ?? $model->target_table; $newFieldKey = $payload['field_key'] ?? $model->field_key; $dup = TenantStatField::query() ->where('tenant_id', $tenantId) ->where('target_table', $newTargetTable) ->where('field_key', $newFieldKey) ->where('id', '!=', $payload['id']) ->exists(); if ($dup) { throw new BadRequestHttpException(__('error.duplicate_key')); } } $payload['updated_by'] = $userId; $model->update($payload); $result['updated']++; } else { // 신규 생성 $dup = TenantStatField::query() ->where('tenant_id', $tenantId) ->where('target_table', $payload['target_table']) ->where('field_key', $payload['field_key']) ->exists(); if ($dup) { throw new BadRequestHttpException(__('error.duplicate_key')); } $payload['tenant_id'] = $tenantId; $payload['is_critical'] = $payload['is_critical'] ?? false; $payload['display_order'] = $payload['display_order'] ?? 0; $payload['created_by'] = $userId; TenantStatField::create($payload); $result['created']++; } } }); return $result; } }