payroll-cutoff-bulk.sql 4.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. -- Parse legacy conflict payloads with the authoritative function's exception semantics.
  2. CREATE OR REPLACE FUNCTION xs_payroll_conflict_payload(value text) RETURNS jsonb LANGUAGE plpgsql IMMUTABLE AS $$
  3. BEGIN RETURN value::jsonb;EXCEPTION WHEN others THEN RETURN '{}'::jsonb;END $$;
  4. -- Fresh set-based conflict calculation; no result cache and no financial writes.
  5. CREATE OR REPLACE FUNCTION xs_payroll_cutoff_conflicts_bulk(co text,mon text) RETURNS SETOF jsonb
  6. LANGUAGE plpgsql STABLE SET jit=off SET work_mem='64MB' AS $$
  7. BEGIN
  8. IF NOT xs_payroll_read_snapshot_authority_ready() THEN RETURN QUERY SELECT s FROM xs_payroll_cutoff_conflicts(co,mon) s;RETURN;END IF;
  9. RETURN QUERY
  10. WITH latest AS MATERIALIZED (
  11. SELECT "runId" FROM "LegacyDirectRun" WHERE company=co AND status IN ('completed','completed-with-preserved-conflicts') ORDER BY "finishedAt" DESC LIMIT 1
  12. ), roots AS MATERIALIZED (
  13. SELECT f.*,c."modelId",c."itemId",c.title,c.subtitle,row_number() OVER(ORDER BY f."objectId") ord
  14. FROM "LegacySyncConflict" f LEFT JOIN "CommonModel" c ON c.company=f.company AND c."generalId"::text=f."legacyKey"
  15. AND c."modelId"=CASE f.dataset WHEN '54' THEN 54 WHEN '59' THEN 59 WHEN '60' THEN 60 END
  16. WHERE f.company=co AND f.dataset IN ('54','59','60') AND NOT COALESCE(f.resolved,false)
  17. ), joined AS MATERIALIZED (
  18. SELECT r.*,CASE r.dataset WHEN '54' THEN to_jsonb(a) WHEN '59' THEN to_jsonb(l) ELSE to_jsonb(m) END item,
  19. xs_payroll_conflict_payload(r.message) payload
  20. FROM roots r
  21. LEFT JOIN "CourseAppointment" a ON r.dataset='54' AND a.company=co AND a.id=r."itemId"
  22. LEFT JOIN "LessonRecord" l ON r.dataset='59' AND l.company=co AND l.id=r."itemId"
  23. LEFT JOIN "MemoryPracticeRecord" m ON r.dataset='60' AND m.company=co AND m.id=r."itemId"
  24. ), ambiguous AS MATERIALIZED (
  25. SELECT EXISTS(SELECT 1 FROM roots GROUP BY "objectId" HAVING count(*)>1)
  26. OR EXISTS(SELECT 1 FROM joined GROUP BY ord HAVING count(*)>1) value
  27. ), described AS MATERIALIZED (
  28. SELECT j.*,CASE dataset WHEN '54' THEN item->>'yysj' WHEN '59' THEN COALESCE(NULLIF(item->>'lessonAt',''),NULLIF(item->>'plpjsj','')) ELSE COALESCE(NULLIF(item->>'wcsj',''),NULLIF(item->>'kywrq','')) END dt,
  29. CASE WHEN jsonb_typeof(payload->'fields')='array' THEN payload->'fields' ELSE '[]'::jsonb END fields
  30. FROM joined j WHERE NOT (SELECT value FROM ambiguous)
  31. ), fingerprinted AS MATERIALIZED (
  32. SELECT d.*,md5(jsonb_build_array(message,item,title,subtitle,(SELECT "runId" FROM latest))::text) fingerprint,
  33. jsonb_array_length(fields)>0 AND NOT EXISTS(SELECT 1 FROM jsonb_array_elements_text(fields) f WHERE f NOT IN ('title','inputer')) cosmetic
  34. FROM described d
  35. WHERE xs_payroll_time(dt) IS NULL OR to_char(xs_payroll_time(dt) AT TIME ZONE 'Asia/Shanghai','YYYY-MM')<=mon
  36. ), results AS (SELECT r.ord,jsonb_build_object('id',r."objectId",'dataset',r.dataset,'legacyKey',r."legacyKey",'student',r.title,'course',r.subtitle,'date',r.dt,'fields',r.fields,'reason',r.payload->>'reason','current',r.item,'fingerprint',r.fingerprint,'cosmetic',r.cosmetic,
  37. 'resolved',r.cosmetic OR EXISTS(SELECT 1 FROM "PayrollCutoffDecision" d WHERE d.company=co AND d.month=mon AND d."conflictId"=r."objectId" AND d.fingerprint=r.fingerprint))
  38. AS value FROM fingerprinted r
  39. UNION ALL SELECT c.ord,c.value FROM ambiguous guard
  40. CROSS JOIN LATERAL xs_payroll_cutoff_conflicts(co,mon) WITH ORDINALITY c(value,ord) WHERE guard.value
  41. ) SELECT value FROM results ORDER BY ord;
  42. END $$;
  43. -- Exact text membership before numeric duplicate counting, without the redundant
  44. -- DISTINCT materialization or a per-ID nested lookup. Local settings affect only
  45. -- this one fresh evidence query, not source readers or financial commands.
  46. CREATE OR REPLACE FUNCTION xs_payroll_evidence_matches(co text,model numeric,ids jsonb) RETURNS integer
  47. LANGUAGE plpgsql STABLE SET jit=off SET work_mem='64MB' SET enable_mergejoin=off SET enable_nestloop=off AS $$
  48. DECLARE tab text; matches integer;
  49. BEGIN
  50. tab:=CASE model WHEN 54 THEN 'CourseAppointment' WHEN 59 THEN 'LessonRecord' WHEN 60 THEN 'MemoryPracticeRecord' END;
  51. IF tab IS NULL THEN RAISE EXCEPTION 'Unsupported evidence model';END IF;
  52. EXECUTE format('WITH local_rows AS MATERIALIZED (SELECT c."generalId" FROM "CommonModel" c JOIN %I a ON a.company=c.company AND a.id=c."itemId" WHERE c.company=$1 AND c."modelId"=$2) SELECT count(*)::int FROM (SELECT l."generalId" FROM local_rows l WHERE EXISTS(SELECT 1 FROM jsonb_array_elements_text($3) w WHERE w=l."generalId"::text) GROUP BY l."generalId" HAVING count(*)=1) x',tab) INTO matches USING co,model,ids;
  53. RETURN matches;
  54. END $$;