TimeSync Module
The TimeSync module synchronizes time entries from YouTrack work items to Autotask time entries, and syncs issue descriptions to Autotask tickets/tasks.
Overview
TimeSync bridges two systems:
- YouTrack — issue tracking with time-logged work items
- Autotask — PSA platform for billing, time tracking, and project management
Work items logged in YouTrack are collected into a local database, then pushed as time entries to the matching Autotask ticket or task. Changes (duration, date, description) are detected and propagated as updates. Deleted work items are removed from Autotask.
Prerequisites
Before time entry sync works, these must be set up:
- Autotask users synced —
php yii timeSync/base-data/sync-autotask-users - Autotask roles synced —
php yii timeSync/base-data/sync-autotask-roles - Autotask user roles synced —
php yii timeSync/base-data/sync-autotask-user-roles - YouTrack users synced —
php yii timeSync/base-data/sync-youtrack-users - User mappings created —
php yii timeSync/base-data/auto-match-users(or manual via web UI) - Issue-ticket links created —
php yii timeSync/base-data/sync-issue-mappings PROJ
Steps 1-5 can be run together via php yii timeSync/base-data/sync-all.
CLI Commands Reference
Commands are split across two controllers:
timeSync/base-data— base data sync (users, roles, mappings)timeSync/sync— time entry sync, description sync, and orchestration
Run All (Full Sync)
Syncs all base data, auto-discovers YouTrack projects with Autotask configuration, then per project: syncs issue mappings, time entries, and descriptions.
php yii timeSync/sync/run-all
php yii timeSync/sync/run-all --dryRun
php yii timeSync/sync/run-all --guard=dateCutoff --from=2026-02-09Base Data Commands
# Sync all base data (users, roles, mappings) in proper order
php yii timeSync/base-data/sync-all
# Individual base data commands
php yii timeSync/base-data/sync-autotask-users
php yii timeSync/base-data/sync-autotask-roles
php yii timeSync/base-data/sync-autotask-user-roles
php yii timeSync/base-data/sync-youtrack-users
php yii timeSync/base-data/auto-match-users
# Sync issue-to-ticket links for a project
php yii timeSync/base-data/sync-issue-mappings PROJ| Option | Default | Description |
|---|---|---|
--dryRun | false | Preview without making changes |
--verbose | true | Show console output |
Collect Work Items
Fetches work items from YouTrack and creates/updates/marks-deleted local TimeEntrySync records. Does not push to Autotask.
php yii timeSync/sync/collect-work-items PROJ
php yii timeSync/sync/collect-work-items PROJ --dryRun
php yii timeSync/sync/collect-work-items PROJ --guard=dateCutoff --from=2026-02-09| Option | Default | Description |
|---|---|---|
--dryRun | false | Preview without making changes |
--verbose | true | Show console output |
--guard | combined | Guard strategy: dateCutoff, apiError, combined |
--from | Monday last week | Start date (Y-m-d), only used with --guard=dateCutoff |
Push Time Entries
Pushes retryable entries (pending + failed) to Autotask. Creates new time entries or updates existing ones.
php yii timeSync/sync/push-time-entries
php yii timeSync/sync/push-time-entries --dryRun
php yii timeSync/sync/push-time-entries --guard=dateCutoff --from=2026-02-09
php yii timeSync/sync/push-time-entries --guard=apiErrorDelete Time Entries
Processes entries marked as deleted — removes them from Autotask, then hard-deletes the local record.
php yii timeSync/sync/delete-time-entries
php yii timeSync/sync/delete-time-entries --dryRunSync Time Entries (Full Pipeline)
Master command: runs collect, push, and delete in sequence for a single project.
php yii timeSync/sync/sync-time-entries PROJ
php yii timeSync/sync/sync-time-entries PROJ --dryRun
php yii timeSync/sync/sync-time-entries PROJ --guard=dateCutoff --from=2026-02-09Sync Descriptions
Syncs YouTrack issue descriptions to Autotask ticket/task descriptions. Uses hash-based change detection.
php yii timeSync/sync/sync-descriptions PROJ
php yii timeSync/sync/sync-descriptions PROJ --dryRunGuard Strategies
Autotask timesheets lock once submitted (typically weekly). Guard strategies handle this:
combined (Default)
- Pre-filter: Skips entries with
work_dateolder than 60 days - Error handling: Catches timesheet-submitted API errors and marks entries as
expired - Best for: Regular automated sync — limits blast radius while still detecting submission errors
dateCutoff
- Pre-filter: Skips entries with
work_datebefore--fromdate (default: Monday of last week) - Error handling: None — relies entirely on pre-filtering
- Best for: Narrow manual syncs where you know the exact date range
apiError
- Pre-filter: None — processes all retryable entries
- Error handling: Catches timesheet-submitted API errors and marks entries as
expired - Best for: One-time full scans to detect and clean up expired entries
Sync Status Lifecycle
pending ──→ synced ──→ (update detected) ──→ pending ──→ synced
│ │
│ └──→ deleted ──→ (AT delete + hard delete)
│
└──→ failed ──→ (retry) ──→ synced
│
└──→ expired (terminal — timesheet submitted)| Status | Description |
|---|---|
pending | Awaiting push to Autotask (new or updated) |
synced | Successfully synced to Autotask |
failed | API error occurred, will be retried on next push |
deleted | Work item removed in YouTrack, awaiting Autotask deletion |
expired | Autotask timesheet was submitted — cannot be modified (terminal state) |
Description Sync
Issue description changes are detected via MD5 hash comparison:
YoutrackIssue.description_hashis auto-updated on saveIssueTicketLink.description_sync_hashstores the hash at last sync- When hashes differ,
needsDescriptionSync()returns true - The
sync-descriptionscommand fetches fresh descriptions from YouTrack and pushes to Autotask
Descriptions are truncated to 8000 characters (Autotask limit).
Typical Workflow
Initial Setup
# 1. Sync all base data (users, roles, mappings)
php yii timeSync/base-data/sync-all
# 2. Review user mappings in web UI, activate/deactivate as needed
# 3. Sync issue-to-ticket links for your project
php yii timeSync/base-data/sync-issue-mappings PROJ
# 4. Dry run to preview what would be synced
php yii timeSync/sync/sync-time-entries PROJ --dryRun
# 5. Run the actual sync
php yii timeSync/sync/sync-time-entries PROJOngoing Sync
# Full sync across all projects (e.g., via cron every 15 minutes)
php yii timeSync/sync/run-all
# Or sync a single project
php yii timeSync/sync/sync-time-entries PROJ
# Sync descriptions periodically (e.g., daily)
php yii timeSync/sync/sync-descriptions PROJTroubleshooting
# Check for failed entries
# → Review in web UI under TimeSync > Time Entries, filter by status "Failed"
# Retry failed entries manually
php yii timeSync/sync/push-time-entries --verbose
# Full scan to detect expired entries
php yii timeSync/sync/push-time-entries --guard=apiError --verbose