Commit graph

964 commits

Author SHA1 Message Date
f49767d1eb fix: update favicon to use Wulf logo PNG format
- Added favicon.png copy of Wulf logo
- Updated metadata to use PNG favicon with multiple size options
- Should fix triangle icon issue in browser tab
- Favicon now properly displays Wulf logo
2026-02-04 08:12:35 -05:00
7b3830a388 fix: move Wulf logo to left navbar, correct spelling to Wulf
- Replaced Pulse icon with Wulf logo on left side of navbar
- Removed duplicate logo from right side
- Corrected alt text from 'Wulff' to 'Wulf'
- Logo now appears next to Pulse branding on left
2026-02-03 23:52:56 -05:00
98199f671d feat: add Wulff Consulting logo to navigation and favicon
- Added Wulff logo (W_RGB.png) to public directory
- Updated favicon to use Wulff logo
- Added logo to upper right of navigation bar (h-10)
- Logo appears next to theme toggle
- Links to home page when clicked
2026-02-03 23:49:58 -05:00
13fd13afd6 style: remove all top padding on kiosk display
- Changed to px-4 pb-4 pt-0 (zero top padding)
- KPI cards now sit right against navigation bar
- Maximizes vertical screen space for TV display
2026-02-03 23:41:47 -05:00
60b58b3f57 style: reduce top padding on kiosk display
- Changed padding from p-16 to p-4 pt-2
- Brings KPI cards closer to navigation bar
- Better use of screen space for TV display
2026-02-03 23:39:38 -05:00
f27b23bec8 fix: pre-populate classifications instead of syncing from Autotask API
- Autotask REST API doesn't expose ClassificationIcons endpoint
- Created migration to populate 17 standard classification icons
- Removed sync button from UI (classifications are pre-loaded)
- Includes: Tools Only, Co-Managed, Wulf 365 Essentials, Partner, etc.
- Users can now select any classification to exclude from kiosk
2026-02-03 20:54:35 -05:00
b222d97225 feat: add classification icons sync from Autotask
- Created company_classifications table to store Autotask classification icons
- Added getClassificationIcons() method to AutotaskClient
- Created /api/sync/classifications endpoint (GET/POST)
- Updated kiosk settings UI to dynamically load classifications
- Added 'Sync from Autotask' button to pull latest classifications
- Removed hardcoded classification list
- Display classification name and description in checkboxes
- Allow excluding any classification synced from Autotask
2026-02-03 20:48:08 -05:00
9940c20379 fix: parse excluded_classifications as array and handle companies API response
- Fixed settings API to parse excluded_classifications as array
- Fixed companies API response handling (returns {companies: []} not array)
- Resolves TypeError: excluded_classifications.filter is not a function
- Resolves TypeError: s.sort is not a function
2026-02-03 09:20:50 -05:00
root
1d99a8f659 feat: add classification-based filtering and fix company name display
- Added classification column to companies table
- Created excluded_classifications setting (default: Tools Only)
- Updated kiosk stats and activity APIs to filter by classification
- Added comprehensive classification filtering UI with checkboxes
- Support for common classifications (Tools Only, Wulff Consulting Client, Customer)
- Allow custom classification entry
- Fixed company name display in settings (convert string IDs properly)
- Classification filtering works alongside company ID exclusions
2026-02-03 09:17:07 -05:00
root
62ec703f81 feat: increase ticket font sizes and fix company name display
- Increased ticket number font from text-lg to text-2xl
- Increased company name font from text-sm to text-lg
- Increased ticket title font from text-xs to text-base
- Increased padding on ticket cards for better spacing
- Fixed company ID to name conversion in settings page
- Ensure excluded_company_ids are parsed as numbers for proper lookup
2026-02-03 09:09:46 -05:00
root
26bfd503f1 feat: add kiosk settings UI and co-managed client filtering
- Created kiosk_settings table for configuration storage
- Added API endpoints for kiosk settings (GET/POST)
- Filter out co-managed clients (configurable company exclusions)
- Built comprehensive settings UI at /kiosk/settings
- Allow excluding specific companies from kiosk display
- Configurable cycle interval, refresh interval, and RMM alert toggle
- Updated dashboard link to point to settings page
- Applied company exclusion filter to all ticket queries and activity feed
- Default excludes Thrasher Group (ID: 29861361)
2026-02-03 08:32:42 -05:00
root
724791121a feat: add top 3 tickets display on kiosk KPI cards
- Show company name and ticket title for top 3 tickets per category
- Critical tickets sorted by priority then create date
- Waiting tickets sorted by oldest activity
- Stale tickets sorted by oldest activity
- Overdue tickets sorted by most overdue
- Closed tickets sorted by most recent
- Adjusted card layout to accommodate ticket list
2026-02-03 08:25:27 -05:00
root
1d1b4d2a71 fix: exclude RMM alert tickets (source=8) from kiosk stats - show only human-generated tickets 2026-02-03 07:02:47 -05:00
root
2ebf8e6732 fix: correct time_entries column name from date_worked to entry_date 2026-02-02 23:48:17 -05:00
root
aec21d2b1e fix: replace Radix UI slider with custom implementation to avoid dependency 2026-02-02 23:39:24 -05:00
root
20a0785ec3 feat: add executive kiosk dashboard for TV display
- Created /kiosk route with full-screen display
- Added API endpoints for stats and activity feed
- Built cycling KPI display with 12 metrics
- Added scrolling ticker for ticket activity
- Implemented UI-configurable cycle interval (3-15s, default 7s)
- Focus on critical tickets and business metrics
- Added navigation link from dashboard
- Dark theme optimized for TV viewing
2026-02-02 23:36:35 -05:00
root
4d531b2f2d feat: auto-populate auvik_tenants and rmm_sites tables when fetching mappings
When includeUnmapped=true, the mapping APIs now populate the
auvik_tenants and rmm_sites tables with all fetched data.
This ensures accurate mapped/unmapped counts on the dashboard.
2026-02-02 23:12:35 -05:00
root
c0190c7dd1 feat: add tenants/sites sync for accurate dashboard stats
- Created auvik_tenants and rmm_sites tables
- Added /api/sync/tenants-sites endpoint to sync all tenants from Auvik
  and all sites from Datto RMM for accurate mapped/unmapped counts
