Dodanie AI do raportów
This commit is contained in:
parent
7b7cc9c02a
commit
74d53c800e
@ -9,6 +9,7 @@ date_default_timezone_set('UTC');
|
||||
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../mail/MailService.php';
|
||||
require_once __DIR__ . '/../ai/LocalAIApi.php';
|
||||
require_once __DIR__ . '/diagnostic_data.php';
|
||||
require_once __DIR__ . '/diagnostic_functions.php';
|
||||
|
||||
|
||||
@ -13,6 +13,10 @@ function ensure_diagnostic_schema(): void
|
||||
current_step INT UNSIGNED NOT NULL DEFAULT 1,
|
||||
answers_json LONGTEXT NULL,
|
||||
result_json LONGTEXT NULL,
|
||||
report_subject VARCHAR(255) NULL,
|
||||
report_html LONGTEXT NULL,
|
||||
report_text LONGTEXT NULL,
|
||||
report_generated_at DATETIME NULL,
|
||||
email_report_status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
email_report_error TEXT NULL,
|
||||
contact_phone VARCHAR(40) NULL,
|
||||
@ -25,6 +29,22 @@ function ensure_diagnostic_schema(): void
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
|
||||
);
|
||||
|
||||
if (!diagnostic_schema_column_exists('diagnostic_attempts', 'report_subject')) {
|
||||
db()->exec("ALTER TABLE diagnostic_attempts ADD COLUMN report_subject VARCHAR(255) NULL AFTER result_json");
|
||||
}
|
||||
|
||||
if (!diagnostic_schema_column_exists('diagnostic_attempts', 'report_html')) {
|
||||
db()->exec("ALTER TABLE diagnostic_attempts ADD COLUMN report_html LONGTEXT NULL AFTER report_subject");
|
||||
}
|
||||
|
||||
if (!diagnostic_schema_column_exists('diagnostic_attempts', 'report_text')) {
|
||||
db()->exec("ALTER TABLE diagnostic_attempts ADD COLUMN report_text LONGTEXT NULL AFTER report_html");
|
||||
}
|
||||
|
||||
if (!diagnostic_schema_column_exists('diagnostic_attempts', 'report_generated_at')) {
|
||||
db()->exec("ALTER TABLE diagnostic_attempts ADD COLUMN report_generated_at DATETIME NULL AFTER report_text");
|
||||
}
|
||||
|
||||
if (!diagnostic_schema_column_exists('diagnostic_attempts', 'contact_phone')) {
|
||||
db()->exec("ALTER TABLE diagnostic_attempts ADD COLUMN contact_phone VARCHAR(40) NULL AFTER email_report_error");
|
||||
}
|
||||
@ -317,7 +337,15 @@ function diagnostic_finalize_attempt(int $attemptId): ?array
|
||||
$result = diagnostic_calculate_result($attempt['answers']);
|
||||
$stmt = db()->prepare(
|
||||
'UPDATE diagnostic_attempts
|
||||
SET status = :status, current_step = :current_step, result_json = :result_json, completed_at = NOW(), updated_at = NOW()
|
||||
SET status = :status,
|
||||
current_step = :current_step,
|
||||
result_json = :result_json,
|
||||
report_subject = NULL,
|
||||
report_html = NULL,
|
||||
report_text = NULL,
|
||||
report_generated_at = NULL,
|
||||
completed_at = NOW(),
|
||||
updated_at = NOW()
|
||||
WHERE id = :id'
|
||||
);
|
||||
$stmt->execute([
|
||||
@ -414,90 +442,387 @@ function diagnostic_email_data_table(array $rows): string
|
||||
}
|
||||
|
||||
|
||||
function diagnostic_build_report_html(array $attempt): string
|
||||
function diagnostic_email_list(array $items, string $accentColor = '#111827'): string
|
||||
{
|
||||
$html = '<ul style="margin:0;padding:0 0 0 20px;color:#374151;font-size:15px;line-height:1.7;">';
|
||||
foreach ($items as $item) {
|
||||
$html .= '<li style="margin:0 0 10px;"><span style="color:' . diagnostic_email_escape($accentColor) . ';">•</span> ' . diagnostic_email_escape((string)$item) . '</li>';
|
||||
}
|
||||
return $html . '</ul>';
|
||||
}
|
||||
|
||||
function diagnostic_report_limit(string $value, int $maxLength): string
|
||||
{
|
||||
$value = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/u', '', $value) ?? $value;
|
||||
$value = str_replace(["\r\n", "\r"], "\n", $value);
|
||||
$value = preg_replace('/[ \t]+/u', ' ', $value) ?? $value;
|
||||
$value = preg_replace("/\n{3,}/u", "\n\n", $value) ?? $value;
|
||||
$value = trim($value);
|
||||
|
||||
if ($maxLength > 0) {
|
||||
if (function_exists('mb_substr')) {
|
||||
$value = mb_substr($value, 0, $maxLength, 'UTF-8');
|
||||
} else {
|
||||
$value = substr($value, 0, $maxLength);
|
||||
}
|
||||
$value = trim($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
function diagnostic_report_list(array $items, int $maxItems = 3, int $maxLength = 220): array
|
||||
{
|
||||
$normalized = [];
|
||||
foreach ($items as $item) {
|
||||
if (!is_scalar($item)) {
|
||||
continue;
|
||||
}
|
||||
$line = diagnostic_report_limit((string)$item, $maxLength);
|
||||
if ($line !== '') {
|
||||
$normalized[] = $line;
|
||||
}
|
||||
if (count($normalized) >= $maxItems) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
function diagnostic_question_answer_rows(array $attempt): array
|
||||
{
|
||||
$rows = [];
|
||||
$questions = diagnostic_flat_questions();
|
||||
$answers = $attempt['answers'] ?? [];
|
||||
foreach ($questions as $question) {
|
||||
$value = $answers[$question['id']] ?? null;
|
||||
if ($value === null || $value === '') {
|
||||
continue;
|
||||
}
|
||||
$rows[] = [
|
||||
'section' => $question['section_name'],
|
||||
'question' => $question['text'],
|
||||
'answer_value' => (int)$value,
|
||||
'answer_label' => diagnostic_answer_label((int)$value),
|
||||
'reverse' => !empty($question['reverse']),
|
||||
];
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
function diagnostic_default_report_copy(array $attempt): array
|
||||
{
|
||||
$result = $attempt['result'] ?? [];
|
||||
$strengths = [];
|
||||
foreach (($result['strongest_areas'] ?? []) as $area) {
|
||||
$strengths[] = sprintf(
|
||||
'%s (%d%%) — to obszar, który już daje Ci relatywnie stabilny fundament operacyjny.',
|
||||
(string)($area['section_name'] ?? 'Mocny obszar'),
|
||||
(int)($area['percentage'] ?? 0)
|
||||
);
|
||||
}
|
||||
|
||||
$priorities = [];
|
||||
foreach (($result['weakest_areas'] ?? []) as $area) {
|
||||
$priorities[] = sprintf(
|
||||
'%s (%d%%) — tutaj najszybciej pojawiają się tarcia, opóźnienia lub zależność od ręcznego nadzoru.',
|
||||
(string)($area['section_name'] ?? 'Priorytet'),
|
||||
(int)($area['percentage'] ?? 0)
|
||||
);
|
||||
}
|
||||
|
||||
$nextSteps = [];
|
||||
foreach (($result['recommendations'] ?? []) as $item) {
|
||||
$nextSteps[] = (string)$item;
|
||||
}
|
||||
|
||||
$segmentLabel = (string)($result['segment_label'] ?? 'Diagnoza zakończona');
|
||||
$segmentSummary = diagnostic_report_limit((string)($result['segment_summary'] ?? ''), 420);
|
||||
$priorityNames = array_map(
|
||||
static fn(array $area): string => (string)($area['section_name'] ?? ''),
|
||||
(array)($result['weakest_areas'] ?? [])
|
||||
);
|
||||
$priorityNames = array_values(array_filter($priorityNames, static fn(string $name): bool => trim($name) !== ''));
|
||||
$whatItMeans = 'Największy potencjał poprawy widać obecnie w obszarach: ' . ($priorityNames ? implode(', ', $priorityNames) : 'organizacji codziennej pracy') . '.';
|
||||
|
||||
return [
|
||||
'subject' => 'Twój raport diagnozy dojrzałości procesowej',
|
||||
'preheader' => 'Gotowe: wynik diagnozy i rekomendowane kolejne kroki dla Twojej firmy.',
|
||||
'intro' => 'Dziękujemy za wypełnienie diagnozy. Poniżej znajdziesz krótkie podsumowanie wyniku oraz rekomendowane następne kroki.',
|
||||
'executive_summary' => $segmentSummary !== '' ? $segmentSummary : 'Masz już gotowy wynik diagnozy oraz wskazanie obszarów, które warto uporządkować w pierwszej kolejności.',
|
||||
'what_it_means' => $whatItMeans,
|
||||
'strengths' => diagnostic_report_list($strengths),
|
||||
'priorities' => diagnostic_report_list($priorities),
|
||||
'next_steps' => diagnostic_report_list($nextSteps),
|
||||
'closing' => 'Wróć do podsumowania diagnozy, aby omówić wynik z zespołem lub zaplanować kolejny krok wdrożeniowy.',
|
||||
];
|
||||
}
|
||||
|
||||
function diagnostic_ai_report_prompt_payload(array $attempt): array
|
||||
{
|
||||
$result = $attempt['result'] ?? [];
|
||||
|
||||
return [
|
||||
'quiz' => [
|
||||
'title' => diagnostic_quiz_definition()['quiz']['title'] ?? 'Diagnoza dojrzałości procesowej',
|
||||
'language' => 'pl',
|
||||
],
|
||||
'recipient' => [
|
||||
'email' => (string)($attempt['email'] ?? ''),
|
||||
],
|
||||
'result' => [
|
||||
'score_percent' => (int)($result['percentage_score'] ?? 0),
|
||||
'segment_label' => (string)($result['segment_label'] ?? ''),
|
||||
'segment_summary' => (string)($result['segment_summary'] ?? ''),
|
||||
'recommendations' => array_values((array)($result['recommendations'] ?? [])),
|
||||
'strongest_areas' => array_values((array)($result['strongest_areas'] ?? [])),
|
||||
'weakest_areas' => array_values((array)($result['weakest_areas'] ?? [])),
|
||||
'section_scores' => array_values((array)($result['section_scores'] ?? [])),
|
||||
],
|
||||
'answers' => diagnostic_question_answer_rows($attempt),
|
||||
];
|
||||
}
|
||||
|
||||
function diagnostic_normalize_report_copy(array $candidate, array $defaults): array
|
||||
{
|
||||
$copy = $defaults;
|
||||
foreach (['subject' => 140, 'preheader' => 180, 'intro' => 420, 'executive_summary' => 650, 'what_it_means' => 520, 'closing' => 320] as $field => $maxLength) {
|
||||
if (!empty($candidate[$field]) && is_scalar($candidate[$field])) {
|
||||
$normalized = diagnostic_report_limit((string)$candidate[$field], $maxLength);
|
||||
if ($normalized !== '') {
|
||||
$copy[$field] = $normalized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['strengths', 'priorities', 'next_steps'] as $field) {
|
||||
if (!empty($candidate[$field]) && is_array($candidate[$field])) {
|
||||
$normalizedList = diagnostic_report_list($candidate[$field]);
|
||||
if ($normalizedList !== []) {
|
||||
$copy[$field] = $normalizedList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $copy;
|
||||
}
|
||||
|
||||
function diagnostic_generate_ai_report_copy(array $attempt): array
|
||||
{
|
||||
$defaults = diagnostic_default_report_copy($attempt);
|
||||
$payload = diagnostic_ai_report_prompt_payload($attempt);
|
||||
|
||||
try {
|
||||
$response = LocalAIApi::createResponse(
|
||||
[
|
||||
'input' => [
|
||||
[
|
||||
'role' => 'system',
|
||||
'content' => 'Jesteś konsultantem operacyjnym B2B. Tworzysz krótkie, konkretne i profesjonalne podsumowania e-mail po polsku na podstawie danych z quizu. Odpowiadaj wyłącznie poprawnym JSON-em UTF-8 bez markdownu i bez HTML. Zachowaj rzeczowy ton. Nie wymyślaj faktów wykraczających poza dane. Zwróć dokładnie pola: subject, preheader, intro, executive_summary, what_it_means, strengths, priorities, next_steps, closing. strengths/priorities/next_steps mają być tablicami 2-3 krótkich punktów.'
|
||||
],
|
||||
[
|
||||
'role' => 'user',
|
||||
'content' => "Przygotuj treść raportu e-mail dla klienta na podstawie tych danych quizu. Dane wejściowe JSON:\n" . json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'poll_interval' => 3,
|
||||
'poll_timeout' => 120,
|
||||
]
|
||||
);
|
||||
|
||||
if (!empty($response['success'])) {
|
||||
$decoded = LocalAIApi::decodeJsonFromResponse($response);
|
||||
if (is_array($decoded)) {
|
||||
return [
|
||||
'copy' => diagnostic_normalize_report_copy($decoded, $defaults),
|
||||
'source' => 'ai',
|
||||
];
|
||||
}
|
||||
|
||||
error_log('Diagnostic AI report generation returned unparsable payload.');
|
||||
} else {
|
||||
error_log('Diagnostic AI report generation failed: ' . (string)($response['error'] ?? $response['message'] ?? 'unknown_error'));
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
error_log('Diagnostic AI report generation failed: ' . $exception->getMessage());
|
||||
}
|
||||
|
||||
return [
|
||||
'copy' => $defaults,
|
||||
'source' => 'fallback',
|
||||
];
|
||||
}
|
||||
|
||||
function diagnostic_build_report_html(array $attempt, array $copy): string
|
||||
{
|
||||
$result = $attempt['result'] ?? [];
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
|
||||
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
||||
$resultUrl = $scheme . '://' . $host . '/diagnostic.php?view=result';
|
||||
|
||||
$priorityCards = '';
|
||||
foreach (($result['weakest_areas'] ?? []) as $area) {
|
||||
$priorityCards .= '<div style="margin:0 0 12px;padding:16px 18px;border:1px solid #e5e7eb;border-radius:14px;background:#f9fafb;">'
|
||||
. '<div style="font-size:12px;letter-spacing:0.08em;text-transform:uppercase;color:#6b7280;margin-bottom:6px;">Priorytet</div>'
|
||||
. '<div style="font-size:16px;font-weight:700;color:#111827;margin-bottom:4px;">' . diagnostic_email_escape($area['section_name'] ?? '') . '</div>'
|
||||
. '<div style="font-size:14px;color:#374151;">' . (int)($area['percentage'] ?? 0) . '% dojrzałości — ten obszar najczęściej wymaga najszybszego uporządkowania.</div>'
|
||||
. '</div>';
|
||||
}
|
||||
if ($priorityCards === '') {
|
||||
$priorityCards = '<p style="margin:0;color:#6b7280;">Brak danych o priorytetowych obszarach do pokazania w tym raporcie.</p>';
|
||||
}
|
||||
$strengthsHtml = diagnostic_email_list($copy['strengths'] ?? []);
|
||||
$prioritiesHtml = diagnostic_email_list($copy['priorities'] ?? []);
|
||||
$nextStepsHtml = diagnostic_email_list($copy['next_steps'] ?? []);
|
||||
|
||||
$recommendations = '';
|
||||
foreach (($result['recommendations'] ?? []) as $item) {
|
||||
$recommendations .= '<li style="margin:0 0 10px;">' . diagnostic_email_escape((string)$item) . '</li>';
|
||||
}
|
||||
if ($recommendations === '') {
|
||||
$recommendations = '<li style="margin:0;">Brak dodatkowych rekomendacji.</li>';
|
||||
}
|
||||
|
||||
$content = '<p style="margin:0 0 18px;font-size:16px;line-height:1.7;color:#374151;">Dziękujemy za wypełnienie diagnozy. Obecny poziom dojrzałości operacyjnej Twojej firmy to <strong>' . diagnostic_email_escape($result['segment_label'] ?? 'Diagnoza zakończona') . '</strong>.</p>'
|
||||
$content = '<p style="margin:0 0 18px;font-size:16px;line-height:1.7;color:#374151;">' . diagnostic_email_escape((string)($copy['intro'] ?? '')) . '</p>'
|
||||
. '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="width:100%;border-collapse:collapse;margin:0 0 24px;">'
|
||||
. '<tr>'
|
||||
. '<td style="padding:20px;border-radius:18px;background:linear-gradient(135deg,#f9fafb 0%,#eef2f7 100%);border:1px solid #e5e7eb;">'
|
||||
. '<div style="font-size:13px;letter-spacing:0.08em;text-transform:uppercase;color:#6b7280;margin-bottom:8px;">Wynik łączny</div>'
|
||||
. '<div style="font-size:36px;line-height:1;font-weight:700;color:#111827;margin-bottom:10px;">' . (int)($result['percentage_score'] ?? 0) . '%</div>'
|
||||
. '<div style="font-size:15px;line-height:1.7;color:#374151;">' . diagnostic_email_escape($result['segment_summary'] ?? '') . '</div>'
|
||||
. '<div style="font-size:36px;line-height:1;font-weight:700;color:#111827;margin-bottom:8px;">' . (int)($result['percentage_score'] ?? 0) . '%</div>'
|
||||
. '<div style="font-size:18px;line-height:1.4;font-weight:700;color:#111827;margin-bottom:10px;">' . diagnostic_email_escape((string)($result['segment_label'] ?? 'Diagnoza zakończona')) . '</div>'
|
||||
. '<div style="font-size:15px;line-height:1.7;color:#374151;">' . diagnostic_email_escape((string)($copy['executive_summary'] ?? '')) . '</div>'
|
||||
. '</td>'
|
||||
. '</tr>'
|
||||
. '</table>'
|
||||
. '<h2 style="font-size:18px;line-height:1.3;margin:0 0 12px;color:#111827;">Priorytetowe obszary do poprawy</h2>'
|
||||
. $priorityCards
|
||||
. '<div style="margin:0 0 24px;padding:18px 20px;border:1px solid #e5e7eb;border-radius:16px;background:#ffffff;">'
|
||||
. '<div style="font-size:12px;letter-spacing:0.08em;text-transform:uppercase;color:#6b7280;margin-bottom:8px;">Co ten wynik oznacza</div>'
|
||||
. '<div style="font-size:15px;line-height:1.7;color:#374151;">' . diagnostic_email_escape((string)($copy['what_it_means'] ?? '')) . '</div>'
|
||||
. '</div>'
|
||||
. '<h2 style="font-size:18px;line-height:1.3;margin:0 0 12px;color:#111827;">Mocne strony</h2>'
|
||||
. $strengthsHtml
|
||||
. '<h2 style="font-size:18px;line-height:1.3;margin:28px 0 12px;color:#111827;">Priorytety na teraz</h2>'
|
||||
. $prioritiesHtml
|
||||
. '<h2 style="font-size:18px;line-height:1.3;margin:28px 0 12px;color:#111827;">Rekomendowane kolejne kroki</h2>'
|
||||
. '<ul style="margin:0;padding:0 0 0 20px;color:#374151;font-size:15px;line-height:1.7;">' . $recommendations . '</ul>'
|
||||
. $nextStepsHtml
|
||||
. '<div style="margin:28px 0 0;padding:18px 20px;border-radius:16px;background:#111827;color:#ffffff;">'
|
||||
. '<div style="font-size:16px;font-weight:700;margin-bottom:6px;">Chcesz omówić wynik z zespołem?</div>'
|
||||
. '<div style="font-size:14px;line-height:1.7;opacity:0.88;margin-bottom:14px;">Wróć do podsumowania diagnozy, aby ustalić priorytety zmian i zamówić kolejny krok.</div>'
|
||||
. '<div style="font-size:16px;font-weight:700;margin-bottom:6px;">' . diagnostic_email_escape((string)($copy['closing'] ?? '')) . '</div>'
|
||||
. '<div style="font-size:14px;line-height:1.7;opacity:0.88;margin-bottom:14px;">W podsumowaniu online zobaczysz pełen wynik i możesz od razu zostawić numer do kontaktu.</div>'
|
||||
. '<a href="' . diagnostic_email_escape($resultUrl) . '" style="display:inline-block;padding:12px 18px;border-radius:12px;background:#ffffff;color:#111827;text-decoration:none;font-weight:700;">Otwórz podsumowanie diagnozy</a>'
|
||||
. '</div>';
|
||||
|
||||
return diagnostic_email_document(
|
||||
'Raport z diagnozy dojrzałości procesowej',
|
||||
'Twój wynik diagnozy i rekomendowane kolejne kroki są gotowe.',
|
||||
(string)($copy['subject'] ?? 'Raport z diagnozy dojrzałości procesowej'),
|
||||
(string)($copy['preheader'] ?? 'Twój wynik diagnozy i rekomendowane kolejne kroki są gotowe.'),
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
function diagnostic_build_report_text(array $attempt): string
|
||||
function diagnostic_build_report_text(array $attempt, array $copy): string
|
||||
{
|
||||
$result = $attempt['result'] ?? [];
|
||||
$lines = [];
|
||||
$lines[] = 'Raport z diagnozy dojrzałości procesowej';
|
||||
$lines[] = (string)($copy['subject'] ?? 'Raport z diagnozy dojrzałości procesowej');
|
||||
$lines[] = 'Wynik: ' . ($result['segment_label'] ?? 'Diagnoza zakończona') . ' (' . (int)($result['percentage_score'] ?? 0) . '%)';
|
||||
$lines[] = (string)($result['segment_summary'] ?? '');
|
||||
$lines[] = '';
|
||||
$lines[] = 'Priorytetowe obszary:';
|
||||
foreach (($result['weakest_areas'] ?? []) as $area) {
|
||||
$lines[] = '- ' . $area['section_name'] . ': ' . (int)$area['percentage'] . '%';
|
||||
}
|
||||
$lines[] = (string)($copy['intro'] ?? '');
|
||||
$lines[] = '';
|
||||
$lines[] = 'Rekomendowane działania:';
|
||||
foreach (($result['recommendations'] ?? []) as $item) {
|
||||
$lines[] = (string)($copy['executive_summary'] ?? '');
|
||||
$lines[] = '';
|
||||
$lines[] = 'Co ten wynik oznacza:';
|
||||
$lines[] = (string)($copy['what_it_means'] ?? '');
|
||||
$lines[] = '';
|
||||
$lines[] = 'Mocne strony:';
|
||||
foreach (($copy['strengths'] ?? []) as $item) {
|
||||
$lines[] = '- ' . $item;
|
||||
}
|
||||
return implode("\n", $lines);
|
||||
$lines[] = '';
|
||||
$lines[] = 'Priorytety na teraz:';
|
||||
foreach (($copy['priorities'] ?? []) as $item) {
|
||||
$lines[] = '- ' . $item;
|
||||
}
|
||||
$lines[] = '';
|
||||
$lines[] = 'Rekomendowane kolejne kroki:';
|
||||
foreach (($copy['next_steps'] ?? []) as $item) {
|
||||
$lines[] = '- ' . $item;
|
||||
}
|
||||
$lines[] = '';
|
||||
$lines[] = (string)($copy['closing'] ?? '');
|
||||
return diagnostic_report_limit(implode("\n", $lines), 10000);
|
||||
}
|
||||
|
||||
function diagnostic_send_report_email(array $attempt): array
|
||||
function diagnostic_store_report_content(int $attemptId, array $package): void
|
||||
{
|
||||
if (empty($attempt['email']) || empty($attempt['result'])) {
|
||||
return ['success' => false, 'error' => 'Brak adresu e-mail lub wyniku próby'];
|
||||
$stmt = db()->prepare(
|
||||
'UPDATE diagnostic_attempts
|
||||
SET report_subject = :report_subject,
|
||||
report_html = :report_html,
|
||||
report_text = :report_text,
|
||||
report_generated_at = NOW(),
|
||||
updated_at = NOW()
|
||||
WHERE id = :id'
|
||||
);
|
||||
$stmt->execute([
|
||||
':report_subject' => (string)($package['subject'] ?? ''),
|
||||
':report_html' => (string)($package['html'] ?? ''),
|
||||
':report_text' => (string)($package['text'] ?? ''),
|
||||
':id' => $attemptId,
|
||||
]);
|
||||
}
|
||||
|
||||
function diagnostic_cached_report_content(array $attempt): ?array
|
||||
{
|
||||
$subject = diagnostic_report_limit((string)($attempt['report_subject'] ?? ''), 255);
|
||||
$html = (string)($attempt['report_html'] ?? '');
|
||||
$text = (string)($attempt['report_text'] ?? '');
|
||||
|
||||
if ($subject === '' || $html === '' || $text === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$subject = 'Raport z diagnozy dojrzałości procesowej';
|
||||
$html = diagnostic_build_report_html($attempt);
|
||||
$text = diagnostic_build_report_text($attempt);
|
||||
return MailService::sendMail($attempt['email'], $subject, $html, $text);
|
||||
return [
|
||||
'success' => true,
|
||||
'subject' => $subject,
|
||||
'html' => $html,
|
||||
'text' => $text,
|
||||
'source' => 'cache',
|
||||
];
|
||||
}
|
||||
|
||||
function diagnostic_generate_report_content(array $attempt): array
|
||||
{
|
||||
if (empty($attempt['result'])) {
|
||||
return ['success' => false, 'error' => 'Brak wyniku potrzebnego do wygenerowania raportu.'];
|
||||
}
|
||||
|
||||
$ai = diagnostic_generate_ai_report_copy($attempt);
|
||||
$copy = $ai['copy'] ?? diagnostic_default_report_copy($attempt);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'subject' => (string)($copy['subject'] ?? 'Raport z diagnozy dojrzałości procesowej'),
|
||||
'html' => diagnostic_build_report_html($attempt, $copy),
|
||||
'text' => diagnostic_build_report_text($attempt, $copy),
|
||||
'source' => (string)($ai['source'] ?? 'fallback'),
|
||||
];
|
||||
}
|
||||
|
||||
function diagnostic_resolve_report_content(array $attempt, bool $forceRegenerate = false): array
|
||||
{
|
||||
if (!$forceRegenerate) {
|
||||
$cached = diagnostic_cached_report_content($attempt);
|
||||
if ($cached !== null) {
|
||||
return $cached;
|
||||
}
|
||||
}
|
||||
|
||||
$generated = diagnostic_generate_report_content($attempt);
|
||||
if (!empty($generated['success']) && !empty($attempt['id'])) {
|
||||
diagnostic_store_report_content((int)$attempt['id'], $generated);
|
||||
}
|
||||
|
||||
return $generated;
|
||||
}
|
||||
|
||||
function diagnostic_send_report_email(array $attempt, bool $forceRegenerate = false): array
|
||||
{
|
||||
if (empty($attempt['email']) || !filter_var((string)$attempt['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
return ['success' => false, 'error' => 'Brak poprawnego adresu e-mail klienta'];
|
||||
}
|
||||
|
||||
$report = diagnostic_resolve_report_content($attempt, $forceRegenerate);
|
||||
if (empty($report['success'])) {
|
||||
return $report;
|
||||
}
|
||||
|
||||
return MailService::sendMail(
|
||||
$attempt['email'],
|
||||
(string)$report['subject'],
|
||||
(string)$report['html'],
|
||||
(string)$report['text']
|
||||
);
|
||||
}
|
||||
|
||||
function diagnostic_admin_setting_get(string $key): ?string
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user