pdo = $pdo; } public function findAllOrders(array $filters = [], int $limit = 50, int $offset = 0): array { $sql = 'SELECT co.*, ap.name as profile_name, cc.name as contract_name, cs.name as structure_name, (SELECT COUNT(*) FROM content_versions WHERE order_id = co.id) as version_count FROM content_orders co LEFT JOIN content_config ap ON co.author_profile_id = ap.id AND ap.type = "author_profile" LEFT JOIN content_config cc ON co.contract_id = cc.id AND cc.type = "contract" LEFT JOIN content_config cs ON co.structure_id = cs.id AND cs.type = "structure" WHERE 1=1'; $params = []; if (isset($filters['status']) && $filters['status'] !== '') { $sql .= ' AND co.status = :status'; $params['status'] = $filters['status']; } if (isset($filters['profile_id']) && $filters['profile_id'] !== '') { $sql .= ' AND co.author_profile_id = :profile_id'; $params['profile_id'] = $filters['profile_id']; } $sql .= ' ORDER BY co.updated_at DESC LIMIT :limit OFFSET :offset'; $stmt = $this->pdo->prepare($sql); foreach ($params as $key => $value) { $stmt->bindValue(':' . $key, $value); } $stmt->bindValue(':limit', $limit, \PDO::PARAM_INT); $stmt->bindValue(':offset', $offset, \PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } public function findOrder(int $id): ?array { $stmt = $this->pdo->prepare(' SELECT co.*, ap.name as profile_name, ap.content as profile_config, cc.name as contract_name, cc.content as contract_config, cs.name as structure_name, cs.content as structure_config FROM content_orders co LEFT JOIN content_config ap ON co.author_profile_id = ap.id AND ap.type = "author_profile" LEFT JOIN content_config cc ON co.contract_id = cc.id AND cc.type = "contract" LEFT JOIN content_config cs ON co.structure_id = cs.id AND cs.type = "structure" WHERE co.id = :id '); $stmt->execute(['id' => $id]); $result = $stmt->fetch(); return $result !== false ? $result : null; } /** * Get settings from the last created order as defaults for new orders. * * @return array */ public function getLastOrderSettings(): array { $stmt = $this->pdo->query(' SELECT model, collections, context_limit, author_profile_id, contract_id, structure_id, temperature, max_tokens, system_prompt_id, selected_critics, quality_check FROM content_orders ORDER BY id DESC LIMIT 1 '); $row = $stmt->fetch(\PDO::FETCH_ASSOC); if (!$row) { return [ 'model' => 'claude-sonnet-4-20250514', 'collections' => ['documents'], 'context_limit' => 5, 'author_profile_id' => null, 'contract_id' => null, 'structure_id' => null, 'temperature' => 0.5, 'max_tokens' => 4096, 'system_prompt_id' => null, 'selected_critics' => [], 'quality_check' => false, ]; } return [ 'model' => $row['model'] ?? 'claude-sonnet-4-20250514', 'collections' => $this->decodeJsonArray($row['collections'] ?? null) ?: ['documents'], 'context_limit' => (int) ($row['context_limit'] ?? 5), 'author_profile_id' => $row['author_profile_id'] !== null ? (int) $row['author_profile_id'] : null, 'contract_id' => $row['contract_id'] !== null ? (int) $row['contract_id'] : null, 'structure_id' => $row['structure_id'] !== null ? (int) $row['structure_id'] : null, 'temperature' => (float) ($row['temperature'] ?? 0.5), 'max_tokens' => (int) ($row['max_tokens'] ?? 4096), 'system_prompt_id' => $row['system_prompt_id'] !== null ? (int) $row['system_prompt_id'] : null, 'selected_critics' => $this->decodeJsonArray($row['selected_critics'] ?? null) ?: [], 'quality_check' => (bool) ($row['quality_check'] ?? false), ]; } public function createOrder(array $data): int { $stmt = $this->pdo->prepare(" INSERT INTO content_orders (title, briefing, author_profile_id, contract_id, structure_id, model, collections, context_limit, status) VALUES (:title, :briefing, :profile_id, :contract_id, :structure_id, :model, :collections, :context_limit, 'draft') "); $stmt->execute([ 'title' => $data['title'], 'briefing' => $data['briefing'], 'profile_id' => ($data['author_profile_id'] !== '' && $data['author_profile_id'] !== null) ? $data['author_profile_id'] : null, 'contract_id' => ($data['contract_id'] !== '' && $data['contract_id'] !== null) ? $data['contract_id'] : null, 'structure_id' => ($data['structure_id'] !== '' && $data['structure_id'] !== null) ? $data['structure_id'] : null, 'model' => $data['model'] ?? 'claude-sonnet-4-20250514', 'collections' => $data['collections'] ?? '["documents"]', 'context_limit' => $data['context_limit'] ?? 5, ]); return (int) $this->pdo->lastInsertId(); } public function updateOrderStatus(int $id, string $status): void { $stmt = $this->pdo->prepare(' UPDATE content_orders SET status = :status, updated_at = NOW() WHERE id = :id '); $stmt->execute(['id' => $id, 'status' => $status]); } public function updateGenerationStatus(int $id, string $status, ?string $error = null): void { $sql = 'UPDATE content_orders SET generation_status = :status, updated_at = NOW()'; $params = ['id' => $id, 'status' => $status]; if ($status === 'generating') { $sql .= ', generation_started_at = NOW()'; } if ($error !== null) { $sql .= ', generation_error = :error'; $params['error'] = $error; } if ($status === 'completed' || $status === 'idle') { $sql .= ', generation_error = NULL'; } $sql .= ' WHERE id = :id'; $stmt = $this->pdo->prepare($sql); $stmt->execute($params); } public function updateCritiqueStatus(int $id, string $status, ?string $error = null): void { $sql = 'UPDATE content_orders SET critique_status = :status, updated_at = NOW()'; $params = ['id' => $id, 'status' => $status]; if ($status === 'critiquing') { $sql .= ', critique_started_at = NOW(), critique_log = NULL'; } if ($error !== null) { $sql .= ', critique_error = :error'; $params['error'] = $error; } if ($status === 'completed' || $status === 'idle') { $sql .= ', critique_error = NULL'; } $sql .= ' WHERE id = :id'; $stmt = $this->pdo->prepare($sql); $stmt->execute($params); } public function updateOrder(int $id, array $data): bool { $stmt = $this->pdo->prepare(' UPDATE content_orders SET title = :title, briefing = :briefing, author_profile_id = :profile_id, contract_id = :contract_id, structure_id = :structure_id, updated_at = NOW() WHERE id = :id '); return $stmt->execute([ 'id' => $id, 'title' => $data['title'], 'briefing' => $data['briefing'], 'profile_id' => ($data['author_profile_id'] !== '' && $data['author_profile_id'] !== null) ? $data['author_profile_id'] : null, 'contract_id' => ($data['contract_id'] !== '' && $data['contract_id'] !== null) ? $data['contract_id'] : null, 'structure_id' => ($data['structure_id'] !== '' && $data['structure_id'] !== null) ? $data['structure_id'] : null, ]); } public function getStatistics(): array { $stats = []; $stmt = $this->pdo->query('SELECT COUNT(*) FROM content_orders'); $stats['total_orders'] = (int) $stmt->fetchColumn(); $stmt = $this->pdo->query('SELECT status, COUNT(*) as count FROM content_orders GROUP BY status'); $stats['by_status'] = $stmt->fetchAll(\PDO::FETCH_KEY_PAIR); return $stats; } }