TaskMonkey Handbuch

Rezept: Wöchentlicher Sales-Report aus der Live-DB

DB Gateway gegen Shop-DB → PDF-Report → Mail an Stakeholder.

Klassisches Reporting-Szenario: jeden Montag um 8:00 soll die Geschäftsführung den Wochenbericht der Vorwoche im Postfach haben. Daten kommen aus der Live-Shop-DB des Kunden, an die TaskMonkey nicht direkt rankommt — perfekt für das Database Gateway.

Ziel

  • Montag 8:00: Scheduled Task läuft
  • DB Gateway wird zur Shop-DB des Kunden deployed (24h-Token)
  • SQL-Queries für Top-Produkte, Wochenumsatz, Vergleich Vorwoche
  • HTML-Bericht generieren, als PDF rendern, per Mail versenden
  • Gateway wieder abräumen

Voraussetzungen

  • SSH-Zugang zum Webserver des Kunden (Key beim Betreiber hinterlegt)
  • DB Gateway-Connection-Config in deinem Workspace

1. DB-Connection-Config

config/remote_databases/kunde_shop.php (oder wo der Betreiber's vorgesehen hat):

<?php
return [
    'kunde_shop' => [
        'hostname' => 'shop.kunde.de',
        'remote_user' => 'kunde',
        'web_root' => '/var/www/html',
        'ssh_key' => '/path/to/private_key',
        'base_url' => 'https://shop.kunde.de',
        'allow_write' => false,
    ],
];

2. Workflow-Tool

tools/reports/weeklySalesReport.php:

<?php
return [
    'tools' => [
        'weeklySalesReport' => [
            'description' => 'Erstellt den Wochen-Sales-Report und mailt ihn.',
            'parameters' => [
                'type' => 'object',
                'properties' => [
                    'recipients' => [
                        'type' => 'array',
                        'items' => ['type' => 'string'],
                        'description' => 'Empfänger-Mail-Adressen',
                    ],
                ],
                'required' => ['recipients'],
            ],
            'handler' => function (array $results, array $args, array $ctx): array {
                $logger = $ctx['logger'];

                // 1. Gateway deployen
                $gateway = $ctx['runTool']('deployGateway', ['project' => 'kunde_shop']);
                if (empty($gateway['success'])) {
                    $logger->error('Gateway-Deploy fehlgeschlagen');
                    return ['error' => 'Gateway konnte nicht deployed werden'];
                }

                try {
                    // 2. Queries
                    $thisWeek = $ctx['runTool']('executeQuery', [
                        'project' => 'kunde_shop',
                        'sql' => "SELECT
                            COUNT(*) AS orders,
                            SUM(total) AS revenue,
                            AVG(total) AS avg_order_value
                        FROM orders
                        WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
                          AND status = 'completed'",
                    ]);

                    $lastWeek = $ctx['runTool']('executeQuery', [
                        'project' => 'kunde_shop',
                        'sql' => "SELECT
                            COUNT(*) AS orders,
                            SUM(total) AS revenue
                        FROM orders
                        WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 14 DAY)
                          AND created_at < DATE_SUB(CURDATE(), INTERVAL 7 DAY)
                          AND status = 'completed'",
                    ]);

                    $topProducts = $ctx['runTool']('executeQuery', [
                        'project' => 'kunde_shop',
                        'sql' => "SELECT p.name, SUM(oi.quantity) AS qty, SUM(oi.line_total) AS revenue
                            FROM order_items oi
                            JOIN products p ON p.id = oi.product_id
                            JOIN orders o ON o.id = oi.order_id
                            WHERE o.created_at >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
                              AND o.status = 'completed'
                            GROUP BY p.id, p.name
                            ORDER BY revenue DESC
                            LIMIT 10",
                    ]);

                    // 3. HTML zusammenbauen
                    $html = renderReport($thisWeek, $lastWeek, $topProducts);

                    // 4. Mail versenden
                    foreach ($args['recipients'] as $to) {
                        $ctx['runTool']('sendMail', [
                            'to' => $to,
                            'subject' => 'Wochen-Sales-Report KW ' . date('W'),
                            'html' => $html,
                        ]);
                    }

                    $logger->success('Report an ' . count($args['recipients']) . ' Empfänger versendet');
                    return ['sent' => count($args['recipients'])];

                } finally {
                    // 5. Gateway abräumen
                    $ctx['runTool']('removeGateway', ['project' => 'kunde_shop']);
                }
            },
        ],
    ],
];

function renderReport($thisWeek, $lastWeek, $topProducts): string
{
    $tw = $thisWeek['rows'][0] ?? [];
    $lw = $lastWeek['rows'][0] ?? [];

    $diff = $lw['revenue'] > 0
        ? round((($tw['revenue'] - $lw['revenue']) / $lw['revenue']) * 100, 1)
        : 0;

    $rows = '';
    foreach ($topProducts['rows'] ?? [] as $p) {
        $rows .= sprintf('<tr><td>%s</td><td>%d</td><td>%.2f €</td></tr>',
            htmlspecialchars($p['name']), $p['qty'], $p['revenue']);
    }

    return <<<HTML
        <h1>Wochen-Sales-Report</h1>
        <h2>Übersicht</h2>
        <ul>
            <li>Bestellungen: <b>{$tw['orders']}</b></li>
            <li>Umsatz: <b>{$tw['revenue']} €</b> ({$diff}% vs. Vorwoche)</li>
            <li>Durchschnittlicher Warenkorb: <b>{$tw['avg_order_value']} €</b></li>
        </ul>
        <h2>Top 10 Produkte</h2>
        <table border="1" cellpadding="6">
            <tr><th>Produkt</th><th>Stück</th><th>Umsatz</th></tr>
            {$rows}
        </table>
    HTML;
}

3. Scheduled Task

<?php
return [
    'scheduled' => [
        'weekly_sales_report' => [
            'enabled' => true,
            'tool' => 'weeklySalesReport',
            'at_time' => '08:00',
            'args' => [
                'recipients' => [
                    'gl@kunde.de',
                    'sales@kunde.de',
                ],
            ],
        ],
    ],
];

(Der Task läuft jeden Tag um 8:00 — wenn du wirklich nur Montags willst, baust du ans Anfang des Handlers if (date('N') !== '1') return;.)

4. Testen

tm test-tool weeklySalesReport recipients='["test@dir.de"]'

In tm logs siehst du jeden SQL-Query und den Mail-Versand.

Erweiterungen

  • PDF statt HTML: PDF-Tool generieren und als Attachment anhängen
  • Charts: QuickChart.io URL einbauen — Bilder im Mail-HTML
  • Mehrere Empfänger-Sets: GL bekommt Übersicht, Produktmanagement bekommt Top-Produkte-Detail
  • Trend-Hinweise vom Modell: Daten ans LLM geben, das schreibt einen kurzen Kommentar („Umsatz unter Vorwoche, vermutlich wegen …")
  • Slack-Variante parallel: Kurzversion in #sales-weekly
Zuletzt aktualisiert: 2026-04-20