2026-02-02 23:02:34 -05:00
root
a050157836 feat: create auvik_tenants and rmm_sites tables for accurate dashboard stats
Added tables to store all tenants/sites from external APIs.
Populated with existing mapped data. Full sync of all tenants/sites
needed for accurate unmapped counts.
2026-02-02 23:01:54 -05:00
root
f1985e2ea5 fix: use loose equality for company ID comparison in mapping dropdowns
The dropdown wasn't showing mapped company names due to type mismatch
between string and number IDs. Changed === to == for comparison.
2026-02-02 22:52:59 -05:00
root
ca61b7785d fix: correct RMM mapping column name from autotask_company_id to company_id 2026-02-02 22:44:40 -05:00
root
4bb8e25f56 fix: transform snake_case database columns to camelCase in companies API
The companies were being returned with database column names (snake_case)
but the TypeScript Company interface expects camelCase. Added transform
function to convert column names, fixing the localeCompare error in
mapping pages.
2026-02-02 21:54:52 -05:00
root
d3eeb4cab3 fix: handle missing tables in dashboard stats API
- Added tableExists helper to check if tables exist before querying
- Gracefully handle missing auvik_tenants, rmm_sites, and quotes tables
- Return partial data when some tables are missing
2026-02-02 21:50:23 -05:00
root
db4d431d26 perf: use cached database data for dashboard stats
- Created /api/dashboard/stats endpoint that queries local PostgreSQL only
- Updated companies API to use cached database instead of Autotask API
- Dashboard now loads instantly from cached data instead of waiting for external APIs
- Scheduled syncs keep data fresh throughout the day
2026-02-02 21:45:18 -05:00
root
6df319166d feat: update favicon to match dashboard Activity icon
Created SVG icon that matches the Activity/pulse icon used in the app:
- Blue gradient background matching the app theme
- White pulse/activity line icon
- Updated layout.tsx to use the new SVG icon
2026-02-02 21:29:52 -05:00
root
49adba17f1 feat: add favicon support
- Added icon metadata to layout.tsx for proper favicon handling
- Copied favicon.ico to public folder for accessibility
2026-02-02 21:27:17 -05:00
root
efff465a86 style: center navigation bar to match rest of app layout
Changed navigation layout from spread (justify-between) to centered:
- Logo positioned absolutely on the left
- Navigation menu centered with mx-auto
- Right actions positioned absolutely on the right
- Container uses justify-center for proper centering
2026-02-02 21:22:57 -05:00
root
1f9ac476b4 fix: correct environment variable name in sync scheduler
The scheduled sync was using AUTOTASK_INTEGRATION_CODE but the actual
environment variable is AUTOTASK_API_INTEGRATION_CODE. This caused
scheduled syncs to fail with 'IntegrationCode is invalid' while
manual syncs worked fine.

