@fayz-ai/plugin-forms 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +3 -3
  2. package/dist/{FormBuilder-7SWZQKFN.js → FormBuilder-JCNHXQXT.js} +4 -4
  3. package/dist/{FormBuilder-7SWZQKFN.js.map → FormBuilder-JCNHXQXT.js.map} +1 -1
  4. package/dist/{chunk-W2ZNJGQC.js → chunk-JCAWSDX6.js} +3 -3
  5. package/dist/chunk-JCAWSDX6.js.map +1 -0
  6. package/dist/components/AddDocumentDropdown.d.ts +1 -1
  7. package/dist/components/AddDocumentDropdown.d.ts.map +1 -1
  8. package/dist/{CustomFormsContext.d.ts → context.d.ts} +1 -1
  9. package/dist/context.d.ts.map +1 -0
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +4 -4
  13. package/dist/index.js.map +1 -1
  14. package/dist/lib/agent-tools.d.ts.map +1 -0
  15. package/dist/lib/document-types.d.ts.map +1 -0
  16. package/package.json +5 -7
  17. package/dist/CustomFormsContext.d.ts.map +0 -1
  18. package/dist/agent-tools.d.ts.map +0 -1
  19. package/dist/chunk-W2ZNJGQC.js.map +0 -1
  20. package/dist/document-types.d.ts.map +0 -1
  21. package/src/CustomFormsContext.tsx +0 -28
  22. package/src/agent-tools.ts +0 -73
  23. package/src/components/AddDocumentDropdown.tsx +0 -92
  24. package/src/components/BuilderCanvas.tsx +0 -87
  25. package/src/components/BuilderField.tsx +0 -81
  26. package/src/components/DocumentFormDialog.tsx +0 -155
  27. package/src/components/DocumentList.tsx +0 -254
  28. package/src/components/FieldConfigDialog.tsx +0 -243
  29. package/src/components/FieldPalette.tsx +0 -81
  30. package/src/components/FormBuilder.tsx +0 -427
  31. package/src/components/FormRenderer.tsx +0 -256
  32. package/src/components/FormViewer.tsx +0 -94
  33. package/src/components/PersonDocumentsWidget.tsx +0 -229
  34. package/src/components/TemplateSelector.tsx +0 -91
  35. package/src/config.ts +0 -43
  36. package/src/data/index.ts +0 -3
  37. package/src/data/mock.ts +0 -193
  38. package/src/data/supabase.ts +0 -408
  39. package/src/data/tables.ts +0 -7
  40. package/src/data/types.ts +0 -33
  41. package/src/document-types.ts +0 -51
  42. package/src/index.ts +0 -234
  43. package/src/lib/person-fields.ts +0 -67
  44. package/src/lib/print.ts +0 -207
  45. package/src/lib/tenant.ts +0 -9
  46. package/src/locales/en.ts +0 -95
  47. package/src/locales/index.ts +0 -7
  48. package/src/locales/pt-BR.ts +0 -95
  49. package/src/migrations/000_plg_rename.sql +0 -21
  50. package/src/migrations/001_frm_base.sql +0 -174
  51. package/src/migrations/002_document_archetype.sql +0 -223
  52. package/src/migrations/003_agent_rpcs.sql +0 -174
  53. package/src/migrations/index.ts +0 -610
  54. package/src/store.ts +0 -167
  55. package/src/types.ts +0 -217
  56. package/src/views/CustomFormsSettingsTab.tsx +0 -105
  57. package/src/views/TemplateListView.tsx +0 -174
  58. /package/dist/{agent-tools.d.ts → lib/agent-tools.d.ts} +0 -0
  59. /package/dist/{document-types.d.ts → lib/document-types.d.ts} +0 -0
