004_action_item_source_integrity.sql 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. CREATE OR REPLACE FUNCTION voc.validate_action_item_source_analysis()
  2. RETURNS trigger
  3. LANGUAGE plpgsql
  4. AS $$
  5. DECLARE
  6. source_result jsonb;
  7. matched_insight jsonb;
  8. allowed_evidence_ids jsonb;
  9. BEGIN
  10. IF NEW.source_analysis_id IS NULL THEN
  11. IF NEW.source_insight_id IS NOT NULL THEN
  12. RAISE EXCEPTION USING
  13. ERRCODE = '23514',
  14. MESSAGE = 'action source insight requires a source analysis';
  15. END IF;
  16. RETURN NEW;
  17. END IF;
  18. SELECT analysis.result
  19. INTO source_result
  20. FROM voc.analysis_run analysis
  21. WHERE analysis.id = NEW.source_analysis_id
  22. AND analysis.workspace_id = NEW.workspace_id
  23. AND analysis.analysis_type = 'voc_insight'
  24. AND analysis.status IN ('completed', 'partial');
  25. IF NOT FOUND THEN
  26. RAISE EXCEPTION USING
  27. ERRCODE = '23514',
  28. MESSAGE = 'action source analysis must be a completed or partial voc_insight run in the same workspace';
  29. END IF;
  30. IF NEW.source_insight_id IS NULL OR btrim(NEW.source_insight_id) = '' THEN
  31. RAISE EXCEPTION USING
  32. ERRCODE = '23514',
  33. MESSAGE = 'action source insight is required';
  34. END IF;
  35. SELECT insight.value
  36. INTO matched_insight
  37. FROM jsonb_array_elements(
  38. CASE
  39. WHEN jsonb_typeof(source_result -> 'insights') = 'array' THEN source_result -> 'insights'
  40. ELSE '[]'::jsonb
  41. END
  42. ) AS insight(value)
  43. WHERE insight.value ->> 'id' = NEW.source_insight_id
  44. LIMIT 1;
  45. IF matched_insight IS NULL THEN
  46. RAISE EXCEPTION USING
  47. ERRCODE = '23514',
  48. MESSAGE = 'action source insight does not exist in the source analysis result';
  49. END IF;
  50. IF jsonb_typeof(NEW.evidence_ids) IS DISTINCT FROM 'array' THEN
  51. RAISE EXCEPTION USING
  52. ERRCODE = '23514',
  53. MESSAGE = 'action source evidence must be an array';
  54. END IF;
  55. IF jsonb_array_length(NEW.evidence_ids) = 0 THEN
  56. RAISE EXCEPTION USING
  57. ERRCODE = '23514',
  58. MESSAGE = 'action source evidence is required';
  59. END IF;
  60. IF EXISTS (
  61. SELECT 1
  62. FROM jsonb_array_elements(NEW.evidence_ids) AS submitted(value)
  63. WHERE jsonb_typeof(submitted.value) <> 'string'
  64. ) THEN
  65. RAISE EXCEPTION USING
  66. ERRCODE = '23514',
  67. MESSAGE = 'action source evidence IDs must be strings';
  68. END IF;
  69. allowed_evidence_ids := CASE
  70. WHEN jsonb_typeof(matched_insight -> 'evidenceIds') = 'array' THEN matched_insight -> 'evidenceIds'
  71. ELSE '[]'::jsonb
  72. END;
  73. IF EXISTS (
  74. SELECT 1
  75. FROM jsonb_array_elements_text(NEW.evidence_ids) AS submitted(id)
  76. WHERE NOT EXISTS (
  77. SELECT 1
  78. FROM jsonb_array_elements(allowed_evidence_ids) AS allowed(value)
  79. WHERE jsonb_typeof(allowed.value) = 'string'
  80. AND allowed.value = to_jsonb(submitted.id)
  81. )
  82. ) THEN
  83. RAISE EXCEPTION USING
  84. ERRCODE = '23514',
  85. MESSAGE = 'action source evidence must belong to the selected insight';
  86. END IF;
  87. RETURN NEW;
  88. END;
  89. $$;
  90. DROP TRIGGER IF EXISTS action_item_source_analysis_guard ON voc.action_item;
  91. CREATE TRIGGER action_item_source_analysis_guard
  92. BEFORE INSERT OR UPDATE OF source_analysis_id, source_insight_id, evidence_ids, workspace_id ON voc.action_item
  93. FOR EACH ROW
  94. EXECUTE FUNCTION voc.validate_action_item_source_analysis();