Changed:
- AUTOTASK_INTEGRATION_CODE -> AUTOTASK_API_INTEGRATION_CODE

This aligns the scheduler with autotask-factory.ts which was already
using the correct variable name.
2026-02-02 21:13:35 -05:00
root
9f912aed24 feat: add authentication, user management, and admin features
Added comprehensive authentication and authorization system:

Authentication System:
- Better Auth integration with session management
- Login/logout pages and API routes
- Middleware for route protection
- Auth utilities and client libraries

User Management:
- User list, detail, and invite pages
- User API endpoints (CRUD operations)
- Session management for users
- Profile settings page

Role-Based Access Control:
- Role management pages (list, create, edit)
- Permission system with granular controls
- Role assignment to users
- Role API endpoints

Admin Features:
- Audit log page for tracking system events
- Admin settings page
- Audit service for logging user actions

Additional Features:
- Quotes management pages and components
- SalesBldr API integration
- Email service for notifications

Configuration & Documentation:
- Updated docker-compose.yml
- MCP server configuration (mcp.json)
- CVE-2025-55182 security review documentation
- Standards guide and PRD documents
- Re-enabling authentication documentation

Database Migrations:
- 012: Auth tables (users, sessions, accounts, verifications)
- 013: Role tables (roles, permissions, role_permissions, user_roles)
- 014: Admin settings table

UI Updates:
- Updated dashboard layout
- Enhanced app layout with auth integration
2026-01-31 12:43:14 -05:00
root
d8e6931b85 fix: ensure Companies and Resources get filters during incremental sync fallback
Fixed critical logic bug where Companies and Resources were not getting
proper filters applied when falling back from incremental to full sync.

Root Cause:
- During scheduled incremental sync, Companies and Resources correctly
  identify they don't support incremental sync
- However, the filter-building logic was in an else block that only
  executed for non-incremental syncs
- This caused Companies and Resources to sync with NO filters at all
- Autotask API now rejects queries without filters, returning:
  'Value cannot be null. Parameter name: filters'

Fix:
- Restructured logic so filter building happens for BOTH:
  1. Non-incremental (full) syncs
  2. Incremental syncs that fall back to full sync
- Companies and Resources now get active filters applied even during
  scheduled incremental syncs

This resolves the scheduled sync failures for Companies, Resources,
and all other entities that were failing due to the cascading effect
of early failures.
2026-01-30 22:50:07 -05:00
root
8405c813a3 feat: add missing Tickets entity fields from Autotask API
Added 10 critical missing fields to Tickets entity:

Database Migration (016):
- billing_code_id: Billing code assignment
- configuration_item_id: Primary asset/CI
- creator_resource_id: Ticket creator
- creator_type: Creator type (resource/contact)
- problem_ticket_id: Link to problem ticket
- rma_status: RMA status tracking
- rma_type: RMA type classification
- service_level_agreement_paused_next_event_hours: SLA pause tracking
- is_assigned_to_comanaged: Co-managed assignment flag
- is_visible_to_comanaged: Co-managed visibility flag

Entity Mapper Updates:
- Added all new fields with correct camelCase mapping
- Ensures all Autotask Tickets API fields are captured

This completes the Tickets entity to match the full Autotask API
specification and should resolve issues with missing ticket data.
2026-01-26 15:26:34 -05:00
root
cc16d9b32d fix: correct Tickets entity field name mappings from Autotask API
Fixed field names to use proper camelCase from Autotask API instead of
snake_case. This should resolve the issue where assigned_resource_id
was NULL because the mapper was looking for incorrect field names.

Changed mappings:
- firstResponseDateTime (was first_response_date_time)
- resolutionPlanDateTime (was resolution_plan_date_time)
- resolvedDateTime (was resolved_date_time)
- firstResponseAssignedResourceID (was first_response_assigned_resource_id)
- firstResponseInitiatingResourceID (was first_response_initiating_resource_id)
- projectID, opportunityID, contractID, monitorID (were snake_case)
- All change approval and ticket fields converted to camelCase
- All service thermometer fields converted to camelCase

This fix should populate assigned_resource_id and other fields correctly
on the next ticket sync.
2026-01-26 15:25:03 -05:00
root
7252d2cfcf feat: add all new Resource fields to data browser detail modal
Updated Resources data browser page to display all 40+ fields in the
detail modal including:
- Name fields (prefix, middle initial, suffix)
- All contact information (3 email addresses, home phone)
- Employment details (payroll, accounting, internal cost)
- Location and availability
- System preferences (date/time/number formats)
- Demographics and security (gender, license, security level)
- Survey ratings

Fields are organized into logical groups with comments for clarity.
2026-01-26 14:57:43 -05:00
root
bc01a6aafb fix: handle non-numeric values in Resources integer fields
Autotask API returns string values like 'PRIMARY' for some integer
fields (e.g., emailTypeCode). Added safeInt() helper function to:
- Parse numeric values correctly
- Return null for non-numeric strings
- Handle null/undefined/empty values

This prevents database errors when syncing Resources with non-standard
field values from Autotask API.
2026-01-26 14:48:37 -05:00
root
8e0ca0a63b feat: expand Resources entity to include all Autotask API fields
Add comprehensive field support for Resources entity including:
- Name fields: middleInitial, namePrefix, nameSuffix
- Contact: emailAddress2, emailAddress3, homePhone
- Employment: accountingReferenceID, payrollType, internalCost
- System: emailTypeCode, numberFormat, timeFormat, dateFormat
- Demographics: gender
- Security: licenseType, securityLevel
- Location: defaultServiceDeskRoleID

Changes:
- Migration 015: Add new columns to resources table
- Updated entity mapper to map all Autotask Resource fields
- Expanded TypeScript Resource interface with all fields
- Maintains backward compatibility with existing field names

This ensures all data exposed by the Autotask Resources API is
now captured and stored in the database.
2026-01-26 14:28:51 -05:00
root
a1e50a7161 docs: update SYNC_BEHAVIOR.md with Companies and Resources limitations
Document that Companies and Resources entities do not support
incremental sync in the Autotask API and automatically fall back
to full sync when incremental sync is requested.

This clarifies expected behavior and prevents confusion about why
these entities always perform full syncs even during incremental
sync operations.
2026-01-26 12:26:57 -05:00
root
fc284aba85 fix: disable incremental sync for Companies and Resources
Companies and Resources entities in Autotask API do not support
date-based filtering for incremental syncs. When attempting incremental
sync, Autotask returns errors:
- Companies: 'Unable to find lastTrackedModificationDateTime'
- Resources: 'Unable to find lastModifiedDate'

