fix(quick-260521-foj-02): defensively nullify ticket company_id for missing companies
- Add getValidCompanyIds() helper mirroring getValidResourceIds() - Add a new TICKETS validation block that nullifies ticket.company_id when the referenced company is not present (is_deleted=false) in the Pulse mirror, instead of letting tickets_company_id_fkey roll back the bulkUpsert transaction - Block runs after the existing recordsWithoutCompany filter and before the existing resource-FK nullification block (correct ordering) - Belt-and-suspenders on top of Task 1: covers hard-deleted-in-Autotask companies that Task 1's widening still won't fetch
This commit is contained in:
parent
1ecaefe85a
commit
62c529fb91
1 changed files with 37 additions and 1 deletions
|
|
@ -255,10 +255,35 @@ export class EntitySyncService {
|
|||
}
|
||||
}
|
||||
|
||||
// Validate company_id foreign keys for tickets (defensive — Task 1 widening
|
||||
// the Companies filter should make this a near-zero count, but catches the
|
||||
// truly hard-deleted Autotask company case).
|
||||
if (entity === EntityType.TICKETS) {
|
||||
const validCompanyIds = await this.getValidCompanyIds();
|
||||
let nullifiedCompanyCount = 0;
|
||||
const nullifiedCompanySamples: number[] = [];
|
||||
mappedRecords = mappedRecords.map(ticket => {
|
||||
if (ticket.company_id && !validCompanyIds.has(ticket.company_id)) {
|
||||
if (nullifiedCompanySamples.length < 5) {
|
||||
nullifiedCompanySamples.push(ticket.id);
|
||||
}
|
||||
ticket.company_id = null;
|
||||
nullifiedCompanyCount++;
|
||||
}
|
||||
return ticket;
|
||||
});
|
||||
if (nullifiedCompanyCount > 0) {
|
||||
entityLogger.warn('Nullified ticket company_id for companies missing from mirror', {
|
||||
nullifiedCount: nullifiedCompanyCount,
|
||||
sampleTicketIds: nullifiedCompanySamples,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Validate resource foreign keys for tickets
|
||||
if (entity === EntityType.TICKETS) {
|
||||
const initialCount = mappedRecords.length;
|
||||
|
||||
|
||||
// Get all valid resource IDs from database
|
||||
const validResourceIds = await this.getValidResourceIds();
|
||||
|
||||
|
|
@ -721,6 +746,17 @@ export class EntitySyncService {
|
|||
return new Set(result.rows.map(row => Number(row.id)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all valid company IDs from the database
|
||||
* Used to validate foreign key references before insert
|
||||
* @returns Set of valid company IDs
|
||||
*/
|
||||
private async getValidCompanyIds(): Promise<Set<number>> {
|
||||
const query = 'SELECT id FROM companies WHERE is_deleted = false';
|
||||
const result = await postgresClient.query<{ id: number }>(query);
|
||||
return new Set(result.rows.map(row => Number(row.id)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to validate foreign key references before insert
|
||||
* @returns Set of valid contact IDs
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue