Implement IIT quality workflow hardening across eQuery deduplication, guard metadata validation, timeline/readability improvements, and chat evidence fallbacks, then synchronize release and development documentation for deployment handoff. Includes migration/scripts for open eQuery dedupe guards, orchestration/status semantics, report/tool readability fixes, and updated module status plus deployment checklist. Made-with: Cursor
98 lines
2.7 KiB
TypeScript
98 lines
2.7 KiB
TypeScript
import { PrismaClient } from '@prisma/client';
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
async function main() {
|
|
const projectId = process.argv[2];
|
|
if (!projectId) {
|
|
throw new Error('Usage: npx tsx scripts/analyze_missing_equery_context.ts <projectId>');
|
|
}
|
|
|
|
const reasonStats = await prisma.$queryRawUnsafe<Array<{ reason: string; cnt: bigint }>>(`
|
|
WITH missing AS (
|
|
SELECT
|
|
e.id,
|
|
e.record_id,
|
|
e.category,
|
|
e.field_name,
|
|
e.event_id,
|
|
e.form_name,
|
|
e.created_at
|
|
FROM iit_schema.equery e
|
|
WHERE e.project_id = $1
|
|
AND (COALESCE(e.event_id, '') = '' OR COALESCE(e.form_name, '') = '')
|
|
),
|
|
flags AS (
|
|
SELECT
|
|
m.*,
|
|
EXISTS (
|
|
SELECT 1
|
|
FROM iit_schema.qc_field_status fs
|
|
WHERE fs.project_id = $1
|
|
AND fs.record_id = m.record_id
|
|
) AS has_record_match,
|
|
EXISTS (
|
|
SELECT 1
|
|
FROM iit_schema.qc_field_status fs
|
|
WHERE fs.project_id = $1
|
|
AND fs.record_id = m.record_id
|
|
AND COALESCE(fs.rule_name, '') = COALESCE(m.category, '')
|
|
) AS has_rule_match,
|
|
EXISTS (
|
|
SELECT 1
|
|
FROM iit_schema.qc_field_status fs
|
|
WHERE fs.project_id = $1
|
|
AND fs.record_id = m.record_id
|
|
AND COALESCE(fs.rule_name, '') = COALESCE(m.category, '')
|
|
AND COALESCE(fs.field_name, '') = COALESCE(m.field_name, '')
|
|
) AS has_rule_field_match
|
|
FROM missing m
|
|
)
|
|
SELECT
|
|
CASE
|
|
WHEN has_rule_field_match THEN 'A_RULE_FIELD_MATCH_BUT_EVENT_FORM_EMPTY'
|
|
WHEN has_rule_match THEN 'B_RULE_MATCH_FIELD_MISMATCH'
|
|
WHEN has_record_match THEN 'C_RECORD_MATCH_ONLY'
|
|
ELSE 'D_NO_RECORD_MATCH'
|
|
END AS reason,
|
|
COUNT(*)::bigint AS cnt
|
|
FROM flags
|
|
GROUP BY 1
|
|
ORDER BY 2 DESC
|
|
`, projectId);
|
|
|
|
const sample = await prisma.$queryRawUnsafe<Array<{
|
|
id: string;
|
|
record_id: string;
|
|
category: string | null;
|
|
field_name: string | null;
|
|
event_id: string | null;
|
|
form_name: string | null;
|
|
created_at: Date;
|
|
}>>(`
|
|
SELECT
|
|
id, record_id, category, field_name, event_id, form_name, created_at
|
|
FROM iit_schema.equery
|
|
WHERE project_id = $1
|
|
AND (COALESCE(event_id, '') = '' OR COALESCE(form_name, '') = '')
|
|
ORDER BY created_at DESC
|
|
LIMIT 20
|
|
`, projectId);
|
|
|
|
console.log(JSON.stringify({
|
|
projectId,
|
|
reasonStats: reasonStats.map((r) => ({ reason: r.reason, cnt: Number(r.cnt) })),
|
|
sample,
|
|
}, null, 2));
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|
|
|