Solution:
- Skip incremental sync for these entities
- Always perform full sync for Companies and Resources
- Log informational message when falling back to full sync
- Other entities continue to support incremental sync normally

This prevents sync failures while maintaining data freshness for
Companies and Resources through full syncs.
2026-01-26 12:07:52 -05:00
root
43e8c74074 fix: correct Autotask API field names for incremental sync
Fixed Autotask API errors for Billing Items and Time Entries during
incremental syncs by using the correct field names:

- Billing Items: Changed from 'createDate' to 'itemDate'
- Time Entries: Changed from 'lastModifiedDate' to 'dateWorked'

These field names match what's used in full sync filters and are
accepted by the Autotask API.

Errors fixed:
- 'Unable to find createDate in the BillingItem Entity'
- 'Unable to find lastModifiedDate in the TimeEntry Entity'

This allows incremental syncs to work properly for these entities.
2026-01-26 10:37:10 -05:00
root
bac9797845 fix: update API route params for Next.js 15+ async params
Next.js 15+ changed dynamic route params to be async Promises.
Updated all schedule API routes to await params before accessing id.

Changes:
- GET /api/sync/schedules/[id] - await params
- PATCH /api/sync/schedules/[id] - await params
- DELETE /api/sync/schedules/[id] - await params
- POST /api/sync/schedules/[id]/trigger - await params

This fixes TypeScript compilation errors during Docker build.
2026-01-26 10:31:46 -05:00
root
3db50d8531 fix: correct SyncService initialization in sync-scheduler
Fixed TypeScript errors in sync-scheduler:
- Added constructor to initialize SyncService with AutotaskClient
- Fixed AutotaskConfig property names (password, apiIntegrationCode)
- Changed method calls to match SyncService API (incrementalSync, fullSync)
- Fixed syncService references to use this.syncService

This resolves build errors preventing Docker image creation.
2026-01-26 10:29:31 -05:00
root
f117210c9d feat: add scheduled sync system with admin UI
Implements comprehensive scheduled sync system using node-cron with
full admin interface for configuration and monitoring.

Features:
- Configurable sync schedules with cron expressions
- Enable/disable schedules without deletion
- Manual trigger for testing
- Status monitoring (last run, next run, success/failure)
- Error tracking and display
- Incremental and full sync support
- Multiple concurrent schedules
- Admin UI with schedule management

Components:

1. Sync Scheduler Service (lib/services/sync-scheduler.ts)
   - node-cron integration for scheduling
   - Database-backed schedule configuration
   - Automatic initialization on startup
   - Prevents concurrent runs of same schedule
   - Calculates next run times
   - Tracks execution status and errors

2. Database Schema (sync_schedules table)
   - Schedule configuration storage
   - Execution history tracking
   - Last run status and errors
   - Next run calculation

3. API Endpoints
   - GET /api/sync/schedules - List all schedules
   - POST /api/sync/schedules - Create schedule
   - GET /api/sync/schedules/[id] - Get schedule
   - PATCH /api/sync/schedules/[id] - Update schedule
   - DELETE /api/sync/schedules/[id] - Delete schedule
   - POST /api/sync/schedules/[id]/trigger - Manual trigger

4. Admin UI (components/admin/SyncScheduler.tsx)
   - View all schedules with status
   - Create/edit/delete schedules
   - Enable/disable toggle
   - Manual trigger button
   - Cron expression presets
   - Real-time status updates
   - Error message display
   - Next run countdown

5. Default Schedules (created on first startup, disabled)
   - Daily Incremental: 2 AM daily (0 2 * * *)
   - Weekly Full: 3 AM Sunday (0 3 * * 0)

