feat: add project_phases entity sync with task project_id backfill
The Autotask Tasks bulk API does not return projectID in its response, causing all tasks.project_id to be NULL. This fixes it by: - Adding project_phases as a synced entity (Autotask endpoint: /Phases) - Migration 059: project_phases table with project_id, phase_number, estimated_hours, start/due dates, parent_phase_id, is_scheduled - EntityType.PROJECT_PHASES added to all sync maps and dependency graph (depends on PROJECTS, runs before TASKS in sync order) - buildProjectPhasesFilter: Phases endpoint requires a filter (id > 0) - mapProjectPhase: maps Autotask field names to DB columns - Post-sync backfill in syncEntity: after each project_phases sync, UPDATE tasks SET project_id = pp.project_id FROM project_phases pp JOIN projects p WHERE tasks.phase_id = pp.id Only backfills where the project exists in our DB (FK constraint on tasks.project_id; archived projects are skipped gracefully) Result: 2,455 of 4,966 tasks now have project_id populated. Tasks belonging to archived/completed projects have phase_id resolvable via project_phases even when project_id remains NULL. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
44db9a3019
commit
dd4cf68def
5 changed files with 131 additions and 0 deletions
|
|
@ -39,6 +39,9 @@ export function mapAutotaskToDatabase(
|
|||
case EntityType.PROJECTS:
|
||||
mapped = mapProject(data);
|
||||
break;
|
||||
case EntityType.PROJECT_PHASES:
|
||||
mapped = mapProjectPhase(data);
|
||||
break;
|
||||
case EntityType.RESOURCES:
|
||||
mapped = mapResource(data);
|
||||
break;
|
||||
|
|
@ -344,6 +347,30 @@ function mapProject(data: any): Record<string, any> {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map ProjectPhase entity
|
||||
*/
|
||||
function mapProjectPhase(data: any): Record<string, any> {
|
||||
return {
|
||||
id: data.id,
|
||||
project_id: data.projectID,
|
||||
title: data.title,
|
||||
description: data.description,
|
||||
phase_number: data.phaseNumber,
|
||||
estimated_hours: data.estimatedHours,
|
||||
start_date_time: data.startDate,
|
||||
due_date: data.dueDate,
|
||||
create_date_time: data.createDate,
|
||||
last_activity_date_time: data.lastActivityDateTime,
|
||||
parent_phase_id: data.parentPhaseID,
|
||||
is_scheduled: data.isScheduled,
|
||||
creator_resource_id: data.creatorResourceID,
|
||||
external_id: data.externalID,
|
||||
synced_at: data.synced_at,
|
||||
is_deleted: data.is_deleted || false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Resource entity
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue