Health probe: dump all relationships for a given contact, flag direction issues
This commit is contained in:
@@ -286,6 +286,72 @@ async function probeChecksumWithSampleContact(): Promise<CheckResult> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function probeContactRelationships(cid: string): Promise<CheckResult> {
|
||||||
|
// Dumps every active relationship involving this contact, regardless of
|
||||||
|
// direction. Useful when /api/data returns 404 — tells you whether the
|
||||||
|
// relationship exists at all and which side this contact is on.
|
||||||
|
try {
|
||||||
|
const res = await civi<{
|
||||||
|
id: number;
|
||||||
|
contact_id_a: number;
|
||||||
|
contact_id_b: number;
|
||||||
|
"relationship_type_id:name_a_b": string;
|
||||||
|
"relationship_type_id:name_b_a": string;
|
||||||
|
is_active: boolean;
|
||||||
|
}>("Relationship", "get", {
|
||||||
|
select: [
|
||||||
|
"id",
|
||||||
|
"contact_id_a",
|
||||||
|
"contact_id_b",
|
||||||
|
"relationship_type_id:name_a_b",
|
||||||
|
"relationship_type_id:name_b_a",
|
||||||
|
"is_active",
|
||||||
|
],
|
||||||
|
where: [
|
||||||
|
["OR", [["contact_id_a", "=", Number(cid)], ["contact_id_b", "=", Number(cid)]]],
|
||||||
|
["is_active", "=", true],
|
||||||
|
],
|
||||||
|
limit: 50,
|
||||||
|
});
|
||||||
|
const rows = res.values ?? [];
|
||||||
|
if (rows.length === 0) {
|
||||||
|
return {
|
||||||
|
check: "contact_relationships_dump",
|
||||||
|
ok: false,
|
||||||
|
detail: `Contact ${cid} has no active relationships at all. Add a relationship of type "${FORM_CONTACT_RELATIONSHIP}" with this contact on side A (Individual) and the target Organization on side B.`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const lines = rows.map((r) => {
|
||||||
|
const sideA = String(r.contact_id_a) === cid ? "★A" : "·A";
|
||||||
|
const sideB = String(r.contact_id_b) === cid ? "★B" : "·B";
|
||||||
|
return ` ${sideA}=${r.contact_id_a} ${sideB}=${r.contact_id_b} type="${r["relationship_type_id:name_a_b"]}" / inverse="${r["relationship_type_id:name_b_a"]}"`;
|
||||||
|
});
|
||||||
|
const usable = rows.find(
|
||||||
|
(r) =>
|
||||||
|
String(r.contact_id_a) === cid &&
|
||||||
|
r["relationship_type_id:name_a_b"] === FORM_CONTACT_RELATIONSHIP,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
check: "contact_relationships_dump",
|
||||||
|
ok: Boolean(usable),
|
||||||
|
detail:
|
||||||
|
`Active relationships involving contact ${cid} (★ marks the side this contact is on):\n` +
|
||||||
|
lines.join("\n") +
|
||||||
|
"\n\n" +
|
||||||
|
(usable
|
||||||
|
? `✓ Found a usable "${FORM_CONTACT_RELATIONSHIP}" with contact ${cid} on side A (id=${usable.id}, org=${usable.contact_id_b}).`
|
||||||
|
: `✗ No relationship matches: type="${FORM_CONTACT_RELATIONSHIP}" with contact ${cid} on side A. ` +
|
||||||
|
`If you see the right relationship above with contact ${cid} on side B, the relationship is stored backwards — delete and re-add with the Individual chosen first, OR change FORM_CONTACT_RELATIONSHIP in config/form.ts to the inverse name (name_b_a).`),
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
check: "contact_relationships_dump",
|
||||||
|
ok: false,
|
||||||
|
detail: e instanceof Error ? e.message : String(e),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function GET(req: Request) {
|
export async function GET(req: Request) {
|
||||||
const env = envSummary();
|
const env = envSummary();
|
||||||
const summary = { mode: env.ok ? "live" : "stub" };
|
const summary = { mode: env.ok ? "live" : "stub" };
|
||||||
@@ -323,7 +389,11 @@ export async function GET(req: Request) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a sample cid+cs was provided, verify that specific checksum.
|
// If a sample cid+cs was provided, verify that specific checksum + dump
|
||||||
|
// the contact's relationships.
|
||||||
|
if (cid) {
|
||||||
|
checks.push(await probeContactRelationships(cid));
|
||||||
|
}
|
||||||
if (cid && cs) {
|
if (cid && cs) {
|
||||||
try {
|
try {
|
||||||
const ok = await verifyChecksum(cid, cs);
|
const ok = await verifyChecksum(cid, cs);
|
||||||
@@ -341,7 +411,7 @@ export async function GET(req: Request) {
|
|||||||
detail: e instanceof Error ? e.message : String(e),
|
detail: e instanceof Error ? e.message : String(e),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!cid) {
|
||||||
checks.push(await probeChecksumWithSampleContact());
|
checks.push(await probeChecksumWithSampleContact());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user