Admin Interface:
- New 'Schedules' tab in sync page
- Schedule cards with status badges
- Enable/disable with play/pause button
- Manual trigger with clock button
- Edit dialog with cron presets
- Create dialog for new schedules
- Real-time status (running, next run, last run)
- Success/failure indicators
- Error message alerts

Cron Features:
- Full cron expression support
- Validation before saving
- Common presets (daily, weekly, hourly)
- Next run time calculation
- Automatic schedule restart on config change

Monitoring:
- Last run timestamp
- Next run countdown (e.g., 'in 2h 15m')
- Success/failure status with icons
- Error messages for failed syncs
- Running indicator (animated badge)
- Schedule validity check

Dependencies:
- node-cron: ^3.0.3
- @types/node-cron: ^3.0.11

UI Components:
- Alert component added (components/ui/alert.tsx)
- Integrated into sync page tabs
- Responsive design

Documentation:
- Complete guide (docs/SCHEDULED_SYNCS.md)
- Cron expression reference
- Best practices
- Troubleshooting guide
- API reference
- Database schema

Use Cases:
1. Daily incremental sync for recent changes
2. Weekly full sync for data integrity
3. Custom schedules for specific needs
4. Off-peak hour automation
5. Backup for webhook failures

Benefits:
- No manual intervention required
- Consistent data freshness
- Flexible scheduling
- Easy monitoring
- Error tracking
- Manual override available

Next Steps:
1. Restart application to initialize scheduler
2. Navigate to Admin → Sync → Schedules tab
3. Enable default schedules or create custom ones
4. Monitor first runs for success
5. Adjust schedules as needed

Files Added/Modified:
- lib/services/sync-scheduler.ts (new)
- app/api/sync/schedules/route.ts (new)
- app/api/sync/schedules/[id]/route.ts (new)
- app/api/sync/schedules/[id]/trigger/route.ts (new)
- components/admin/SyncScheduler.tsx (new)
- components/ui/alert.tsx (new)
- app/admin/sync/page.tsx (modified - added Schedules tab)
- docs/SCHEDULED_SYNCS.md (new)
- package.json (node-cron added)
2026-01-26 10:24:58 -05:00
root
a093f8787c feat: add IP address logging to webhooks for whitelisting
Implements comprehensive IP logging for webhook requests to enable
IP whitelisting and security monitoring.

Features:
- Capture source IP from webhook requests (x-forwarded-for, x-real-ip)
- Capture user agent for identification
- Store in webhook_logs table
- New API endpoint: GET /api/webhooks/ips
- View unique IPs with request counts and statistics
- Identify Autotask IPs for whitelisting

Database Changes:
- Added source_ip column (VARCHAR 45) to webhook_logs
- Added user_agent column (TEXT) to webhook_logs
- Added index on source_ip for efficient queries
- Migration 005 for existing installations

API Endpoints:
- GET /api/webhooks/ips?hours=168&entityType=Tickets
  Returns unique IPs with:
  * Request counts (total, successful, failed)
  * First/last seen timestamps
  * Entity types accessed
  * User agent strings

Use Cases:
1. Identify Autotask webhook IPs
2. Configure IP whitelist in nginx/Pangolin/Cloudflare
3. Monitor for unauthorized webhook attempts
4. Audit webhook sources
5. Detect IP changes from Autotask

Security Benefits:
- Enable IP whitelisting for webhook endpoint
- Block unauthorized webhook attempts
- Monitor for suspicious activity
- Audit trail of webhook sources

Documentation:
- Complete IP whitelisting guide (WEBHOOK_IP_WHITELISTING.md)
- Configuration examples for nginx, Pangolin, Cloudflare
- Monitoring queries and best practices
- Troubleshooting guide

Files Modified:
- migrations/004_webhook_support.sql - Added IP columns
- migrations/005_add_webhook_ip_logging.sql - Migration for existing installs
- lib/types/webhook.ts - Added IP fields to WebhookLog
- lib/services/webhook-service.ts - Capture and log IPs
- app/api/webhooks/autotask/route.ts - Extract IP from headers
- app/api/webhooks/ips/route.ts - New IP viewing endpoint
- docs/WEBHOOK_IP_WHITELISTING.md - Complete guide

