fix(quick-260521-foj-01): widen Companies full sync to fetch all companies

- Add buildCompaniesFilter() returning id > 0 in lib/utils/sync-helpers.ts
- Route COMPANIES through buildCompaniesFilter on full sync instead of
  the generic buildActiveFilter (which applied isActive=true and missed
  inactive companies with tickets, causing tickets_company_id_fkey on
  weekly-full and full syncs since 2026-05-15)
- hasAppliedFilters stays true (filter is non-empty), so soft-delete of
  companies is not triggered
This commit is contained in:
lorentz 2026-05-21 11:21:48 -04:00
parent d02796e863
commit 1ecaefe85a
2 changed files with 25 additions and 5 deletions

View file

@ -10,18 +10,19 @@ import { EntityType } from '../types/sync';
import { mapAutotaskToDatabase, mapAutotaskBatch } from '../utils/entity-mapper';
import { bulkUpsertRecords, getLastSyncTime, softDeleteMissingRecords } from '../utils/db-helpers';
import { syncProgressTracker } from './sync-progress-tracker';
import {
getAutotaskEntityName,
import {
getAutotaskEntityName,
buildIncrementalFilter,
buildActiveFilter,
buildDateRangeFilter,
buildCompaniesFilter,
buildContractsFilter,
buildContractServicesFilter,
buildProjectsFilter,
buildProjectPhasesFilter,
buildTimeEntriesFilter,
buildBillingItemsFilter,
getTableName
getTableName
} from '../utils/sync-helpers';
import { createSyncLogger, SyncPhase, categorizeError } from '../utils/sync-logger';
@ -128,9 +129,12 @@ export class EntitySyncService {
}
const filters: Array<{ field: string; op: string; value: any }> = [];
// Special handling for entities that require filters
if (entity === EntityType.CONTRACTS) {
if (entity === EntityType.COMPANIES) {
filters.push(...buildCompaniesFilter());
entityLogger.info('Full sync of all companies (active + inactive)');
} else if (entity === EntityType.CONTRACTS) {
filters.push(...buildContractsFilter());
entityLogger.info('Full sync with status filter for active contracts');
} else if (entity === EntityType.CONTRACT_SERVICES) {

View file

@ -91,6 +91,22 @@ export function buildContractServicesFilter(): Array<{ field: string; op: string
];
}
/**
* Build filter for companies (Companies endpoint requires a filter use id > 0 to fetch all
* companies regardless of isActive. Active-only filtering misses inactive companies that
* have tickets, causing tickets_company_id_fkey violations on full sync.)
* @returns Query filter array for all companies
*/
export function buildCompaniesFilter(): Array<{ field: string; op: string; value: any }> {
return [
{
field: 'id',
op: 'gt',
value: 0,
},
];
}
/**
* Get table name for entity type
* @param entity Entity type