query( 'SELECT id, name, description, default_price, category FROM item_templates ORDER BY category, name' ); successResponse(['templates' => $stmt->fetchAll()]); } function handleSaveItemTemplate(PDO $pdo): void { $input = getJsonInput(); if (empty($input['name'])) { errorResponse('Název šablony je povinný'); } $id = isset($input['id']) ? (int)$input['id'] : null; if ($id) { // Update $stmt = $pdo->prepare(' UPDATE item_templates SET name = ?, description = ?, default_price = ?, category = ?, modified_at = NOW(), sync_version = sync_version + 1 WHERE id = ? '); $stmt->execute([ $input['name'], $input['description'] ?? '', $input['default_price'] ?? 0, $input['category'] ?? '', $id, ]); successResponse(null, 'Šablona byla aktualizována'); } else { // Create $uuid = sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0x0fff) | 0x4000, random_int(0, 0x3fff) | 0x8000, random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff) ); $stmt = $pdo->prepare(' INSERT INTO item_templates (name, description, default_price, category, uuid, modified_at, sync_version) VALUES (?, ?, ?, ?, ?, NOW(), 1) '); $stmt->execute([ $input['name'], $input['description'] ?? '', $input['default_price'] ?? 0, $input['category'] ?? '', $uuid, ]); $newId = (int)$pdo->lastInsertId(); AuditLog::logCreate( 'offers_item_template', (int)$newId, ['name' => $input['name']], "Vytvořena šablona položky '{$input['name']}'" ); successResponse(['id' => $newId], 'Šablona byla vytvořena'); } } function handleDeleteItemTemplate(PDO $pdo, int $id): void { $stmt = $pdo->prepare('SELECT name FROM item_templates WHERE id = ?'); $stmt->execute([$id]); $template = $stmt->fetch(); if (!$template) { errorResponse('Šablona nebyla nalezena', 404); } $stmt = $pdo->prepare('DELETE FROM item_templates WHERE id = ?'); $stmt->execute([$id]); AuditLog::logDelete( 'offers_item_template', $id, ['name' => $template['name']], "Smazána šablona položky '{$template['name']}'" ); successResponse(null, 'Šablona byla smazána'); } // --- Scope Templates --- function handleGetScopeTemplates(PDO $pdo): void { $stmt = $pdo->query( 'SELECT id, name, title, description FROM scope_templates ORDER BY name' ); successResponse(['templates' => $stmt->fetchAll()]); } function handleGetScopeDetail(PDO $pdo, int $id): void { $stmt = $pdo->prepare( 'SELECT id, name, title, description FROM scope_templates WHERE id = ?' ); $stmt->execute([$id]); $template = $stmt->fetch(); if (!$template) { errorResponse('Šablona nebyla nalezena', 404); } $stmt = $pdo->prepare( 'SELECT id, scope_template_id, position, title, title_cz, content FROM scope_template_sections WHERE scope_template_id = ? ORDER BY position' ); $stmt->execute([$id]); $template['sections'] = $stmt->fetchAll(); successResponse($template); } function handleSaveScopeTemplate(PDO $pdo): void { $input = getJsonInput(); if (empty($input['name'])) { errorResponse('Název šablony je povinný'); } $id = isset($input['id']) ? (int)$input['id'] : null; $sections = $input['sections'] ?? []; $pdo->beginTransaction(); try { if ($id) { // Update template $stmt = $pdo->prepare(' UPDATE scope_templates SET name = ?, title = ?, description = ?, modified_at = NOW(), sync_version = sync_version + 1 WHERE id = ? '); $stmt->execute([ $input['name'], $input['title'] ?? '', $input['description'] ?? '', $id, ]); } else { // Create template $uuid = sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0x0fff) | 0x4000, random_int(0, 0x3fff) | 0x8000, random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff) ); $stmt = $pdo->prepare(' INSERT INTO scope_templates (name, title, description, uuid, modified_at, sync_version) VALUES (?, ?, ?, ?, NOW(), 1) '); $stmt->execute([ $input['name'], $input['title'] ?? '', $input['description'] ?? '', $uuid, ]); $id = (int)$pdo->lastInsertId(); } // Delete existing sections and re-insert $stmt = $pdo->prepare('DELETE FROM scope_template_sections WHERE scope_template_id = ?'); $stmt->execute([$id]); $stmt = $pdo->prepare(' INSERT INTO scope_template_sections (scope_template_id, title, title_cz, content, position, uuid, modified_at, sync_version) VALUES (?, ?, ?, ?, ?, ?, NOW(), 1) '); foreach ($sections as $i => $section) { $sectionUuid = sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0x0fff) | 0x4000, random_int(0, 0x3fff) | 0x8000, random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff) ); $stmt->execute([ $id, $section['title'] ?? '', $section['title_cz'] ?? '', $section['content'] ?? '', $i + 1, $sectionUuid, ]); } $pdo->commit(); AuditLog::logCreate( 'offers_scope_template', $id, ['name' => $input['name']], "Uložena šablona rozsahu '{$input['name']}'" ); successResponse(['id' => $id], 'Šablona rozsahu byla uložena'); } catch (PDOException $e) { $pdo->rollBack(); throw $e; } } function handleDeleteScopeTemplate(PDO $pdo, int $id): void { $stmt = $pdo->prepare('SELECT name FROM scope_templates WHERE id = ?'); $stmt->execute([$id]); $template = $stmt->fetch(); if (!$template) { errorResponse('Šablona nebyla nalezena', 404); } $pdo->beginTransaction(); try { // Delete sections $stmt = $pdo->prepare('DELETE FROM scope_template_sections WHERE scope_template_id = ?'); $stmt->execute([$id]); // Delete template $stmt = $pdo->prepare('DELETE FROM scope_templates WHERE id = ?'); $stmt->execute([$id]); $pdo->commit(); AuditLog::logDelete( 'offers_scope_template', $id, ['name' => $template['name']], "Smazána šablona rozsahu '{$template['name']}'" ); successResponse(null, 'Šablona rozsahu byla smazána'); } catch (PDOException $e) { $pdo->rollBack(); throw $e; } }