Next Steps:
1. Run migration (004 for new, 005 for existing)
2. Deploy updated code
3. Receive webhooks from Autotask
4. View IPs via /api/webhooks/ips
5. Configure IP whitelist in proxy/tunnel
2026-01-24 17:28:56 -05:00
root
8e83347138 docs: add Pangolin tunnel setup guide for webhook endpoint
User confirmed they use Pangolin (similar to Cloudflare Tunnel), so
created a comprehensive Pangolin-specific configuration guide.

Complete guide includes:
- Pangolin agent installation
- Tunnel configuration with path-based access control
- DNS setup
- Systemd service configuration
- Security settings (rate limiting, IP whitelisting)
- Testing procedures
- Troubleshooting guide
- Performance optimization
- High availability setup

Configuration features:
- Only /api/webhooks/autotask exposed
- Rate limiting: 100 req/min, burst 20
- Automatic SSL/TLS via Pangolin
- All other paths return 404
- No firewall changes needed
- No open ports required

Benefits over other approaches:
- No public IP needed
- Zero Trust security model
- Automatic DDoS protection
- Built-in load balancing
- Simple configuration

File: docs/WEBHOOK_PANGOLIN_SETUP.md
2026-01-24 17:18:27 -05:00
root
80d8d40f06 docs: add reverse proxy configuration guide for webhook endpoint
Since Pulse is not publicly accessible, added comprehensive guide for
exposing only the webhook endpoint to Autotask via reverse proxy.

Covers 4 approaches:
1. Nginx + Let's Encrypt (recommended for production)
2. Cloudflare Tunnel (easiest, no firewall changes)
3. Caddy (automatic HTTPS)
4. Traefik (for Docker users)

Each includes:
- Complete configuration examples
- Setup steps
- Security recommendations (rate limiting, IP whitelisting)
- Testing procedures
- Troubleshooting guides

Security features:
- Only /api/webhooks/autotask exposed
- SSL/TLS encryption required
- Rate limiting (100 req/min, burst 20)
- Optional IP whitelisting for Autotask
- All other paths return 404

File: docs/WEBHOOK_REVERSE_PROXY.md
2026-01-24 17:14:55 -05:00
root
1f83456199 feat: add webhook support for real-time Autotask updates
Implements comprehensive webhook infrastructure to receive and process
real-time entity updates from Autotask, reducing API calls and improving
data freshness.

Features:
- Webhook receiver endpoint: POST /api/webhooks/autotask
- Automatic entity mapping and upsert to PostgreSQL
- Event logging and tracking in webhook_logs table
- Duplicate event prevention via unique event_id
- Failed event tracking with error messages
- Statistics and monitoring APIs
- Support for 8 entity types: Companies, Tickets, Tasks, Projects,
  Time Entries, Contacts, Contracts, Configuration Items

Architecture:
- WebhookService: Core processing logic
- Database tables: webhook_logs, webhook_configs
- API endpoints: /autotask (receiver), /logs, /stats
- Automatic data mapping using existing entity-mapper

Benefits:
- Near real-time updates (<1 minute vs 24 hours)
- Reduced API usage (webhooks vs polling)
- Complements daily incremental sync for redundancy
- Automatic recovery from webhook failures

Files Added:
- lib/types/webhook.ts - TypeScript types and interfaces
- lib/services/webhook-service.ts - Webhook processing service
- app/api/webhooks/autotask/route.ts - Webhook receiver
- app/api/webhooks/logs/route.ts - Logs API
- app/api/webhooks/stats/route.ts - Statistics API
- migrations/004_webhook_support.sql - Database schema
- docs/WEBHOOK_SETUP.md - Complete setup guide (47 sections)
- docs/WEBHOOKS_README.md - Quick start guide