@@ -1,95 +0,0 @@
1
- export const ptBR: Record<string, string> = {
2
- // Settings
3
- 'customForms.settingsTitle': 'Formulários e Documentos',
4
- 'customForms.settingsSubtitle': 'Crie e gerencie formulários personalizados para o seu negócio',
5
-
6
- // Templates
7
- 'customForms.templates': 'Modelos',
8
- 'customForms.newTemplate': 'Novo Modelo',
9
- 'customForms.editTemplate': 'Editar Modelo',
10
- 'customForms.templateName': 'Nome do formulário',
11
- 'customForms.templateDescription': 'Descrição',
12
- 'customForms.templateCategory': 'Categoria',
13
- 'customForms.templateSpecialty': 'Especialidade',
14
- 'customForms.noTemplates': 'Nenhum modelo criado',
15
- 'customForms.noTemplatesDescription': 'Crie seu primeiro formulário personalizado para começar a coletar dados estruturados.',
16
- 'customForms.deleteTemplateConfirm': 'Excluir este modelo de formulário? Documentos existentes serão preservados.',
17
- 'customForms.archiveTemplateConfirm': 'Arquivar este modelo? Ele sai da lista e do seletor de documentos, mas fica guardado e os documentos existentes são preservados.',
18
-
19
- // Categories
20
- 'customForms.category.anamnesis': 'Anamnese',
21
- 'customForms.category.evolution': 'Evolução',
22
- 'customForms.category.report': 'Laudo',
23
- 'customForms.category.contract': 'Contrato',
24
- 'customForms.category.general': 'Geral',
25
-
26
- // Builder
27
- 'customForms.builder.fields': 'Campos',
28
- 'customForms.builder.fieldCount': '{{count}} campos',
29
- 'customForms.builder.settings': 'Configurações',
30
- 'customForms.builder.save': 'Salvar',
31
- 'customForms.builder.saving': 'Salvando...',
32
- 'customForms.builder.saved': 'Formulário salvo',
33
- 'customForms.builder.emptyCanvas': 'Arraste os campos do painel esquerdo para começar a montar seu formulário',
34
- 'customForms.builder.fieldLabel': 'Rótulo do campo',
35
- 'customForms.builder.fieldPlaceholder': 'Placeholder',
36
- 'customForms.builder.fieldRequired': 'Obrigatório',
37
- 'customForms.builder.fieldOptions': 'Opções',
38
- 'customForms.builder.addOption': 'Adicionar opção',
39
- 'customForms.builder.colSpan': 'Largura em colunas',
40
- 'customForms.builder.deleteField': 'Remover campo',
41
- 'customForms.builder.mapToPerson': 'Preencher com dado da ficha',
42
- 'customForms.builder.mapNone': 'Não preencher',
43
- 'customForms.builder.mapHint': 'Ao criar o documento na ficha da pessoa, este campo já vem preenchido com o dado escolhido (editável).',
44
- 'customForms.preview.editor': 'Editor',
45
- 'customForms.preview.print': 'Impressão',
46
-
47
- // Person field mappings (auto-fill)
48
- 'customForms.personField.name': 'Nome',
49
- 'customForms.personField.documentNumber': 'CPF / Documento',
50
- 'customForms.personField.email': 'E-mail',
51
- 'customForms.personField.phone': 'Telefone',
52
- 'customForms.personField.dateOfBirth': 'Data de Nascimento',
53
- 'customForms.personField.guardianName': 'Responsável',
54
- 'customForms.personField.address': 'Endereço',
55
- 'customForms.personField.city': 'Cidade',
56
- 'customForms.personField.state': 'Estado',
57
-
58
- // Field types
59
- 'customForms.fieldType.title': 'Título',
60
- 'customForms.fieldType.text': 'Texto Simples',
61
- 'customForms.fieldType.memo': 'Memorando',
62
- 'customForms.fieldType.richtext': 'Texto Rico',
63
- 'customForms.fieldType.date': 'Data',
64
- 'customForms.fieldType.select': 'Seleção',
65
- 'customForms.fieldType.radio': 'Radio',
66
- 'customForms.fieldType.tags': 'Tags',
67
- 'customForms.fieldType.checkbox': 'Checkbox',
68
- 'customForms.fieldType.image': 'Imagem / Desenho',
69
- 'customForms.fieldType.gallery': 'Galeria',
70
- 'customForms.fieldType.budget': 'Orçamento',
71
-
72
- // Documents
73
- 'customForms.documents': 'Documentos',
74
- 'customForms.addDocument': 'Novo Documento',
75
- 'customForms.selectTemplate': 'Selecione um formulário',
76
- 'customForms.noDocuments': 'Nenhum documento',
77
- 'customForms.noDocumentsDescription': 'Adicione um documento para começar a registrar informações.',
78
- 'customForms.documentTitle': 'Título do documento',
79
- 'customForms.saveAsDraft': 'Salvar Rascunho',
80
- 'customForms.saveAndComplete': 'Salvar e Finalizar',
81
- 'customForms.deleteDocumentConfirm': 'Excluir este documento?',
82
- 'customForms.archive': 'Arquivar',
83
- 'customForms.archiveDocumentConfirm': 'Arquivar este documento? Ele sai da lista ativa mas fica guardado.',
84
- 'customForms.printPdf': 'Imprimir / PDF',
85
-
86
- // Registry
87
- 'registry.form-categories': 'Categorias',
88
- 'registry.form-categories.description': 'Categorias para organizar modelos de formulários',
89
-
90
- // Status
91
- 'customForms.status.draft': 'Rascunho',
92
- 'customForms.status.completed': 'Finalizado',
93
- 'customForms.status.signed': 'Assinado',
94
- 'customForms.status.archived': 'Arquivado',
95
- }
@@ -1,21 +0,0 @@
1
- -- 000_plg_rename.sql — rename legacy forms tables to plg_forms_* for pools
2
- -- provisioned before the industry-pool rename. Guarded: fires only when the legacy
3
- -- name exists and the target does not, so fresh pools skip every branch.
4
- -- The core `documents` archetype table is NOT renamed — it stays public.documents.
5
- DO $$
6
- BEGIN
7
- IF to_regclass('public.frm_documents') IS NOT NULL AND to_regclass('public.plg_forms_documents') IS NULL THEN
8
- ALTER TABLE public.frm_documents RENAME TO plg_forms_documents;
9
- END IF;
10
- IF to_regclass('public.frm_templates') IS NOT NULL AND to_regclass('public.plg_forms_templates') IS NULL THEN
11
- ALTER TABLE public.frm_templates RENAME TO plg_forms_templates;
12
- END IF;
13
- IF to_regclass('public.frm_document_files') IS NOT NULL AND to_regclass('public.plg_forms_document_files') IS NULL THEN
14
- ALTER TABLE public.frm_document_files RENAME TO plg_forms_document_files;
15
- END IF;
16
- -- frm_categories: registry-declared (form-template categories); no base-table
17
- -- DDL ships in this plugin, but rename in place if a pool created one.
18
- IF to_regclass('public.frm_categories') IS NOT NULL AND to_regclass('public.plg_forms_categories') IS NULL THEN
19
- ALTER TABLE public.frm_categories RENAME TO plg_forms_categories;
20
- END IF;
21
- END $$;
@@ -1,174 +0,0 @@
1
- -- ============================================================
2
- -- Custom Forms Plugin — Base Tables
3
- -- ============================================================
4
-
5
- -- plg_forms_templates: form template definitions (versioned)
6
- CREATE TABLE IF NOT EXISTS public.plg_forms_templates (
7
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
8
- tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
9
- name text NOT NULL,
10
- description text,
11
- category text NOT NULL DEFAULT 'general',
12
- version integer NOT NULL DEFAULT 1,
13
- is_current boolean NOT NULL DEFAULT true,
14
- parent_id uuid REFERENCES public.plg_forms_templates(id),
15
- schema jsonb NOT NULL DEFAULT '{"fields":[],"layout":{"columns":12}}',
16
- specialty text,
17
- tags text[] DEFAULT '{}',
18
- metadata jsonb DEFAULT '{}',
19
- is_active boolean NOT NULL DEFAULT true,
20
- is_deleted boolean NOT NULL DEFAULT false,
21
- created_by uuid,
22
- updated_by uuid,
23
- created_at timestamptz NOT NULL DEFAULT now(),
24
- updated_at timestamptz NOT NULL DEFAULT now()
25
- );
26
-
27
- ALTER TABLE public.plg_forms_templates ENABLE ROW LEVEL SECURITY;
28
-
29
- CREATE INDEX IF NOT EXISTS idx_plg_forms_templates_tenant
30
- ON public.plg_forms_templates(tenant_id);
31
- CREATE INDEX IF NOT EXISTS idx_plg_forms_templates_parent
32
- ON public.plg_forms_templates(parent_id);
33
- CREATE INDEX IF NOT EXISTS idx_plg_forms_templates_category
34
- ON public.plg_forms_templates(tenant_id, category);
35
- CREATE INDEX IF NOT EXISTS idx_plg_forms_templates_current
36
- ON public.plg_forms_templates(tenant_id, is_current, is_active)
37
- WHERE is_current = true AND is_active = true AND is_deleted = false;
38
-
39
- DROP POLICY IF EXISTS "plg_forms_templates_select" ON public.plg_forms_templates;
40
- CREATE POLICY "plg_forms_templates_select" ON public.plg_forms_templates
41
- FOR SELECT TO authenticated
42
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
43
- DROP POLICY IF EXISTS "plg_forms_templates_insert" ON public.plg_forms_templates;
44
- CREATE POLICY "plg_forms_templates_insert" ON public.plg_forms_templates
45
- FOR INSERT TO authenticated
46
- WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
47
- DROP POLICY IF EXISTS "plg_forms_templates_update" ON public.plg_forms_templates;
48
- CREATE POLICY "plg_forms_templates_update" ON public.plg_forms_templates
49
- FOR UPDATE TO authenticated
50
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
51
- DROP POLICY IF EXISTS "plg_forms_templates_delete" ON public.plg_forms_templates;
52
- CREATE POLICY "plg_forms_templates_delete" ON public.plg_forms_templates
53
- FOR DELETE TO authenticated
54
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
55
-
56
- -- plg_forms_documents: filled form instances
57
- CREATE TABLE IF NOT EXISTS public.plg_forms_documents (
58
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
59
- tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
60
- template_id uuid NOT NULL REFERENCES public.plg_forms_templates(id),
61
- person_id uuid REFERENCES public.people(id) ON DELETE SET NULL,
62
- title text,
63
- data jsonb NOT NULL DEFAULT '{}',
64
- status text NOT NULL DEFAULT 'draft',
65
- signed_at timestamptz,
66
- signed_by uuid,
67
- notes text,
68
- metadata jsonb DEFAULT '{}',
69
- is_deleted boolean NOT NULL DEFAULT false,
70
- created_by uuid,
71
- updated_by uuid,
72
- created_at timestamptz NOT NULL DEFAULT now(),
73
- updated_at timestamptz NOT NULL DEFAULT now()
74
- );
75
-
76
- ALTER TABLE public.plg_forms_documents ENABLE ROW LEVEL SECURITY;
77
-
78
- CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_tenant
79
- ON public.plg_forms_documents(tenant_id);
80
- -- person_id/status only exist in the pre-archetype shape this file creates;
81
- -- converted pools (salon) already carry the archetype extension shape
82
- -- (document_id PK, no person_id) — 002 owns that shape, so guard these.
83
- DO $$
84
- BEGIN
85
- IF EXISTS (
86
- SELECT 1 FROM information_schema.columns
87
- WHERE table_schema = 'public' AND table_name = 'plg_forms_documents'
88
- AND column_name = 'person_id'
89
- ) THEN
90
- EXECUTE 'CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_person
91
- ON public.plg_forms_documents(person_id)';
92
- EXECUTE 'CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_status
93
- ON public.plg_forms_documents(tenant_id, status)';
94
- END IF;
95
- END $$;
96
- CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_template
97
- ON public.plg_forms_documents(template_id);
98
-
99
- DROP POLICY IF EXISTS "plg_forms_documents_select" ON public.plg_forms_documents;
100
- CREATE POLICY "plg_forms_documents_select" ON public.plg_forms_documents
101
- FOR SELECT TO authenticated
102
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
103
- DROP POLICY IF EXISTS "plg_forms_documents_insert" ON public.plg_forms_documents;
104
- CREATE POLICY "plg_forms_documents_insert" ON public.plg_forms_documents
105
- FOR INSERT TO authenticated
106
- WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
107
- DROP POLICY IF EXISTS "plg_forms_documents_update" ON public.plg_forms_documents;
108
- CREATE POLICY "plg_forms_documents_update" ON public.plg_forms_documents
109
- FOR UPDATE TO authenticated
110
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
111
- DROP POLICY IF EXISTS "plg_forms_documents_delete" ON public.plg_forms_documents;
112
- CREATE POLICY "plg_forms_documents_delete" ON public.plg_forms_documents
113
- FOR DELETE TO authenticated
114
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
115
-
116
- -- plg_forms_document_files: file attachments for image/gallery/drawing fields
117
- CREATE TABLE IF NOT EXISTS public.plg_forms_document_files (
118
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
119
- tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
120
- document_id uuid NOT NULL REFERENCES public.plg_forms_documents(id) ON DELETE CASCADE,
121
- field_key text NOT NULL,
122
- file_url text NOT NULL,
123
- file_name text,
124
- file_size integer,
125
- mime_type text,
126
- sort_order integer DEFAULT 0,
127
- metadata jsonb DEFAULT '{}',
128
- created_at timestamptz NOT NULL DEFAULT now()
129
- );
130
-
131
- ALTER TABLE public.plg_forms_document_files ENABLE ROW LEVEL SECURITY;
132
-
133
- CREATE INDEX IF NOT EXISTS idx_plg_forms_document_files_document
134
- ON public.plg_forms_document_files(document_id);
135
-
136
- DROP POLICY IF EXISTS "plg_forms_document_files_select" ON public.plg_forms_document_files;
137
- CREATE POLICY "plg_forms_document_files_select" ON public.plg_forms_document_files
138
- FOR SELECT TO authenticated
139
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
140
- DROP POLICY IF EXISTS "plg_forms_document_files_insert" ON public.plg_forms_document_files;
141
- CREATE POLICY "plg_forms_document_files_insert" ON public.plg_forms_document_files
142
- FOR INSERT TO authenticated
143
- WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
144
- DROP POLICY IF EXISTS "plg_forms_document_files_update" ON public.plg_forms_document_files;
145
- CREATE POLICY "plg_forms_document_files_update" ON public.plg_forms_document_files
146
- FOR UPDATE TO authenticated
147
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
148
- DROP POLICY IF EXISTS "plg_forms_document_files_delete" ON public.plg_forms_document_files;
149
- CREATE POLICY "plg_forms_document_files_delete" ON public.plg_forms_document_files
150
- FOR DELETE TO authenticated
151
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
152
-
153
- -- View: pre-archetype read model (needs person_id; archetype pools get
154
- -- v_documents from 002 instead, which also drops this view when migrating).
155
- DO $$
156
- BEGIN
157
- IF EXISTS (
158
- SELECT 1 FROM information_schema.columns
159
- WHERE table_schema = 'public' AND table_name = 'plg_forms_documents'
160
- AND column_name = 'person_id'
161
- ) THEN
162
- EXECUTE $v$
163
- CREATE OR REPLACE VIEW public.v_frm_documents AS
164
- SELECT
165
- d.*,
166
- t.name AS template_name,
167
- t.category AS template_category,
168
- p.name AS person_name
169
- FROM public.plg_forms_documents d
170
- LEFT JOIN public.plg_forms_templates t ON t.id = d.template_id
171
- LEFT JOIN public.people p ON p.id = d.person_id
172
- $v$;
173
- END IF;
174
- END $$;
@@ -1,223 +0,0 @@
1
- -- ============================================================
2
- -- Document Archetype — public.documents
3
- -- A document is any record associated with a person (or standalone):
4
- -- forms, images, attachments, prescriptions, contracts, etc.
5
- -- The `kind` column discriminates the type.
6
- --
7
- -- DATA SAFETY (converted pools): plg_forms_documents may already hold REAL
8
- -- rows in its PRE-archetype shape (its own `id` PK, no `document_id` column —
9
- -- see 001_frm_base.sql). This migration MIGRATES those rows into the new
10
- -- document archetype instead of dropping them:
11
- -- * pre-archetype + rows -> copy each legacy row into public.documents
12
- -- (reusing its id) + into the new extension
13
- -- table, migrate its files, then drop legacy.
14
- -- * pre-archetype + empty -> plain drop + create (fresh shape).
15
- -- * already new shape -> no-op.
16
- -- ============================================================
17
-
18
- CREATE TABLE IF NOT EXISTS public.documents (
19
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
20
- tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
21
- kind text NOT NULL DEFAULT 'attachment',
22
- -- kind: 'form', 'image', 'attachment', 'prescription', 'contract', etc.
23
- person_id uuid REFERENCES public.people(id) ON DELETE SET NULL,
24
- title text,
25
- description text,
26
- status text NOT NULL DEFAULT 'draft',
27
- -- status: 'draft', 'completed', 'signed', 'archived'
28
- file_url text,
29
- file_name text,
30
- file_size integer,
31
- mime_type text,
32
- tags text[] DEFAULT '{}',
33
- notes text,
34
- is_active boolean NOT NULL DEFAULT true,
35
- metadata jsonb DEFAULT '{}',
36
- created_by uuid,
37
- updated_by uuid,
38
- created_at timestamptz NOT NULL DEFAULT now(),
39
- updated_at timestamptz NOT NULL DEFAULT now()
40
- );
41
-
42
- ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
43
-
44
- CREATE INDEX IF NOT EXISTS idx_documents_tenant ON public.documents(tenant_id, kind);
45
- CREATE INDEX IF NOT EXISTS idx_documents_person ON public.documents(person_id);
46
- CREATE INDEX IF NOT EXISTS idx_documents_status ON public.documents(tenant_id, status);
47
-
48
- DROP POLICY IF EXISTS "documents_select" ON public.documents;
49
- CREATE POLICY "documents_select" ON public.documents
50
- FOR SELECT TO authenticated
51
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
52
- DROP POLICY IF EXISTS "documents_insert" ON public.documents;
53
- CREATE POLICY "documents_insert" ON public.documents
54
- FOR INSERT TO authenticated
55
- WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
56
- DROP POLICY IF EXISTS "documents_update" ON public.documents;
57
- CREATE POLICY "documents_update" ON public.documents
58
- FOR UPDATE TO authenticated
59
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
60
- DROP POLICY IF EXISTS "documents_delete" ON public.documents;
61
- CREATE POLICY "documents_delete" ON public.documents
62
- FOR DELETE TO authenticated
63
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
64
-
65
- -- ============================================================
66
- -- Reconcile plg_forms_documents / plg_forms_document_files with the archetype.
67
- -- ============================================================
68
-
69
- -- Step 1: if a PRE-archetype plg_forms_documents is present (no document_id
70
- -- column), rename it (and its files table + dependent view) out of the way so
71
- -- the new archetype-shaped tables can be created and — when it holds rows —
72
- -- its data copied across. Fully guarded, so already-migrated pools skip this.
73
- DO $$
74
- BEGIN
75
- IF to_regclass('public.plg_forms_documents') IS NOT NULL
76
- AND NOT EXISTS (
77
- SELECT 1 FROM information_schema.columns
78
- WHERE table_schema = 'public'
79
- AND table_name = 'plg_forms_documents'
80
- AND column_name = 'document_id'
81
- ) THEN
82
- DROP VIEW IF EXISTS public.v_frm_documents;
83
- ALTER TABLE public.plg_forms_documents RENAME TO plg_forms_documents_legacy;
84
- IF to_regclass('public.plg_forms_document_files') IS NOT NULL THEN
85
- ALTER TABLE public.plg_forms_document_files RENAME TO plg_forms_document_files_legacy;
86
- END IF;
87
- END IF;
88
- END $$;
89
-
90
- -- Step 2: create the new archetype-shaped extension tables. IF NOT EXISTS makes
91
- -- this a no-op on pools already migrated to the new shape; after Step 1 the
92
- -- names are free on pre-archetype pools.
93
-
94
- -- plg_forms_documents: extension table for form-type documents
95
- CREATE TABLE IF NOT EXISTS public.plg_forms_documents (
96
- document_id uuid PRIMARY KEY REFERENCES public.documents(id) ON DELETE CASCADE,
97
- tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
98
- template_id uuid NOT NULL REFERENCES public.plg_forms_templates(id),
99
- data jsonb NOT NULL DEFAULT '{}',
100
- signed_at timestamptz,
101
- signed_by uuid,
102
- created_at timestamptz NOT NULL DEFAULT now(),
103
- updated_at timestamptz NOT NULL DEFAULT now()
104
- );
105
-
106
- ALTER TABLE public.plg_forms_documents ENABLE ROW LEVEL SECURITY;
107
-
108
- CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_template ON public.plg_forms_documents(template_id);
109
-
110
- DROP POLICY IF EXISTS "plg_forms_documents_select" ON public.plg_forms_documents;
111
- CREATE POLICY "plg_forms_documents_select" ON public.plg_forms_documents
112
- FOR SELECT TO authenticated
113
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
114
- DROP POLICY IF EXISTS "plg_forms_documents_insert" ON public.plg_forms_documents;
115
- CREATE POLICY "plg_forms_documents_insert" ON public.plg_forms_documents
116
- FOR INSERT TO authenticated
117
- WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
118
- DROP POLICY IF EXISTS "plg_forms_documents_update" ON public.plg_forms_documents;
119
- CREATE POLICY "plg_forms_documents_update" ON public.plg_forms_documents
120
- FOR UPDATE TO authenticated
121
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
122
- DROP POLICY IF EXISTS "plg_forms_documents_delete" ON public.plg_forms_documents;
123
- CREATE POLICY "plg_forms_documents_delete" ON public.plg_forms_documents
124
- FOR DELETE TO authenticated
125
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
126
-
127
- -- plg_forms_document_files: file attachments for form fields
128
- CREATE TABLE IF NOT EXISTS public.plg_forms_document_files (
129
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
130
- tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
131
- document_id uuid NOT NULL REFERENCES public.documents(id) ON DELETE CASCADE,
132
- field_key text NOT NULL,
133
- file_url text NOT NULL,
134
- file_name text,
135
- file_size integer,
136
- mime_type text,
137
- sort_order integer DEFAULT 0,
138
- metadata jsonb DEFAULT '{}',
139
- created_at timestamptz NOT NULL DEFAULT now()
140
- );
141
-
142
- ALTER TABLE public.plg_forms_document_files ENABLE ROW LEVEL SECURITY;
143
-
144
- CREATE INDEX IF NOT EXISTS idx_plg_forms_document_files_document ON public.plg_forms_document_files(document_id);
145
-
146
- DROP POLICY IF EXISTS "plg_forms_document_files_select" ON public.plg_forms_document_files;
147
- CREATE POLICY "plg_forms_document_files_select" ON public.plg_forms_document_files
148
- FOR SELECT TO authenticated
149
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
150
- DROP POLICY IF EXISTS "plg_forms_document_files_insert" ON public.plg_forms_document_files;
151
- CREATE POLICY "plg_forms_document_files_insert" ON public.plg_forms_document_files
152
- FOR INSERT TO authenticated
153
- WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
154
- DROP POLICY IF EXISTS "plg_forms_document_files_update" ON public.plg_forms_document_files;
155
- CREATE POLICY "plg_forms_document_files_update" ON public.plg_forms_document_files
156
- FOR UPDATE TO authenticated
157
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
158
- DROP POLICY IF EXISTS "plg_forms_document_files_delete" ON public.plg_forms_document_files;
159
- CREATE POLICY "plg_forms_document_files_delete" ON public.plg_forms_document_files
160
- FOR DELETE TO authenticated
161
- USING (tenant_id IN (SELECT public.user_tenant_ids()));
162
-
163
- -- Step 3: if legacy rows exist, migrate them, then drop the quarantined legacy
164
- -- tables. Reusing each legacy id as the documents.id keeps every legacy file's
165
- -- document_id FK valid after the copy. ON CONFLICT DO NOTHING makes a partial
166
- -- re-run safe.
167
- DO $$
168
- BEGIN
169
- IF to_regclass('public.plg_forms_documents_legacy') IS NOT NULL THEN
170
- -- 3a. base document (one per legacy form document; is_active mirrors NOT is_deleted)
171
- INSERT INTO public.documents (
172
- id, tenant_id, kind, person_id, title, status, notes, metadata,
173
- is_active, created_by, updated_by, created_at, updated_at
174
- )
175
- SELECT
176
- id, tenant_id, 'form', person_id, title, status, notes, metadata,
177
- NOT COALESCE(is_deleted, false), created_by, updated_by, created_at, updated_at
178
- FROM public.plg_forms_documents_legacy
179
- ON CONFLICT (id) DO NOTHING;
180
-
181
- -- 3b. form extension row (keyed by the reused document id)
182
- INSERT INTO public.plg_forms_documents (
183
- document_id, tenant_id, template_id, data, signed_at, signed_by, created_at, updated_at
184
- )
185
- SELECT
186
- id, tenant_id, template_id, data, signed_at, signed_by, created_at, updated_at
187
- FROM public.plg_forms_documents_legacy
188
- ON CONFLICT (document_id) DO NOTHING;
189
-
190
- -- 3c. file attachments (document_id already points at the reused id)
191
- IF to_regclass('public.plg_forms_document_files_legacy') IS NOT NULL THEN
192
- INSERT INTO public.plg_forms_document_files (
193
- id, tenant_id, document_id, field_key, file_url, file_name,
194
- file_size, mime_type, sort_order, metadata, created_at
195
- )
196
- SELECT
197
- id, tenant_id, document_id, field_key, file_url, file_name,
198
- file_size, mime_type, sort_order, metadata, created_at
199
- FROM public.plg_forms_document_files_legacy
200
- ON CONFLICT (id) DO NOTHING;
201
- END IF;
202
- END IF;
203
-
204
- -- Drop legacy remnants now that any data has been copied across.
205
- DROP TABLE IF EXISTS public.plg_forms_document_files_legacy;
206
- DROP TABLE IF EXISTS public.plg_forms_documents_legacy;
207
- END $$;
208
-
209
- -- View: all documents for a person with form data joined when applicable
210
- CREATE OR REPLACE VIEW public.v_documents AS
211
- SELECT
212
- d.*,
213
- f.template_id,
214
- f.data AS form_data,
215
- f.signed_at,
216
- f.signed_by,
217
- t.name AS template_name,
218
- t.category AS template_category,
219
- p.name AS person_name
220
- FROM public.documents d
221
- LEFT JOIN public.plg_forms_documents f ON f.document_id = d.id
222
- LEFT JOIN public.plg_forms_templates t ON t.id = f.template_id
223
- LEFT JOIN public.people p ON p.id = d.person_id;