# Hesk 3.x import One-time historical migration of tickets (with full reply/note history) from a Hesk 3.x helpdesk database into this app, restricted to a single e-mail domain. Read-only against the Hesk database — never writes there. This is **not** an ongoing sync. Run it once to backfill history from an old Hesk install; it doesn't pick up edits made in Hesk afterward. ## What it does - Matches Hesk tickets by requester e-mail domain (`--domain=firma.pl`). - Imports each ticket's subject/body, status, priority, and full reply + internal-note history, converting Hesk's `
`-laden "plain" text into real line breaks. - Maps Hesk categories to this app's categories by exact (case/whitespace- insensitive) name match. A Hesk category with no match is skipped by default — pass `--include-unmapped-categories` to import those tickets anyway, uncategorized. - Auto-assigns a team when every subcategory under the matched category routes to the same single team (same rule `TicketService::autoAssignTeam()` uses for normal ticket creation); ambiguous categories are left unrouted. - Finds the local client account per requester e-mail (matched by e-mail, adding the `client` role if it doesn't have it yet). **Never creates a User** — the servicedesk user base is treated as authoritative/complete, so a Hesk requester e-mail with no matching account means that ticket is skipped (reported at the end, with the list of skipped e-mails). - Hesk staff replies/notes are linked to a real operator account when the Hesk staff member's e-mail matches an existing servicedesk operator/admin account; otherwise they fall back to showing the correct staff name and "operator" badge via `author_name` only, without a clickable user behind it (this script never creates operator accounts either). - Every imported ticket also stores its source Hesk ticket id (`tickets.hesk_ticket_id`, unique). This is a second, DB-level guard against duplicate imports on top of the state file below — if the state file is ever lost or out of sync, a re-run still can't create a duplicate ticket for the same Hesk id. - A ticket's Hesk owner is matched the same way as reply/note authors and set as `assignee_id`, so imported tickets show up correctly assigned in the operator queue instead of everything landing in "Nieprzypisane". ## Setup ```bash cp scripts/hesk-import/.env.example scripts/hesk-import/.env ``` Fill in `scripts/hesk-import/.env` with the Hesk database's host/port/database/username/password. That file is gitignored — it holds real credentials for a database this app otherwise has no access to. ## Usage Always dry-run first — it reports what *would* happen without writing anything: ```bash scripts/hesk-import/hesk-import.sh --domain=firma.pl ``` Try a small batch for real before committing to the whole thing: ```bash scripts/hesk-import/hesk-import.sh --domain=firma.pl --limit=10 --commit ``` Then the full import: ```bash scripts/hesk-import/hesk-import.sh --domain=firma.pl --commit ``` Safe to re-run (including after an interrupted/crashed run): already-imported Hesk ticket ids are tracked in `storage/app/hesk-import-state.json` inside the app container and skipped on subsequent runs. ### Backfilling team assignment If tickets were already imported before team-by-category mapping existed (or teams/subcategories changed since), backfill `team_id` on existing imported tickets without importing anything new: ```bash scripts/hesk-import/hesk-import.sh --assign-teams --commit ``` ### Fixing closed-ticket dates New imports already use Hesk's dedicated `closedat` column (not `lastchange`, which moves forward on any later edit — e.g. a note added after closing) for a closed ticket's date, and record a matching "Status zmieniony na: Zamknięte" history entry. To apply the same correction to tickets imported before this existed (including the original import, from before `hesk_ticket_id` was even tracked — matched back to Hesk via the unique `(email, created_at)` pair instead): ```bash scripts/hesk-import/hesk-import.sh --fix-closed-dates --commit ``` Doesn't import anything new; safe to re-run (already-correct tickets are left alone). ### Backfilling ticket ownership New imports already set `assignee_id` from Hesk's ticket owner. To apply the same to tickets imported before this existed: ```bash scripts/hesk-import/hesk-import.sh --assign-operators --commit ``` Only touches tickets with no `assignee_id` yet (never overwrites a manual reassignment made since import) and never invents an assignment — a Hesk owner of 0 or one with no matching servicedesk account is left unassigned, unless it's one of the two ids in `ImportHeskTickets::DELETED_STAFF_REASSIGNMENT` (Hesk staff accounts deleted since, with historical tickets explicitly reassigned to a current operator per the app owner). ## How it's wired up `hesk-import.sh` is a thin wrapper: it loads `.env` in this folder, then runs `php artisan hesk:import` inside the `app` container via `docker compose exec`, passing the Hesk DB credentials as one-off environment variables (they never touch the app's own `.env` or get persisted anywhere but the state file). The actual import logic lives in [`../../src/app/Console/Commands/ImportHeskTickets.php`](../../src/app/Console/Commands/ImportHeskTickets.php).