Next Steps:
1. Run database migration
2. Configure webhooks in Autotask
3. Test endpoint and monitor logs

See docs/WEBHOOK_SETUP.md for detailed setup instructions.
2026-01-24 10:07:20 -05:00
root
31c2d94a1b fix: skip soft deletes for ALL entities with filters applied
More robust fix based on user feedback: instead of hardcoding specific
entity types, now dynamically checks if ANY filters were applied during
the sync and skips soft deletes accordingly.

Previous approach (hardcoded):
- Maintained list of specific entities to skip
- Easy to miss new entities (like billing_items bug)
- Required manual updates when adding new filters

New approach (dynamic):
- Tracks whether params.filter has any values
- Applies to ALL entities with ANY filter type:
  * Date filters (tickets, tasks, time_entries, billing_items)
  * Status filters (contracts, projects)
  * Active filters (companies, resources, contacts, etc.)
- Future-proof: automatically handles new filtered entities

Logic:
- hasAppliedFilters = params.filter && params.filter.length > 0
- if (!isIncremental && !hasAppliedFilters) → perform soft deletes
- if (!isIncremental && hasAppliedFilters) → skip soft deletes

This prevents deleting records that exist outside any filter criteria,
not just date ranges.
2026-01-24 09:57:01 -05:00
root
5b7532ee59 fix: prevent incorrect soft deletes of billing items
CRITICAL BUG FIX: Billing items were being incorrectly soft-deleted during
full sync because BILLING_ITEMS was missing from the hasDateFilter check.

The Issue:
- Billing items have a date filter (itemDate >= now - yearsBack)
- Full sync with 90-day range fetched only recent billing items
- Soft delete logic saw 89,714 older items not in fetched set
- Incorrectly marked them as deleted (outside sync window)

The Fix:
- Added EntityType.BILLING_ITEMS to hasDateFilter check
- Now billing items skip soft deletes (like tickets, tasks, time entries)
- Prevents deletion of records outside the sync date range

Recovery:
- Restored all 89,714 incorrectly deleted billing items
- UPDATE billing_items SET is_deleted = false WHERE is_deleted = true

This is the same pattern used for tickets, tasks, and time entries which
also have date filters and skip soft deletes.
2026-01-24 09:53:45 -05:00
root
71873dfb3b fix: correct picklist sync statistics to properly track added vs updated
Previously, all picklist syncs (Statuses, Issue Types, Sub-Issue Types, Work Types)
incorrectly reported all records as 'added' even on subsequent syncs.

The issue was that bulkUpsert returns total rowCount without distinguishing
between inserts and updates.

Fix:
- Query existing values before upserting
- Calculate recordsAdded = new values not in existing set
- Calculate recordsUpdated = values already in existing set
- Applied to all 4 picklist sync methods

This resolves the confusing sync history where Sub-Issue Types showed
+805 on every sync instead of ~0 added, ~805 updated.
2026-01-24 08:47:52 -05:00
root
8b50cae71c docs: add comprehensive sync behavior documentation
Created detailed documentation covering:
- Sync types (Full, Incremental, Sync Selected)
- Date range filtering and entity-specific behaviors
- Database operations (UPSERT, soft deletes)
- Foreign key validation mechanisms
- Performance considerations and optimization tips
- Entity-specific filters and requirements
- Troubleshooting guide and best practices
- Workflow examples and API reference

This complements the existing SYNC_INTERFACE_GUIDE.md with
technical implementation details and behavioral specifications.
2026-01-24 08:43:35 -05:00
root
2f20b99195 fix: add resource foreign key validation for tasks
Tasks also reference resources via assigned_resource_id and other fields.
Added validation for all task resource foreign keys:
- assigned_resource_id
- creator_resource_id
- completed_by_resource_id
- last_activity_resource_id

This completes the fix for tasks foreign key constraint violations.
2026-01-24 08:13:18 -05:00