Tikettinumerointi (VVNKKNN) + automaattinen vastaus

Tikettinumero:
- Uudet tiketit saavat juoksevan numeron VVNKKNN-formaatissa
  (vuosi+kuukausi sekoitettu sekvenssiin, esim. 2600301)
- Numero näkyy tikettilistassa ja detail-näkymässä (#-merkillä)
- Sähköpostin aihe muotoa "Tiketti #2600301: Alkuperäinen aihe"
- Vastaukset ketjuuntuvat automaattisesti

Autoreply:
- Postilaatikkokohtainen asetus: checkbox + viestisisältö
- Uusi tiketti lähettää automaattisen vastauksen asiakkaalle
- Autoreply näkyy tiketin viestiketjussa ( Automaattinen vastaus)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 00:24:17 +02:00
parent 96a35c7e0b
commit 07e9c63c47
4 changed files with 107 additions and 12 deletions

44
db.php
View File

@@ -236,6 +236,7 @@ function initDatabase(): void {
"CREATE TABLE IF NOT EXISTS tickets (
id VARCHAR(20) PRIMARY KEY,
ticket_number INT DEFAULT NULL,
company_id VARCHAR(50) NOT NULL,
subject VARCHAR(500),
from_email VARCHAR(255),
@@ -317,6 +318,8 @@ function initDatabase(): void {
smtp_from_email VARCHAR(255),
smtp_from_name VARCHAR(255),
aktiivinen BOOLEAN DEFAULT TRUE,
auto_reply_enabled BOOLEAN DEFAULT FALSE,
auto_reply_body TEXT,
FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE,
INDEX idx_company (company_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
@@ -441,6 +444,9 @@ function initDatabase(): void {
"ALTER TABLE mailboxes ADD COLUMN smtp_user VARCHAR(255) DEFAULT '' AFTER smtp_port",
"ALTER TABLE mailboxes ADD COLUMN smtp_password VARCHAR(255) DEFAULT '' AFTER smtp_user",
"ALTER TABLE mailboxes ADD COLUMN smtp_encryption VARCHAR(10) DEFAULT 'tls' AFTER smtp_password",
"ALTER TABLE tickets ADD COLUMN ticket_number INT DEFAULT NULL AFTER id",
"ALTER TABLE mailboxes ADD COLUMN auto_reply_enabled BOOLEAN DEFAULT FALSE AFTER aktiivinen",
"ALTER TABLE mailboxes ADD COLUMN auto_reply_body TEXT AFTER auto_reply_enabled",
];
foreach ($alters as $sql) {
try { $db->query($sql); } catch (\Throwable $e) { /* sarake on jo olemassa / jo ajettu */ }
@@ -986,6 +992,24 @@ function dbDeleteLead(string $leadId): void {
// ==================== TIKETIT ====================
/**
* Generoi seuraava tikettinumero (VVNKKNN-formaatti).
* Vuosi+kuukausi sekoitetaan juoksevaan numeroon.
*/
function dbNextTicketNumber(string $companyId): int {
$yy = (int)date('y');
$mm = (int)date('m');
$fullYear = (int)date('Y');
$count = (int)_dbFetchScalar(
"SELECT COUNT(*) FROM tickets WHERE company_id = ? AND YEAR(created) = ? AND MONTH(created) = ?",
[$companyId, $fullYear, $mm]
);
$seq = $count + 1;
$hundreds = intdiv($seq, 100);
$remainder = $seq % 100;
return $yy * 100000 + $hundreds * 10000 + $mm * 100 + $remainder;
}
function dbLoadTickets(string $companyId): array {
$tickets = _dbFetchAll("SELECT * FROM tickets WHERE company_id = ? ORDER BY updated DESC", [$companyId]);
@@ -1017,9 +1041,9 @@ function dbSaveTicket(string $companyId, array $ticket): void {
$db->begin_transaction();
try {
_dbExecute("
INSERT INTO tickets (id, company_id, subject, from_email, from_name, status, type,
INSERT INTO tickets (id, ticket_number, company_id, subject, from_email, from_name, status, type,
assigned_to, customer_id, customer_name, message_id, mailbox_id, cc, priority, auto_close_at, created, updated)
VALUES (:id, :company_id, :subject, :from_email, :from_name, :status, :type,
VALUES (:id, :ticket_number, :company_id, :subject, :from_email, :from_name, :status, :type,
:assigned_to, :customer_id, :customer_name, :message_id, :mailbox_id, :cc, :priority, :auto_close_at, :created, :updated)
ON DUPLICATE KEY UPDATE
subject = VALUES(subject), from_email = VALUES(from_email), from_name = VALUES(from_name),
@@ -1030,6 +1054,7 @@ function dbSaveTicket(string $companyId, array $ticket): void {
auto_close_at = VALUES(auto_close_at), updated = VALUES(updated)
", [
'id' => $ticket['id'],
'ticket_number' => $ticket['ticket_number'] ?? null,
'company_id' => $companyId,
'subject' => $ticket['subject'] ?? '',
'from_email' => $ticket['from_email'] ?? '',
@@ -1157,6 +1182,8 @@ function dbLoadMailboxes(string $companyId): array {
$boxes = _dbFetchAll("SELECT * FROM mailboxes WHERE company_id = ?", [$companyId]);
foreach ($boxes as &$b) {
$b['aktiivinen'] = (bool)$b['aktiivinen'];
$b['auto_reply_enabled'] = (bool)($b['auto_reply_enabled'] ?? false);
$b['auto_reply_body'] = $b['auto_reply_body'] ?? '';
$b['imap_port'] = (int)$b['imap_port'];
$b['smtp_port'] = (int)($b['smtp_port'] ?? 587);
unset($b['company_id']);
@@ -1166,15 +1193,16 @@ function dbLoadMailboxes(string $companyId): array {
function dbSaveMailbox(string $companyId, array $mailbox): void {
_dbExecute("
INSERT INTO mailboxes (id, company_id, nimi, imap_host, imap_port, imap_user, imap_encryption, imap_password, smtp_from_email, smtp_from_name, smtp_host, smtp_port, smtp_user, smtp_password, smtp_encryption, aktiivinen)
VALUES (:id, :company_id, :nimi, :imap_host, :imap_port, :imap_user, :imap_encryption, :imap_password, :smtp_from_email, :smtp_from_name, :smtp_host, :smtp_port, :smtp_user, :smtp_password, :smtp_encryption, :aktiivinen)
INSERT INTO mailboxes (id, company_id, nimi, imap_host, imap_port, imap_user, imap_encryption, imap_password, smtp_from_email, smtp_from_name, smtp_host, smtp_port, smtp_user, smtp_password, smtp_encryption, aktiivinen, auto_reply_enabled, auto_reply_body)
VALUES (:id, :company_id, :nimi, :imap_host, :imap_port, :imap_user, :imap_encryption, :imap_password, :smtp_from_email, :smtp_from_name, :smtp_host, :smtp_port, :smtp_user, :smtp_password, :smtp_encryption, :aktiivinen, :auto_reply_enabled, :auto_reply_body)
ON DUPLICATE KEY UPDATE
nimi = VALUES(nimi), imap_host = VALUES(imap_host), imap_port = VALUES(imap_port),
imap_user = VALUES(imap_user), imap_encryption = VALUES(imap_encryption),
imap_password = VALUES(imap_password), smtp_from_email = VALUES(smtp_from_email),
smtp_from_name = VALUES(smtp_from_name), smtp_host = VALUES(smtp_host), smtp_port = VALUES(smtp_port),
smtp_user = VALUES(smtp_user), smtp_password = VALUES(smtp_password),
smtp_encryption = VALUES(smtp_encryption), aktiivinen = VALUES(aktiivinen)
smtp_encryption = VALUES(smtp_encryption), aktiivinen = VALUES(aktiivinen),
auto_reply_enabled = VALUES(auto_reply_enabled), auto_reply_body = VALUES(auto_reply_body)
", [
'id' => $mailbox['id'],
'company_id' => $companyId,
@@ -1190,8 +1218,10 @@ function dbSaveMailbox(string $companyId, array $mailbox): void {
'smtp_port' => $mailbox['smtp_port'] ?? 587,
'smtp_user' => $mailbox['smtp_user'] ?? '',
'smtp_password' => $mailbox['smtp_password'] ?? '',
'smtp_encryption' => $mailbox['smtp_encryption'] ?? 'tls',
'aktiivinen' => $mailbox['aktiivinen'] ?? true,
'smtp_encryption' => $mailbox['smtp_encryption'] ?? 'tls',
'aktiivinen' => $mailbox['aktiivinen'] ?? true,
'auto_reply_enabled' => $mailbox['auto_reply_enabled'] ?? false,
'auto_reply_body' => $mailbox['auto_reply_body'] ?? '',
]);
}