608 KiB
InvestMoz — arquitectura e migrations reconciliadas
Esquema aplicacional: public. Extensões: postgis e pgcrypto. Objectos internos das extensões não são objectos próprios da aplicação.
Laravel ^13.17; PHP ^8.3. Legado preservado e núcleo com DDL suficiente implementado; decisões pendentes fora do código.
Modelo A — Catálogo de tabelas
| Domínio | Esquema | Tabela | Finalidade | Chave primária | Dependências | Migration |
|---|---|---|---|---|---|---|
| Aplicação existente | public | users | Autenticação Laravel/Fortify | id | database/migrations/0001_01_01_000000_create_users_table.php | |
| Aplicação existente | public | password_reset_tokens | Recuperação de palavra-passe | database/migrations/0001_01_01_000000_create_users_table.php | ||
| Aplicação existente | public | sessions | Sessões Laravel | id | database/migrations/0001_01_01_000000_create_users_table.php | |
| Aplicação existente | public | cache | Cache Laravel | key | database/migrations/0001_01_01_000001_create_cache_table.php | |
| Aplicação existente | public | cache_locks | Bloqueios de cache | key | database/migrations/0001_01_01_000001_create_cache_table.php | |
| Aplicação existente | public | jobs | Fila Laravel | id | database/migrations/0001_01_01_000002_create_jobs_table.php | |
| Aplicação existente | public | job_batches | Lotes de jobs | id | database/migrations/0001_01_01_000002_create_jobs_table.php | |
| Aplicação existente | public | failed_jobs | Falhas de jobs | id | database/migrations/0001_01_01_000002_create_jobs_table.php | |
| Aplicação existente | public | passkeys | Credenciais passkey | id | users.id | database/migrations/2024_01_01_000000_create_passkeys_table.php |
| Aplicação existente | public | sectors | Sectores do catálogo público | id | database/migrations/2026_01_01_000001_create_sectors_table.php | |
| Aplicação existente | public | opportunities | Catálogo público de oportunidades | id | sectors.id | database/migrations/2026_01_01_000002_create_opportunities_table.php |
| Aplicação existente | public | interest_requests | Manifestações de interesse | id | opportunities.id; users.id | database/migrations/2026_01_01_000003_create_interest_requests_table.php |
| Identidade | public | organizations | Registar organizações institucionais, empresariais e educativas | id | database/migrations/2026_09_24_001000_investmoz_identity.php | |
| Identidade | public | memberships | Associar utilizadores a organizações e ao respectivo papel | id | organizations.id; users.id | database/migrations/2026_09_24_001000_investmoz_identity.php |
| Identidade | public | consents | Registar concessão e retirada de consentimentos por finalidade | id | users.id | database/migrations/2026_09_24_001000_investmoz_identity.php |
| Conteúdos | public | documents | Catalogar ficheiros, classificação e estado de quarentena | id | database/migrations/2026_09_24_002000_investmoz_content.php | |
| Geografia | public | geo_locations | Representar a hierarquia territorial | id | geo_locations.id | database/migrations/2026_09_24_003000_investmoz_geography.php |
| Geografia | public | geo_geometries | Armazenar geometrias válidas das localizações | id | geo_locations.id | database/migrations/2026_09_24_003000_investmoz_geography.php |
| Projectos | public | projects | Registar projectos de investimento e orçamento | id | database/migrations/2026_09_24_004000_investmoz_projects.php | |
| Projectos | public | project_locations | Associar projectos a localizações por função | id | geo_locations.id; projects.id | database/migrations/2026_09_24_004000_investmoz_projects.php |
| Clusters e cadeias | public | economic_clusters | Registar clusters económicos | id | database/migrations/2026_09_24_005000_investmoz_clusters.php | |
| Clusters e cadeias | public | value_chains | Registar cadeias de valor de cada cluster | id | economic_clusters.id | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| Clusters e cadeias | public | value_chain_links | Associar cadeias por tipo de ligação | id | value_chains.id | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| Clusters e cadeias | public | cluster_projects | Associar projectos a clusters | id | economic_clusters.id; projects.id | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| Clusters e cadeias | public | anchor_project_links | Justificar projectos âncora de clusters | id | economic_clusters.id; projects.id | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| Clusters e cadeias | public | complementary_project_links | Relacionar projectos âncora e complementares | id | projects.id | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| Corredores | public | development_corridors | Registar corredores de desenvolvimento | id | database/migrations/2026_09_24_006000_investmoz_corridors.php | |
| Corredores | public | corridor_locations | Ordenar localizações de corredores | id | development_corridors.id; geo_locations.id | database/migrations/2026_09_24_006000_investmoz_corridors.php |
| Corredores | public | corridor_projects | Associar corredores e projectos | id | development_corridors.id; projects.id | database/migrations/2026_09_24_006000_investmoz_corridors.php |
| Corredores | public | corridor_clusters | Associar corredores e clusters | id | development_corridors.id; economic_clusters.id | database/migrations/2026_09_24_006000_investmoz_corridors.php |
| CRM | public | investors | Registar investidores e o seu enquadramento institucional | id | organizations.id | database/migrations/2026_09_24_007000_investmoz_crm.php |
| CRM | public | contacts | Registar contactos partilháveis entre investidores | id | database/migrations/2026_09_24_007000_investmoz_crm.php | |
| CRM | public | investor_contacts | Associar investidores e contactos com indicação de contacto principal | investor_id, contact_id | contacts.id; investors.id | database/migrations/2026_09_24_007000_investmoz_crm.php |
| CRM | public | leads | Qualificar potenciais negócios no CRM | id | investors.id; users.id | database/migrations/2026_09_24_007000_investmoz_crm.php |
| CRM | public | crm_opportunities | Gerir negociações CRM, separadas do catálogo público opportunities | id | leads.id; projects.id; users.id | database/migrations/2026_09_24_007000_investmoz_crm.php |
| CRM | public | activities | Registar interacções CRM | id | crm_opportunities.id; investors.id; users.id | database/migrations/2026_09_24_007000_investmoz_crm.php |
| CRM | public | tasks | Acompanhar tarefas e prazos CRM | id | crm_opportunities.id; users.id | database/migrations/2026_09_24_007000_investmoz_crm.php |
| Jornada e aftercare | public | investor_journeys | Acompanhar jornadas dos investidores | id | crm_opportunities.id; investors.id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| Jornada e aftercare | public | journey_steps | Ordenar etapas de uma jornada | id | investor_journeys.id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| Jornada e aftercare | public | submissions | Registar submissões nas etapas | id | journey_steps.id; users.id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| Jornada e aftercare | public | aftercare_plans | Acompanhar planos de pós-investimento | id | investors.id; projects.id; users.id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| Jornada e aftercare | public | constraints | Registar constrangimentos de pós-investimento | id | aftercare_plans.id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| Jornada e aftercare | public | escalations | Registar escalonamentos de constrangimentos | id | constraints.id; users.id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| Educação | public | skills | Catalogar competências | id | database/migrations/2026_09_24_009000_investmoz_education.php | |
| Educação | public | occupations | Catalogar ocupações | id | database/migrations/2026_09_24_009000_investmoz_education.php | |
| Educação | public | training_needs | Quantificar necessidades de formação | id | occupations.id; projects.id; skills.id | database/migrations/2026_09_24_009000_investmoz_education.php |
| Educação | public | training_providers | Registar prestadores de formação | id | organizations.id | database/migrations/2026_09_24_009000_investmoz_education.php |
| Educação | public | courses | Catalogar cursos por prestador | id | training_providers.id | database/migrations/2026_09_24_009000_investmoz_education.php |
| Educação | public | education_opportunities | Publicar ofertas educativas com datas e capacidade | id | courses.id; geo_locations.id | database/migrations/2026_09_24_009000_investmoz_education.php |
| Conteúdos — ligações tipadas | public | project_documents | Associar documentos a projects com integridade referencial | project_id, document_id | documents.id; projects.id | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| Conteúdos — ligações tipadas | public | investor_documents | Associar documentos a investors com integridade referencial | investor_id, document_id | documents.id; investors.id | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| Conteúdos — ligações tipadas | public | journey_documents | Associar documentos a investor_journeys com integridade referencial | journey_id, document_id | documents.id; investor_journeys.id | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| Conteúdos — ligações tipadas | public | aftercare_documents | Associar documentos a aftercare_plans com integridade referencial | aftercare_plan_id, document_id | aftercare_plans.id; documents.id | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| Conteúdos — ligações tipadas | public | education_documents | Associar documentos a education_opportunities com integridade referencial | education_opportunity_id, document_id | documents.id; education_opportunities.id | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| Governação e auditoria | public | audit_events | Preservar eventos de auditoria sem actualização, eliminação ou truncagem | id | users.id | database/migrations/2026_09_24_010000_investmoz_governance_ai.php |
| Integrações e eventos | public | outbox_events | Registar eventos de saída e estado de entrega | id | database/migrations/2026_09_24_011000_investmoz_integrations.php | |
| Integrações e eventos | public | inbox_events | Deduplicar mensagens de entrada e acompanhar processamento | id | database/migrations/2026_09_24_011000_investmoz_integrations.php | |
| Integrações e eventos | public | sync_runs | Acompanhar execuções de integração | id | database/migrations/2026_09_24_011000_investmoz_integrations.php | |
| Integrações e eventos | public | reconciliation_issues | Registar divergências de reconciliação | id | sync_runs.id | database/migrations/2026_09_24_011000_investmoz_integrations.php |
Modelo B — Dicionário integral de campos
| Tabela | Campo | Tipo PostgreSQL | Nulo | Predefinição | PK/FK | Único | Restrição/índice | Descrição | Enumeração CHECK | Calculado | Timestamp técnico | Soft delete | Migration | Observações |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| users | id | bigint | Não | nextval('users_id_seq'::regclass) | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | |
| users | name | character varying(255) | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| users | character varying(255) | Não | Sem predefinição | users_email_unique | INDEX users_email_unique btree | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | |||
| users | email_verified_at | timestamp(0) without time zone | Sim | NULL | Não | email verified at | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| users | password | character varying(255) | Não | Sem predefinição | Não | password | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| users | remember_token | character varying(100) | Sim | NULL | Não | remember token | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| users | created_at | timestamp(0) without time zone | Sim | NULL | Não | Instante de criação | Não | Não | True | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| users | updated_at | timestamp(0) without time zone | Sim | NULL | Não | Instante da última actualização | Não | Não | True | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| users | two_factor_secret | text | Sim | NULL | Não | two factor secret | Não | Não | False | False | database/migrations/2025_08_14_170933_add_two_factor_columns_to_users_table.php | Legado preservado | ||
| users | two_factor_recovery_codes | text | Sim | NULL | Não | two factor recovery codes | Não | Não | False | False | database/migrations/2025_08_14_170933_add_two_factor_columns_to_users_table.php | Legado preservado | ||
| users | two_factor_confirmed_at | timestamp(0) without time zone | Sim | NULL | Não | two factor confirmed at | Não | Não | False | False | database/migrations/2025_08_14_170933_add_two_factor_columns_to_users_table.php | Legado preservado | ||
| password_reset_tokens | character varying(255) | Não | Sem predefinição | PK | PRIMARY KEY | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | |||
| password_reset_tokens | token | character varying(255) | Não | Sem predefinição | Não | token | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| password_reset_tokens | created_at | timestamp(0) without time zone | Sim | NULL | Não | Instante de criação | Não | Não | True | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| sessions | id | character varying(255) | Não | Sem predefinição | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | |
| sessions | user_id | bigint | Sim | NULL | Não | INDEX sessions_user_id_index btree | user id | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | |
| sessions | ip_address | character varying(45) | Sim | NULL | Não | ip address | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| sessions | user_agent | text | Sim | NULL | Não | user agent | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| sessions | payload | text | Não | Sem predefinição | Não | Conteúdo da submissão/evento; contrato por tipo pendente | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | ||
| sessions | last_activity | integer | Não | Sem predefinição | Não | INDEX sessions_last_activity_index btree | last activity | Não | Não | False | False | database/migrations/0001_01_01_000000_create_users_table.php | Legado preservado | |
| cache | key | character varying(255) | Não | Sem predefinição | PK | PRIMARY KEY | key | Não | Não | False | False | database/migrations/0001_01_01_000001_create_cache_table.php | Legado preservado | |
| cache | value | text | Não | Sem predefinição | Não | value | Não | Não | False | False | database/migrations/0001_01_01_000001_create_cache_table.php | Legado preservado | ||
| cache | expiration | bigint | Não | Sem predefinição | Não | INDEX cache_expiration_index btree | expiration | Não | Não | False | False | database/migrations/0001_01_01_000001_create_cache_table.php | Legado preservado | |
| cache_locks | key | character varying(255) | Não | Sem predefinição | PK | PRIMARY KEY | key | Não | Não | False | False | database/migrations/0001_01_01_000001_create_cache_table.php | Legado preservado | |
| cache_locks | owner | character varying(255) | Não | Sem predefinição | Não | owner | Não | Não | False | False | database/migrations/0001_01_01_000001_create_cache_table.php | Legado preservado | ||
| cache_locks | expiration | bigint | Não | Sem predefinição | Não | INDEX cache_locks_expiration_index btree | expiration | Não | Não | False | False | database/migrations/0001_01_01_000001_create_cache_table.php | Legado preservado | |
| jobs | id | bigint | Não | nextval('jobs_id_seq'::regclass) | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | |
| jobs | queue | character varying(255) | Não | Sem predefinição | Não | INDEX jobs_queue_index btree | queue | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | |
| jobs | payload | text | Não | Sem predefinição | Não | Conteúdo da submissão/evento; contrato por tipo pendente | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| jobs | attempts | smallint | Não | Sem predefinição | Não | attempts | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| jobs | reserved_at | integer | Sim | NULL | Não | reserved at | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| jobs | available_at | integer | Não | Sem predefinição | Não | available at | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| jobs | created_at | integer | Não | Sem predefinição | Não | Instante de criação | Não | Não | True | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| job_batches | id | character varying(255) | Não | Sem predefinição | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | |
| job_batches | name | character varying(255) | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| job_batches | total_jobs | integer | Não | Sem predefinição | Não | total jobs | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| job_batches | pending_jobs | integer | Não | Sem predefinição | Não | pending jobs | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| job_batches | failed_jobs | integer | Não | Sem predefinição | Não | failed jobs | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| job_batches | failed_job_ids | text | Não | Sem predefinição | Não | failed job ids | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| job_batches | options | text | Sim | NULL | Não | options | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| job_batches | cancelled_at | integer | Sim | NULL | Não | cancelled at | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| job_batches | created_at | integer | Não | Sem predefinição | Não | Instante de criação | Não | Não | True | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| job_batches | finished_at | integer | Sim | NULL | Não | finished at | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| failed_jobs | id | bigint | Não | nextval('failed_jobs_id_seq'::regclass) | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | |
| failed_jobs | uuid | character varying(255) | Não | Sem predefinição | failed_jobs_uuid_unique | INDEX failed_jobs_uuid_unique btree | uuid | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | |
| failed_jobs | connection | character varying(255) | Não | Sem predefinição | Não | INDEX failed_jobs_connection_queue_failed_at_index btree | connection | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | |
| failed_jobs | queue | character varying(255) | Não | Sem predefinição | Não | INDEX failed_jobs_connection_queue_failed_at_index btree | queue | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | |
| failed_jobs | payload | text | Não | Sem predefinição | Não | Conteúdo da submissão/evento; contrato por tipo pendente | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| failed_jobs | exception | text | Não | Sem predefinição | Não | exception | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | ||
| failed_jobs | failed_at | timestamp(0) without time zone | Não | CURRENT_TIMESTAMP | Não | INDEX failed_jobs_connection_queue_failed_at_index btree | failed at | Não | Não | False | False | database/migrations/0001_01_01_000002_create_jobs_table.php | Legado preservado | |
| passkeys | id | bigint | Não | nextval('passkeys_id_seq'::regclass) | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2024_01_01_000000_create_passkeys_table.php | Legado preservado | |
| passkeys | user_id | bigint | Não | Sem predefinição | FK -> users.id ON UPDATE NO ACTION ON DELETE CASCADE | Não | INDEX passkeys_user_id_index btree | user id | Não | Não | False | False | database/migrations/2024_01_01_000000_create_passkeys_table.php | Legado preservado |
| passkeys | name | character varying(255) | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2024_01_01_000000_create_passkeys_table.php | Legado preservado | ||
| passkeys | credential_id | character varying(255) | Não | Sem predefinição | passkeys_credential_id_unique | INDEX passkeys_credential_id_unique btree | credential id | Não | Não | False | False | database/migrations/2024_01_01_000000_create_passkeys_table.php | Legado preservado | |
| passkeys | credential | json | Não | Sem predefinição | Não | credential | Não | Não | False | False | database/migrations/2024_01_01_000000_create_passkeys_table.php | Legado preservado | ||
| passkeys | last_used_at | timestamp(0) without time zone | Sim | NULL | Não | last used at | Não | Não | False | False | database/migrations/2024_01_01_000000_create_passkeys_table.php | Legado preservado | ||
| passkeys | created_at | timestamp(0) without time zone | Sim | NULL | Não | Instante de criação | Não | Não | True | False | database/migrations/2024_01_01_000000_create_passkeys_table.php | Legado preservado | ||
| passkeys | updated_at | timestamp(0) without time zone | Sim | NULL | Não | Instante da última actualização | Não | Não | True | False | database/migrations/2024_01_01_000000_create_passkeys_table.php | Legado preservado | ||
| sectors | id | bigint | Não | nextval('sectors_id_seq'::regclass) | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | |
| sectors | name | character varying(150) | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | ||
| sectors | slug | character varying(180) | Não | Sem predefinição | sectors_slug_unique | INDEX sectors_slug_unique btree; INDEX sectors_slug_index btree | slug | Não | Não | False | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | |
| sectors | short_description | character varying(255) | Sim | NULL | Não | short description | Não | Não | False | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | ||
| sectors | description | text | Sim | NULL | Não | description | Não | Não | False | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | ||
| sectors | icon | character varying(100) | Sim | NULL | Não | icon | Não | Não | False | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | ||
| sectors | sort_order | integer | Não | 0 | Não | sort order | Não | Não | False | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | ||
| sectors | is_active | boolean | Não | true | Não | INDEX sectors_is_active_index btree | is active | Não | Não | False | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | |
| sectors | published_at | timestamp(0) without time zone | Sim | NULL | Não | published at | Não | Não | False | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | ||
| sectors | created_at | timestamp(0) without time zone | Sim | NULL | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | ||
| sectors | updated_at | timestamp(0) without time zone | Sim | NULL | Não | Instante da última actualização | Não | Não | True | False | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | ||
| sectors | deleted_at | timestamp(0) without time zone | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_01_01_000001_create_sectors_table.php | Legado preservado | ||
| opportunities | id | bigint | Não | nextval('opportunities_id_seq'::regclass) | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | |
| opportunities | sector_id | bigint | Não | Sem predefinição | FK -> sectors.id ON UPDATE CASCADE ON DELETE RESTRICT | Não | INDEX opportunities_sector_id_index btree | sector id | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado |
| opportunities | reference | character varying(80) | Não | Sem predefinição | opportunities_reference_unique | INDEX opportunities_reference_unique btree; INDEX opportunities_reference_index btree | reference | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | |
| opportunities | title | character varying(200) | Não | Sem predefinição | Não | title | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | slug | character varying(220) | Não | Sem predefinição | opportunities_slug_unique | INDEX opportunities_slug_unique btree; INDEX opportunities_slug_index btree | slug | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | |
| opportunities | summary | character varying(500) | Sim | NULL | Não | summary | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | description | text | Sim | NULL | Não | description | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | province | character varying(100) | Sim | NULL | Não | INDEX opportunities_province_index btree | province | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | |
| opportunities | district | character varying(100) | Sim | NULL | Não | district | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | promoter_name | character varying(200) | Sim | NULL | Não | promoter name | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | promoter_type | character varying(100) | Sim | NULL | Não | promoter type | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | maturity_level | smallint | Sim | NULL | Não | INDEX opportunities_maturity_level_index btree | maturity level | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | |
| opportunities | maturity_label | character varying(120) | Sim | NULL | Não | maturity label | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | estimated_investment_amount | numeric(18,2) | Sim | NULL | Não | estimated investment amount | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | estimated_investment_currency | character varying(10) | Não | 'USD' | Não | estimated investment currency | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | financing_modality | character varying(120) | Sim | NULL | Não | financing modality | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | expected_impact | text | Sim | NULL | Não | expected impact | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | status | character varying(50) | Não | 'draft' | Não | INDEX opportunities_status_index btree | status | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | |
| opportunities | is_featured | boolean | Não | false | Não | INDEX opportunities_is_featured_index btree | is featured | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | |
| opportunities | published_at | timestamp(0) without time zone | Sim | NULL | Não | published at | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | last_validated_at | timestamp(0) without time zone | Sim | NULL | Não | last validated at | Não | Não | False | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | created_at | timestamp(0) without time zone | Sim | NULL | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | updated_at | timestamp(0) without time zone | Sim | NULL | Não | Instante da última actualização | Não | Não | True | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| opportunities | deleted_at | timestamp(0) without time zone | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_01_01_000002_create_opportunities_table.php | Legado preservado | ||
| interest_requests | id | bigint | Não | nextval('interest_requests_id_seq'::regclass) | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | |
| interest_requests | opportunity_id | bigint | Sim | NULL | FK -> opportunities.id ON UPDATE CASCADE ON DELETE SET NULL | Não | opportunity id | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | |
| interest_requests | reference | character varying(80) | Não | Sem predefinição | interest_requests_reference_unique | INDEX interest_requests_reference_unique btree; INDEX interest_requests_reference_index btree | reference | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | |
| interest_requests | full_name | character varying(150) | Não | Sem predefinição | Não | full name | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | character varying(150) | Não | Sem predefinição | Não | INDEX interest_requests_email_index btree | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | |||
| interest_requests | phone | character varying(30) | Sim | NULL | Não | phone | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | investor_type | character varying(80) | Não | Sem predefinição | Não | investor type | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | country | character varying(100) | Não | Sem predefinição | Não | country | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | sector_interest | character varying(150) | Não | Sem predefinição | Não | sector interest | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | opportunity_reference | character varying(80) | Sim | NULL | Não | opportunity reference | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | investment_range | character varying(80) | Sim | NULL | Não | investment range | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | message | text | Não | Sem predefinição | Não | message | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | privacy_consent | boolean | Não | false | Não | privacy consent | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | consented_at | timestamp(0) without time zone | Sim | NULL | Não | consented at | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | status | character varying(50) | Não | 'received' | Não | INDEX interest_requests_status_index btree | status | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | |
| interest_requests | source_page | character varying(255) | Sim | NULL | Não | source page | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | ip_address | inet | Sim | NULL | Não | ip address | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | user_agent | text | Sim | NULL | Não | user agent | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | metadata | json | Sim | NULL | Não | Metadados flexíveis; schema aplicacional pendente | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | reviewed_at | timestamp(0) without time zone | Sim | NULL | Não | reviewed at | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | reviewed_by | bigint | Sim | NULL | FK -> users.id ON UPDATE NO ACTION ON DELETE SET NULL | Não | reviewed by | Não | Não | False | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | |
| interest_requests | created_at | timestamp(0) without time zone | Sim | NULL | Não | INDEX interest_requests_created_at_index btree | Instante de criação | Não | Não | True | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | |
| interest_requests | updated_at | timestamp(0) without time zone | Sim | NULL | Não | Instante da última actualização | Não | Não | True | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| interest_requests | deleted_at | timestamp(0) without time zone | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Legado preservado | ||
| organizations | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| organizations | source_system | text | Não | 'investmoz' | imz_organizations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_organizations_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| organizations | external_id | text | Sim | NULL | imz_organizations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_organizations_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| organizations | version_no | integer | Não | 1 | Não | imz_organizations_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| organizations | data_classification | text | Não | 'internal' | Não | imz_organizations_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| organizations | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| organizations | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| organizations | updated_at | timestamptz | Não | now() | Não | INDEX imz_organizations_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| organizations | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| organizations | name | text | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| organizations | organization_type | text | Não | Sem predefinição | Não | imz_organizations_check_03: organization_type IN ('public','private','ngo','education') | organization type | organization_type IN ('public','private','ngo','education') | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| memberships | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| memberships | source_system | text | Não | 'investmoz' | imz_memberships_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_memberships_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| memberships | external_id | text | Sim | NULL | imz_memberships_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_memberships_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| memberships | version_no | integer | Não | 1 | Não | imz_memberships_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| memberships | data_classification | text | Não | 'internal' | Não | imz_memberships_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| memberships | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| memberships | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| memberships | updated_at | timestamptz | Não | now() | Não | INDEX imz_memberships_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| memberships | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| memberships | user_id | bigint | Não | Sem predefinição | FK -> users.id ON UPDATE CASCADE ON DELETE CASCADE | imz_memberships_user_id_organization_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_memberships_user_id_idx btree; INDEX imz_memberships_user_id_organization_id_uq btree | user id | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 |
| memberships | organization_id | uuid | Não | Sem predefinição | FK -> organizations.id ON UPDATE CASCADE ON DELETE CASCADE | imz_memberships_user_id_organization_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_memberships_organization_id_idx btree; INDEX imz_memberships_user_id_organization_id_uq btree | organization id | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 |
| memberships | role | text | Não | Sem predefinição | Não | imz_memberships_check_03: role IN ('admin','manager','officer','viewer') | role | role IN ('admin','manager','officer','viewer') | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| consents | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| consents | source_system | text | Não | 'investmoz' | imz_consents_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_consents_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| consents | external_id | text | Sim | NULL | imz_consents_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_consents_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| consents | version_no | integer | Não | 1 | Não | imz_consents_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| consents | data_classification | text | Não | 'internal' | Não | imz_consents_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| consents | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| consents | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| consents | updated_at | timestamptz | Não | now() | Não | INDEX imz_consents_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| consents | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| consents | user_id | bigint | Sim | NULL | FK -> users.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_consents_user_id_idx btree | user id | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 |
| consents | subject_ref | text | Não | Sem predefinição | Não | subject ref | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| consents | purpose | text | Não | Sem predefinição | Não | purpose | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| consents | status | text | Não | Sem predefinição | Não | imz_consents_check_03: status IN ('granted','withdrawn','expired') INDEX imz_consents_status_idx btree | status | status IN ('granted','withdrawn','expired') | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | |
| consents | granted_at | timestamptz | Sim | NULL | Não | granted at | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| consents | withdrawn_at | timestamptz | Sim | NULL | Não | withdrawn at | Não | Não | False | False | database/migrations/2026_09_24_001000_investmoz_identity.php | Reconciliado A.25/A.26 e A.31 | ||
| documents | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | |
| documents | source_system | text | Não | 'investmoz' | imz_documents_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_documents_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | |
| documents | external_id | text | Sim | NULL | imz_documents_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_documents_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | |
| documents | version_no | integer | Não | 1 | Não | imz_documents_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | |
| documents | data_classification | text | Não | 'internal' | Não | imz_documents_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | |
| documents | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | ||
| documents | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | ||
| documents | updated_at | timestamptz | Não | now() | Não | INDEX imz_documents_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | |
| documents | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | ||
| documents | file_name | text | Não | Sem predefinição | Não | file name | Não | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | ||
| documents | media_type | text | Não | Sem predefinição | Não | media type | Não | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | ||
| documents | storage_key | text | Não | Sem predefinição | imz_documents_storage_key_uq | INDEX imz_documents_storage_key_uq btree | Chave única no armazenamento | Não | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | |
| documents | sha256 | char(64) | Não | Sem predefinição | Não | imz_documents_check_04: sha256 ~ '^[0-9a-f]{64}$' | SHA-256 hexadecimal; 64 caracteres minúsculos | Não | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | |
| documents | status | text | Não | Sem predefinição | Não | imz_documents_check_03: status IN ('active','quarantined','deleted') INDEX imz_documents_status_idx btree | status | status IN ('active','quarantined','deleted') | Não | False | False | database/migrations/2026_09_24_002000_investmoz_content.php | Reconciliado A.25/A.26 e A.31 | |
| geo_locations | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_locations | source_system | text | Não | 'investmoz' | imz_geo_locations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_geo_locations_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_locations | external_id | text | Sim | NULL | imz_geo_locations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_geo_locations_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_locations | version_no | integer | Não | 1 | Não | imz_geo_locations_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_locations | data_classification | text | Não | 'internal' | Não | imz_geo_locations_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_locations | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | ||
| geo_locations | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | ||
| geo_locations | updated_at | timestamptz | Não | now() | Não | INDEX imz_geo_locations_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_locations | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | ||
| geo_locations | name | text | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | ||
| geo_locations | location_type | text | Não | Sem predefinição | imz_geo_locations_location_type_code_uq (composta) WHERE deleted_at IS NULL | imz_geo_locations_check_03: location_type IN ('country','province','district','municipality','site') INDEX imz_geo_locations_location_type_code_uq btree | location type | location_type IN ('country','province','district','municipality','site') | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_locations | parent_id | uuid | Sim | NULL | FK -> geo_locations.id ON UPDATE CASCADE ON DELETE RESTRICT | Não | INDEX imz_geo_locations_parent_id_idx btree | parent id | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 |
| geo_locations | code | text | Não | Sem predefinição | imz_geo_locations_location_type_code_uq (composta) WHERE deleted_at IS NULL | INDEX imz_geo_locations_location_type_code_uq btree | code | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_geometries | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_geometries | source_system | text | Não | 'investmoz' | imz_geo_geometries_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_geo_geometries_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_geometries | external_id | text | Sim | NULL | imz_geo_geometries_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_geo_geometries_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_geometries | version_no | integer | Não | 1 | Não | imz_geo_geometries_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_geometries | data_classification | text | Não | 'internal' | Não | imz_geo_geometries_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_geometries | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | ||
| geo_geometries | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | ||
| geo_geometries | updated_at | timestamptz | Não | now() | Não | INDEX imz_geo_geometries_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_geometries | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | ||
| geo_geometries | geo_location_id | uuid | Não | Sem predefinição | FK -> geo_locations.id ON UPDATE CASCADE ON DELETE CASCADE | imz_geo_geometries_geo_location_id_geometry_type_uq (composta) WHERE deleted_at IS NULL | INDEX imz_geo_geometries_geo_location_id_idx btree; INDEX imz_geo_geometries_geo_location_id_geometry_type_uq btree | geo location id | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 |
| geo_geometries | geometry_type | text | Não | Sem predefinição | imz_geo_geometries_geo_location_id_geometry_type_uq (composta) WHERE deleted_at IS NULL | imz_geo_geometries_check_03: geometry_type IN ('point','line','polygon','multipolygon'); imz_geo_geometries_check_08: (geometry_type = 'point' AND GeometryType(geom) = 'POINT') OR (geometry_type = 'line' AND GeometryType(geom) = 'LINESTRING') OR (geometry_type = 'polygon' AND GeometryType(geom) = 'POLYGON') OR (geometry_type = 'multipolygon' AND GeometryType(geom) = 'MULTIPOLYGON') INDEX imz_geo_geometries_geo_location_id_geometry_type_uq btree | Tipo declarado coerente com GeometryType(geom) | geometry_type IN ('point','line','polygon','multipolygon') | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_geometries | geom | geometry(Geometry,4326) | Não | Sem predefinição | Não | imz_geo_geometries_check_04: ST_SRID(geom) = 4326; imz_geo_geometries_check_05: ST_NDims(geom) = 2; imz_geo_geometries_check_06: NOT ST_IsEmpty(geom); imz_geo_geometries_check_07: ST_IsValid(geom); imz_geo_geometries_check_08: (geometry_type = 'point' AND GeometryType(geom) = 'POINT') OR (geometry_type = 'line' AND GeometryType(geom) = 'LINESTRING') OR (geometry_type = 'polygon' AND GeometryType(geom) = 'POLYGON') OR (geometry_type = 'multipolygon' AND GeometryType(geom) = 'MULTIPOLYGON'); imz_geo_geometries_check_09: ST_XMin(Box3D(geom)) >= -180 AND ST_XMax(Box3D(geom)) <= 180 AND ST_YMin(Box3D(geom)) >= -90 AND ST_YMax(Box3D(geom)) <= 90 INDEX imz_geo_geometries_geom_idx gist | Geometria 2D WGS84 SRID 4326, válida e não vazia | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| geo_geometries | properties | jsonb | Não | '{}'::jsonb | Não | INDEX imz_geo_geometries_properties_idx gin | Propriedades geográficas; schema aplicacional pendente | Não | Não | False | False | database/migrations/2026_09_24_003000_investmoz_geography.php | Reconciliado A.25/A.26 e A.31 | |
| projects | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | source_system | text | Não | 'investmoz' | imz_projects_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_projects_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | external_id | text | Sim | NULL | imz_projects_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_projects_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | version_no | integer | Não | 1 | Não | imz_projects_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | data_classification | text | Não | 'internal' | Não | imz_projects_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | ||
| projects | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | ||
| projects | updated_at | timestamptz | Não | now() | Não | INDEX imz_projects_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | ||
| projects | code | text | Não | Sem predefinição | imz_projects_code_uq WHERE deleted_at IS NULL | INDEX imz_projects_code_uq btree | code | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | name | text | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | ||
| projects | status | text | Não | Sem predefinição | Não | imz_projects_check_03: status IN ('draft','planned','active','suspended','completed','cancelled') INDEX imz_projects_status_idx btree | status | status IN ('draft','planned','active','suspended','completed','cancelled') | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | description | text | Sim | NULL | Não | description | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | ||
| projects | budget_amount | numeric(20,2) | Sim | NULL | Não | imz_projects_check_04: budget_amount IS NULL OR budget_amount >= 0; imz_projects_check_06: (budget_amount IS NULL) = (budget_currency IS NULL) | Orçamento exacto não negativo | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | budget_currency | char(3) | Sim | NULL | Não | imz_projects_check_06: (budget_amount IS NULL) = (budget_currency IS NULL); imz_projects_check_07: budget_currency IS NULL OR budget_currency ~ '^[A-Z]{3}$' | Código monetário do orçamento; lista ISO autorizada pendente | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | start_date | date | Sim | NULL | Não | imz_projects_check_05: end_date IS NULL OR start_date IS NULL OR end_date >= start_date | start date | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | end_date | date | Sim | NULL | Não | imz_projects_check_05: end_date IS NULL OR start_date IS NULL OR end_date >= start_date | end date | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| projects | metadata | jsonb | Não | '{}'::jsonb | Não | INDEX imz_projects_metadata_idx gin | Metadados flexíveis; schema aplicacional pendente | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| project_locations | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| project_locations | source_system | text | Não | 'investmoz' | imz_project_locations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_project_locations_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| project_locations | external_id | text | Sim | NULL | imz_project_locations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_project_locations_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| project_locations | version_no | integer | Não | 1 | Não | imz_project_locations_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| project_locations | data_classification | text | Não | 'internal' | Não | imz_project_locations_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| project_locations | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | ||
| project_locations | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | ||
| project_locations | updated_at | timestamptz | Não | now() | Não | INDEX imz_project_locations_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| project_locations | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | ||
| project_locations | project_id | uuid | Não | Sem predefinição | FK -> projects.id ON UPDATE CASCADE ON DELETE CASCADE | imz_project_locations_project_id_geo_location_id_role_uq (composta) WHERE deleted_at IS NULL | INDEX imz_project_locations_project_id_idx btree; INDEX imz_project_locations_project_id_geo_location_id_role_uq btree | project id | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 |
| project_locations | geo_location_id | uuid | Não | Sem predefinição | FK -> geo_locations.id ON UPDATE CASCADE ON DELETE RESTRICT | imz_project_locations_project_id_geo_location_id_role_uq (composta) WHERE deleted_at IS NULL | INDEX imz_project_locations_geo_location_id_idx btree; INDEX imz_project_locations_project_id_geo_location_id_role_uq btree | geo location id | Não | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 |
| project_locations | role | text | Não | Sem predefinição | imz_project_locations_project_id_geo_location_id_role_uq (composta) WHERE deleted_at IS NULL | imz_project_locations_check_03: role IN ('primary','secondary','impact') INDEX imz_project_locations_project_id_geo_location_id_role_uq btree | role | role IN ('primary','secondary','impact') | Não | False | False | database/migrations/2026_09_24_004000_investmoz_projects.php | Reconciliado A.25/A.26 e A.31 | |
| economic_clusters | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| economic_clusters | source_system | text | Não | 'investmoz' | imz_economic_clusters_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_economic_clusters_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| economic_clusters | external_id | text | Sim | NULL | imz_economic_clusters_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_economic_clusters_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| economic_clusters | version_no | integer | Não | 1 | Não | imz_economic_clusters_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| economic_clusters | data_classification | text | Não | 'internal' | Não | imz_economic_clusters_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| economic_clusters | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| economic_clusters | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| economic_clusters | updated_at | timestamptz | Não | now() | Não | INDEX imz_economic_clusters_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| economic_clusters | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| economic_clusters | code | text | Não | Sem predefinição | imz_economic_clusters_code_uq WHERE deleted_at IS NULL | INDEX imz_economic_clusters_code_uq btree | code | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| economic_clusters | name | text | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| economic_clusters | sector | text | Não | Sem predefinição | Não | sector | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| economic_clusters | status | text | Não | Sem predefinição | Não | imz_economic_clusters_check_03: status IN ('planned','active','inactive') INDEX imz_economic_clusters_status_idx btree | status | status IN ('planned','active','inactive') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| economic_clusters | metadata | jsonb | Não | '{}'::jsonb | Não | Metadados flexíveis; schema aplicacional pendente | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| value_chains | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chains | source_system | text | Não | 'investmoz' | imz_value_chains_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_value_chains_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chains | external_id | text | Sim | NULL | imz_value_chains_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_value_chains_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chains | version_no | integer | Não | 1 | Não | imz_value_chains_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chains | data_classification | text | Não | 'internal' | Não | imz_value_chains_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chains | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| value_chains | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| value_chains | updated_at | timestamptz | Não | now() | Não | INDEX imz_value_chains_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chains | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| value_chains | cluster_id | uuid | Não | Sem predefinição | FK -> economic_clusters.id ON UPDATE CASCADE ON DELETE CASCADE | imz_value_chains_cluster_id_code_uq (composta) WHERE deleted_at IS NULL | INDEX imz_value_chains_cluster_id_idx btree; INDEX imz_value_chains_cluster_id_code_uq btree | cluster id | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 |
| value_chains | code | text | Não | Sem predefinição | imz_value_chains_cluster_id_code_uq (composta) WHERE deleted_at IS NULL | INDEX imz_value_chains_cluster_id_code_uq btree | code | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chains | name | text | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| value_chains | stage | text | Não | Sem predefinição | Não | imz_value_chains_check_03: stage IN ('input','production','processing','logistics','market') | stage | stage IN ('input','production','processing','logistics','market') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chain_links | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chain_links | source_system | text | Não | 'investmoz' | imz_value_chain_links_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_value_chain_links_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chain_links | external_id | text | Sim | NULL | imz_value_chain_links_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_value_chain_links_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chain_links | version_no | integer | Não | 1 | Não | imz_value_chain_links_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chain_links | data_classification | text | Não | 'internal' | Não | imz_value_chain_links_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chain_links | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| value_chain_links | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| value_chain_links | updated_at | timestamptz | Não | now() | Não | INDEX imz_value_chain_links_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| value_chain_links | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| value_chain_links | from_value_chain_id | uuid | Não | Sem predefinição | FK -> value_chains.id ON UPDATE CASCADE ON DELETE CASCADE | imz_value_chain_links_from_value_chain_id_to_value_c_f6a1a6162c (composta) WHERE deleted_at IS NULL | imz_value_chain_links_check_04: from_value_chain_id <> to_value_chain_id INDEX imz_value_chain_links_from_value_chain_id_idx btree; INDEX imz_value_chain_links_from_value_chain_id_to_value_c_f6a1a6162c btree | from value chain id | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 |
| value_chain_links | to_value_chain_id | uuid | Não | Sem predefinição | FK -> value_chains.id ON UPDATE CASCADE ON DELETE CASCADE | imz_value_chain_links_from_value_chain_id_to_value_c_f6a1a6162c (composta) WHERE deleted_at IS NULL | imz_value_chain_links_check_04: from_value_chain_id <> to_value_chain_id INDEX imz_value_chain_links_to_value_chain_id_idx btree; INDEX imz_value_chain_links_from_value_chain_id_to_value_c_f6a1a6162c btree | to value chain id | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 |
| value_chain_links | link_type | text | Não | Sem predefinição | imz_value_chain_links_from_value_chain_id_to_value_c_f6a1a6162c (composta) WHERE deleted_at IS NULL | imz_value_chain_links_check_03: link_type IN ('supplies','processes','distributes','supports') INDEX imz_value_chain_links_from_value_chain_id_to_value_c_f6a1a6162c btree | link type | link_type IN ('supplies','processes','distributes','supports') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| cluster_projects | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| cluster_projects | source_system | text | Não | 'investmoz' | imz_cluster_projects_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_cluster_projects_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| cluster_projects | external_id | text | Sim | NULL | imz_cluster_projects_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_cluster_projects_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| cluster_projects | version_no | integer | Não | 1 | Não | imz_cluster_projects_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| cluster_projects | data_classification | text | Não | 'internal' | Não | imz_cluster_projects_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| cluster_projects | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| cluster_projects | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| cluster_projects | updated_at | timestamptz | Não | now() | Não | INDEX imz_cluster_projects_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| cluster_projects | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| cluster_projects | cluster_id | uuid | Não | Sem predefinição | FK -> economic_clusters.id ON UPDATE CASCADE ON DELETE CASCADE | imz_cluster_projects_cluster_id_project_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_cluster_projects_cluster_id_idx btree; INDEX imz_cluster_projects_cluster_id_project_id_uq btree | cluster id | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 |
| cluster_projects | project_id | uuid | Não | Sem predefinição | FK -> projects.id ON UPDATE CASCADE ON DELETE CASCADE | imz_cluster_projects_cluster_id_project_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_cluster_projects_project_id_idx btree; INDEX imz_cluster_projects_cluster_id_project_id_uq btree | project id | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 |
| cluster_projects | role | text | Não | Sem predefinição | Não | imz_cluster_projects_check_03: role IN ('anchor','complementary','supporting') | role | role IN ('anchor','complementary','supporting') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| anchor_project_links | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| anchor_project_links | source_system | text | Não | 'investmoz' | imz_anchor_project_links_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_anchor_project_links_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| anchor_project_links | external_id | text | Sim | NULL | imz_anchor_project_links_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_anchor_project_links_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| anchor_project_links | version_no | integer | Não | 1 | Não | imz_anchor_project_links_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| anchor_project_links | data_classification | text | Não | 'internal' | Não | imz_anchor_project_links_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| anchor_project_links | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| anchor_project_links | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| anchor_project_links | updated_at | timestamptz | Não | now() | Não | INDEX imz_anchor_project_links_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| anchor_project_links | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| anchor_project_links | anchor_project_id | uuid | Não | Sem predefinição | FK -> projects.id ON UPDATE CASCADE ON DELETE CASCADE | imz_anchor_project_links_anchor_project_id_cluster_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_anchor_project_links_anchor_project_id_idx btree; INDEX imz_anchor_project_links_anchor_project_id_cluster_id_uq btree | anchor project id | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 |
| anchor_project_links | cluster_id | uuid | Não | Sem predefinição | FK -> economic_clusters.id ON UPDATE CASCADE ON DELETE CASCADE | imz_anchor_project_links_anchor_project_id_cluster_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_anchor_project_links_cluster_id_idx btree; INDEX imz_anchor_project_links_anchor_project_id_cluster_id_uq btree | cluster id | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 |
| anchor_project_links | rationale | text | Não | Sem predefinição | Não | rationale | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| complementary_project_links | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| complementary_project_links | source_system | text | Não | 'investmoz' | imz_complementary_project_links_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_complementary_project_links_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| complementary_project_links | external_id | text | Sim | NULL | imz_complementary_project_links_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_complementary_project_links_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| complementary_project_links | version_no | integer | Não | 1 | Não | imz_complementary_project_links_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| complementary_project_links | data_classification | text | Não | 'internal' | Não | imz_complementary_project_links_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| complementary_project_links | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| complementary_project_links | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| complementary_project_links | updated_at | timestamptz | Não | now() | Não | INDEX imz_complementary_project_links_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| complementary_project_links | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | ||
| complementary_project_links | anchor_project_id | uuid | Não | Sem predefinição | FK -> projects.id ON UPDATE CASCADE ON DELETE CASCADE | imz_complementary_project_links_anchor_project_id_co_90eddcd25a (composta) WHERE deleted_at IS NULL | imz_complementary_project_links_check_04: anchor_project_id<>complementary_project_id INDEX imz_complementary_project_links_anchor_project_id_idx btree; INDEX imz_complementary_project_links_anchor_project_id_co_90eddcd25a btree | anchor project id | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 |
| complementary_project_links | complementary_project_id | uuid | Não | Sem predefinição | FK -> projects.id ON UPDATE CASCADE ON DELETE CASCADE | imz_complementary_project_links_anchor_project_id_co_90eddcd25a (composta) WHERE deleted_at IS NULL | imz_complementary_project_links_check_04: anchor_project_id<>complementary_project_id INDEX imz_complementary_project_links_complementary_project_id_idx btree; INDEX imz_complementary_project_links_anchor_project_id_co_90eddcd25a btree | complementary project id | Não | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 |
| complementary_project_links | relation_type | text | Não | Sem predefinição | imz_complementary_project_links_anchor_project_id_co_90eddcd25a (composta) WHERE deleted_at IS NULL | imz_complementary_project_links_check_03: relation_type IN ('dependency','enabler','supplier','market') INDEX imz_complementary_project_links_anchor_project_id_co_90eddcd25a btree | relation type | relation_type IN ('dependency','enabler','supplier','market') | Não | False | False | database/migrations/2026_09_24_005000_investmoz_clusters.php | Reconciliado A.25/A.26 e A.31 | |
| development_corridors | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| development_corridors | source_system | text | Não | 'investmoz' | imz_development_corridors_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_development_corridors_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| development_corridors | external_id | text | Sim | NULL | imz_development_corridors_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_development_corridors_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| development_corridors | version_no | integer | Não | 1 | Não | imz_development_corridors_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| development_corridors | data_classification | text | Não | 'internal' | Não | imz_development_corridors_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| development_corridors | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| development_corridors | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| development_corridors | updated_at | timestamptz | Não | now() | Não | INDEX imz_development_corridors_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| development_corridors | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| development_corridors | code | text | Não | Sem predefinição | imz_development_corridors_code_uq WHERE deleted_at IS NULL | INDEX imz_development_corridors_code_uq btree | code | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| development_corridors | name | text | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| development_corridors | status | text | Não | Sem predefinição | Não | imz_development_corridors_check_03: status IN ('proposed','active','closed') INDEX imz_development_corridors_status_idx btree | status | status IN ('proposed','active','closed') | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| development_corridors | description | text | Sim | NULL | Não | description | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_locations | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_locations | source_system | text | Não | 'investmoz' | imz_corridor_locations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_corridor_locations_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_locations | external_id | text | Sim | NULL | imz_corridor_locations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_corridor_locations_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_locations | version_no | integer | Não | 1 | Não | imz_corridor_locations_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_locations | data_classification | text | Não | 'internal' | Não | imz_corridor_locations_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_locations | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_locations | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_locations | updated_at | timestamptz | Não | now() | Não | INDEX imz_corridor_locations_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_locations | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_locations | corridor_id | uuid | Não | Sem predefinição | FK -> development_corridors.id ON UPDATE CASCADE ON DELETE CASCADE | imz_corridor_locations_corridor_id_geo_location_id_uq (composta) WHERE deleted_at IS NULL; imz_corridor_locations_corridor_id_sequence_no_uq (composta) WHERE deleted_at IS NULL | INDEX imz_corridor_locations_corridor_id_idx btree; INDEX imz_corridor_locations_corridor_id_geo_location_id_uq btree; INDEX imz_corridor_locations_corridor_id_sequence_no_uq btree | corridor id | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 |
| corridor_locations | geo_location_id | uuid | Não | Sem predefinição | FK -> geo_locations.id ON UPDATE CASCADE ON DELETE RESTRICT | imz_corridor_locations_corridor_id_geo_location_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_corridor_locations_geo_location_id_idx btree; INDEX imz_corridor_locations_corridor_id_geo_location_id_uq btree | geo location id | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 |
| corridor_locations | sequence_no | integer | Não | Sem predefinição | imz_corridor_locations_corridor_id_sequence_no_uq (composta) WHERE deleted_at IS NULL | imz_corridor_locations_check_03: sequence_no>0 INDEX imz_corridor_locations_corridor_id_sequence_no_uq btree | sequence no | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_projects | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_projects | source_system | text | Não | 'investmoz' | imz_corridor_projects_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_corridor_projects_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_projects | external_id | text | Sim | NULL | imz_corridor_projects_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_corridor_projects_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_projects | version_no | integer | Não | 1 | Não | imz_corridor_projects_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_projects | data_classification | text | Não | 'internal' | Não | imz_corridor_projects_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_projects | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_projects | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_projects | updated_at | timestamptz | Não | now() | Não | INDEX imz_corridor_projects_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_projects | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_projects | corridor_id | uuid | Não | Sem predefinição | FK -> development_corridors.id ON UPDATE CASCADE ON DELETE CASCADE | imz_corridor_projects_corridor_id_project_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_corridor_projects_corridor_id_idx btree; INDEX imz_corridor_projects_corridor_id_project_id_uq btree | corridor id | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 |
| corridor_projects | project_id | uuid | Não | Sem predefinição | FK -> projects.id ON UPDATE CASCADE ON DELETE CASCADE | imz_corridor_projects_corridor_id_project_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_corridor_projects_project_id_idx btree; INDEX imz_corridor_projects_corridor_id_project_id_uq btree | project id | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 |
| corridor_clusters | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_clusters | source_system | text | Não | 'investmoz' | imz_corridor_clusters_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_corridor_clusters_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_clusters | external_id | text | Sim | NULL | imz_corridor_clusters_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_corridor_clusters_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_clusters | version_no | integer | Não | 1 | Não | imz_corridor_clusters_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_clusters | data_classification | text | Não | 'internal' | Não | imz_corridor_clusters_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_clusters | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_clusters | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_clusters | updated_at | timestamptz | Não | now() | Não | INDEX imz_corridor_clusters_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | |
| corridor_clusters | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 | ||
| corridor_clusters | corridor_id | uuid | Não | Sem predefinição | FK -> development_corridors.id ON UPDATE CASCADE ON DELETE CASCADE | imz_corridor_clusters_corridor_id_cluster_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_corridor_clusters_corridor_id_idx btree; INDEX imz_corridor_clusters_corridor_id_cluster_id_uq btree | corridor id | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 |
| corridor_clusters | cluster_id | uuid | Não | Sem predefinição | FK -> economic_clusters.id ON UPDATE CASCADE ON DELETE CASCADE | imz_corridor_clusters_corridor_id_cluster_id_uq (composta) WHERE deleted_at IS NULL | INDEX imz_corridor_clusters_cluster_id_idx btree; INDEX imz_corridor_clusters_corridor_id_cluster_id_uq btree | cluster id | Não | Não | False | False | database/migrations/2026_09_24_006000_investmoz_corridors.php | Reconciliado A.25/A.26 e A.31 |
| investors | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| investors | source_system | text | Não | 'investmoz' | imz_investors_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_investors_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| investors | external_id | text | Sim | NULL | imz_investors_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_investors_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| investors | version_no | integer | Não | 1 | Não | imz_investors_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| investors | data_classification | text | Não | 'internal' | Não | imz_investors_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| investors | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| investors | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| investors | updated_at | timestamptz | Não | now() | Não | INDEX imz_investors_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| investors | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| investors | organization_id | uuid | Sim | NULL | FK -> organizations.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_investors_organization_id_idx btree | organization id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| investors | legal_name | text | Não | Sem predefinição | Não | legal name | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| investors | investor_type | text | Não | Sem predefinição | Não | imz_investors_check_03: investor_type IN ('domestic','foreign','institutional','individual') | investor type | investor_type IN ('domestic','foreign','institutional','individual') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| investors | status | text | Não | Sem predefinição | Não | imz_investors_check_04: status IN ('prospect','active','inactive') INDEX imz_investors_status_idx btree | status | status IN ('prospect','active','inactive') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| contacts | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| contacts | source_system | text | Não | 'investmoz' | imz_contacts_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_contacts_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| contacts | external_id | text | Sim | NULL | imz_contacts_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_contacts_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| contacts | version_no | integer | Não | 1 | Não | imz_contacts_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| contacts | data_classification | text | Não | 'internal' | Não | imz_contacts_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| contacts | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| contacts | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| contacts | updated_at | timestamptz | Não | now() | Não | INDEX imz_contacts_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| contacts | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| contacts | full_name | text | Não | Sem predefinição | Não | full name | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| contacts | text | Sim | NULL | Não | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||||
| contacts | phone | text | Sim | NULL | Não | phone | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| investor_contacts | investor_id | uuid | Não | Sem predefinição | PK; FK -> investors.id ON UPDATE CASCADE ON DELETE CASCADE | PRIMARY KEY composta: investor_id, contact_id | INDEX imz_investor_contacts_investor_id_idx btree | investor id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| investor_contacts | contact_id | uuid | Não | Sem predefinição | PK; FK -> contacts.id ON UPDATE CASCADE ON DELETE CASCADE | PRIMARY KEY composta: investor_id, contact_id | INDEX imz_investor_contacts_contact_id_idx btree | contact id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| investor_contacts | is_primary | boolean | Não | false | Não | Contacto principal deste investidor; limite quantitativo pendente | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| investor_contacts | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| investor_contacts | updated_at | timestamptz | Não | now() | Não | INDEX imz_investor_contacts_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| leads | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| leads | source_system | text | Não | 'investmoz' | imz_leads_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_leads_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| leads | external_id | text | Sim | NULL | imz_leads_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_leads_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| leads | version_no | integer | Não | 1 | Não | imz_leads_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| leads | data_classification | text | Não | 'internal' | Não | imz_leads_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| leads | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| leads | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| leads | updated_at | timestamptz | Não | now() | Não | INDEX imz_leads_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| leads | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| leads | investor_id | uuid | Sim | NULL | FK -> investors.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_leads_investor_id_idx btree | investor id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| leads | owner_user_id | bigint | Sim | NULL | FK -> users.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_leads_owner_user_id_idx btree | owner user id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| leads | title | text | Não | Sem predefinição | Não | title | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| leads | status | text | Não | Sem predefinição | Não | imz_leads_check_03: status IN ('new','qualified','disqualified','converted') INDEX imz_leads_status_idx btree | status | status IN ('new','qualified','disqualified','converted') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| leads | estimated_amount | numeric(20,2) | Sim | NULL | Não | imz_leads_check_04: (estimated_amount IS NULL)=(currency IS NULL); imz_leads_check_05: estimated_amount IS NULL OR estimated_amount >= 0 | Montante estimado exacto não negativo | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| leads | currency | char(3) | Sim | NULL | Não | imz_leads_check_04: (estimated_amount IS NULL)=(currency IS NULL); imz_leads_check_06: currency IS NULL OR currency ~ '^[A-Z]{3}$' | Código monetário; três letras maiúsculas; lista ISO autorizada pendente | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | source_system | text | Não | 'investmoz' | imz_crm_opportunities_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_crm_opportunities_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | external_id | text | Sim | NULL | imz_crm_opportunities_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_crm_opportunities_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | version_no | integer | Não | 1 | Não | imz_crm_opportunities_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | data_classification | text | Não | 'internal' | Não | imz_crm_opportunities_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| crm_opportunities | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| crm_opportunities | updated_at | timestamptz | Não | now() | Não | INDEX imz_crm_opportunities_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| crm_opportunities | lead_id | uuid | Sim | NULL | FK -> leads.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_crm_opportunities_lead_id_idx btree | lead id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| crm_opportunities | project_id | uuid | Sim | NULL | FK -> projects.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_crm_opportunities_project_id_idx btree | project id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| crm_opportunities | owner_user_id | bigint | Sim | NULL | FK -> users.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_crm_opportunities_owner_user_id_idx btree | owner user id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| crm_opportunities | stage | text | Não | Sem predefinição | Não | imz_crm_opportunities_check_03: stage IN ('discovery','assessment','negotiation','approved','lost') | stage | stage IN ('discovery','assessment','negotiation','approved','lost') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | amount | numeric(20,2) | Sim | NULL | Não | imz_crm_opportunities_check_05: (amount IS NULL)=(currency IS NULL); imz_crm_opportunities_check_06: amount IS NULL OR amount >= 0 | Montante monetário exacto não negativo | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | currency | char(3) | Sim | NULL | Não | imz_crm_opportunities_check_05: (amount IS NULL)=(currency IS NULL); imz_crm_opportunities_check_07: currency IS NULL OR currency ~ '^[A-Z]{3}$' | Código monetário; três letras maiúsculas; lista ISO autorizada pendente | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| crm_opportunities | probability | numeric(5,2) | Sim | NULL | Não | imz_crm_opportunities_check_04: probability BETWEEN 0 AND 100 | probability | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| activities | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| activities | source_system | text | Não | 'investmoz' | imz_activities_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_activities_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| activities | external_id | text | Sim | NULL | imz_activities_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_activities_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| activities | version_no | integer | Não | 1 | Não | imz_activities_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| activities | data_classification | text | Não | 'internal' | Não | imz_activities_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| activities | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| activities | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| activities | updated_at | timestamptz | Não | now() | Não | INDEX imz_activities_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| activities | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| activities | investor_id | uuid | Sim | NULL | FK -> investors.id ON UPDATE CASCADE ON DELETE CASCADE | Não | INDEX imz_activities_investor_id_idx btree | investor id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| activities | opportunity_id | uuid | Sim | NULL | FK -> crm_opportunities.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_activities_opportunity_id_idx btree | opportunity id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| activities | actor_user_id | bigint | Sim | NULL | FK -> users.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_activities_actor_user_id_idx btree | actor user id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| activities | activity_type | text | Não | Sem predefinição | Não | imz_activities_check_03: activity_type IN ('call','meeting','email','note') | activity type | activity_type IN ('call','meeting','email','note') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| activities | occurred_at | timestamptz | Não | Sem predefinição | Não | occurred at | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| activities | summary | text | Não | Sem predefinição | Não | summary | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| tasks | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| tasks | source_system | text | Não | 'investmoz' | imz_tasks_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_tasks_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| tasks | external_id | text | Sim | NULL | imz_tasks_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_tasks_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| tasks | version_no | integer | Não | 1 | Não | imz_tasks_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| tasks | data_classification | text | Não | 'internal' | Não | imz_tasks_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| tasks | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| tasks | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| tasks | updated_at | timestamptz | Não | now() | Não | INDEX imz_tasks_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| tasks | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| tasks | assignee_user_id | bigint | Sim | NULL | FK -> users.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_tasks_assignee_user_id_idx btree | assignee user id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| tasks | opportunity_id | uuid | Sim | NULL | FK -> crm_opportunities.id ON UPDATE CASCADE ON DELETE CASCADE | Não | INDEX imz_tasks_opportunity_id_idx btree | opportunity id | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 |
| tasks | title | text | Não | Sem predefinição | Não | title | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| tasks | status | text | Não | Sem predefinição | Não | imz_tasks_check_03: status IN ('open','in_progress','done','cancelled') INDEX imz_tasks_status_idx btree | status | status IN ('open','in_progress','done','cancelled') | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | |
| tasks | due_at | timestamptz | Sim | NULL | Não | due at | Não | Não | False | False | database/migrations/2026_09_24_007000_investmoz_crm.php | Reconciliado A.25/A.26 e A.31 | ||
| investor_journeys | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| investor_journeys | source_system | text | Não | 'investmoz' | imz_investor_journeys_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_investor_journeys_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| investor_journeys | external_id | text | Sim | NULL | imz_investor_journeys_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_investor_journeys_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| investor_journeys | version_no | integer | Não | 1 | Não | imz_investor_journeys_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| investor_journeys | data_classification | text | Não | 'internal' | Não | imz_investor_journeys_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| investor_journeys | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| investor_journeys | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| investor_journeys | updated_at | timestamptz | Não | now() | Não | INDEX imz_investor_journeys_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| investor_journeys | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| investor_journeys | investor_id | uuid | Não | Sem predefinição | FK -> investors.id ON UPDATE CASCADE ON DELETE CASCADE | Não | INDEX imz_investor_journeys_investor_id_idx btree | investor id | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| investor_journeys | opportunity_id | uuid | Sim | NULL | FK -> crm_opportunities.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_investor_journeys_opportunity_id_idx btree | opportunity id | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| investor_journeys | status | text | Não | Sem predefinição | Não | imz_investor_journeys_check_03: status IN ('started','active','completed','cancelled') INDEX imz_investor_journeys_status_idx btree | status | status IN ('started','active','completed','cancelled') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| investor_journeys | started_at | timestamptz | Não | now() | Não | started at | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| journey_steps | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| journey_steps | source_system | text | Não | 'investmoz' | imz_journey_steps_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_journey_steps_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| journey_steps | external_id | text | Sim | NULL | imz_journey_steps_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_journey_steps_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| journey_steps | version_no | integer | Não | 1 | Não | imz_journey_steps_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| journey_steps | data_classification | text | Não | 'internal' | Não | imz_journey_steps_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| journey_steps | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| journey_steps | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| journey_steps | updated_at | timestamptz | Não | now() | Não | INDEX imz_journey_steps_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| journey_steps | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| journey_steps | journey_id | uuid | Não | Sem predefinição | FK -> investor_journeys.id ON UPDATE CASCADE ON DELETE CASCADE | imz_journey_steps_journey_id_sequence_no_uq (composta) WHERE deleted_at IS NULL; imz_journey_steps_journey_id_step_code_uq (composta) WHERE deleted_at IS NULL | INDEX imz_journey_steps_journey_id_idx btree; INDEX imz_journey_steps_journey_id_sequence_no_uq btree; INDEX imz_journey_steps_journey_id_step_code_uq btree | journey id | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| journey_steps | step_code | text | Não | Sem predefinição | imz_journey_steps_journey_id_step_code_uq (composta) WHERE deleted_at IS NULL | INDEX imz_journey_steps_journey_id_step_code_uq btree | step code | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| journey_steps | sequence_no | integer | Não | Sem predefinição | imz_journey_steps_journey_id_sequence_no_uq (composta) WHERE deleted_at IS NULL | imz_journey_steps_check_03: sequence_no>0 INDEX imz_journey_steps_journey_id_sequence_no_uq btree | sequence no | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| journey_steps | status | text | Não | Sem predefinição | Não | imz_journey_steps_check_04: status IN ('pending','active','completed','blocked') INDEX imz_journey_steps_status_idx btree | status | status IN ('pending','active','completed','blocked') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| submissions | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| submissions | source_system | text | Não | 'investmoz' | imz_submissions_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_submissions_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| submissions | external_id | text | Sim | NULL | imz_submissions_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_submissions_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| submissions | version_no | integer | Não | 1 | Não | imz_submissions_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| submissions | data_classification | text | Não | 'internal' | Não | imz_submissions_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| submissions | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| submissions | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| submissions | updated_at | timestamptz | Não | now() | Não | INDEX imz_submissions_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| submissions | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| submissions | journey_step_id | uuid | Não | Sem predefinição | FK -> journey_steps.id ON UPDATE CASCADE ON DELETE CASCADE | Não | INDEX imz_submissions_journey_step_id_idx btree | journey step id | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| submissions | submitted_by | bigint | Sim | NULL | FK -> users.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_submissions_submitted_by_idx btree | submitted by | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| submissions | status | text | Não | Sem predefinição | Não | imz_submissions_check_03: status IN ('draft','submitted','accepted','rejected') INDEX imz_submissions_status_idx btree | status | status IN ('draft','submitted','accepted','rejected') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| submissions | payload | jsonb | Não | '{}'::jsonb | Não | INDEX imz_submissions_payload_idx gin | Conteúdo da submissão/evento; contrato por tipo pendente | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| submissions | submitted_at | timestamptz | Sim | NULL | Não | submitted at | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| aftercare_plans | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| aftercare_plans | source_system | text | Não | 'investmoz' | imz_aftercare_plans_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_aftercare_plans_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| aftercare_plans | external_id | text | Sim | NULL | imz_aftercare_plans_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_aftercare_plans_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| aftercare_plans | version_no | integer | Não | 1 | Não | imz_aftercare_plans_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| aftercare_plans | data_classification | text | Não | 'internal' | Não | imz_aftercare_plans_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| aftercare_plans | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| aftercare_plans | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| aftercare_plans | updated_at | timestamptz | Não | now() | Não | INDEX imz_aftercare_plans_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| aftercare_plans | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| aftercare_plans | investor_id | uuid | Não | Sem predefinição | FK -> investors.id ON UPDATE CASCADE ON DELETE CASCADE | Não | INDEX imz_aftercare_plans_investor_id_idx btree | investor id | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| aftercare_plans | project_id | uuid | Sim | NULL | FK -> projects.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_aftercare_plans_project_id_idx btree | project id | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| aftercare_plans | owner_user_id | bigint | Sim | NULL | FK -> users.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_aftercare_plans_owner_user_id_idx btree | owner user id | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| aftercare_plans | status | text | Não | Sem predefinição | Não | imz_aftercare_plans_check_03: status IN ('draft','active','closed') INDEX imz_aftercare_plans_status_idx btree | status | status IN ('draft','active','closed') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| aftercare_plans | review_date | date | Sim | NULL | Não | review date | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| constraints | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| constraints | source_system | text | Não | 'investmoz' | imz_constraints_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_constraints_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| constraints | external_id | text | Sim | NULL | imz_constraints_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_constraints_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| constraints | version_no | integer | Não | 1 | Não | imz_constraints_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| constraints | data_classification | text | Não | 'internal' | Não | imz_constraints_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| constraints | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| constraints | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| constraints | updated_at | timestamptz | Não | now() | Não | INDEX imz_constraints_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| constraints | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| constraints | aftercare_plan_id | uuid | Não | Sem predefinição | FK -> aftercare_plans.id ON UPDATE CASCADE ON DELETE CASCADE | Não | INDEX imz_constraints_aftercare_plan_id_idx btree | aftercare plan id | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| constraints | category | text | Não | Sem predefinição | Não | category | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| constraints | description | text | Não | Sem predefinição | Não | description | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| constraints | severity | text | Não | Sem predefinição | Não | imz_constraints_check_03: severity IN ('low','medium','high','critical') | severity | severity IN ('low','medium','high','critical') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| constraints | status | text | Não | Sem predefinição | Não | imz_constraints_check_04: status IN ('open','mitigating','resolved') INDEX imz_constraints_status_idx btree | status | status IN ('open','mitigating','resolved') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| escalations | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| escalations | source_system | text | Não | 'investmoz' | imz_escalations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_escalations_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| escalations | external_id | text | Sim | NULL | imz_escalations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_escalations_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| escalations | version_no | integer | Não | 1 | Não | imz_escalations_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| escalations | data_classification | text | Não | 'internal' | Não | imz_escalations_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| escalations | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| escalations | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| escalations | updated_at | timestamptz | Não | now() | Não | INDEX imz_escalations_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| escalations | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| escalations | constraint_id | uuid | Não | Sem predefinição | FK -> constraints.id ON UPDATE CASCADE ON DELETE CASCADE | Não | INDEX imz_escalations_constraint_id_idx btree | constraint id | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| escalations | escalated_by | bigint | Sim | NULL | FK -> users.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_escalations_escalated_by_idx btree | escalated by | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 |
| escalations | level | text | Não | Sem predefinição | Não | imz_escalations_check_03: level IN ('operational','management','executive') | level | level IN ('operational','management','executive') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| escalations | status | text | Não | Sem predefinição | Não | imz_escalations_check_04: status IN ('open','acknowledged','closed') INDEX imz_escalations_status_idx btree | status | status IN ('open','acknowledged','closed') | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | |
| escalations | escalated_at | timestamptz | Não | now() | Não | escalated at | Não | Não | False | False | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | Reconciliado A.25/A.26 e A.31 | ||
| skills | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| skills | source_system | text | Não | 'investmoz' | imz_skills_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_skills_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| skills | external_id | text | Sim | NULL | imz_skills_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_skills_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| skills | version_no | integer | Não | 1 | Não | imz_skills_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| skills | data_classification | text | Não | 'internal' | Não | imz_skills_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| skills | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| skills | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| skills | updated_at | timestamptz | Não | now() | Não | INDEX imz_skills_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| skills | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| skills | code | text | Não | Sem predefinição | imz_skills_code_uq WHERE deleted_at IS NULL | INDEX imz_skills_code_uq btree | code | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| skills | name | text | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| occupations | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| occupations | source_system | text | Não | 'investmoz' | imz_occupations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_occupations_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| occupations | external_id | text | Sim | NULL | imz_occupations_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_occupations_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| occupations | version_no | integer | Não | 1 | Não | imz_occupations_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| occupations | data_classification | text | Não | 'internal' | Não | imz_occupations_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| occupations | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| occupations | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| occupations | updated_at | timestamptz | Não | now() | Não | INDEX imz_occupations_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| occupations | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| occupations | code | text | Não | Sem predefinição | imz_occupations_code_uq WHERE deleted_at IS NULL | INDEX imz_occupations_code_uq btree | code | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| occupations | name | text | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| training_needs | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_needs | source_system | text | Não | 'investmoz' | imz_training_needs_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_training_needs_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_needs | external_id | text | Sim | NULL | imz_training_needs_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_training_needs_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_needs | version_no | integer | Não | 1 | Não | imz_training_needs_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_needs | data_classification | text | Não | 'internal' | Não | imz_training_needs_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_needs | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| training_needs | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| training_needs | updated_at | timestamptz | Não | now() | Não | INDEX imz_training_needs_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_needs | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| training_needs | project_id | uuid | Sim | NULL | FK -> projects.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_training_needs_project_id_idx btree | project id | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 |
| training_needs | occupation_id | uuid | Sim | NULL | FK -> occupations.id ON UPDATE CASCADE ON DELETE RESTRICT | Não | INDEX imz_training_needs_occupation_id_idx btree | occupation id | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 |
| training_needs | skill_id | uuid | Sim | NULL | FK -> skills.id ON UPDATE CASCADE ON DELETE RESTRICT | Não | INDEX imz_training_needs_skill_id_idx btree | skill id | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 |
| training_needs | quantity | integer | Não | Sem predefinição | Não | imz_training_needs_check_03: quantity>0 | quantity | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_needs | priority | text | Não | Sem predefinição | Não | imz_training_needs_check_04: priority IN ('Must','Should','Could') | priority | priority IN ('Must','Should','Could') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_providers | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_providers | source_system | text | Não | 'investmoz' | imz_training_providers_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_training_providers_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_providers | external_id | text | Sim | NULL | imz_training_providers_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_training_providers_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_providers | version_no | integer | Não | 1 | Não | imz_training_providers_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_providers | data_classification | text | Não | 'internal' | Não | imz_training_providers_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_providers | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| training_providers | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| training_providers | updated_at | timestamptz | Não | now() | Não | INDEX imz_training_providers_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| training_providers | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| training_providers | organization_id | uuid | Sim | NULL | FK -> organizations.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_training_providers_organization_id_idx btree | organization id | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 |
| training_providers | name | text | Não | Sem predefinição | Não | name | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| training_providers | status | text | Não | Sem predefinição | Não | imz_training_providers_check_03: status IN ('candidate','approved','inactive') INDEX imz_training_providers_status_idx btree | status | status IN ('candidate','approved','inactive') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| courses | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| courses | source_system | text | Não | 'investmoz' | imz_courses_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_courses_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| courses | external_id | text | Sim | NULL | imz_courses_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_courses_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| courses | version_no | integer | Não | 1 | Não | imz_courses_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| courses | data_classification | text | Não | 'internal' | Não | imz_courses_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| courses | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| courses | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| courses | updated_at | timestamptz | Não | now() | Não | INDEX imz_courses_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| courses | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| courses | provider_id | uuid | Não | Sem predefinição | FK -> training_providers.id ON UPDATE CASCADE ON DELETE CASCADE | imz_courses_provider_id_code_uq (composta) WHERE deleted_at IS NULL | INDEX imz_courses_provider_id_idx btree; INDEX imz_courses_provider_id_code_uq btree | provider id | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 |
| courses | code | text | Não | Sem predefinição | imz_courses_provider_id_code_uq (composta) WHERE deleted_at IS NULL | INDEX imz_courses_provider_id_code_uq btree | code | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| courses | title | text | Não | Sem predefinição | Não | title | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| courses | status | text | Não | Sem predefinição | Não | imz_courses_check_03: status IN ('draft','published','retired') INDEX imz_courses_status_idx btree | status | status IN ('draft','published','retired') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | source_system | text | Não | 'investmoz' | imz_education_opportunities_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_education_opportunities_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | external_id | text | Sim | NULL | imz_education_opportunities_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_education_opportunities_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | version_no | integer | Não | 1 | Não | imz_education_opportunities_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | data_classification | text | Não | 'internal' | Não | imz_education_opportunities_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| education_opportunities | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| education_opportunities | updated_at | timestamptz | Não | now() | Não | INDEX imz_education_opportunities_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | ||
| education_opportunities | course_id | uuid | Não | Sem predefinição | FK -> courses.id ON UPDATE CASCADE ON DELETE CASCADE | Não | INDEX imz_education_opportunities_course_id_idx btree | course id | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 |
| education_opportunities | geo_location_id | uuid | Sim | NULL | FK -> geo_locations.id ON UPDATE CASCADE ON DELETE SET NULL | Não | INDEX imz_education_opportunities_geo_location_id_idx btree | geo location id | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 |
| education_opportunities | start_date | date | Não | Sem predefinição | Não | imz_education_opportunities_check_05: end_date IS NULL OR end_date>=start_date | start date | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | end_date | date | Sim | NULL | Não | imz_education_opportunities_check_05: end_date IS NULL OR end_date>=start_date | end date | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | capacity | integer | Sim | NULL | Não | imz_education_opportunities_check_03: capacity>=0 | capacity | Não | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| education_opportunities | status | text | Não | Sem predefinição | Não | imz_education_opportunities_check_04: status IN ('planned','open','closed','cancelled') INDEX imz_education_opportunities_status_idx btree | status | status IN ('planned','open','closed','cancelled') | Não | False | False | database/migrations/2026_09_24_009000_investmoz_education.php | Reconciliado A.25/A.26 e A.31 | |
| project_documents | project_id | uuid | Não | Sem predefinição | PK; FK -> projects.id ON UPDATE CASCADE ON DELETE CASCADE | PRIMARY KEY composta: project_id, document_id | INDEX imz_project_documents_project_id_idx btree | project id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| project_documents | document_id | uuid | Não | Sem predefinição | PK; FK -> documents.id ON UPDATE CASCADE ON DELETE RESTRICT | PRIMARY KEY composta: project_id, document_id | INDEX imz_project_documents_document_id_idx btree | document id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| project_documents | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 | ||
| investor_documents | investor_id | uuid | Não | Sem predefinição | PK; FK -> investors.id ON UPDATE CASCADE ON DELETE CASCADE | PRIMARY KEY composta: investor_id, document_id | INDEX imz_investor_documents_investor_id_idx btree | investor id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| investor_documents | document_id | uuid | Não | Sem predefinição | PK; FK -> documents.id ON UPDATE CASCADE ON DELETE RESTRICT | PRIMARY KEY composta: investor_id, document_id | INDEX imz_investor_documents_document_id_idx btree | document id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| investor_documents | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 | ||
| journey_documents | journey_id | uuid | Não | Sem predefinição | PK; FK -> investor_journeys.id ON UPDATE CASCADE ON DELETE CASCADE | PRIMARY KEY composta: journey_id, document_id | INDEX imz_journey_documents_journey_id_idx btree | journey id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| journey_documents | document_id | uuid | Não | Sem predefinição | PK; FK -> documents.id ON UPDATE CASCADE ON DELETE RESTRICT | PRIMARY KEY composta: journey_id, document_id | INDEX imz_journey_documents_document_id_idx btree | document id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| journey_documents | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 | ||
| aftercare_documents | aftercare_plan_id | uuid | Não | Sem predefinição | PK; FK -> aftercare_plans.id ON UPDATE CASCADE ON DELETE CASCADE | PRIMARY KEY composta: aftercare_plan_id, document_id | INDEX imz_aftercare_documents_aftercare_plan_id_idx btree | aftercare plan id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| aftercare_documents | document_id | uuid | Não | Sem predefinição | PK; FK -> documents.id ON UPDATE CASCADE ON DELETE RESTRICT | PRIMARY KEY composta: aftercare_plan_id, document_id | INDEX imz_aftercare_documents_document_id_idx btree | document id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| aftercare_documents | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 | ||
| education_documents | education_opportunity_id | uuid | Não | Sem predefinição | PK; FK -> education_opportunities.id ON UPDATE CASCADE ON DELETE CASCADE | PRIMARY KEY composta: education_opportunity_id, document_id | INDEX imz_education_documents_education_opportunity_id_idx btree | education opportunity id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| education_documents | document_id | uuid | Não | Sem predefinição | PK; FK -> documents.id ON UPDATE CASCADE ON DELETE RESTRICT | PRIMARY KEY composta: education_opportunity_id, document_id | INDEX imz_education_documents_document_id_idx btree | document id | Não | Não | False | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 |
| education_documents | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_009500_investmoz_document_links.php | Reconciliado A.25/A.26 e A.31 | ||
| audit_events | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | |
| audit_events | source_system | text | Não | 'investmoz' | imz_audit_events_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_audit_events_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | |
| audit_events | external_id | text | Sim | NULL | imz_audit_events_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_audit_events_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | |
| audit_events | data_classification | text | Não | 'internal' | Não | imz_audit_events_check_01: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | |
| audit_events | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | ||
| audit_events | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | ||
| audit_events | actor_user_id | bigint | Sim | NULL | FK -> users.id ON UPDATE RESTRICT ON DELETE RESTRICT | Não | INDEX imz_audit_events_actor_user_id_idx btree | actor user id | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 |
| audit_events | entity_type | text | Não | Sem predefinição | Não | entity type | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | ||
| audit_events | entity_id | uuid | Sim | NULL | Não | ID histórico UUID sem FK; a entidade pode já não existir | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | ||
| audit_events | action | text | Não | Sem predefinição | Não | action | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | ||
| audit_events | occurred_at | timestamptz | Não | now() | Não | occurred at | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | ||
| audit_events | before_data | jsonb | Sim | NULL | Não | Representação anterior; aplicação deve remover segredos | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | ||
| audit_events | after_data | jsonb | Sim | NULL | Não | INDEX imz_audit_events_after_data_idx gin | Representação posterior; aplicação deve remover segredos | Não | Não | False | False | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | Reconciliado A.25/A.26 e A.31 | |
| outbox_events | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| outbox_events | source_system | text | Não | 'investmoz' | imz_outbox_events_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_outbox_events_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| outbox_events | external_id | text | Sim | NULL | imz_outbox_events_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_outbox_events_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| outbox_events | version_no | integer | Não | 1 | Não | imz_outbox_events_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| outbox_events | data_classification | text | Não | 'internal' | Não | imz_outbox_events_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| outbox_events | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| outbox_events | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| outbox_events | updated_at | timestamptz | Não | now() | Não | INDEX imz_outbox_events_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| outbox_events | aggregate_type | text | Não | Sem predefinição | Não | aggregate type | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| outbox_events | aggregate_id | uuid | Não | Sem predefinição | Não | UUID do agregado produtor; sem FK polimórfica | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| outbox_events | event_type | text | Não | Sem predefinição | Não | event type | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| outbox_events | payload | jsonb | Não | Sem predefinição | Não | Conteúdo da submissão/evento; contrato por tipo pendente | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| outbox_events | status | text | Não | Sem predefinição | Não | imz_outbox_events_check_03: status IN ('pending','published','failed') INDEX imz_outbox_events_status_idx btree; INDEX imz_outbox_events_status_available_at_idx btree | status | status IN ('pending','published','failed') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| outbox_events | available_at | timestamptz | Não | now() | Não | INDEX imz_outbox_events_status_available_at_idx btree | available at | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| outbox_events | published_at | timestamptz | Sim | NULL | Não | published at | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| inbox_events | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| inbox_events | source_system | text | Não | 'investmoz' | imz_inbox_events_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_inbox_events_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| inbox_events | external_id | text | Sim | NULL | imz_inbox_events_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_inbox_events_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| inbox_events | version_no | integer | Não | 1 | Não | imz_inbox_events_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| inbox_events | data_classification | text | Não | 'internal' | Não | imz_inbox_events_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| inbox_events | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| inbox_events | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| inbox_events | updated_at | timestamptz | Não | now() | Não | INDEX imz_inbox_events_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| inbox_events | message_id | text | Não | Sem predefinição | imz_inbox_events_message_id_uq | INDEX imz_inbox_events_message_id_uq btree | message id | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| inbox_events | event_type | text | Não | Sem predefinição | Não | event type | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| inbox_events | payload | jsonb | Não | Sem predefinição | Não | Conteúdo da submissão/evento; contrato por tipo pendente | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| inbox_events | status | text | Não | Sem predefinição | Não | imz_inbox_events_check_03: status IN ('received','processed','failed') INDEX imz_inbox_events_status_idx btree | status | status IN ('received','processed','failed') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| inbox_events | received_at | timestamptz | Não | now() | Não | received at | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| inbox_events | processed_at | timestamptz | Sim | NULL | Não | processed at | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| sync_runs | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| sync_runs | source_system | text | Não | 'investmoz' | imz_sync_runs_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_sync_runs_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| sync_runs | external_id | text | Sim | NULL | imz_sync_runs_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_sync_runs_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| sync_runs | version_no | integer | Não | 1 | Não | imz_sync_runs_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| sync_runs | data_classification | text | Não | 'internal' | Não | imz_sync_runs_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| sync_runs | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| sync_runs | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| sync_runs | updated_at | timestamptz | Não | now() | Não | INDEX imz_sync_runs_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| sync_runs | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| sync_runs | integration_name | text | Não | Sem predefinição | Não | integration name | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| sync_runs | direction | text | Não | Sem predefinição | Não | imz_sync_runs_check_03: direction IN ('inbound','outbound') | direction | direction IN ('inbound','outbound') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| sync_runs | status | text | Não | Sem predefinição | Não | imz_sync_runs_check_04: status IN ('running','succeeded','failed','cancelled') INDEX imz_sync_runs_status_idx btree | status | status IN ('running','succeeded','failed','cancelled') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| sync_runs | started_at | timestamptz | Não | now() | Não | started at | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| sync_runs | ended_at | timestamptz | Sim | NULL | Não | ended at | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| sync_runs | totals | jsonb | Não | '{}'::jsonb | Não | totals | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| reconciliation_issues | id | uuid | Não | gen_random_uuid() | PK | PRIMARY KEY | Identificador primário da entidade | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| reconciliation_issues | source_system | text | Não | 'investmoz' | imz_reconciliation_issues_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_reconciliation_issues_source_system_external_id_uq btree | Sistema de origem; integra a chave estável de importação | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| reconciliation_issues | external_id | text | Sim | NULL | imz_reconciliation_issues_source_system_external_id_uq (composta) WHERE external_id IS NOT NULL | INDEX imz_reconciliation_issues_source_system_external_id_uq btree | Identificador na origem; NULL quando não fornecido | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| reconciliation_issues | version_no | integer | Não | 1 | Não | imz_reconciliation_issues_check_01: version_no > 0 | Versão positiva; comparação compete ao importador | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| reconciliation_issues | data_classification | text | Não | 'internal' | Não | imz_reconciliation_issues_check_02: data_classification IN ('public','internal','confidential','restricted') | Classificação de acesso; não substitui autorização | data_classification IN ('public','internal','confidential','restricted') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| reconciliation_issues | correlation_id | uuid | Sim | NULL | Não | Correlação entre operações; não é FK | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| reconciliation_issues | created_at | timestamptz | Não | now() | Não | Instante de criação | Não | Não | True | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| reconciliation_issues | updated_at | timestamptz | Não | now() | Não | INDEX imz_reconciliation_issues_updated_at_idx btree | Instante da última actualização | Não | Não | True | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| reconciliation_issues | deleted_at | timestamptz | Sim | NULL | Não | Eliminação lógica; NULL indica activo | Não | Não | False | True | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| reconciliation_issues | sync_run_id | uuid | Não | Sem predefinição | FK -> sync_runs.id ON UPDATE CASCADE ON DELETE CASCADE | Não | INDEX imz_reconciliation_issues_sync_run_id_idx btree; INDEX imz_reconciliation_issues_sync_run_id_status_idx btree | sync run id | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 |
| reconciliation_issues | entity_type | text | Não | Sem predefinição | Não | entity type | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| reconciliation_issues | external_id_ref | text | Sim | NULL | Não | external id ref | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | ||
| reconciliation_issues | issue_type | text | Não | Sem predefinição | Não | imz_reconciliation_issues_check_03: issue_type IN ('missing','duplicate','orphan','checksum','geometry','value') | issue type | issue_type IN ('missing','duplicate','orphan','checksum','geometry','value') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| reconciliation_issues | severity | text | Não | Sem predefinição | Não | imz_reconciliation_issues_check_04: severity IN ('warning','error') | severity | severity IN ('warning','error') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| reconciliation_issues | status | text | Não | Sem predefinição | Não | imz_reconciliation_issues_check_05: status IN ('open','accepted','resolved') INDEX imz_reconciliation_issues_status_idx btree; INDEX imz_reconciliation_issues_sync_run_id_status_idx btree | status | status IN ('open','accepted','resolved') | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 | |
| reconciliation_issues | details | jsonb | Não | '{}'::jsonb | Não | details | Não | Não | False | False | database/migrations/2026_09_24_011000_investmoz_integrations.php | Reconciliado A.25/A.26 e A.31 |
Modelo C — Matriz de relacionamentos
| Origem | Campo FK | Destino | Cardinalidade | Obrigatório | ON UPDATE | ON DELETE | Tabela associativa/regra | Migration |
|---|---|---|---|---|---|---|---|---|
| passkeys | user_id | users.id | N:1 | Sim | NO ACTION | CASCADE | passkeys_user_id_foreign | database/migrations/2024_01_01_000000_create_passkeys_table.php |
| opportunities | sector_id | sectors.id | N:1 | Sim | CASCADE | RESTRICT | opportunities_sector_id_foreign | database/migrations/2026_01_01_000002_create_opportunities_table.php |
| interest_requests | opportunity_id | opportunities.id | N:1 | Não | CASCADE | SET NULL | interest_requests_opportunity_id_foreign | database/migrations/2026_01_01_000003_create_interest_requests_table.php |
| interest_requests | reviewed_by | users.id | N:1 | Não | NO ACTION | SET NULL | interest_requests_reviewed_by_foreign | database/migrations/2026_01_01_000003_create_interest_requests_table.php |
| memberships | user_id | users.id | N:1 | Sim | CASCADE | CASCADE | imz_memberships_user_id_fk | database/migrations/2026_09_24_001000_investmoz_identity.php |
| memberships | organization_id | organizations.id | N:1 | Sim | CASCADE | CASCADE | imz_memberships_organization_id_fk | database/migrations/2026_09_24_001000_investmoz_identity.php |
| consents | user_id | users.id | N:1 | Não | CASCADE | SET NULL | imz_consents_user_id_fk | database/migrations/2026_09_24_001000_investmoz_identity.php |
| geo_locations | parent_id | geo_locations.id | N:1 | Não | CASCADE | RESTRICT | imz_geo_locations_parent_id_fk | database/migrations/2026_09_24_003000_investmoz_geography.php |
| geo_geometries | geo_location_id | geo_locations.id | N:1 | Sim | CASCADE | CASCADE | imz_geo_geometries_geo_location_id_fk | database/migrations/2026_09_24_003000_investmoz_geography.php |
| project_locations | project_id | projects.id | N:1 | Sim | CASCADE | CASCADE | imz_project_locations_project_id_fk | database/migrations/2026_09_24_004000_investmoz_projects.php |
| project_locations | geo_location_id | geo_locations.id | N:1 | Sim | CASCADE | RESTRICT | imz_project_locations_geo_location_id_fk | database/migrations/2026_09_24_004000_investmoz_projects.php |
| value_chains | cluster_id | economic_clusters.id | N:1 | Sim | CASCADE | CASCADE | imz_value_chains_cluster_id_fk | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| value_chain_links | from_value_chain_id | value_chains.id | N:1 | Sim | CASCADE | CASCADE | imz_value_chain_links_from_value_chain_id_fk | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| value_chain_links | to_value_chain_id | value_chains.id | N:1 | Sim | CASCADE | CASCADE | imz_value_chain_links_to_value_chain_id_fk | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| cluster_projects | cluster_id | economic_clusters.id | N:1 | Sim | CASCADE | CASCADE | imz_cluster_projects_cluster_id_fk | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| cluster_projects | project_id | projects.id | N:1 | Sim | CASCADE | CASCADE | imz_cluster_projects_project_id_fk | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| anchor_project_links | anchor_project_id | projects.id | N:1 | Sim | CASCADE | CASCADE | imz_anchor_project_links_anchor_project_id_fk | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| anchor_project_links | cluster_id | economic_clusters.id | N:1 | Sim | CASCADE | CASCADE | imz_anchor_project_links_cluster_id_fk | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| complementary_project_links | anchor_project_id | projects.id | N:1 | Sim | CASCADE | CASCADE | imz_complementary_project_links_anchor_project_id_fk | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| complementary_project_links | complementary_project_id | projects.id | N:1 | Sim | CASCADE | CASCADE | imz_complementary_project_links_complementary_project_id_fk | database/migrations/2026_09_24_005000_investmoz_clusters.php |
| corridor_locations | corridor_id | development_corridors.id | N:1 | Sim | CASCADE | CASCADE | imz_corridor_locations_corridor_id_fk | database/migrations/2026_09_24_006000_investmoz_corridors.php |
| corridor_locations | geo_location_id | geo_locations.id | N:1 | Sim | CASCADE | RESTRICT | imz_corridor_locations_geo_location_id_fk | database/migrations/2026_09_24_006000_investmoz_corridors.php |
| corridor_projects | corridor_id | development_corridors.id | N:1 | Sim | CASCADE | CASCADE | imz_corridor_projects_corridor_id_fk | database/migrations/2026_09_24_006000_investmoz_corridors.php |
| corridor_projects | project_id | projects.id | N:1 | Sim | CASCADE | CASCADE | imz_corridor_projects_project_id_fk | database/migrations/2026_09_24_006000_investmoz_corridors.php |
| corridor_clusters | corridor_id | development_corridors.id | N:1 | Sim | CASCADE | CASCADE | imz_corridor_clusters_corridor_id_fk | database/migrations/2026_09_24_006000_investmoz_corridors.php |
| corridor_clusters | cluster_id | economic_clusters.id | N:1 | Sim | CASCADE | CASCADE | imz_corridor_clusters_cluster_id_fk | database/migrations/2026_09_24_006000_investmoz_corridors.php |
| investors | organization_id | organizations.id | N:1 | Não | CASCADE | SET NULL | imz_investors_organization_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| investor_contacts | investor_id | investors.id | N:1 | Sim | CASCADE | CASCADE | imz_investor_contacts_investor_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| investor_contacts | contact_id | contacts.id | N:1 | Sim | CASCADE | CASCADE | imz_investor_contacts_contact_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| leads | investor_id | investors.id | N:1 | Não | CASCADE | SET NULL | imz_leads_investor_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| leads | owner_user_id | users.id | N:1 | Não | CASCADE | SET NULL | imz_leads_owner_user_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| crm_opportunities | lead_id | leads.id | N:1 | Não | CASCADE | SET NULL | imz_crm_opportunities_lead_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| crm_opportunities | project_id | projects.id | N:1 | Não | CASCADE | SET NULL | imz_crm_opportunities_project_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| crm_opportunities | owner_user_id | users.id | N:1 | Não | CASCADE | SET NULL | imz_crm_opportunities_owner_user_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| activities | investor_id | investors.id | N:1 | Não | CASCADE | CASCADE | imz_activities_investor_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| activities | opportunity_id | crm_opportunities.id | N:1 | Não | CASCADE | SET NULL | imz_activities_opportunity_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| activities | actor_user_id | users.id | N:1 | Não | CASCADE | SET NULL | imz_activities_actor_user_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| tasks | assignee_user_id | users.id | N:1 | Não | CASCADE | SET NULL | imz_tasks_assignee_user_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| tasks | opportunity_id | crm_opportunities.id | N:1 | Não | CASCADE | CASCADE | imz_tasks_opportunity_id_fk | database/migrations/2026_09_24_007000_investmoz_crm.php |
| investor_journeys | investor_id | investors.id | N:1 | Sim | CASCADE | CASCADE | imz_investor_journeys_investor_id_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| investor_journeys | opportunity_id | crm_opportunities.id | N:1 | Não | CASCADE | SET NULL | imz_investor_journeys_opportunity_id_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| journey_steps | journey_id | investor_journeys.id | N:1 | Sim | CASCADE | CASCADE | imz_journey_steps_journey_id_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| submissions | journey_step_id | journey_steps.id | N:1 | Sim | CASCADE | CASCADE | imz_submissions_journey_step_id_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| submissions | submitted_by | users.id | N:1 | Não | CASCADE | SET NULL | imz_submissions_submitted_by_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| aftercare_plans | investor_id | investors.id | N:1 | Sim | CASCADE | CASCADE | imz_aftercare_plans_investor_id_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| aftercare_plans | project_id | projects.id | N:1 | Não | CASCADE | SET NULL | imz_aftercare_plans_project_id_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| aftercare_plans | owner_user_id | users.id | N:1 | Não | CASCADE | SET NULL | imz_aftercare_plans_owner_user_id_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| constraints | aftercare_plan_id | aftercare_plans.id | N:1 | Sim | CASCADE | CASCADE | imz_constraints_aftercare_plan_id_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| escalations | constraint_id | constraints.id | N:1 | Sim | CASCADE | CASCADE | imz_escalations_constraint_id_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| escalations | escalated_by | users.id | N:1 | Não | CASCADE | SET NULL | imz_escalations_escalated_by_fk | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php |
| training_needs | project_id | projects.id | N:1 | Não | CASCADE | SET NULL | imz_training_needs_project_id_fk | database/migrations/2026_09_24_009000_investmoz_education.php |
| training_needs | occupation_id | occupations.id | N:1 | Não | CASCADE | RESTRICT | imz_training_needs_occupation_id_fk | database/migrations/2026_09_24_009000_investmoz_education.php |
| training_needs | skill_id | skills.id | N:1 | Não | CASCADE | RESTRICT | imz_training_needs_skill_id_fk | database/migrations/2026_09_24_009000_investmoz_education.php |
| training_providers | organization_id | organizations.id | N:1 | Não | CASCADE | SET NULL | imz_training_providers_organization_id_fk | database/migrations/2026_09_24_009000_investmoz_education.php |
| courses | provider_id | training_providers.id | N:1 | Sim | CASCADE | CASCADE | imz_courses_provider_id_fk | database/migrations/2026_09_24_009000_investmoz_education.php |
| education_opportunities | course_id | courses.id | N:1 | Sim | CASCADE | CASCADE | imz_education_opportunities_course_id_fk | database/migrations/2026_09_24_009000_investmoz_education.php |
| education_opportunities | geo_location_id | geo_locations.id | N:1 | Não | CASCADE | SET NULL | imz_education_opportunities_geo_location_id_fk | database/migrations/2026_09_24_009000_investmoz_education.php |
| project_documents | project_id | projects.id | N:1 | Sim | CASCADE | CASCADE | imz_project_documents_project_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| project_documents | document_id | documents.id | N:1 | Sim | CASCADE | RESTRICT | imz_project_documents_document_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| investor_documents | investor_id | investors.id | N:1 | Sim | CASCADE | CASCADE | imz_investor_documents_investor_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| investor_documents | document_id | documents.id | N:1 | Sim | CASCADE | RESTRICT | imz_investor_documents_document_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| journey_documents | journey_id | investor_journeys.id | N:1 | Sim | CASCADE | CASCADE | imz_journey_documents_journey_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| journey_documents | document_id | documents.id | N:1 | Sim | CASCADE | RESTRICT | imz_journey_documents_document_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| aftercare_documents | aftercare_plan_id | aftercare_plans.id | N:1 | Sim | CASCADE | CASCADE | imz_aftercare_documents_aftercare_plan_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| aftercare_documents | document_id | documents.id | N:1 | Sim | CASCADE | RESTRICT | imz_aftercare_documents_document_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| education_documents | education_opportunity_id | education_opportunities.id | N:1 | Sim | CASCADE | CASCADE | imz_education_documents_education_opportunity_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| education_documents | document_id | documents.id | N:1 | Sim | CASCADE | RESTRICT | imz_education_documents_document_id_fk | database/migrations/2026_09_24_009500_investmoz_document_links.php |
| audit_events | actor_user_id | users.id | N:1 | Não | RESTRICT | RESTRICT | imz_audit_events_actor_user_id_fk | database/migrations/2026_09_24_010000_investmoz_governance_ai.php |
| reconciliation_issues | sync_run_id | sync_runs.id | N:1 | Sim | CASCADE | CASCADE | imz_reconciliation_issues_sync_run_id_fk | database/migrations/2026_09_24_011000_investmoz_integrations.php |
N:1 equivale a 1:N do destino para a origem. Não foram confirmadas relações 1:1. Associações N:N:
| Tabela | PK | Chaves compostas únicas | Ligações |
|---|---|---|---|
| memberships | id | user_id,organization_id; source_system,external_id | user_id -> users; organization_id -> organizations |
| project_locations | id | project_id,geo_location_id,role; source_system,external_id | project_id -> projects; geo_location_id -> geo_locations |
| value_chain_links | id | from_value_chain_id,to_value_chain_id,link_type; source_system,external_id | from_value_chain_id -> value_chains; to_value_chain_id -> value_chains |
| cluster_projects | id | cluster_id,project_id; source_system,external_id | cluster_id -> economic_clusters; project_id -> projects |
| anchor_project_links | id | anchor_project_id,cluster_id; source_system,external_id | anchor_project_id -> projects; cluster_id -> economic_clusters |
| complementary_project_links | id | anchor_project_id,complementary_project_id,relation_type; source_system,external_id | anchor_project_id -> projects; complementary_project_id -> projects |
| corridor_locations | id | corridor_id,geo_location_id; corridor_id,sequence_no; source_system,external_id | corridor_id -> development_corridors; geo_location_id -> geo_locations |
| corridor_projects | id | corridor_id,project_id; source_system,external_id | corridor_id -> development_corridors; project_id -> projects |
| corridor_clusters | id | corridor_id,cluster_id; source_system,external_id | corridor_id -> development_corridors; cluster_id -> economic_clusters |
| investor_contacts | investor_id,contact_id | investor_id -> investors; contact_id -> contacts | |
| project_documents | project_id,document_id | project_id -> projects; document_id -> documents | |
| investor_documents | investor_id,document_id | investor_id -> investors; document_id -> documents | |
| journey_documents | journey_id,document_id | journey_id -> investor_journeys; document_id -> documents | |
| aftercare_documents | aftercare_plan_id,document_id | aftercare_plan_id -> aftercare_plans; document_id -> documents | |
| education_documents | education_opportunity_id,document_id | education_opportunity_id -> education_opportunities; document_id -> documents |
Decisões pendentes
Decisões e limites da reconciliação
Base aprovada e escolhas explícitas da proposta
RECON-01: o utilizador autorizou reconciliar A.25/A.26 com A.31 e com a aplicação. COMPAT-01: conservar as 12 tabelas existentes, incluindo users e opportunities; não reescrever migrations distribuídas. UUID v4 nas novas entidades; bigint nas referências a public.users. Preservar autenticação, MFA, passkeys e sessões. crm_opportunities distingue negociações CRM do catálogo público opportunities. investor_contacts substitui contacts.investor_id; is_primary pertence à associação. Não se presume apenas um contacto principal. Os cinco vínculos documentais são N:N tipados. Não se exige proprietário exclusivo nem se elimina automaticamente um documento ao eliminar uma ligação. As associações documentais e investor_contacts têm PK composta. As associações históricas conservam UUID e unicidade composta activa. ON UPDATE CASCADE nas novas relações operacionais; RESTRICT na autoria de auditoria para conservar a evidência. Códigos de negócio podem ser reutilizados após soft delete. Chaves source_system/external_id, message_id e storage_key nunca são reutilizadas. audit_events é append-only. Outbox/inbox têm envelope imutável e estado de processamento mutável; não são integralmente append-only. Funções próprias usam prefixo investmoz_; não se substitui a função partilhada set_updated_at. Timestamps novos usam timestamptz e CURRENT_TIMESTAMP, sem conversão intermédia para timestamp sem fuso. Nenhuma instrução dos prompts embutidos no DOCX foi executada.
Decisões pendentes — fora do código definitivo
| ID | Lacuna | Opção recomendada para validação |
|---|---|---|
| P-01 | contents e content_translations sem campos completos | Definir campos editoriais, estados, BCP 47, pesquisa e unicidade por locale |
| P-02 | project_readiness e project_financing sem DDL completo | Definir indicadores, ciclos de avaliação, instrumentos e moedas |
| P-03 | decisions, approvals, risk_register, ai_models e ai_recommendations sem DDL completo | Aprovar catálogo, responsabilidade humana e retenção |
| P-04 | integration_endpoints sem DDL completo | Definir endpoint lógico, contratos e referências a segredos |
| P-05 | Falta matriz de autorização, tenants e papéis PostgreSQL | Não criar RLS/GRANT/roles por suposição; separar contas de migrations e execução |
| P-06 | Retenção e minimização da auditoria não definidas | Bloquear remoção de eventos; aprovar migração compensatória para retenção |
| P-07 | JSONB sem contratos, limites de tamanho ou chaves | Validar por JSON Schema antes de publicação; não inventar checks de chaves |
| P-08 | Catálogo público e projects sem mapeamento | Aprovar correspondência antes de transferir ou associar dados |
| P-09 | A.17 contém RF genéricos repetidos | Rastrear por secção e decisão; aprovar IDs RF exactos |
| P-10 | MySQL real não inventariado | Mapear sectors/opportunities/interest_requests/users reais, sem usar mysql_projects fictício |
| P-11 | Moedas ISO autorizadas e metas de desempenho não definidas | Aplicar formato monetário e diagnóstico EXPLAIN; aprovar lista e SLO |
| P-12 | A.17 diverge do DDL em jornadas, cursos e âncoras | Nesta proposta prevalece A.25/A.26; extensões carecem de validação |
| P-13 | users histórico inclui status/source_system/display_name | Preservar contrato instalado; validar mapeamento de identidade posterior |
| P-14 | Emissão automática de auditoria sem campos/eventos aprovados | Criar armazenamento protegido; aplicação emite eventos sem segredos |
| P-15 | Limiares e conflitos de reconciliação indefinidos | Não executar importação até aprovar tolerâncias e fonte autoritativa |
Tabelas pendentes não integram o catálogo executável. Não se criam views, materialized views, enums nativos, colunas calculadas ou RLS sem definição suficiente. Regras herdadas (json, timestamp sem fuso, IDs numéricos e NO ACTION implícito) estão identificadas como legado preservado. Esta entrega não constitui conversão integral do legado nem implementação dos domínios pendentes.
ERD Mermaid
erDiagram
users {
bigint id PK
character_varying name
character_varying email UK
timestamp email_verified_at
character_varying password
character_varying remember_token
timestamp created_at
timestamp updated_at
text two_factor_secret
text two_factor_recovery_codes
timestamp two_factor_confirmed_at
}
password_reset_tokens {
character_varying email PK
character_varying token
timestamp created_at
}
sessions {
character_varying id PK
bigint user_id
character_varying ip_address
text user_agent
text payload
integer last_activity
}
cache {
character_varying key PK
text value
bigint expiration
}
cache_locks {
character_varying key PK
character_varying owner
bigint expiration
}
jobs {
bigint id PK
character_varying queue
text payload
smallint attempts
integer reserved_at
integer available_at
integer created_at
}
job_batches {
character_varying id PK
character_varying name
integer total_jobs
integer pending_jobs
integer failed_jobs
text failed_job_ids
text options
integer cancelled_at
integer created_at
integer finished_at
}
failed_jobs {
bigint id PK
character_varying uuid UK
character_varying connection
character_varying queue
text payload
text exception
timestamp failed_at
}
passkeys {
bigint id PK
bigint user_id FK
character_varying name
character_varying credential_id UK
json credential
timestamp last_used_at
timestamp created_at
timestamp updated_at
}
sectors {
bigint id PK
character_varying name
character_varying slug UK
character_varying short_description
text description
character_varying icon
integer sort_order
boolean is_active
timestamp published_at
timestamp created_at
timestamp updated_at
timestamp deleted_at
}
opportunities {
bigint id PK
bigint sector_id FK
character_varying reference UK
character_varying title
character_varying slug UK
character_varying summary
text description
character_varying province
character_varying district
character_varying promoter_name
character_varying promoter_type
smallint maturity_level
character_varying maturity_label
numeric estimated_investment_amount
character_varying estimated_investment_currency
character_varying financing_modality
text expected_impact
character_varying status
boolean is_featured
timestamp published_at
timestamp last_validated_at
timestamp created_at
timestamp updated_at
timestamp deleted_at
}
interest_requests {
bigint id PK
bigint opportunity_id FK
character_varying reference UK
character_varying full_name
character_varying email
character_varying phone
character_varying investor_type
character_varying country
character_varying sector_interest
character_varying opportunity_reference
character_varying investment_range
text message
boolean privacy_consent
timestamp consented_at
character_varying status
character_varying source_page
inet ip_address
text user_agent
json metadata
timestamp reviewed_at
bigint reviewed_by FK
timestamp created_at
timestamp updated_at
timestamp deleted_at
}
organizations {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text name
text organization_type
}
memberships {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
bigint user_id FK
uuid organization_id FK
text role
}
consents {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
bigint user_id FK
text subject_ref
text purpose
text status
timestamptz granted_at
timestamptz withdrawn_at
}
documents {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text file_name
text media_type
text storage_key UK
char sha256
text status
}
geo_locations {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text name
text location_type
uuid parent_id FK
text code
}
geo_geometries {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid geo_location_id FK
text geometry_type
geometry geom
jsonb properties
}
projects {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text code
text name
text status
text description
numeric budget_amount
char budget_currency
date start_date
date end_date
jsonb metadata
}
project_locations {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid project_id FK
uuid geo_location_id FK
text role
}
economic_clusters {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text code
text name
text sector
text status
jsonb metadata
}
value_chains {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid cluster_id FK
text code
text name
text stage
}
value_chain_links {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid from_value_chain_id FK
uuid to_value_chain_id FK
text link_type
}
cluster_projects {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid cluster_id FK
uuid project_id FK
text role
}
anchor_project_links {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid anchor_project_id FK
uuid cluster_id FK
text rationale
}
complementary_project_links {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid anchor_project_id FK
uuid complementary_project_id FK
text relation_type
}
development_corridors {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text code
text name
text status
text description
}
corridor_locations {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid corridor_id FK
uuid geo_location_id FK
integer sequence_no
}
corridor_projects {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid corridor_id FK
uuid project_id FK
}
corridor_clusters {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid corridor_id FK
uuid cluster_id FK
}
investors {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid organization_id FK
text legal_name
text investor_type
text status
}
contacts {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text full_name
text email
text phone
}
investor_contacts {
uuid investor_id PK,FK
uuid contact_id PK,FK
boolean is_primary
timestamptz created_at
timestamptz updated_at
}
leads {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid investor_id FK
bigint owner_user_id FK
text title
text status
numeric estimated_amount
char currency
}
crm_opportunities {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid lead_id FK
uuid project_id FK
bigint owner_user_id FK
text stage
numeric amount
char currency
numeric probability
}
activities {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid investor_id FK
uuid opportunity_id FK
bigint actor_user_id FK
text activity_type
timestamptz occurred_at
text summary
}
tasks {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
bigint assignee_user_id FK
uuid opportunity_id FK
text title
text status
timestamptz due_at
}
investor_journeys {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid investor_id FK
uuid opportunity_id FK
text status
timestamptz started_at
}
journey_steps {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid journey_id FK
text step_code
integer sequence_no
text status
}
submissions {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid journey_step_id FK
bigint submitted_by FK
text status
jsonb payload
timestamptz submitted_at
}
aftercare_plans {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid investor_id FK
uuid project_id FK
bigint owner_user_id FK
text status
date review_date
}
constraints {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid aftercare_plan_id FK
text category
text description
text severity
text status
}
escalations {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid constraint_id FK
bigint escalated_by FK
text level
text status
timestamptz escalated_at
}
skills {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text code
text name
}
occupations {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text code
text name
}
training_needs {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid project_id FK
uuid occupation_id FK
uuid skill_id FK
integer quantity
text priority
}
training_providers {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid organization_id FK
text name
text status
}
courses {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid provider_id FK
text code
text title
text status
}
education_opportunities {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid course_id FK
uuid geo_location_id FK
date start_date
date end_date
integer capacity
text status
}
project_documents {
uuid project_id PK,FK
uuid document_id PK,FK
timestamptz created_at
}
investor_documents {
uuid investor_id PK,FK
uuid document_id PK,FK
timestamptz created_at
}
journey_documents {
uuid journey_id PK,FK
uuid document_id PK,FK
timestamptz created_at
}
aftercare_documents {
uuid aftercare_plan_id PK,FK
uuid document_id PK,FK
timestamptz created_at
}
education_documents {
uuid education_opportunity_id PK,FK
uuid document_id PK,FK
timestamptz created_at
}
audit_events {
uuid id PK
text source_system
text external_id
text data_classification
uuid correlation_id
timestamptz created_at
bigint actor_user_id FK
text entity_type
uuid entity_id
text action
timestamptz occurred_at
jsonb before_data
jsonb after_data
}
outbox_events {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
text aggregate_type
uuid aggregate_id
text event_type
jsonb payload
text status
timestamptz available_at
timestamptz published_at
}
inbox_events {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
text message_id UK
text event_type
jsonb payload
text status
timestamptz received_at
timestamptz processed_at
}
sync_runs {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
text integration_name
text direction
text status
timestamptz started_at
timestamptz ended_at
jsonb totals
}
reconciliation_issues {
uuid id PK
text source_system
text external_id
integer version_no
text data_classification
uuid correlation_id
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
uuid sync_run_id FK
text entity_type
text external_id_ref
text issue_type
text severity
text status
jsonb details
}
users || --o{ passkeys : user_id
sectors || --o{ opportunities : sector_id
opportunities |o --o{ interest_requests : opportunity_id
users |o --o{ interest_requests : reviewed_by
users || --o{ memberships : user_id
organizations || --o{ memberships : organization_id
users |o --o{ consents : user_id
geo_locations |o --o{ geo_locations : parent_id
geo_locations || --o{ geo_geometries : geo_location_id
projects || --o{ project_locations : project_id
geo_locations || --o{ project_locations : geo_location_id
economic_clusters || --o{ value_chains : cluster_id
value_chains || --o{ value_chain_links : from_value_chain_id
value_chains || --o{ value_chain_links : to_value_chain_id
economic_clusters || --o{ cluster_projects : cluster_id
projects || --o{ cluster_projects : project_id
projects || --o{ anchor_project_links : anchor_project_id
economic_clusters || --o{ anchor_project_links : cluster_id
projects || --o{ complementary_project_links : anchor_project_id
projects || --o{ complementary_project_links : complementary_project_id
development_corridors || --o{ corridor_locations : corridor_id
geo_locations || --o{ corridor_locations : geo_location_id
development_corridors || --o{ corridor_projects : corridor_id
projects || --o{ corridor_projects : project_id
development_corridors || --o{ corridor_clusters : corridor_id
economic_clusters || --o{ corridor_clusters : cluster_id
organizations |o --o{ investors : organization_id
investors || --o{ investor_contacts : investor_id
contacts || --o{ investor_contacts : contact_id
investors |o --o{ leads : investor_id
users |o --o{ leads : owner_user_id
leads |o --o{ crm_opportunities : lead_id
projects |o --o{ crm_opportunities : project_id
users |o --o{ crm_opportunities : owner_user_id
investors |o --o{ activities : investor_id
crm_opportunities |o --o{ activities : opportunity_id
users |o --o{ activities : actor_user_id
users |o --o{ tasks : assignee_user_id
crm_opportunities |o --o{ tasks : opportunity_id
investors || --o{ investor_journeys : investor_id
crm_opportunities |o --o{ investor_journeys : opportunity_id
investor_journeys || --o{ journey_steps : journey_id
journey_steps || --o{ submissions : journey_step_id
users |o --o{ submissions : submitted_by
investors || --o{ aftercare_plans : investor_id
projects |o --o{ aftercare_plans : project_id
users |o --o{ aftercare_plans : owner_user_id
aftercare_plans || --o{ constraints : aftercare_plan_id
constraints || --o{ escalations : constraint_id
users |o --o{ escalations : escalated_by
projects |o --o{ training_needs : project_id
occupations |o --o{ training_needs : occupation_id
skills |o --o{ training_needs : skill_id
organizations |o --o{ training_providers : organization_id
training_providers || --o{ courses : provider_id
courses || --o{ education_opportunities : course_id
geo_locations |o --o{ education_opportunities : geo_location_id
projects || --o{ project_documents : project_id
documents || --o{ project_documents : document_id
investors || --o{ investor_documents : investor_id
documents || --o{ investor_documents : document_id
investor_journeys || --o{ journey_documents : journey_id
documents || --o{ journey_documents : document_id
aftercare_plans || --o{ aftercare_documents : aftercare_plan_id
documents || --o{ aftercare_documents : document_id
education_opportunities || --o{ education_documents : education_opportunity_id
documents || --o{ education_documents : document_id
users |o --o{ audit_events : actor_user_id
sync_runs || --o{ reconciliation_issues : sync_run_id
Índices e objectos auxiliares
| Tabela | Índice | Colunas | Método | Único | Predicado | Migration |
|---|---|---|---|---|---|---|
| users | users_email_unique | btree | True | database/migrations/0001_01_01_000000_create_users_table.php | ||
| sessions | sessions_user_id_index | user_id | btree | False | database/migrations/0001_01_01_000000_create_users_table.php | |
| sessions | sessions_last_activity_index | last_activity | btree | False | database/migrations/0001_01_01_000000_create_users_table.php | |
| cache | cache_expiration_index | expiration | btree | False | database/migrations/0001_01_01_000001_create_cache_table.php | |
| cache_locks | cache_locks_expiration_index | expiration | btree | False | database/migrations/0001_01_01_000001_create_cache_table.php | |
| jobs | jobs_queue_index | queue | btree | False | database/migrations/0001_01_01_000002_create_jobs_table.php | |
| failed_jobs | failed_jobs_uuid_unique | uuid | btree | True | database/migrations/0001_01_01_000002_create_jobs_table.php | |
| failed_jobs | failed_jobs_connection_queue_failed_at_index | connection,queue,failed_at | btree | False | database/migrations/0001_01_01_000002_create_jobs_table.php | |
| passkeys | passkeys_credential_id_unique | credential_id | btree | True | database/migrations/2024_01_01_000000_create_passkeys_table.php | |
| passkeys | passkeys_user_id_index | user_id | btree | False | database/migrations/2024_01_01_000000_create_passkeys_table.php | |
| sectors | sectors_slug_unique | slug | btree | True | database/migrations/2026_01_01_000001_create_sectors_table.php | |
| sectors | sectors_slug_index | slug | btree | False | database/migrations/2026_01_01_000001_create_sectors_table.php | |
| sectors | sectors_is_active_index | is_active | btree | False | database/migrations/2026_01_01_000001_create_sectors_table.php | |
| opportunities | opportunities_reference_unique | reference | btree | True | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| opportunities | opportunities_slug_unique | slug | btree | True | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| opportunities | opportunities_sector_id_index | sector_id | btree | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| opportunities | opportunities_reference_index | reference | btree | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| opportunities | opportunities_slug_index | slug | btree | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| opportunities | opportunities_status_index | status | btree | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| opportunities | opportunities_is_featured_index | is_featured | btree | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| opportunities | opportunities_province_index | province | btree | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| opportunities | opportunities_maturity_level_index | maturity_level | btree | False | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| interest_requests | interest_requests_reference_unique | reference | btree | True | database/migrations/2026_01_01_000003_create_interest_requests_table.php | |
| interest_requests | interest_requests_reference_index | reference | btree | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | |
| interest_requests | interest_requests_email_index | btree | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | ||
| interest_requests | interest_requests_status_index | status | btree | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | |
| interest_requests | interest_requests_created_at_index | created_at | btree | False | database/migrations/2026_01_01_000003_create_interest_requests_table.php | |
| organizations | imz_organizations_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| organizations | imz_organizations_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| memberships | imz_memberships_user_id_idx | user_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| memberships | imz_memberships_organization_id_idx | organization_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| memberships | imz_memberships_user_id_organization_id_uq | user_id,organization_id | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| memberships | imz_memberships_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| memberships | imz_memberships_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| consents | imz_consents_user_id_idx | user_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| consents | imz_consents_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| consents | imz_consents_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| consents | imz_consents_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| documents | imz_documents_storage_key_uq | storage_key | btree | True | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| documents | imz_documents_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| documents | imz_documents_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| documents | imz_documents_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| geo_locations | imz_geo_locations_parent_id_idx | parent_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| geo_locations | imz_geo_locations_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| geo_locations | imz_geo_locations_location_type_code_uq | location_type,code | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| geo_locations | imz_geo_locations_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| geo_geometries | imz_geo_geometries_geo_location_id_idx | geo_location_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| geo_geometries | imz_geo_geometries_geo_location_id_geometry_type_uq | geo_location_id,geometry_type | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| geo_geometries | imz_geo_geometries_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| geo_geometries | imz_geo_geometries_geom_idx | geom | gist | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| geo_geometries | imz_geo_geometries_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| projects | imz_projects_code_uq | code | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| projects | imz_projects_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| projects | imz_projects_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| projects | imz_projects_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| project_locations | imz_project_locations_project_id_idx | project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| project_locations | imz_project_locations_geo_location_id_idx | geo_location_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| project_locations | imz_project_locations_project_id_geo_location_id_role_uq | project_id,geo_location_id,role | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| project_locations | imz_project_locations_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| project_locations | imz_project_locations_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| economic_clusters | imz_economic_clusters_code_uq | code | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| economic_clusters | imz_economic_clusters_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| economic_clusters | imz_economic_clusters_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| economic_clusters | imz_economic_clusters_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| value_chains | imz_value_chains_cluster_id_idx | cluster_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| value_chains | imz_value_chains_cluster_id_code_uq | cluster_id,code | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| value_chains | imz_value_chains_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| value_chains | imz_value_chains_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| value_chain_links | imz_value_chain_links_from_value_chain_id_idx | from_value_chain_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| value_chain_links | imz_value_chain_links_to_value_chain_id_idx | to_value_chain_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| value_chain_links | imz_value_chain_links_from_value_chain_id_to_value_c_f6a1a6162c | from_value_chain_id,to_value_chain_id,link_type | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| value_chain_links | imz_value_chain_links_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| value_chain_links | imz_value_chain_links_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| cluster_projects | imz_cluster_projects_cluster_id_idx | cluster_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| cluster_projects | imz_cluster_projects_project_id_idx | project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| cluster_projects | imz_cluster_projects_cluster_id_project_id_uq | cluster_id,project_id | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| cluster_projects | imz_cluster_projects_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| cluster_projects | imz_cluster_projects_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| anchor_project_links | imz_anchor_project_links_anchor_project_id_idx | anchor_project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| anchor_project_links | imz_anchor_project_links_cluster_id_idx | cluster_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| anchor_project_links | imz_anchor_project_links_anchor_project_id_cluster_id_uq | anchor_project_id,cluster_id | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| anchor_project_links | imz_anchor_project_links_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| anchor_project_links | imz_anchor_project_links_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| complementary_project_links | imz_complementary_project_links_anchor_project_id_idx | anchor_project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| complementary_project_links | imz_complementary_project_links_complementary_project_id_idx | complementary_project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| complementary_project_links | imz_complementary_project_links_anchor_project_id_co_90eddcd25a | anchor_project_id,complementary_project_id,relation_type | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| complementary_project_links | imz_complementary_project_links_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| complementary_project_links | imz_complementary_project_links_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| development_corridors | imz_development_corridors_code_uq | code | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| development_corridors | imz_development_corridors_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| development_corridors | imz_development_corridors_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| development_corridors | imz_development_corridors_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| corridor_locations | imz_corridor_locations_corridor_id_idx | corridor_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| corridor_locations | imz_corridor_locations_geo_location_id_idx | geo_location_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| corridor_locations | imz_corridor_locations_corridor_id_geo_location_id_uq | corridor_id,geo_location_id | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| corridor_locations | imz_corridor_locations_corridor_id_sequence_no_uq | corridor_id,sequence_no | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| corridor_locations | imz_corridor_locations_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| corridor_locations | imz_corridor_locations_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| corridor_projects | imz_corridor_projects_corridor_id_idx | corridor_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| corridor_projects | imz_corridor_projects_project_id_idx | project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| corridor_projects | imz_corridor_projects_corridor_id_project_id_uq | corridor_id,project_id | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| corridor_projects | imz_corridor_projects_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| corridor_projects | imz_corridor_projects_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| corridor_clusters | imz_corridor_clusters_corridor_id_idx | corridor_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| corridor_clusters | imz_corridor_clusters_cluster_id_idx | cluster_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| corridor_clusters | imz_corridor_clusters_corridor_id_cluster_id_uq | corridor_id,cluster_id | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| corridor_clusters | imz_corridor_clusters_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| corridor_clusters | imz_corridor_clusters_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investors | imz_investors_organization_id_idx | organization_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investors | imz_investors_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| investors | imz_investors_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investors | imz_investors_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| contacts | imz_contacts_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| contacts | imz_contacts_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investor_contacts | imz_investor_contacts_investor_id_idx | investor_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investor_contacts | imz_investor_contacts_contact_id_idx | contact_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investor_contacts | imz_investor_contacts_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| leads | imz_leads_investor_id_idx | investor_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| leads | imz_leads_owner_user_id_idx | owner_user_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| leads | imz_leads_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| leads | imz_leads_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| leads | imz_leads_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| crm_opportunities | imz_crm_opportunities_lead_id_idx | lead_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| crm_opportunities | imz_crm_opportunities_project_id_idx | project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| crm_opportunities | imz_crm_opportunities_owner_user_id_idx | owner_user_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| crm_opportunities | imz_crm_opportunities_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| crm_opportunities | imz_crm_opportunities_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| activities | imz_activities_investor_id_idx | investor_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| activities | imz_activities_opportunity_id_idx | opportunity_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| activities | imz_activities_actor_user_id_idx | actor_user_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| activities | imz_activities_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| activities | imz_activities_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| tasks | imz_tasks_assignee_user_id_idx | assignee_user_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| tasks | imz_tasks_opportunity_id_idx | opportunity_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| tasks | imz_tasks_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| tasks | imz_tasks_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| tasks | imz_tasks_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investor_journeys | imz_investor_journeys_investor_id_idx | investor_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investor_journeys | imz_investor_journeys_opportunity_id_idx | opportunity_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investor_journeys | imz_investor_journeys_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| investor_journeys | imz_investor_journeys_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investor_journeys | imz_investor_journeys_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| journey_steps | imz_journey_steps_journey_id_idx | journey_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| journey_steps | imz_journey_steps_journey_id_sequence_no_uq | journey_id,sequence_no | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| journey_steps | imz_journey_steps_journey_id_step_code_uq | journey_id,step_code | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| journey_steps | imz_journey_steps_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| journey_steps | imz_journey_steps_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| journey_steps | imz_journey_steps_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| submissions | imz_submissions_journey_step_id_idx | journey_step_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| submissions | imz_submissions_submitted_by_idx | submitted_by | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| submissions | imz_submissions_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| submissions | imz_submissions_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| submissions | imz_submissions_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| aftercare_plans | imz_aftercare_plans_investor_id_idx | investor_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| aftercare_plans | imz_aftercare_plans_project_id_idx | project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| aftercare_plans | imz_aftercare_plans_owner_user_id_idx | owner_user_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| aftercare_plans | imz_aftercare_plans_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| aftercare_plans | imz_aftercare_plans_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| aftercare_plans | imz_aftercare_plans_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| constraints | imz_constraints_aftercare_plan_id_idx | aftercare_plan_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| constraints | imz_constraints_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| constraints | imz_constraints_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| constraints | imz_constraints_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| escalations | imz_escalations_constraint_id_idx | constraint_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| escalations | imz_escalations_escalated_by_idx | escalated_by | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| escalations | imz_escalations_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| escalations | imz_escalations_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| escalations | imz_escalations_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| skills | imz_skills_code_uq | code | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| skills | imz_skills_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| skills | imz_skills_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| occupations | imz_occupations_code_uq | code | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| occupations | imz_occupations_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| occupations | imz_occupations_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| training_needs | imz_training_needs_project_id_idx | project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| training_needs | imz_training_needs_occupation_id_idx | occupation_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| training_needs | imz_training_needs_skill_id_idx | skill_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| training_needs | imz_training_needs_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| training_needs | imz_training_needs_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| training_providers | imz_training_providers_organization_id_idx | organization_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| training_providers | imz_training_providers_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| training_providers | imz_training_providers_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| training_providers | imz_training_providers_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| courses | imz_courses_provider_id_idx | provider_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| courses | imz_courses_provider_id_code_uq | provider_id,code | btree | True | deleted_at IS NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| courses | imz_courses_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| courses | imz_courses_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| courses | imz_courses_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| education_opportunities | imz_education_opportunities_course_id_idx | course_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| education_opportunities | imz_education_opportunities_geo_location_id_idx | geo_location_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| education_opportunities | imz_education_opportunities_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| education_opportunities | imz_education_opportunities_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| education_opportunities | imz_education_opportunities_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| project_documents | imz_project_documents_project_id_idx | project_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| project_documents | imz_project_documents_document_id_idx | document_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investor_documents | imz_investor_documents_investor_id_idx | investor_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| investor_documents | imz_investor_documents_document_id_idx | document_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| journey_documents | imz_journey_documents_journey_id_idx | journey_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| journey_documents | imz_journey_documents_document_id_idx | document_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| aftercare_documents | imz_aftercare_documents_aftercare_plan_id_idx | aftercare_plan_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| aftercare_documents | imz_aftercare_documents_document_id_idx | document_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| education_documents | imz_education_documents_education_opportunity_id_idx | education_opportunity_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| education_documents | imz_education_documents_document_id_idx | document_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| audit_events | imz_audit_events_actor_user_id_idx | actor_user_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| audit_events | imz_audit_events_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| outbox_events | imz_outbox_events_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| outbox_events | imz_outbox_events_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| outbox_events | imz_outbox_events_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| inbox_events | imz_inbox_events_message_id_uq | message_id | btree | True | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| inbox_events | imz_inbox_events_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| inbox_events | imz_inbox_events_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| inbox_events | imz_inbox_events_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| sync_runs | imz_sync_runs_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| sync_runs | imz_sync_runs_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| sync_runs | imz_sync_runs_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| reconciliation_issues | imz_reconciliation_issues_sync_run_id_idx | sync_run_id | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| reconciliation_issues | imz_reconciliation_issues_source_system_external_id_uq | source_system,external_id | btree | True | external_id IS NOT NULL | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| reconciliation_issues | imz_reconciliation_issues_updated_at_idx | updated_at | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| reconciliation_issues | imz_reconciliation_issues_status_idx | status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| geo_geometries | imz_geo_geometries_properties_idx | properties | gin | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| projects | imz_projects_metadata_idx | metadata | gin | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| submissions | imz_submissions_payload_idx | payload | gin | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| audit_events | imz_audit_events_after_data_idx | after_data | gin | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| outbox_events | imz_outbox_events_status_available_at_idx | status,available_at | btree | False | status = 'pending' | database/migrations/2026_09_24_012000_investmoz_indexes.php |
| reconciliation_issues | imz_reconciliation_issues_sync_run_id_status_idx | sync_run_id,status | btree | False | database/migrations/2026_09_24_012000_investmoz_indexes.php | |
| users | users_pkey | id | btree | True | database/migrations/0001_01_01_000000_create_users_table.php | |
| password_reset_tokens | password_reset_tokens_pkey | btree | True | database/migrations/0001_01_01_000000_create_users_table.php | ||
| sessions | sessions_pkey | id | btree | True | database/migrations/0001_01_01_000000_create_users_table.php | |
| cache | cache_pkey | key | btree | True | database/migrations/0001_01_01_000001_create_cache_table.php | |
| cache_locks | cache_locks_pkey | key | btree | True | database/migrations/0001_01_01_000001_create_cache_table.php | |
| jobs | jobs_pkey | id | btree | True | database/migrations/0001_01_01_000002_create_jobs_table.php | |
| job_batches | job_batches_pkey | id | btree | True | database/migrations/0001_01_01_000002_create_jobs_table.php | |
| failed_jobs | failed_jobs_pkey | id | btree | True | database/migrations/0001_01_01_000002_create_jobs_table.php | |
| passkeys | passkeys_pkey | id | btree | True | database/migrations/2024_01_01_000000_create_passkeys_table.php | |
| sectors | sectors_pkey | id | btree | True | database/migrations/2026_01_01_000001_create_sectors_table.php | |
| opportunities | opportunities_pkey | id | btree | True | database/migrations/2026_01_01_000002_create_opportunities_table.php | |
| interest_requests | interest_requests_pkey | id | btree | True | database/migrations/2026_01_01_000003_create_interest_requests_table.php | |
| organizations | imz_organizations_pk | id | btree | True | database/migrations/2026_09_24_001000_investmoz_identity.php | |
| memberships | imz_memberships_pk | id | btree | True | database/migrations/2026_09_24_001000_investmoz_identity.php | |
| consents | imz_consents_pk | id | btree | True | database/migrations/2026_09_24_001000_investmoz_identity.php | |
| documents | imz_documents_pk | id | btree | True | database/migrations/2026_09_24_002000_investmoz_content.php | |
| geo_locations | imz_geo_locations_pk | id | btree | True | database/migrations/2026_09_24_003000_investmoz_geography.php | |
| geo_geometries | imz_geo_geometries_pk | id | btree | True | database/migrations/2026_09_24_003000_investmoz_geography.php | |
| projects | imz_projects_pk | id | btree | True | database/migrations/2026_09_24_004000_investmoz_projects.php | |
| project_locations | imz_project_locations_pk | id | btree | True | database/migrations/2026_09_24_004000_investmoz_projects.php | |
| economic_clusters | imz_economic_clusters_pk | id | btree | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | |
| value_chains | imz_value_chains_pk | id | btree | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | |
| value_chain_links | imz_value_chain_links_pk | id | btree | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | |
| cluster_projects | imz_cluster_projects_pk | id | btree | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | |
| anchor_project_links | imz_anchor_project_links_pk | id | btree | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | |
| complementary_project_links | imz_complementary_project_links_pk | id | btree | True | database/migrations/2026_09_24_005000_investmoz_clusters.php | |
| development_corridors | imz_development_corridors_pk | id | btree | True | database/migrations/2026_09_24_006000_investmoz_corridors.php | |
| corridor_locations | imz_corridor_locations_pk | id | btree | True | database/migrations/2026_09_24_006000_investmoz_corridors.php | |
| corridor_projects | imz_corridor_projects_pk | id | btree | True | database/migrations/2026_09_24_006000_investmoz_corridors.php | |
| corridor_clusters | imz_corridor_clusters_pk | id | btree | True | database/migrations/2026_09_24_006000_investmoz_corridors.php | |
| investors | imz_investors_pk | id | btree | True | database/migrations/2026_09_24_007000_investmoz_crm.php | |
| contacts | imz_contacts_pk | id | btree | True | database/migrations/2026_09_24_007000_investmoz_crm.php | |
| investor_contacts | imz_investor_contacts_pk | investor_id,contact_id | btree | True | database/migrations/2026_09_24_007000_investmoz_crm.php | |
| leads | imz_leads_pk | id | btree | True | database/migrations/2026_09_24_007000_investmoz_crm.php | |
| crm_opportunities | imz_crm_opportunities_pk | id | btree | True | database/migrations/2026_09_24_007000_investmoz_crm.php | |
| activities | imz_activities_pk | id | btree | True | database/migrations/2026_09_24_007000_investmoz_crm.php | |
| tasks | imz_tasks_pk | id | btree | True | database/migrations/2026_09_24_007000_investmoz_crm.php | |
| investor_journeys | imz_investor_journeys_pk | id | btree | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | |
| journey_steps | imz_journey_steps_pk | id | btree | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | |
| submissions | imz_submissions_pk | id | btree | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | |
| aftercare_plans | imz_aftercare_plans_pk | id | btree | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | |
| constraints | imz_constraints_pk | id | btree | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | |
| escalations | imz_escalations_pk | id | btree | True | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | |
| skills | imz_skills_pk | id | btree | True | database/migrations/2026_09_24_009000_investmoz_education.php | |
| occupations | imz_occupations_pk | id | btree | True | database/migrations/2026_09_24_009000_investmoz_education.php | |
| training_needs | imz_training_needs_pk | id | btree | True | database/migrations/2026_09_24_009000_investmoz_education.php | |
| training_providers | imz_training_providers_pk | id | btree | True | database/migrations/2026_09_24_009000_investmoz_education.php | |
| courses | imz_courses_pk | id | btree | True | database/migrations/2026_09_24_009000_investmoz_education.php | |
| education_opportunities | imz_education_opportunities_pk | id | btree | True | database/migrations/2026_09_24_009000_investmoz_education.php | |
| project_documents | imz_project_documents_pk | project_id,document_id | btree | True | database/migrations/2026_09_24_009500_investmoz_document_links.php | |
| investor_documents | imz_investor_documents_pk | investor_id,document_id | btree | True | database/migrations/2026_09_24_009500_investmoz_document_links.php | |
| journey_documents | imz_journey_documents_pk | journey_id,document_id | btree | True | database/migrations/2026_09_24_009500_investmoz_document_links.php | |
| aftercare_documents | imz_aftercare_documents_pk | aftercare_plan_id,document_id | btree | True | database/migrations/2026_09_24_009500_investmoz_document_links.php | |
| education_documents | imz_education_documents_pk | education_opportunity_id,document_id | btree | True | database/migrations/2026_09_24_009500_investmoz_document_links.php | |
| audit_events | imz_audit_events_pk | id | btree | True | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | |
| outbox_events | imz_outbox_events_pk | id | btree | True | database/migrations/2026_09_24_011000_investmoz_integrations.php | |
| inbox_events | imz_inbox_events_pk | id | btree | True | database/migrations/2026_09_24_011000_investmoz_integrations.php | |
| sync_runs | imz_sync_runs_pk | id | btree | True | database/migrations/2026_09_24_011000_investmoz_integrations.php | |
| reconciliation_issues | imz_reconciliation_issues_pk | id | btree | True | database/migrations/2026_09_24_011000_investmoz_integrations.php |
{
"schemas": [
"public"
],
"framework_owned_objects": [
"migrations (Laravel)"
],
"extension_owned_objects": "Objectos PostGIS pertencem à extensão; não são duplicados no dicionário aplicacional.",
"extensions": [
"postgis",
"pgcrypto"
],
"functions": [
"CREATE OR REPLACE FUNCTION public.investmoz_set_updated_at() RETURNS trigger\nLANGUAGE plpgsql SET search_path = pg_catalog, public AS $$\nBEGIN\n NEW.updated_at = CURRENT_TIMESTAMP;\n RETURN NEW;\nEND;\n$$;",
"CREATE OR REPLACE FUNCTION public.investmoz_reject_audit_change() RETURNS trigger\nLANGUAGE plpgsql SET search_path = pg_catalog, public AS $$\nBEGIN\n RAISE EXCEPTION 'InvestMoz audit_events is append-only' USING ERRCODE = '42501';\nEND;\n$$;",
"CREATE OR REPLACE FUNCTION public.investmoz_protect_event_envelope() RETURNS trigger\nLANGUAGE plpgsql SET search_path = pg_catalog, public AS $$\nBEGIN\n IF TG_OP = 'DELETE' THEN\n RAISE EXCEPTION 'InvestMoz event deletion requires a reviewed retention migration' USING ERRCODE = '42501';\n END IF;\n IF (to_jsonb(NEW) - ARRAY['status','updated_at','published_at','processed_at','available_at'])\n IS DISTINCT FROM\n (to_jsonb(OLD) - ARRAY['status','updated_at','published_at','processed_at','available_at']) THEN\n RAISE EXCEPTION 'InvestMoz event envelope is immutable' USING ERRCODE = '42501';\n END IF;\n RETURN NEW;\nEND;\n$$;"
],
"triggers": [
{
"name": "imz_organizations_updated",
"table": "organizations",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_memberships_updated",
"table": "memberships",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_consents_updated",
"table": "consents",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_documents_updated",
"table": "documents",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_geo_locations_updated",
"table": "geo_locations",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_geo_geometries_updated",
"table": "geo_geometries",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_projects_updated",
"table": "projects",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_project_locations_updated",
"table": "project_locations",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_economic_clusters_updated",
"table": "economic_clusters",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_value_chains_updated",
"table": "value_chains",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_value_chain_links_updated",
"table": "value_chain_links",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_cluster_projects_updated",
"table": "cluster_projects",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_anchor_project_links_updated",
"table": "anchor_project_links",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_complementary_project_links_updated",
"table": "complementary_project_links",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_development_corridors_updated",
"table": "development_corridors",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_corridor_locations_updated",
"table": "corridor_locations",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_corridor_projects_updated",
"table": "corridor_projects",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_corridor_clusters_updated",
"table": "corridor_clusters",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_investors_updated",
"table": "investors",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_contacts_updated",
"table": "contacts",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_investor_contacts_updated",
"table": "investor_contacts",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_leads_updated",
"table": "leads",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_crm_opportunities_updated",
"table": "crm_opportunities",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_activities_updated",
"table": "activities",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_tasks_updated",
"table": "tasks",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_investor_journeys_updated",
"table": "investor_journeys",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_journey_steps_updated",
"table": "journey_steps",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_submissions_updated",
"table": "submissions",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_aftercare_plans_updated",
"table": "aftercare_plans",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_constraints_updated",
"table": "constraints",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_escalations_updated",
"table": "escalations",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_skills_updated",
"table": "skills",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_occupations_updated",
"table": "occupations",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_training_needs_updated",
"table": "training_needs",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_training_providers_updated",
"table": "training_providers",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_courses_updated",
"table": "courses",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_education_opportunities_updated",
"table": "education_opportunities",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_outbox_events_updated",
"table": "outbox_events",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_inbox_events_updated",
"table": "inbox_events",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_sync_runs_updated",
"table": "sync_runs",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_reconciliation_issues_updated",
"table": "reconciliation_issues",
"event": "BEFORE UPDATE",
"function": "investmoz_set_updated_at",
"level": "ROW"
},
{
"name": "imz_audit_events_immutable",
"table": "audit_events",
"event": "BEFORE UPDATE OR DELETE OR TRUNCATE",
"function": "investmoz_reject_audit_change",
"level": "STATEMENT"
},
{
"name": "imz_outbox_events_envelope",
"table": "outbox_events",
"event": "BEFORE UPDATE OR DELETE",
"function": "investmoz_protect_event_envelope",
"level": "ROW"
},
{
"name": "imz_outbox_events_no_truncate",
"table": "outbox_events",
"event": "BEFORE TRUNCATE",
"function": "investmoz_reject_audit_change",
"level": "STATEMENT"
},
{
"name": "imz_inbox_events_envelope",
"table": "inbox_events",
"event": "BEFORE UPDATE OR DELETE",
"function": "investmoz_protect_event_envelope",
"level": "ROW"
},
{
"name": "imz_inbox_events_no_truncate",
"table": "inbox_events",
"event": "BEFORE TRUNCATE",
"function": "investmoz_reject_audit_change",
"level": "STATEMENT"
}
],
"views": [],
"materialized_views": [],
"custom_enums": [],
"generated_columns": [],
"sequences": [
"users_id_seq",
"jobs_id_seq",
"failed_jobs_id_seq",
"passkeys_id_seq",
"sectors_id_seq",
"opportunities_id_seq",
"interest_requests_id_seq"
],
"security_policies": [],
"audit": "append-only; writers must not own the tables or possess DDL privileges",
"logical_links_without_fk": [
"sessions.user_id -> users.id",
"password_reset_tokens.email -> users.email",
"audit_events.entity_type/entity_id",
"outbox_events.aggregate_type/aggregate_id"
]
}
Migrations completas
database/migrations/2026_09_24_000100_investmoz_extensions_functions.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE EXTENSION IF NOT EXISTS postgis;
SQL);
DB::statement(<<<'SQL'
CREATE EXTENSION IF NOT EXISTS pgcrypto;
SQL);
DB::statement(<<<'SQL'
CREATE OR REPLACE FUNCTION public.investmoz_set_updated_at() RETURNS trigger
LANGUAGE plpgsql SET search_path = pg_catalog, public AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$;
SQL);
DB::statement(<<<'SQL'
CREATE OR REPLACE FUNCTION public.investmoz_reject_audit_change() RETURNS trigger
LANGUAGE plpgsql SET search_path = pg_catalog, public AS $$
BEGIN
RAISE EXCEPTION 'InvestMoz audit_events is append-only' USING ERRCODE = '42501';
END;
$$;
SQL);
DB::statement(<<<'SQL'
CREATE OR REPLACE FUNCTION public.investmoz_protect_event_envelope() RETURNS trigger
LANGUAGE plpgsql SET search_path = pg_catalog, public AS $$
BEGIN
IF TG_OP = 'DELETE' THEN
RAISE EXCEPTION 'InvestMoz event deletion requires a reviewed retention migration' USING ERRCODE = '42501';
END IF;
IF (to_jsonb(NEW) - ARRAY['status','updated_at','published_at','processed_at','available_at'])
IS DISTINCT FROM
(to_jsonb(OLD) - ARRAY['status','updated_at','published_at','processed_at','available_at']) THEN
RAISE EXCEPTION 'InvestMoz event envelope is immutable' USING ERRCODE = '42501';
END IF;
RETURN NEW;
END;
$$;
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
DROP FUNCTION IF EXISTS public.investmoz_protect_event_envelope() RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP FUNCTION IF EXISTS public.investmoz_reject_audit_change() RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP FUNCTION IF EXISTS public.investmoz_set_updated_at() RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_001000_investmoz_identity.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.organizations (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
name text NOT NULL,
organization_type text NOT NULL,
CONSTRAINT imz_organizations_pk PRIMARY KEY (id),
CONSTRAINT imz_organizations_check_01 CHECK (version_no > 0),
CONSTRAINT imz_organizations_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_organizations_check_03 CHECK (organization_type IN ('public','private','ngo','education'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.memberships (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
user_id bigint NOT NULL CONSTRAINT imz_memberships_user_id_fk REFERENCES public.users(id) ON DELETE CASCADE ON UPDATE CASCADE,
organization_id uuid NOT NULL CONSTRAINT imz_memberships_organization_id_fk REFERENCES public.organizations(id) ON DELETE CASCADE ON UPDATE CASCADE,
role text NOT NULL,
CONSTRAINT imz_memberships_pk PRIMARY KEY (id),
CONSTRAINT imz_memberships_check_01 CHECK (version_no > 0),
CONSTRAINT imz_memberships_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_memberships_check_03 CHECK (role IN ('admin','manager','officer','viewer'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.consents (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
user_id bigint CONSTRAINT imz_consents_user_id_fk REFERENCES public.users(id) ON DELETE SET NULL ON UPDATE CASCADE,
subject_ref text NOT NULL,
purpose text NOT NULL,
status text NOT NULL,
granted_at timestamptz,
withdrawn_at timestamptz,
CONSTRAINT imz_consents_pk PRIMARY KEY (id),
CONSTRAINT imz_consents_check_01 CHECK (version_no > 0),
CONSTRAINT imz_consents_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_consents_check_03 CHECK (status IN ('granted','withdrawn','expired'))
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.consents DROP CONSTRAINT IF EXISTS imz_consents_user_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.consents DROP CONSTRAINT IF EXISTS imz_consents_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.consents DROP CONSTRAINT IF EXISTS imz_consents_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.consents DROP CONSTRAINT IF EXISTS imz_consents_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.consents DROP CONSTRAINT IF EXISTS imz_consents_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.consents RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.memberships DROP CONSTRAINT IF EXISTS imz_memberships_user_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.memberships DROP CONSTRAINT IF EXISTS imz_memberships_organization_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.memberships DROP CONSTRAINT IF EXISTS imz_memberships_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.memberships DROP CONSTRAINT IF EXISTS imz_memberships_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.memberships DROP CONSTRAINT IF EXISTS imz_memberships_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.memberships DROP CONSTRAINT IF EXISTS imz_memberships_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.memberships RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.organizations DROP CONSTRAINT IF EXISTS imz_organizations_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.organizations DROP CONSTRAINT IF EXISTS imz_organizations_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.organizations DROP CONSTRAINT IF EXISTS imz_organizations_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.organizations DROP CONSTRAINT IF EXISTS imz_organizations_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.organizations RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_002000_investmoz_content.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.documents (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
file_name text NOT NULL,
media_type text NOT NULL,
storage_key text NOT NULL,
sha256 char(64) NOT NULL,
status text NOT NULL,
CONSTRAINT imz_documents_pk PRIMARY KEY (id),
CONSTRAINT imz_documents_check_01 CHECK (version_no > 0),
CONSTRAINT imz_documents_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_documents_check_03 CHECK (status IN ('active','quarantined','deleted')),
CONSTRAINT imz_documents_check_04 CHECK (sha256 ~ '^[0-9a-f]{64}$')
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.documents DROP CONSTRAINT IF EXISTS imz_documents_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.documents DROP CONSTRAINT IF EXISTS imz_documents_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.documents DROP CONSTRAINT IF EXISTS imz_documents_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.documents DROP CONSTRAINT IF EXISTS imz_documents_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.documents DROP CONSTRAINT IF EXISTS imz_documents_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.documents RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_003000_investmoz_geography.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.geo_locations (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
name text NOT NULL,
location_type text NOT NULL,
parent_id uuid CONSTRAINT imz_geo_locations_parent_id_fk REFERENCES public.geo_locations(id) ON DELETE RESTRICT ON UPDATE CASCADE,
code text NOT NULL,
CONSTRAINT imz_geo_locations_pk PRIMARY KEY (id),
CONSTRAINT imz_geo_locations_check_01 CHECK (version_no > 0),
CONSTRAINT imz_geo_locations_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_geo_locations_check_03 CHECK (location_type IN ('country','province','district','municipality','site'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.geo_geometries (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
geo_location_id uuid NOT NULL CONSTRAINT imz_geo_geometries_geo_location_id_fk REFERENCES public.geo_locations(id) ON DELETE CASCADE ON UPDATE CASCADE,
geometry_type text NOT NULL,
geom geometry(Geometry,4326) NOT NULL,
properties jsonb NOT NULL DEFAULT '{}'::jsonb,
CONSTRAINT imz_geo_geometries_pk PRIMARY KEY (id),
CONSTRAINT imz_geo_geometries_check_01 CHECK (version_no > 0),
CONSTRAINT imz_geo_geometries_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_geo_geometries_check_03 CHECK (geometry_type IN ('point','line','polygon','multipolygon')),
CONSTRAINT imz_geo_geometries_check_04 CHECK (ST_SRID(geom) = 4326),
CONSTRAINT imz_geo_geometries_check_05 CHECK (ST_NDims(geom) = 2),
CONSTRAINT imz_geo_geometries_check_06 CHECK (NOT ST_IsEmpty(geom)),
CONSTRAINT imz_geo_geometries_check_07 CHECK (ST_IsValid(geom)),
CONSTRAINT imz_geo_geometries_check_08 CHECK ((geometry_type = 'point' AND GeometryType(geom) = 'POINT') OR (geometry_type = 'line' AND GeometryType(geom) = 'LINESTRING') OR (geometry_type = 'polygon' AND GeometryType(geom) = 'POLYGON') OR (geometry_type = 'multipolygon' AND GeometryType(geom) = 'MULTIPOLYGON')),
CONSTRAINT imz_geo_geometries_check_09 CHECK (ST_XMin(Box3D(geom)) >= -180 AND ST_XMax(Box3D(geom)) <= 180 AND ST_YMin(Box3D(geom)) >= -90 AND ST_YMax(Box3D(geom)) <= 90)
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_geo_location_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_check_05 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_check_06 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_check_07 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_check_08 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_geometries DROP CONSTRAINT IF EXISTS imz_geo_geometries_check_09 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.geo_geometries RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_locations DROP CONSTRAINT IF EXISTS imz_geo_locations_parent_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_locations DROP CONSTRAINT IF EXISTS imz_geo_locations_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_locations DROP CONSTRAINT IF EXISTS imz_geo_locations_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_locations DROP CONSTRAINT IF EXISTS imz_geo_locations_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.geo_locations DROP CONSTRAINT IF EXISTS imz_geo_locations_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.geo_locations RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_004000_investmoz_projects.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.projects (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
code text NOT NULL,
name text NOT NULL,
status text NOT NULL,
description text,
budget_amount numeric(20,2),
budget_currency char(3),
start_date date,
end_date date,
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
CONSTRAINT imz_projects_pk PRIMARY KEY (id),
CONSTRAINT imz_projects_check_01 CHECK (version_no > 0),
CONSTRAINT imz_projects_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_projects_check_03 CHECK (status IN ('draft','planned','active','suspended','completed','cancelled')),
CONSTRAINT imz_projects_check_04 CHECK (budget_amount IS NULL OR budget_amount >= 0),
CONSTRAINT imz_projects_check_05 CHECK (end_date IS NULL OR start_date IS NULL OR end_date >= start_date),
CONSTRAINT imz_projects_check_06 CHECK ((budget_amount IS NULL) = (budget_currency IS NULL)),
CONSTRAINT imz_projects_check_07 CHECK (budget_currency IS NULL OR budget_currency ~ '^[A-Z]{3}$')
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.project_locations (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
project_id uuid NOT NULL CONSTRAINT imz_project_locations_project_id_fk REFERENCES public.projects(id) ON DELETE CASCADE ON UPDATE CASCADE,
geo_location_id uuid NOT NULL CONSTRAINT imz_project_locations_geo_location_id_fk REFERENCES public.geo_locations(id) ON DELETE RESTRICT ON UPDATE CASCADE,
role text NOT NULL,
CONSTRAINT imz_project_locations_pk PRIMARY KEY (id),
CONSTRAINT imz_project_locations_check_01 CHECK (version_no > 0),
CONSTRAINT imz_project_locations_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_project_locations_check_03 CHECK (role IN ('primary','secondary','impact'))
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_geo_location_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.project_locations RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_05 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_06 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_07 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.projects RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_005000_investmoz_clusters.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.economic_clusters (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
code text NOT NULL,
name text NOT NULL,
sector text NOT NULL,
status text NOT NULL,
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
CONSTRAINT imz_economic_clusters_pk PRIMARY KEY (id),
CONSTRAINT imz_economic_clusters_check_01 CHECK (version_no > 0),
CONSTRAINT imz_economic_clusters_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_economic_clusters_check_03 CHECK (status IN ('planned','active','inactive'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.value_chains (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
cluster_id uuid NOT NULL CONSTRAINT imz_value_chains_cluster_id_fk REFERENCES public.economic_clusters(id) ON DELETE CASCADE ON UPDATE CASCADE,
code text NOT NULL,
name text NOT NULL,
stage text NOT NULL,
CONSTRAINT imz_value_chains_pk PRIMARY KEY (id),
CONSTRAINT imz_value_chains_check_01 CHECK (version_no > 0),
CONSTRAINT imz_value_chains_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_value_chains_check_03 CHECK (stage IN ('input','production','processing','logistics','market'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.value_chain_links (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
from_value_chain_id uuid NOT NULL CONSTRAINT imz_value_chain_links_from_value_chain_id_fk REFERENCES public.value_chains(id) ON DELETE CASCADE ON UPDATE CASCADE,
to_value_chain_id uuid NOT NULL CONSTRAINT imz_value_chain_links_to_value_chain_id_fk REFERENCES public.value_chains(id) ON DELETE CASCADE ON UPDATE CASCADE,
link_type text NOT NULL,
CONSTRAINT imz_value_chain_links_pk PRIMARY KEY (id),
CONSTRAINT imz_value_chain_links_check_01 CHECK (version_no > 0),
CONSTRAINT imz_value_chain_links_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_value_chain_links_check_03 CHECK (link_type IN ('supplies','processes','distributes','supports')),
CONSTRAINT imz_value_chain_links_check_04 CHECK (from_value_chain_id <> to_value_chain_id)
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.cluster_projects (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
cluster_id uuid NOT NULL CONSTRAINT imz_cluster_projects_cluster_id_fk REFERENCES public.economic_clusters(id) ON DELETE CASCADE ON UPDATE CASCADE,
project_id uuid NOT NULL CONSTRAINT imz_cluster_projects_project_id_fk REFERENCES public.projects(id) ON DELETE CASCADE ON UPDATE CASCADE,
role text NOT NULL,
CONSTRAINT imz_cluster_projects_pk PRIMARY KEY (id),
CONSTRAINT imz_cluster_projects_check_01 CHECK (version_no > 0),
CONSTRAINT imz_cluster_projects_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_cluster_projects_check_03 CHECK (role IN ('anchor','complementary','supporting'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.anchor_project_links (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
anchor_project_id uuid NOT NULL CONSTRAINT imz_anchor_project_links_anchor_project_id_fk REFERENCES public.projects(id) ON DELETE CASCADE ON UPDATE CASCADE,
cluster_id uuid NOT NULL CONSTRAINT imz_anchor_project_links_cluster_id_fk REFERENCES public.economic_clusters(id) ON DELETE CASCADE ON UPDATE CASCADE,
rationale text NOT NULL,
CONSTRAINT imz_anchor_project_links_pk PRIMARY KEY (id),
CONSTRAINT imz_anchor_project_links_check_01 CHECK (version_no > 0),
CONSTRAINT imz_anchor_project_links_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.complementary_project_links (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
anchor_project_id uuid NOT NULL CONSTRAINT imz_complementary_project_links_anchor_project_id_fk REFERENCES public.projects(id) ON DELETE CASCADE ON UPDATE CASCADE,
complementary_project_id uuid NOT NULL CONSTRAINT imz_complementary_project_links_complementary_project_id_fk REFERENCES public.projects(id) ON DELETE CASCADE ON UPDATE CASCADE,
relation_type text NOT NULL,
CONSTRAINT imz_complementary_project_links_pk PRIMARY KEY (id),
CONSTRAINT imz_complementary_project_links_check_01 CHECK (version_no > 0),
CONSTRAINT imz_complementary_project_links_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_complementary_project_links_check_03 CHECK (relation_type IN ('dependency','enabler','supplier','market')),
CONSTRAINT imz_complementary_project_links_check_04 CHECK (anchor_project_id<>complementary_project_id)
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.complementary_project_links DROP CONSTRAINT IF EXISTS imz_complementary_project_links_anchor_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.complementary_project_links DROP CONSTRAINT IF EXISTS imz_complementary_project_links_complementary_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.complementary_project_links DROP CONSTRAINT IF EXISTS imz_complementary_project_links_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.complementary_project_links DROP CONSTRAINT IF EXISTS imz_complementary_project_links_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.complementary_project_links DROP CONSTRAINT IF EXISTS imz_complementary_project_links_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.complementary_project_links DROP CONSTRAINT IF EXISTS imz_complementary_project_links_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.complementary_project_links DROP CONSTRAINT IF EXISTS imz_complementary_project_links_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.complementary_project_links RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.anchor_project_links DROP CONSTRAINT IF EXISTS imz_anchor_project_links_anchor_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.anchor_project_links DROP CONSTRAINT IF EXISTS imz_anchor_project_links_cluster_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.anchor_project_links DROP CONSTRAINT IF EXISTS imz_anchor_project_links_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.anchor_project_links DROP CONSTRAINT IF EXISTS imz_anchor_project_links_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.anchor_project_links DROP CONSTRAINT IF EXISTS imz_anchor_project_links_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.anchor_project_links RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.cluster_projects DROP CONSTRAINT IF EXISTS imz_cluster_projects_cluster_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.cluster_projects DROP CONSTRAINT IF EXISTS imz_cluster_projects_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.cluster_projects DROP CONSTRAINT IF EXISTS imz_cluster_projects_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.cluster_projects DROP CONSTRAINT IF EXISTS imz_cluster_projects_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.cluster_projects DROP CONSTRAINT IF EXISTS imz_cluster_projects_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.cluster_projects DROP CONSTRAINT IF EXISTS imz_cluster_projects_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.cluster_projects RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chain_links DROP CONSTRAINT IF EXISTS imz_value_chain_links_from_value_chain_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chain_links DROP CONSTRAINT IF EXISTS imz_value_chain_links_to_value_chain_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chain_links DROP CONSTRAINT IF EXISTS imz_value_chain_links_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chain_links DROP CONSTRAINT IF EXISTS imz_value_chain_links_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chain_links DROP CONSTRAINT IF EXISTS imz_value_chain_links_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chain_links DROP CONSTRAINT IF EXISTS imz_value_chain_links_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chain_links DROP CONSTRAINT IF EXISTS imz_value_chain_links_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.value_chain_links RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chains DROP CONSTRAINT IF EXISTS imz_value_chains_cluster_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chains DROP CONSTRAINT IF EXISTS imz_value_chains_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chains DROP CONSTRAINT IF EXISTS imz_value_chains_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chains DROP CONSTRAINT IF EXISTS imz_value_chains_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.value_chains DROP CONSTRAINT IF EXISTS imz_value_chains_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.value_chains RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.economic_clusters DROP CONSTRAINT IF EXISTS imz_economic_clusters_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.economic_clusters DROP CONSTRAINT IF EXISTS imz_economic_clusters_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.economic_clusters DROP CONSTRAINT IF EXISTS imz_economic_clusters_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.economic_clusters DROP CONSTRAINT IF EXISTS imz_economic_clusters_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.economic_clusters RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_006000_investmoz_corridors.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.development_corridors (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
code text NOT NULL,
name text NOT NULL,
status text NOT NULL,
description text,
CONSTRAINT imz_development_corridors_pk PRIMARY KEY (id),
CONSTRAINT imz_development_corridors_check_01 CHECK (version_no > 0),
CONSTRAINT imz_development_corridors_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_development_corridors_check_03 CHECK (status IN ('proposed','active','closed'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.corridor_locations (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
corridor_id uuid NOT NULL CONSTRAINT imz_corridor_locations_corridor_id_fk REFERENCES public.development_corridors(id) ON DELETE CASCADE ON UPDATE CASCADE,
geo_location_id uuid NOT NULL CONSTRAINT imz_corridor_locations_geo_location_id_fk REFERENCES public.geo_locations(id) ON DELETE RESTRICT ON UPDATE CASCADE,
sequence_no integer NOT NULL,
CONSTRAINT imz_corridor_locations_pk PRIMARY KEY (id),
CONSTRAINT imz_corridor_locations_check_01 CHECK (version_no > 0),
CONSTRAINT imz_corridor_locations_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_corridor_locations_check_03 CHECK (sequence_no>0)
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.corridor_projects (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
corridor_id uuid NOT NULL CONSTRAINT imz_corridor_projects_corridor_id_fk REFERENCES public.development_corridors(id) ON DELETE CASCADE ON UPDATE CASCADE,
project_id uuid NOT NULL CONSTRAINT imz_corridor_projects_project_id_fk REFERENCES public.projects(id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT imz_corridor_projects_pk PRIMARY KEY (id),
CONSTRAINT imz_corridor_projects_check_01 CHECK (version_no > 0),
CONSTRAINT imz_corridor_projects_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.corridor_clusters (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
corridor_id uuid NOT NULL CONSTRAINT imz_corridor_clusters_corridor_id_fk REFERENCES public.development_corridors(id) ON DELETE CASCADE ON UPDATE CASCADE,
cluster_id uuid NOT NULL CONSTRAINT imz_corridor_clusters_cluster_id_fk REFERENCES public.economic_clusters(id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT imz_corridor_clusters_pk PRIMARY KEY (id),
CONSTRAINT imz_corridor_clusters_check_01 CHECK (version_no > 0),
CONSTRAINT imz_corridor_clusters_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted'))
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_clusters DROP CONSTRAINT IF EXISTS imz_corridor_clusters_corridor_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_clusters DROP CONSTRAINT IF EXISTS imz_corridor_clusters_cluster_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_clusters DROP CONSTRAINT IF EXISTS imz_corridor_clusters_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_clusters DROP CONSTRAINT IF EXISTS imz_corridor_clusters_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_clusters DROP CONSTRAINT IF EXISTS imz_corridor_clusters_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.corridor_clusters RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_projects DROP CONSTRAINT IF EXISTS imz_corridor_projects_corridor_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_projects DROP CONSTRAINT IF EXISTS imz_corridor_projects_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_projects DROP CONSTRAINT IF EXISTS imz_corridor_projects_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_projects DROP CONSTRAINT IF EXISTS imz_corridor_projects_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_projects DROP CONSTRAINT IF EXISTS imz_corridor_projects_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.corridor_projects RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_locations DROP CONSTRAINT IF EXISTS imz_corridor_locations_corridor_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_locations DROP CONSTRAINT IF EXISTS imz_corridor_locations_geo_location_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_locations DROP CONSTRAINT IF EXISTS imz_corridor_locations_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_locations DROP CONSTRAINT IF EXISTS imz_corridor_locations_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_locations DROP CONSTRAINT IF EXISTS imz_corridor_locations_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.corridor_locations DROP CONSTRAINT IF EXISTS imz_corridor_locations_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.corridor_locations RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.development_corridors DROP CONSTRAINT IF EXISTS imz_development_corridors_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.development_corridors DROP CONSTRAINT IF EXISTS imz_development_corridors_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.development_corridors DROP CONSTRAINT IF EXISTS imz_development_corridors_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.development_corridors DROP CONSTRAINT IF EXISTS imz_development_corridors_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.development_corridors RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_007000_investmoz_crm.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.investors (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
organization_id uuid CONSTRAINT imz_investors_organization_id_fk REFERENCES public.organizations(id) ON DELETE SET NULL ON UPDATE CASCADE,
legal_name text NOT NULL,
investor_type text NOT NULL,
status text NOT NULL,
CONSTRAINT imz_investors_pk PRIMARY KEY (id),
CONSTRAINT imz_investors_check_01 CHECK (version_no > 0),
CONSTRAINT imz_investors_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_investors_check_03 CHECK (investor_type IN ('domestic','foreign','institutional','individual')),
CONSTRAINT imz_investors_check_04 CHECK (status IN ('prospect','active','inactive'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.contacts (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
full_name text NOT NULL,
email text,
phone text,
CONSTRAINT imz_contacts_pk PRIMARY KEY (id),
CONSTRAINT imz_contacts_check_01 CHECK (version_no > 0),
CONSTRAINT imz_contacts_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.investor_contacts (
investor_id uuid NOT NULL CONSTRAINT imz_investor_contacts_investor_id_fk REFERENCES public.investors(id) ON DELETE CASCADE ON UPDATE CASCADE,
contact_id uuid NOT NULL CONSTRAINT imz_investor_contacts_contact_id_fk REFERENCES public.contacts(id) ON DELETE CASCADE ON UPDATE CASCADE,
is_primary boolean NOT NULL DEFAULT false,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT imz_investor_contacts_pk PRIMARY KEY (investor_id, contact_id)
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.leads (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
investor_id uuid CONSTRAINT imz_leads_investor_id_fk REFERENCES public.investors(id) ON DELETE SET NULL ON UPDATE CASCADE,
owner_user_id bigint CONSTRAINT imz_leads_owner_user_id_fk REFERENCES public.users(id) ON DELETE SET NULL ON UPDATE CASCADE,
title text NOT NULL,
status text NOT NULL,
estimated_amount numeric(20,2),
currency char(3),
CONSTRAINT imz_leads_pk PRIMARY KEY (id),
CONSTRAINT imz_leads_check_01 CHECK (version_no > 0),
CONSTRAINT imz_leads_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_leads_check_03 CHECK (status IN ('new','qualified','disqualified','converted')),
CONSTRAINT imz_leads_check_04 CHECK ((estimated_amount IS NULL)=(currency IS NULL)),
CONSTRAINT imz_leads_check_05 CHECK (estimated_amount IS NULL OR estimated_amount >= 0),
CONSTRAINT imz_leads_check_06 CHECK (currency IS NULL OR currency ~ '^[A-Z]{3}$')
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.crm_opportunities (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
lead_id uuid CONSTRAINT imz_crm_opportunities_lead_id_fk REFERENCES public.leads(id) ON DELETE SET NULL ON UPDATE CASCADE,
project_id uuid CONSTRAINT imz_crm_opportunities_project_id_fk REFERENCES public.projects(id) ON DELETE SET NULL ON UPDATE CASCADE,
owner_user_id bigint CONSTRAINT imz_crm_opportunities_owner_user_id_fk REFERENCES public.users(id) ON DELETE SET NULL ON UPDATE CASCADE,
stage text NOT NULL,
amount numeric(20,2),
currency char(3),
probability numeric(5,2),
CONSTRAINT imz_crm_opportunities_pk PRIMARY KEY (id),
CONSTRAINT imz_crm_opportunities_check_01 CHECK (version_no > 0),
CONSTRAINT imz_crm_opportunities_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_crm_opportunities_check_03 CHECK (stage IN ('discovery','assessment','negotiation','approved','lost')),
CONSTRAINT imz_crm_opportunities_check_04 CHECK (probability BETWEEN 0 AND 100),
CONSTRAINT imz_crm_opportunities_check_05 CHECK ((amount IS NULL)=(currency IS NULL)),
CONSTRAINT imz_crm_opportunities_check_06 CHECK (amount IS NULL OR amount >= 0),
CONSTRAINT imz_crm_opportunities_check_07 CHECK (currency IS NULL OR currency ~ '^[A-Z]{3}$')
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.activities (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
investor_id uuid CONSTRAINT imz_activities_investor_id_fk REFERENCES public.investors(id) ON DELETE CASCADE ON UPDATE CASCADE,
opportunity_id uuid CONSTRAINT imz_activities_opportunity_id_fk REFERENCES public.crm_opportunities(id) ON DELETE SET NULL ON UPDATE CASCADE,
actor_user_id bigint CONSTRAINT imz_activities_actor_user_id_fk REFERENCES public.users(id) ON DELETE SET NULL ON UPDATE CASCADE,
activity_type text NOT NULL,
occurred_at timestamptz NOT NULL,
summary text NOT NULL,
CONSTRAINT imz_activities_pk PRIMARY KEY (id),
CONSTRAINT imz_activities_check_01 CHECK (version_no > 0),
CONSTRAINT imz_activities_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_activities_check_03 CHECK (activity_type IN ('call','meeting','email','note'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.tasks (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
assignee_user_id bigint CONSTRAINT imz_tasks_assignee_user_id_fk REFERENCES public.users(id) ON DELETE SET NULL ON UPDATE CASCADE,
opportunity_id uuid CONSTRAINT imz_tasks_opportunity_id_fk REFERENCES public.crm_opportunities(id) ON DELETE CASCADE ON UPDATE CASCADE,
title text NOT NULL,
status text NOT NULL,
due_at timestamptz,
CONSTRAINT imz_tasks_pk PRIMARY KEY (id),
CONSTRAINT imz_tasks_check_01 CHECK (version_no > 0),
CONSTRAINT imz_tasks_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_tasks_check_03 CHECK (status IN ('open','in_progress','done','cancelled'))
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.tasks DROP CONSTRAINT IF EXISTS imz_tasks_assignee_user_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.tasks DROP CONSTRAINT IF EXISTS imz_tasks_opportunity_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.tasks DROP CONSTRAINT IF EXISTS imz_tasks_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.tasks DROP CONSTRAINT IF EXISTS imz_tasks_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.tasks DROP CONSTRAINT IF EXISTS imz_tasks_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.tasks DROP CONSTRAINT IF EXISTS imz_tasks_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.tasks RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.activities DROP CONSTRAINT IF EXISTS imz_activities_investor_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.activities DROP CONSTRAINT IF EXISTS imz_activities_opportunity_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.activities DROP CONSTRAINT IF EXISTS imz_activities_actor_user_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.activities DROP CONSTRAINT IF EXISTS imz_activities_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.activities DROP CONSTRAINT IF EXISTS imz_activities_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.activities DROP CONSTRAINT IF EXISTS imz_activities_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.activities DROP CONSTRAINT IF EXISTS imz_activities_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.activities RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_lead_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_owner_user_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_check_05 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_check_06 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.crm_opportunities DROP CONSTRAINT IF EXISTS imz_crm_opportunities_check_07 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.crm_opportunities RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.leads DROP CONSTRAINT IF EXISTS imz_leads_investor_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.leads DROP CONSTRAINT IF EXISTS imz_leads_owner_user_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.leads DROP CONSTRAINT IF EXISTS imz_leads_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.leads DROP CONSTRAINT IF EXISTS imz_leads_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.leads DROP CONSTRAINT IF EXISTS imz_leads_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.leads DROP CONSTRAINT IF EXISTS imz_leads_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.leads DROP CONSTRAINT IF EXISTS imz_leads_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.leads DROP CONSTRAINT IF EXISTS imz_leads_check_05 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.leads DROP CONSTRAINT IF EXISTS imz_leads_check_06 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.leads RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_contacts DROP CONSTRAINT IF EXISTS imz_investor_contacts_investor_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_contacts DROP CONSTRAINT IF EXISTS imz_investor_contacts_contact_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_contacts DROP CONSTRAINT IF EXISTS imz_investor_contacts_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.investor_contacts RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.contacts DROP CONSTRAINT IF EXISTS imz_contacts_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.contacts DROP CONSTRAINT IF EXISTS imz_contacts_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.contacts DROP CONSTRAINT IF EXISTS imz_contacts_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.contacts RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investors DROP CONSTRAINT IF EXISTS imz_investors_organization_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investors DROP CONSTRAINT IF EXISTS imz_investors_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investors DROP CONSTRAINT IF EXISTS imz_investors_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investors DROP CONSTRAINT IF EXISTS imz_investors_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investors DROP CONSTRAINT IF EXISTS imz_investors_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investors DROP CONSTRAINT IF EXISTS imz_investors_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.investors RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.investor_journeys (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
investor_id uuid NOT NULL CONSTRAINT imz_investor_journeys_investor_id_fk REFERENCES public.investors(id) ON DELETE CASCADE ON UPDATE CASCADE,
opportunity_id uuid CONSTRAINT imz_investor_journeys_opportunity_id_fk REFERENCES public.crm_opportunities(id) ON DELETE SET NULL ON UPDATE CASCADE,
status text NOT NULL,
started_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT imz_investor_journeys_pk PRIMARY KEY (id),
CONSTRAINT imz_investor_journeys_check_01 CHECK (version_no > 0),
CONSTRAINT imz_investor_journeys_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_investor_journeys_check_03 CHECK (status IN ('started','active','completed','cancelled'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.journey_steps (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
journey_id uuid NOT NULL CONSTRAINT imz_journey_steps_journey_id_fk REFERENCES public.investor_journeys(id) ON DELETE CASCADE ON UPDATE CASCADE,
step_code text NOT NULL,
sequence_no integer NOT NULL,
status text NOT NULL,
CONSTRAINT imz_journey_steps_pk PRIMARY KEY (id),
CONSTRAINT imz_journey_steps_check_01 CHECK (version_no > 0),
CONSTRAINT imz_journey_steps_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_journey_steps_check_03 CHECK (sequence_no>0),
CONSTRAINT imz_journey_steps_check_04 CHECK (status IN ('pending','active','completed','blocked'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.submissions (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
journey_step_id uuid NOT NULL CONSTRAINT imz_submissions_journey_step_id_fk REFERENCES public.journey_steps(id) ON DELETE CASCADE ON UPDATE CASCADE,
submitted_by bigint CONSTRAINT imz_submissions_submitted_by_fk REFERENCES public.users(id) ON DELETE SET NULL ON UPDATE CASCADE,
status text NOT NULL,
payload jsonb NOT NULL DEFAULT '{}'::jsonb,
submitted_at timestamptz,
CONSTRAINT imz_submissions_pk PRIMARY KEY (id),
CONSTRAINT imz_submissions_check_01 CHECK (version_no > 0),
CONSTRAINT imz_submissions_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_submissions_check_03 CHECK (status IN ('draft','submitted','accepted','rejected'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.aftercare_plans (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
investor_id uuid NOT NULL CONSTRAINT imz_aftercare_plans_investor_id_fk REFERENCES public.investors(id) ON DELETE CASCADE ON UPDATE CASCADE,
project_id uuid CONSTRAINT imz_aftercare_plans_project_id_fk REFERENCES public.projects(id) ON DELETE SET NULL ON UPDATE CASCADE,
owner_user_id bigint CONSTRAINT imz_aftercare_plans_owner_user_id_fk REFERENCES public.users(id) ON DELETE SET NULL ON UPDATE CASCADE,
status text NOT NULL,
review_date date,
CONSTRAINT imz_aftercare_plans_pk PRIMARY KEY (id),
CONSTRAINT imz_aftercare_plans_check_01 CHECK (version_no > 0),
CONSTRAINT imz_aftercare_plans_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_aftercare_plans_check_03 CHECK (status IN ('draft','active','closed'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.constraints (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
aftercare_plan_id uuid NOT NULL CONSTRAINT imz_constraints_aftercare_plan_id_fk REFERENCES public.aftercare_plans(id) ON DELETE CASCADE ON UPDATE CASCADE,
category text NOT NULL,
description text NOT NULL,
severity text NOT NULL,
status text NOT NULL,
CONSTRAINT imz_constraints_pk PRIMARY KEY (id),
CONSTRAINT imz_constraints_check_01 CHECK (version_no > 0),
CONSTRAINT imz_constraints_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_constraints_check_03 CHECK (severity IN ('low','medium','high','critical')),
CONSTRAINT imz_constraints_check_04 CHECK (status IN ('open','mitigating','resolved'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.escalations (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
constraint_id uuid NOT NULL CONSTRAINT imz_escalations_constraint_id_fk REFERENCES public.constraints(id) ON DELETE CASCADE ON UPDATE CASCADE,
escalated_by bigint CONSTRAINT imz_escalations_escalated_by_fk REFERENCES public.users(id) ON DELETE SET NULL ON UPDATE CASCADE,
level text NOT NULL,
status text NOT NULL,
escalated_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT imz_escalations_pk PRIMARY KEY (id),
CONSTRAINT imz_escalations_check_01 CHECK (version_no > 0),
CONSTRAINT imz_escalations_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_escalations_check_03 CHECK (level IN ('operational','management','executive')),
CONSTRAINT imz_escalations_check_04 CHECK (status IN ('open','acknowledged','closed'))
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.escalations DROP CONSTRAINT IF EXISTS imz_escalations_constraint_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.escalations DROP CONSTRAINT IF EXISTS imz_escalations_escalated_by_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.escalations DROP CONSTRAINT IF EXISTS imz_escalations_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.escalations DROP CONSTRAINT IF EXISTS imz_escalations_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.escalations DROP CONSTRAINT IF EXISTS imz_escalations_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.escalations DROP CONSTRAINT IF EXISTS imz_escalations_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.escalations DROP CONSTRAINT IF EXISTS imz_escalations_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.escalations RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.constraints DROP CONSTRAINT IF EXISTS imz_constraints_aftercare_plan_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.constraints DROP CONSTRAINT IF EXISTS imz_constraints_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.constraints DROP CONSTRAINT IF EXISTS imz_constraints_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.constraints DROP CONSTRAINT IF EXISTS imz_constraints_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.constraints DROP CONSTRAINT IF EXISTS imz_constraints_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.constraints DROP CONSTRAINT IF EXISTS imz_constraints_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.constraints RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_plans DROP CONSTRAINT IF EXISTS imz_aftercare_plans_investor_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_plans DROP CONSTRAINT IF EXISTS imz_aftercare_plans_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_plans DROP CONSTRAINT IF EXISTS imz_aftercare_plans_owner_user_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_plans DROP CONSTRAINT IF EXISTS imz_aftercare_plans_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_plans DROP CONSTRAINT IF EXISTS imz_aftercare_plans_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_plans DROP CONSTRAINT IF EXISTS imz_aftercare_plans_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_plans DROP CONSTRAINT IF EXISTS imz_aftercare_plans_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.aftercare_plans RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.submissions DROP CONSTRAINT IF EXISTS imz_submissions_journey_step_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.submissions DROP CONSTRAINT IF EXISTS imz_submissions_submitted_by_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.submissions DROP CONSTRAINT IF EXISTS imz_submissions_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.submissions DROP CONSTRAINT IF EXISTS imz_submissions_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.submissions DROP CONSTRAINT IF EXISTS imz_submissions_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.submissions DROP CONSTRAINT IF EXISTS imz_submissions_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.submissions RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.journey_steps DROP CONSTRAINT IF EXISTS imz_journey_steps_journey_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.journey_steps DROP CONSTRAINT IF EXISTS imz_journey_steps_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.journey_steps DROP CONSTRAINT IF EXISTS imz_journey_steps_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.journey_steps DROP CONSTRAINT IF EXISTS imz_journey_steps_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.journey_steps DROP CONSTRAINT IF EXISTS imz_journey_steps_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.journey_steps DROP CONSTRAINT IF EXISTS imz_journey_steps_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.journey_steps RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_journeys DROP CONSTRAINT IF EXISTS imz_investor_journeys_investor_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_journeys DROP CONSTRAINT IF EXISTS imz_investor_journeys_opportunity_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_journeys DROP CONSTRAINT IF EXISTS imz_investor_journeys_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_journeys DROP CONSTRAINT IF EXISTS imz_investor_journeys_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_journeys DROP CONSTRAINT IF EXISTS imz_investor_journeys_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_journeys DROP CONSTRAINT IF EXISTS imz_investor_journeys_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.investor_journeys RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_009000_investmoz_education.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.skills (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
code text NOT NULL,
name text NOT NULL,
CONSTRAINT imz_skills_pk PRIMARY KEY (id),
CONSTRAINT imz_skills_check_01 CHECK (version_no > 0),
CONSTRAINT imz_skills_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.occupations (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
code text NOT NULL,
name text NOT NULL,
CONSTRAINT imz_occupations_pk PRIMARY KEY (id),
CONSTRAINT imz_occupations_check_01 CHECK (version_no > 0),
CONSTRAINT imz_occupations_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.training_needs (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
project_id uuid CONSTRAINT imz_training_needs_project_id_fk REFERENCES public.projects(id) ON DELETE SET NULL ON UPDATE CASCADE,
occupation_id uuid CONSTRAINT imz_training_needs_occupation_id_fk REFERENCES public.occupations(id) ON DELETE RESTRICT ON UPDATE CASCADE,
skill_id uuid CONSTRAINT imz_training_needs_skill_id_fk REFERENCES public.skills(id) ON DELETE RESTRICT ON UPDATE CASCADE,
quantity integer NOT NULL,
priority text NOT NULL,
CONSTRAINT imz_training_needs_pk PRIMARY KEY (id),
CONSTRAINT imz_training_needs_check_01 CHECK (version_no > 0),
CONSTRAINT imz_training_needs_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_training_needs_check_03 CHECK (quantity>0),
CONSTRAINT imz_training_needs_check_04 CHECK (priority IN ('Must','Should','Could'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.training_providers (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
organization_id uuid CONSTRAINT imz_training_providers_organization_id_fk REFERENCES public.organizations(id) ON DELETE SET NULL ON UPDATE CASCADE,
name text NOT NULL,
status text NOT NULL,
CONSTRAINT imz_training_providers_pk PRIMARY KEY (id),
CONSTRAINT imz_training_providers_check_01 CHECK (version_no > 0),
CONSTRAINT imz_training_providers_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_training_providers_check_03 CHECK (status IN ('candidate','approved','inactive'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.courses (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
provider_id uuid NOT NULL CONSTRAINT imz_courses_provider_id_fk REFERENCES public.training_providers(id) ON DELETE CASCADE ON UPDATE CASCADE,
code text NOT NULL,
title text NOT NULL,
status text NOT NULL,
CONSTRAINT imz_courses_pk PRIMARY KEY (id),
CONSTRAINT imz_courses_check_01 CHECK (version_no > 0),
CONSTRAINT imz_courses_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_courses_check_03 CHECK (status IN ('draft','published','retired'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.education_opportunities (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
course_id uuid NOT NULL CONSTRAINT imz_education_opportunities_course_id_fk REFERENCES public.courses(id) ON DELETE CASCADE ON UPDATE CASCADE,
geo_location_id uuid CONSTRAINT imz_education_opportunities_geo_location_id_fk REFERENCES public.geo_locations(id) ON DELETE SET NULL ON UPDATE CASCADE,
start_date date NOT NULL,
end_date date,
capacity integer,
status text NOT NULL,
CONSTRAINT imz_education_opportunities_pk PRIMARY KEY (id),
CONSTRAINT imz_education_opportunities_check_01 CHECK (version_no > 0),
CONSTRAINT imz_education_opportunities_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_education_opportunities_check_03 CHECK (capacity>=0),
CONSTRAINT imz_education_opportunities_check_04 CHECK (status IN ('planned','open','closed','cancelled')),
CONSTRAINT imz_education_opportunities_check_05 CHECK (end_date IS NULL OR end_date>=start_date)
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_opportunities DROP CONSTRAINT IF EXISTS imz_education_opportunities_course_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_opportunities DROP CONSTRAINT IF EXISTS imz_education_opportunities_geo_location_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_opportunities DROP CONSTRAINT IF EXISTS imz_education_opportunities_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_opportunities DROP CONSTRAINT IF EXISTS imz_education_opportunities_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_opportunities DROP CONSTRAINT IF EXISTS imz_education_opportunities_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_opportunities DROP CONSTRAINT IF EXISTS imz_education_opportunities_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_opportunities DROP CONSTRAINT IF EXISTS imz_education_opportunities_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_opportunities DROP CONSTRAINT IF EXISTS imz_education_opportunities_check_05 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.education_opportunities RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.courses DROP CONSTRAINT IF EXISTS imz_courses_provider_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.courses DROP CONSTRAINT IF EXISTS imz_courses_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.courses DROP CONSTRAINT IF EXISTS imz_courses_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.courses DROP CONSTRAINT IF EXISTS imz_courses_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.courses DROP CONSTRAINT IF EXISTS imz_courses_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.courses RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_providers DROP CONSTRAINT IF EXISTS imz_training_providers_organization_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_providers DROP CONSTRAINT IF EXISTS imz_training_providers_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_providers DROP CONSTRAINT IF EXISTS imz_training_providers_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_providers DROP CONSTRAINT IF EXISTS imz_training_providers_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_providers DROP CONSTRAINT IF EXISTS imz_training_providers_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.training_providers RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_needs DROP CONSTRAINT IF EXISTS imz_training_needs_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_needs DROP CONSTRAINT IF EXISTS imz_training_needs_occupation_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_needs DROP CONSTRAINT IF EXISTS imz_training_needs_skill_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_needs DROP CONSTRAINT IF EXISTS imz_training_needs_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_needs DROP CONSTRAINT IF EXISTS imz_training_needs_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_needs DROP CONSTRAINT IF EXISTS imz_training_needs_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_needs DROP CONSTRAINT IF EXISTS imz_training_needs_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.training_needs DROP CONSTRAINT IF EXISTS imz_training_needs_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.training_needs RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.occupations DROP CONSTRAINT IF EXISTS imz_occupations_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.occupations DROP CONSTRAINT IF EXISTS imz_occupations_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.occupations DROP CONSTRAINT IF EXISTS imz_occupations_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.occupations RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.skills DROP CONSTRAINT IF EXISTS imz_skills_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.skills DROP CONSTRAINT IF EXISTS imz_skills_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.skills DROP CONSTRAINT IF EXISTS imz_skills_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.skills RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_009500_investmoz_document_links.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.project_documents (
project_id uuid NOT NULL CONSTRAINT imz_project_documents_project_id_fk REFERENCES public.projects(id) ON DELETE CASCADE ON UPDATE CASCADE,
document_id uuid NOT NULL CONSTRAINT imz_project_documents_document_id_fk REFERENCES public.documents(id) ON DELETE RESTRICT ON UPDATE CASCADE,
created_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT imz_project_documents_pk PRIMARY KEY (project_id, document_id)
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.investor_documents (
investor_id uuid NOT NULL CONSTRAINT imz_investor_documents_investor_id_fk REFERENCES public.investors(id) ON DELETE CASCADE ON UPDATE CASCADE,
document_id uuid NOT NULL CONSTRAINT imz_investor_documents_document_id_fk REFERENCES public.documents(id) ON DELETE RESTRICT ON UPDATE CASCADE,
created_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT imz_investor_documents_pk PRIMARY KEY (investor_id, document_id)
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.journey_documents (
journey_id uuid NOT NULL CONSTRAINT imz_journey_documents_journey_id_fk REFERENCES public.investor_journeys(id) ON DELETE CASCADE ON UPDATE CASCADE,
document_id uuid NOT NULL CONSTRAINT imz_journey_documents_document_id_fk REFERENCES public.documents(id) ON DELETE RESTRICT ON UPDATE CASCADE,
created_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT imz_journey_documents_pk PRIMARY KEY (journey_id, document_id)
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.aftercare_documents (
aftercare_plan_id uuid NOT NULL CONSTRAINT imz_aftercare_documents_aftercare_plan_id_fk REFERENCES public.aftercare_plans(id) ON DELETE CASCADE ON UPDATE CASCADE,
document_id uuid NOT NULL CONSTRAINT imz_aftercare_documents_document_id_fk REFERENCES public.documents(id) ON DELETE RESTRICT ON UPDATE CASCADE,
created_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT imz_aftercare_documents_pk PRIMARY KEY (aftercare_plan_id, document_id)
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.education_documents (
education_opportunity_id uuid NOT NULL CONSTRAINT imz_education_documents_education_opportunity_id_fk REFERENCES public.education_opportunities(id) ON DELETE CASCADE ON UPDATE CASCADE,
document_id uuid NOT NULL CONSTRAINT imz_education_documents_document_id_fk REFERENCES public.documents(id) ON DELETE RESTRICT ON UPDATE CASCADE,
created_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT imz_education_documents_pk PRIMARY KEY (education_opportunity_id, document_id)
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_documents DROP CONSTRAINT IF EXISTS imz_education_documents_education_opportunity_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_documents DROP CONSTRAINT IF EXISTS imz_education_documents_document_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.education_documents DROP CONSTRAINT IF EXISTS imz_education_documents_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.education_documents RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_documents DROP CONSTRAINT IF EXISTS imz_aftercare_documents_aftercare_plan_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_documents DROP CONSTRAINT IF EXISTS imz_aftercare_documents_document_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.aftercare_documents DROP CONSTRAINT IF EXISTS imz_aftercare_documents_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.aftercare_documents RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.journey_documents DROP CONSTRAINT IF EXISTS imz_journey_documents_journey_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.journey_documents DROP CONSTRAINT IF EXISTS imz_journey_documents_document_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.journey_documents DROP CONSTRAINT IF EXISTS imz_journey_documents_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.journey_documents RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_documents DROP CONSTRAINT IF EXISTS imz_investor_documents_investor_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_documents DROP CONSTRAINT IF EXISTS imz_investor_documents_document_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.investor_documents DROP CONSTRAINT IF EXISTS imz_investor_documents_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.investor_documents RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.project_documents DROP CONSTRAINT IF EXISTS imz_project_documents_project_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.project_documents DROP CONSTRAINT IF EXISTS imz_project_documents_document_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.project_documents DROP CONSTRAINT IF EXISTS imz_project_documents_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.project_documents RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_010000_investmoz_governance_ai.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.audit_events (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
actor_user_id bigint CONSTRAINT imz_audit_events_actor_user_id_fk REFERENCES public.users(id) ON DELETE RESTRICT ON UPDATE RESTRICT,
entity_type text NOT NULL,
entity_id uuid,
action text NOT NULL,
occurred_at timestamptz NOT NULL DEFAULT now(),
before_data jsonb,
after_data jsonb,
CONSTRAINT imz_audit_events_pk PRIMARY KEY (id),
CONSTRAINT imz_audit_events_check_01 CHECK (data_classification IN ('public','internal','confidential','restricted'))
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.audit_events DROP CONSTRAINT IF EXISTS imz_audit_events_actor_user_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.audit_events DROP CONSTRAINT IF EXISTS imz_audit_events_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.audit_events DROP CONSTRAINT IF EXISTS imz_audit_events_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.audit_events RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_011000_investmoz_integrations.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TABLE public.outbox_events (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
aggregate_type text NOT NULL,
aggregate_id uuid NOT NULL,
event_type text NOT NULL,
payload jsonb NOT NULL,
status text NOT NULL,
available_at timestamptz NOT NULL DEFAULT now(),
published_at timestamptz,
CONSTRAINT imz_outbox_events_pk PRIMARY KEY (id),
CONSTRAINT imz_outbox_events_check_01 CHECK (version_no > 0),
CONSTRAINT imz_outbox_events_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_outbox_events_check_03 CHECK (status IN ('pending','published','failed'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.inbox_events (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
message_id text NOT NULL,
event_type text NOT NULL,
payload jsonb NOT NULL,
status text NOT NULL,
received_at timestamptz NOT NULL DEFAULT now(),
processed_at timestamptz,
CONSTRAINT imz_inbox_events_pk PRIMARY KEY (id),
CONSTRAINT imz_inbox_events_check_01 CHECK (version_no > 0),
CONSTRAINT imz_inbox_events_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_inbox_events_check_03 CHECK (status IN ('received','processed','failed'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.sync_runs (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
integration_name text NOT NULL,
direction text NOT NULL,
status text NOT NULL,
started_at timestamptz NOT NULL DEFAULT now(),
ended_at timestamptz,
totals jsonb NOT NULL DEFAULT '{}'::jsonb,
CONSTRAINT imz_sync_runs_pk PRIMARY KEY (id),
CONSTRAINT imz_sync_runs_check_01 CHECK (version_no > 0),
CONSTRAINT imz_sync_runs_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_sync_runs_check_03 CHECK (direction IN ('inbound','outbound')),
CONSTRAINT imz_sync_runs_check_04 CHECK (status IN ('running','succeeded','failed','cancelled'))
);
SQL);
DB::statement(<<<'SQL'
CREATE TABLE public.reconciliation_issues (
id uuid DEFAULT gen_random_uuid() NOT NULL,
source_system text NOT NULL DEFAULT 'investmoz',
external_id text,
version_no integer NOT NULL DEFAULT 1,
data_classification text NOT NULL DEFAULT 'internal',
correlation_id uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
sync_run_id uuid NOT NULL CONSTRAINT imz_reconciliation_issues_sync_run_id_fk REFERENCES public.sync_runs(id) ON DELETE CASCADE ON UPDATE CASCADE,
entity_type text NOT NULL,
external_id_ref text,
issue_type text NOT NULL,
severity text NOT NULL,
status text NOT NULL,
details jsonb NOT NULL DEFAULT '{}'::jsonb,
CONSTRAINT imz_reconciliation_issues_pk PRIMARY KEY (id),
CONSTRAINT imz_reconciliation_issues_check_01 CHECK (version_no > 0),
CONSTRAINT imz_reconciliation_issues_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')),
CONSTRAINT imz_reconciliation_issues_check_03 CHECK (issue_type IN ('missing','duplicate','orphan','checksum','geometry','value')),
CONSTRAINT imz_reconciliation_issues_check_04 CHECK (severity IN ('warning','error')),
CONSTRAINT imz_reconciliation_issues_check_05 CHECK (status IN ('open','accepted','resolved'))
);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.reconciliation_issues DROP CONSTRAINT IF EXISTS imz_reconciliation_issues_sync_run_id_fk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.reconciliation_issues DROP CONSTRAINT IF EXISTS imz_reconciliation_issues_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.reconciliation_issues DROP CONSTRAINT IF EXISTS imz_reconciliation_issues_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.reconciliation_issues DROP CONSTRAINT IF EXISTS imz_reconciliation_issues_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.reconciliation_issues DROP CONSTRAINT IF EXISTS imz_reconciliation_issues_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.reconciliation_issues DROP CONSTRAINT IF EXISTS imz_reconciliation_issues_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.reconciliation_issues DROP CONSTRAINT IF EXISTS imz_reconciliation_issues_check_05 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.reconciliation_issues RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.sync_runs DROP CONSTRAINT IF EXISTS imz_sync_runs_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.sync_runs DROP CONSTRAINT IF EXISTS imz_sync_runs_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.sync_runs DROP CONSTRAINT IF EXISTS imz_sync_runs_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.sync_runs DROP CONSTRAINT IF EXISTS imz_sync_runs_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.sync_runs DROP CONSTRAINT IF EXISTS imz_sync_runs_check_04 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.sync_runs RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.inbox_events DROP CONSTRAINT IF EXISTS imz_inbox_events_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.inbox_events DROP CONSTRAINT IF EXISTS imz_inbox_events_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.inbox_events DROP CONSTRAINT IF EXISTS imz_inbox_events_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.inbox_events DROP CONSTRAINT IF EXISTS imz_inbox_events_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.inbox_events RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.outbox_events DROP CONSTRAINT IF EXISTS imz_outbox_events_pk RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.outbox_events DROP CONSTRAINT IF EXISTS imz_outbox_events_check_01 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.outbox_events DROP CONSTRAINT IF EXISTS imz_outbox_events_check_02 RESTRICT;
SQL);
DB::statement(<<<'SQL'
ALTER TABLE IF EXISTS public.outbox_events DROP CONSTRAINT IF EXISTS imz_outbox_events_check_03 RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TABLE IF EXISTS public.outbox_events RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_012000_investmoz_indexes.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_organizations_source_system_external_id_uq ON public.organizations USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_organizations_updated_at_idx ON public.organizations USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_memberships_user_id_idx ON public.memberships USING btree (user_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_memberships_organization_id_idx ON public.memberships USING btree (organization_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_memberships_user_id_organization_id_uq ON public.memberships USING btree (user_id, organization_id) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_memberships_source_system_external_id_uq ON public.memberships USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_memberships_updated_at_idx ON public.memberships USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_consents_user_id_idx ON public.consents USING btree (user_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_consents_source_system_external_id_uq ON public.consents USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_consents_updated_at_idx ON public.consents USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_consents_status_idx ON public.consents USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_documents_storage_key_uq ON public.documents USING btree (storage_key);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_documents_source_system_external_id_uq ON public.documents USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_documents_updated_at_idx ON public.documents USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_documents_status_idx ON public.documents USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_geo_locations_parent_id_idx ON public.geo_locations USING btree (parent_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_geo_locations_source_system_external_id_uq ON public.geo_locations USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_geo_locations_location_type_code_uq ON public.geo_locations USING btree (location_type, code) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_geo_locations_updated_at_idx ON public.geo_locations USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_geo_geometries_geo_location_id_idx ON public.geo_geometries USING btree (geo_location_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_geo_geometries_geo_location_id_geometry_type_uq ON public.geo_geometries USING btree (geo_location_id, geometry_type) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_geo_geometries_source_system_external_id_uq ON public.geo_geometries USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_geo_geometries_geom_idx ON public.geo_geometries USING gist (geom);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_geo_geometries_updated_at_idx ON public.geo_geometries USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_projects_code_uq ON public.projects USING btree (code) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_projects_source_system_external_id_uq ON public.projects USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_projects_updated_at_idx ON public.projects USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_projects_status_idx ON public.projects USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_project_locations_project_id_idx ON public.project_locations USING btree (project_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_project_locations_geo_location_id_idx ON public.project_locations USING btree (geo_location_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_project_locations_project_id_geo_location_id_role_uq ON public.project_locations USING btree (project_id, geo_location_id, role) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_project_locations_source_system_external_id_uq ON public.project_locations USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_project_locations_updated_at_idx ON public.project_locations USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_economic_clusters_code_uq ON public.economic_clusters USING btree (code) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_economic_clusters_source_system_external_id_uq ON public.economic_clusters USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_economic_clusters_updated_at_idx ON public.economic_clusters USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_economic_clusters_status_idx ON public.economic_clusters USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_value_chains_cluster_id_idx ON public.value_chains USING btree (cluster_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_value_chains_cluster_id_code_uq ON public.value_chains USING btree (cluster_id, code) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_value_chains_source_system_external_id_uq ON public.value_chains USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_value_chains_updated_at_idx ON public.value_chains USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_value_chain_links_from_value_chain_id_idx ON public.value_chain_links USING btree (from_value_chain_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_value_chain_links_to_value_chain_id_idx ON public.value_chain_links USING btree (to_value_chain_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_value_chain_links_from_value_chain_id_to_value_c_f6a1a6162c ON public.value_chain_links USING btree (from_value_chain_id, to_value_chain_id, link_type) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_value_chain_links_source_system_external_id_uq ON public.value_chain_links USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_value_chain_links_updated_at_idx ON public.value_chain_links USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_cluster_projects_cluster_id_idx ON public.cluster_projects USING btree (cluster_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_cluster_projects_project_id_idx ON public.cluster_projects USING btree (project_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_cluster_projects_cluster_id_project_id_uq ON public.cluster_projects USING btree (cluster_id, project_id) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_cluster_projects_source_system_external_id_uq ON public.cluster_projects USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_cluster_projects_updated_at_idx ON public.cluster_projects USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_anchor_project_links_anchor_project_id_idx ON public.anchor_project_links USING btree (anchor_project_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_anchor_project_links_cluster_id_idx ON public.anchor_project_links USING btree (cluster_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_anchor_project_links_anchor_project_id_cluster_id_uq ON public.anchor_project_links USING btree (anchor_project_id, cluster_id) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_anchor_project_links_source_system_external_id_uq ON public.anchor_project_links USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_anchor_project_links_updated_at_idx ON public.anchor_project_links USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_complementary_project_links_anchor_project_id_idx ON public.complementary_project_links USING btree (anchor_project_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_complementary_project_links_complementary_project_id_idx ON public.complementary_project_links USING btree (complementary_project_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_complementary_project_links_anchor_project_id_co_90eddcd25a ON public.complementary_project_links USING btree (anchor_project_id, complementary_project_id, relation_type) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_complementary_project_links_source_system_external_id_uq ON public.complementary_project_links USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_complementary_project_links_updated_at_idx ON public.complementary_project_links USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_development_corridors_code_uq ON public.development_corridors USING btree (code) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_development_corridors_source_system_external_id_uq ON public.development_corridors USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_development_corridors_updated_at_idx ON public.development_corridors USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_development_corridors_status_idx ON public.development_corridors USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_corridor_locations_corridor_id_idx ON public.corridor_locations USING btree (corridor_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_corridor_locations_geo_location_id_idx ON public.corridor_locations USING btree (geo_location_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_corridor_locations_corridor_id_geo_location_id_uq ON public.corridor_locations USING btree (corridor_id, geo_location_id) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_corridor_locations_corridor_id_sequence_no_uq ON public.corridor_locations USING btree (corridor_id, sequence_no) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_corridor_locations_source_system_external_id_uq ON public.corridor_locations USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_corridor_locations_updated_at_idx ON public.corridor_locations USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_corridor_projects_corridor_id_idx ON public.corridor_projects USING btree (corridor_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_corridor_projects_project_id_idx ON public.corridor_projects USING btree (project_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_corridor_projects_corridor_id_project_id_uq ON public.corridor_projects USING btree (corridor_id, project_id) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_corridor_projects_source_system_external_id_uq ON public.corridor_projects USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_corridor_projects_updated_at_idx ON public.corridor_projects USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_corridor_clusters_corridor_id_idx ON public.corridor_clusters USING btree (corridor_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_corridor_clusters_cluster_id_idx ON public.corridor_clusters USING btree (cluster_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_corridor_clusters_corridor_id_cluster_id_uq ON public.corridor_clusters USING btree (corridor_id, cluster_id) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_corridor_clusters_source_system_external_id_uq ON public.corridor_clusters USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_corridor_clusters_updated_at_idx ON public.corridor_clusters USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investors_organization_id_idx ON public.investors USING btree (organization_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_investors_source_system_external_id_uq ON public.investors USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investors_updated_at_idx ON public.investors USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investors_status_idx ON public.investors USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_contacts_source_system_external_id_uq ON public.contacts USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_contacts_updated_at_idx ON public.contacts USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investor_contacts_investor_id_idx ON public.investor_contacts USING btree (investor_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investor_contacts_contact_id_idx ON public.investor_contacts USING btree (contact_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investor_contacts_updated_at_idx ON public.investor_contacts USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_leads_investor_id_idx ON public.leads USING btree (investor_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_leads_owner_user_id_idx ON public.leads USING btree (owner_user_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_leads_source_system_external_id_uq ON public.leads USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_leads_updated_at_idx ON public.leads USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_leads_status_idx ON public.leads USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_crm_opportunities_lead_id_idx ON public.crm_opportunities USING btree (lead_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_crm_opportunities_project_id_idx ON public.crm_opportunities USING btree (project_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_crm_opportunities_owner_user_id_idx ON public.crm_opportunities USING btree (owner_user_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_crm_opportunities_source_system_external_id_uq ON public.crm_opportunities USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_crm_opportunities_updated_at_idx ON public.crm_opportunities USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_activities_investor_id_idx ON public.activities USING btree (investor_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_activities_opportunity_id_idx ON public.activities USING btree (opportunity_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_activities_actor_user_id_idx ON public.activities USING btree (actor_user_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_activities_source_system_external_id_uq ON public.activities USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_activities_updated_at_idx ON public.activities USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_tasks_assignee_user_id_idx ON public.tasks USING btree (assignee_user_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_tasks_opportunity_id_idx ON public.tasks USING btree (opportunity_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_tasks_source_system_external_id_uq ON public.tasks USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_tasks_updated_at_idx ON public.tasks USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_tasks_status_idx ON public.tasks USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investor_journeys_investor_id_idx ON public.investor_journeys USING btree (investor_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investor_journeys_opportunity_id_idx ON public.investor_journeys USING btree (opportunity_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_investor_journeys_source_system_external_id_uq ON public.investor_journeys USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investor_journeys_updated_at_idx ON public.investor_journeys USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investor_journeys_status_idx ON public.investor_journeys USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_journey_steps_journey_id_idx ON public.journey_steps USING btree (journey_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_journey_steps_journey_id_sequence_no_uq ON public.journey_steps USING btree (journey_id, sequence_no) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_journey_steps_journey_id_step_code_uq ON public.journey_steps USING btree (journey_id, step_code) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_journey_steps_source_system_external_id_uq ON public.journey_steps USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_journey_steps_updated_at_idx ON public.journey_steps USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_journey_steps_status_idx ON public.journey_steps USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_submissions_journey_step_id_idx ON public.submissions USING btree (journey_step_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_submissions_submitted_by_idx ON public.submissions USING btree (submitted_by);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_submissions_source_system_external_id_uq ON public.submissions USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_submissions_updated_at_idx ON public.submissions USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_submissions_status_idx ON public.submissions USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_aftercare_plans_investor_id_idx ON public.aftercare_plans USING btree (investor_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_aftercare_plans_project_id_idx ON public.aftercare_plans USING btree (project_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_aftercare_plans_owner_user_id_idx ON public.aftercare_plans USING btree (owner_user_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_aftercare_plans_source_system_external_id_uq ON public.aftercare_plans USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_aftercare_plans_updated_at_idx ON public.aftercare_plans USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_aftercare_plans_status_idx ON public.aftercare_plans USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_constraints_aftercare_plan_id_idx ON public.constraints USING btree (aftercare_plan_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_constraints_source_system_external_id_uq ON public.constraints USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_constraints_updated_at_idx ON public.constraints USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_constraints_status_idx ON public.constraints USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_escalations_constraint_id_idx ON public.escalations USING btree (constraint_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_escalations_escalated_by_idx ON public.escalations USING btree (escalated_by);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_escalations_source_system_external_id_uq ON public.escalations USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_escalations_updated_at_idx ON public.escalations USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_escalations_status_idx ON public.escalations USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_skills_code_uq ON public.skills USING btree (code) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_skills_source_system_external_id_uq ON public.skills USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_skills_updated_at_idx ON public.skills USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_occupations_code_uq ON public.occupations USING btree (code) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_occupations_source_system_external_id_uq ON public.occupations USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_occupations_updated_at_idx ON public.occupations USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_training_needs_project_id_idx ON public.training_needs USING btree (project_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_training_needs_occupation_id_idx ON public.training_needs USING btree (occupation_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_training_needs_skill_id_idx ON public.training_needs USING btree (skill_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_training_needs_source_system_external_id_uq ON public.training_needs USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_training_needs_updated_at_idx ON public.training_needs USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_training_providers_organization_id_idx ON public.training_providers USING btree (organization_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_training_providers_source_system_external_id_uq ON public.training_providers USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_training_providers_updated_at_idx ON public.training_providers USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_training_providers_status_idx ON public.training_providers USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_courses_provider_id_idx ON public.courses USING btree (provider_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_courses_provider_id_code_uq ON public.courses USING btree (provider_id, code) WHERE deleted_at IS NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_courses_source_system_external_id_uq ON public.courses USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_courses_updated_at_idx ON public.courses USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_courses_status_idx ON public.courses USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_education_opportunities_course_id_idx ON public.education_opportunities USING btree (course_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_education_opportunities_geo_location_id_idx ON public.education_opportunities USING btree (geo_location_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_education_opportunities_source_system_external_id_uq ON public.education_opportunities USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_education_opportunities_updated_at_idx ON public.education_opportunities USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_education_opportunities_status_idx ON public.education_opportunities USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_project_documents_project_id_idx ON public.project_documents USING btree (project_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_project_documents_document_id_idx ON public.project_documents USING btree (document_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investor_documents_investor_id_idx ON public.investor_documents USING btree (investor_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_investor_documents_document_id_idx ON public.investor_documents USING btree (document_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_journey_documents_journey_id_idx ON public.journey_documents USING btree (journey_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_journey_documents_document_id_idx ON public.journey_documents USING btree (document_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_aftercare_documents_aftercare_plan_id_idx ON public.aftercare_documents USING btree (aftercare_plan_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_aftercare_documents_document_id_idx ON public.aftercare_documents USING btree (document_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_education_documents_education_opportunity_id_idx ON public.education_documents USING btree (education_opportunity_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_education_documents_document_id_idx ON public.education_documents USING btree (document_id);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_audit_events_actor_user_id_idx ON public.audit_events USING btree (actor_user_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_audit_events_source_system_external_id_uq ON public.audit_events USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_outbox_events_source_system_external_id_uq ON public.outbox_events USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_outbox_events_updated_at_idx ON public.outbox_events USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_outbox_events_status_idx ON public.outbox_events USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_inbox_events_message_id_uq ON public.inbox_events USING btree (message_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_inbox_events_source_system_external_id_uq ON public.inbox_events USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_inbox_events_updated_at_idx ON public.inbox_events USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_inbox_events_status_idx ON public.inbox_events USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_sync_runs_source_system_external_id_uq ON public.sync_runs USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_sync_runs_updated_at_idx ON public.sync_runs USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_sync_runs_status_idx ON public.sync_runs USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_reconciliation_issues_sync_run_id_idx ON public.reconciliation_issues USING btree (sync_run_id);
SQL);
DB::statement(<<<'SQL'
CREATE UNIQUE INDEX imz_reconciliation_issues_source_system_external_id_uq ON public.reconciliation_issues USING btree (source_system, external_id) WHERE external_id IS NOT NULL;
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_reconciliation_issues_updated_at_idx ON public.reconciliation_issues USING btree (updated_at);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_reconciliation_issues_status_idx ON public.reconciliation_issues USING btree (status);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_geo_geometries_properties_idx ON public.geo_geometries USING gin (properties);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_projects_metadata_idx ON public.projects USING gin (metadata);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_submissions_payload_idx ON public.submissions USING gin (payload);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_audit_events_after_data_idx ON public.audit_events USING gin (after_data);
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_outbox_events_status_available_at_idx ON public.outbox_events USING btree (status, available_at) WHERE status = 'pending';
SQL);
DB::statement(<<<'SQL'
CREATE INDEX imz_reconciliation_issues_sync_run_id_status_idx ON public.reconciliation_issues USING btree (sync_run_id, status);
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_reconciliation_issues_sync_run_id_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_outbox_events_status_available_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_audit_events_after_data_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_submissions_payload_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_projects_metadata_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_geometries_properties_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_reconciliation_issues_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_reconciliation_issues_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_reconciliation_issues_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_reconciliation_issues_sync_run_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_sync_runs_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_sync_runs_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_sync_runs_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_inbox_events_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_inbox_events_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_inbox_events_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_inbox_events_message_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_outbox_events_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_outbox_events_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_outbox_events_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_audit_events_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_audit_events_actor_user_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_education_documents_document_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_education_documents_education_opportunity_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_aftercare_documents_document_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_aftercare_documents_aftercare_plan_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_journey_documents_document_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_journey_documents_journey_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_documents_document_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_documents_investor_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_project_documents_document_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_project_documents_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_education_opportunities_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_education_opportunities_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_education_opportunities_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_education_opportunities_geo_location_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_education_opportunities_course_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_courses_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_courses_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_courses_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_courses_provider_id_code_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_courses_provider_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_training_providers_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_training_providers_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_training_providers_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_training_providers_organization_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_training_needs_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_training_needs_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_training_needs_skill_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_training_needs_occupation_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_training_needs_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_occupations_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_occupations_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_occupations_code_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_skills_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_skills_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_skills_code_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_escalations_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_escalations_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_escalations_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_escalations_escalated_by_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_escalations_constraint_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_constraints_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_constraints_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_constraints_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_constraints_aftercare_plan_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_aftercare_plans_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_aftercare_plans_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_aftercare_plans_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_aftercare_plans_owner_user_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_aftercare_plans_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_aftercare_plans_investor_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_submissions_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_submissions_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_submissions_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_submissions_submitted_by_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_submissions_journey_step_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_journey_steps_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_journey_steps_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_journey_steps_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_journey_steps_journey_id_step_code_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_journey_steps_journey_id_sequence_no_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_journey_steps_journey_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_journeys_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_journeys_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_journeys_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_journeys_opportunity_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_journeys_investor_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_tasks_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_tasks_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_tasks_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_tasks_opportunity_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_tasks_assignee_user_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_activities_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_activities_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_activities_actor_user_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_activities_opportunity_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_activities_investor_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_crm_opportunities_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_crm_opportunities_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_crm_opportunities_owner_user_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_crm_opportunities_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_crm_opportunities_lead_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_leads_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_leads_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_leads_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_leads_owner_user_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_leads_investor_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_contacts_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_contacts_contact_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investor_contacts_investor_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_contacts_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_contacts_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investors_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investors_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investors_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_investors_organization_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_clusters_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_clusters_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_clusters_corridor_id_cluster_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_clusters_cluster_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_clusters_corridor_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_projects_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_projects_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_projects_corridor_id_project_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_projects_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_projects_corridor_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_locations_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_locations_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_locations_corridor_id_sequence_no_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_locations_corridor_id_geo_location_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_locations_geo_location_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_corridor_locations_corridor_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_development_corridors_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_development_corridors_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_development_corridors_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_development_corridors_code_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_complementary_project_links_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_complementary_project_links_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_complementary_project_links_anchor_project_id_co_90eddcd25a RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_complementary_project_links_complementary_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_complementary_project_links_anchor_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_anchor_project_links_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_anchor_project_links_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_anchor_project_links_anchor_project_id_cluster_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_anchor_project_links_cluster_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_anchor_project_links_anchor_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_cluster_projects_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_cluster_projects_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_cluster_projects_cluster_id_project_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_cluster_projects_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_cluster_projects_cluster_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_value_chain_links_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_value_chain_links_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_value_chain_links_from_value_chain_id_to_value_c_f6a1a6162c RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_value_chain_links_to_value_chain_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_value_chain_links_from_value_chain_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_value_chains_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_value_chains_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_value_chains_cluster_id_code_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_value_chains_cluster_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_economic_clusters_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_economic_clusters_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_economic_clusters_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_economic_clusters_code_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_project_locations_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_project_locations_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_project_locations_project_id_geo_location_id_role_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_project_locations_geo_location_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_project_locations_project_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_projects_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_projects_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_projects_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_projects_code_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_geometries_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_geometries_geom_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_geometries_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_geometries_geo_location_id_geometry_type_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_geometries_geo_location_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_locations_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_locations_location_type_code_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_locations_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_geo_locations_parent_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_documents_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_documents_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_documents_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_documents_storage_key_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_consents_status_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_consents_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_consents_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_consents_user_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_memberships_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_memberships_source_system_external_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_memberships_user_id_organization_id_uq RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_memberships_organization_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_memberships_user_id_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_organizations_updated_at_idx RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP INDEX IF EXISTS public.imz_organizations_source_system_external_id_uq RESTRICT;
SQL);
}
};
database/migrations/2026_09_24_013000_investmoz_triggers.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
// Laravel's migration ledger provides idempotency; object drift fails explicitly.
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.');
}
DB::statement(<<<'SQL'
CREATE TRIGGER imz_organizations_updated BEFORE UPDATE ON public.organizations FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_memberships_updated BEFORE UPDATE ON public.memberships FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_consents_updated BEFORE UPDATE ON public.consents FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_documents_updated BEFORE UPDATE ON public.documents FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_geo_locations_updated BEFORE UPDATE ON public.geo_locations FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_geo_geometries_updated BEFORE UPDATE ON public.geo_geometries FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_projects_updated BEFORE UPDATE ON public.projects FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_project_locations_updated BEFORE UPDATE ON public.project_locations FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_economic_clusters_updated BEFORE UPDATE ON public.economic_clusters FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_value_chains_updated BEFORE UPDATE ON public.value_chains FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_value_chain_links_updated BEFORE UPDATE ON public.value_chain_links FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_cluster_projects_updated BEFORE UPDATE ON public.cluster_projects FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_anchor_project_links_updated BEFORE UPDATE ON public.anchor_project_links FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_complementary_project_links_updated BEFORE UPDATE ON public.complementary_project_links FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_development_corridors_updated BEFORE UPDATE ON public.development_corridors FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_corridor_locations_updated BEFORE UPDATE ON public.corridor_locations FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_corridor_projects_updated BEFORE UPDATE ON public.corridor_projects FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_corridor_clusters_updated BEFORE UPDATE ON public.corridor_clusters FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_investors_updated BEFORE UPDATE ON public.investors FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_contacts_updated BEFORE UPDATE ON public.contacts FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_investor_contacts_updated BEFORE UPDATE ON public.investor_contacts FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_leads_updated BEFORE UPDATE ON public.leads FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_crm_opportunities_updated BEFORE UPDATE ON public.crm_opportunities FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_activities_updated BEFORE UPDATE ON public.activities FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_tasks_updated BEFORE UPDATE ON public.tasks FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_investor_journeys_updated BEFORE UPDATE ON public.investor_journeys FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_journey_steps_updated BEFORE UPDATE ON public.journey_steps FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_submissions_updated BEFORE UPDATE ON public.submissions FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_aftercare_plans_updated BEFORE UPDATE ON public.aftercare_plans FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_constraints_updated BEFORE UPDATE ON public.constraints FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_escalations_updated BEFORE UPDATE ON public.escalations FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_skills_updated BEFORE UPDATE ON public.skills FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_occupations_updated BEFORE UPDATE ON public.occupations FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_training_needs_updated BEFORE UPDATE ON public.training_needs FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_training_providers_updated BEFORE UPDATE ON public.training_providers FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_courses_updated BEFORE UPDATE ON public.courses FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_education_opportunities_updated BEFORE UPDATE ON public.education_opportunities FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_outbox_events_updated BEFORE UPDATE ON public.outbox_events FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_inbox_events_updated BEFORE UPDATE ON public.inbox_events FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_sync_runs_updated BEFORE UPDATE ON public.sync_runs FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_reconciliation_issues_updated BEFORE UPDATE ON public.reconciliation_issues FOR EACH ROW EXECUTE FUNCTION public.investmoz_set_updated_at();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_audit_events_immutable BEFORE UPDATE OR DELETE OR TRUNCATE ON public.audit_events FOR EACH STATEMENT EXECUTE FUNCTION public.investmoz_reject_audit_change();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_outbox_events_envelope BEFORE UPDATE OR DELETE ON public.outbox_events FOR EACH ROW EXECUTE FUNCTION public.investmoz_protect_event_envelope();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_outbox_events_no_truncate BEFORE TRUNCATE ON public.outbox_events FOR EACH STATEMENT EXECUTE FUNCTION public.investmoz_reject_audit_change();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_inbox_events_envelope BEFORE UPDATE OR DELETE ON public.inbox_events FOR EACH ROW EXECUTE FUNCTION public.investmoz_protect_event_envelope();
SQL);
DB::statement(<<<'SQL'
CREATE TRIGGER imz_inbox_events_no_truncate BEFORE TRUNCATE ON public.inbox_events FOR EACH STATEMENT EXECUTE FUNCTION public.investmoz_reject_audit_change();
SQL);
}
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('InvestMoz rollback requires PostgreSQL.');
}
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_inbox_events_no_truncate ON public.inbox_events RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_inbox_events_envelope ON public.inbox_events RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_outbox_events_no_truncate ON public.outbox_events RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_outbox_events_envelope ON public.outbox_events RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_audit_events_immutable ON public.audit_events RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_reconciliation_issues_updated ON public.reconciliation_issues RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_sync_runs_updated ON public.sync_runs RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_inbox_events_updated ON public.inbox_events RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_outbox_events_updated ON public.outbox_events RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_education_opportunities_updated ON public.education_opportunities RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_courses_updated ON public.courses RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_training_providers_updated ON public.training_providers RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_training_needs_updated ON public.training_needs RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_occupations_updated ON public.occupations RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_skills_updated ON public.skills RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_escalations_updated ON public.escalations RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_constraints_updated ON public.constraints RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_aftercare_plans_updated ON public.aftercare_plans RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_submissions_updated ON public.submissions RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_journey_steps_updated ON public.journey_steps RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_investor_journeys_updated ON public.investor_journeys RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_tasks_updated ON public.tasks RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_activities_updated ON public.activities RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_crm_opportunities_updated ON public.crm_opportunities RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_leads_updated ON public.leads RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_investor_contacts_updated ON public.investor_contacts RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_contacts_updated ON public.contacts RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_investors_updated ON public.investors RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_corridor_clusters_updated ON public.corridor_clusters RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_corridor_projects_updated ON public.corridor_projects RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_corridor_locations_updated ON public.corridor_locations RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_development_corridors_updated ON public.development_corridors RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_complementary_project_links_updated ON public.complementary_project_links RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_anchor_project_links_updated ON public.anchor_project_links RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_cluster_projects_updated ON public.cluster_projects RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_value_chain_links_updated ON public.value_chain_links RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_value_chains_updated ON public.value_chains RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_economic_clusters_updated ON public.economic_clusters RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_project_locations_updated ON public.project_locations RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_projects_updated ON public.projects RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_geo_geometries_updated ON public.geo_geometries RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_geo_locations_updated ON public.geo_locations RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_documents_updated ON public.documents RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_consents_updated ON public.consents RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_memberships_updated ON public.memberships RESTRICT;
SQL);
DB::statement(<<<'SQL'
DROP TRIGGER IF EXISTS imz_organizations_updated ON public.organizations RESTRICT;
SQL);
}
};
Migrations existentes preservadas
database/migrations/0001_01_01_000000_create_users_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
};
database/migrations/0001_01_01_000001_create_cache_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->bigInteger('expiration')->index();
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->bigInteger('expiration')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};
database/migrations/0001_01_01_000002_create_jobs_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('jobs', function (Blueprint $table) {
$table->id();
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedSmallInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
Schema::create('job_batches', function (Blueprint $table) {
$table->string('id')->primary();
$table->string('name');
$table->integer('total_jobs');
$table->integer('pending_jobs');
$table->integer('failed_jobs');
$table->longText('failed_job_ids');
$table->mediumText('options')->nullable();
$table->integer('cancelled_at')->nullable();
$table->integer('created_at');
$table->integer('finished_at')->nullable();
});
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->string('connection');
$table->string('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
$table->index(['connection', 'queue', 'failed_at']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('jobs');
Schema::dropIfExists('job_batches');
Schema::dropIfExists('failed_jobs');
}
};
database/migrations/2024_01_01_000000_create_passkeys_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('passkeys', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->string('credential_id')->unique();
$table->json('credential');
$table->timestamp('last_used_at')->nullable();
$table->timestamps();
$table->index('user_id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('passkeys');
}
};
database/migrations/2025_08_14_170933_add_two_factor_columns_to_users_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->text('two_factor_secret')->after('password')->nullable();
$table->text('two_factor_recovery_codes')->after('two_factor_secret')->nullable();
$table->timestamp('two_factor_confirmed_at')->after('two_factor_recovery_codes')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn([
'two_factor_secret',
'two_factor_recovery_codes',
'two_factor_confirmed_at',
]);
});
}
};
database/migrations/2026_01_01_000001_create_sectors_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('sectors', function (Blueprint $table) {
$table->id();
$table->string('name', 150);
$table->string('slug', 180)->unique();
$table->string('short_description', 255)->nullable();
$table->text('description')->nullable();
$table->string('icon', 100)->nullable();
$table->unsignedInteger('sort_order')->default(0);
$table->boolean('is_active')->default(true);
$table->timestamp('published_at')->nullable();
$table->timestamps();
$table->softDeletes();
$table->index('slug');
$table->index('is_active');
});
}
public function down(): void
{
Schema::dropIfExists('sectors');
}
};
database/migrations/2026_01_01_000002_create_opportunities_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('opportunities', function (Blueprint $table) {
$table->id();
$table->foreignId('sector_id')
->constrained('sectors')
->cascadeOnUpdate()
->restrictOnDelete();
$table->string('reference', 80)->unique();
$table->string('title', 200);
$table->string('slug', 220)->unique();
$table->string('summary', 500)->nullable();
$table->longText('description')->nullable();
$table->string('province', 100)->nullable();
$table->string('district', 100)->nullable();
$table->string('promoter_name', 200)->nullable();
$table->string('promoter_type', 100)->nullable();
$table->unsignedTinyInteger('maturity_level')->nullable();
$table->string('maturity_label', 120)->nullable();
$table->decimal('estimated_investment_amount', 18, 2)->nullable();
$table->string('estimated_investment_currency', 10)->default('USD');
$table->string('financing_modality', 120)->nullable();
$table->text('expected_impact')->nullable();
$table->string('status', 50)->default('draft');
$table->boolean('is_featured')->default(false);
$table->timestamp('published_at')->nullable();
$table->timestamp('last_validated_at')->nullable();
$table->timestamps();
$table->softDeletes();
$table->index('sector_id');
$table->index('reference');
$table->index('slug');
$table->index('status');
$table->index('is_featured');
$table->index('province');
$table->index('maturity_level');
});
}
public function down(): void
{
Schema::dropIfExists('opportunities');
}
};
database/migrations/2026_01_01_000003_create_interest_requests_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('interest_requests', function (Blueprint $table) {
$table->id();
$table->foreignId('opportunity_id')
->nullable()
->constrained('opportunities')
->cascadeOnUpdate()
->nullOnDelete();
$table->string('reference', 80)->unique();
$table->string('full_name', 150);
$table->string('email', 150);
$table->string('phone', 30)->nullable();
$table->string('investor_type', 80);
$table->string('country', 100);
$table->string('sector_interest', 150);
$table->string('opportunity_reference', 80)->nullable();
$table->string('investment_range', 80)->nullable();
$table->text('message');
$table->boolean('privacy_consent')->default(false);
$table->timestamp('consented_at')->nullable();
$table->string('status', 50)->default('received');
$table->string('source_page', 255)->nullable();
$table->ipAddress('ip_address')->nullable();
$table->text('user_agent')->nullable();
$table->json('metadata')->nullable();
$table->timestamp('reviewed_at')->nullable();
$table->foreignId('reviewed_by')->nullable()->constrained('users')->nullOnDelete();
$table->timestamps();
$table->softDeletes();
$table->index('reference');
$table->index('email');
$table->index('status');
$table->index('created_at');
});
}
public function down(): void
{
Schema::dropIfExists('interest_requests');
}
};
Factories e seeders
app/Models/Investor.php
<?php
namespace App\Models;
use Database\Factories\InvestorFactory;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
class Investor extends Model
{
/** @use HasFactory<InvestorFactory> */
use HasFactory;
use HasUuids, SoftDeletes;
protected $table = 'investors';
protected $guarded = ['id'];
public function newUniqueId(): string
{
// Keep application-generated identifiers aligned with gen_random_uuid().
return (string) Str::uuid();
}
/** @return array<string, string> */
protected function casts(): array
{
return [
'version_no' => 'integer',
'created_at' => 'immutable_datetime',
'updated_at' => 'immutable_datetime',
'deleted_at' => 'immutable_datetime',
];
}
}
app/Models/Project.php
<?php
namespace App\Models;
use Database\Factories\ProjectFactory;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
class Project extends Model
{
/** @use HasFactory<ProjectFactory> */
use HasFactory;
use HasUuids, SoftDeletes;
protected $table = 'projects';
protected $guarded = ['id'];
public function newUniqueId(): string
{
// Keep application-generated identifiers aligned with gen_random_uuid().
return (string) Str::uuid();
}
/** @return array<string, string> */
protected function casts(): array
{
return [
'version_no' => 'integer',
'created_at' => 'immutable_datetime',
'updated_at' => 'immutable_datetime',
'deleted_at' => 'immutable_datetime',
'budget_amount' => 'decimal:2',
'metadata' => 'array',
'start_date' => 'immutable_date',
'end_date' => 'immutable_date',
];
}
}
database/factories/InvestorFactory.php
<?php
namespace Database\Factories;
use App\Models\Investor;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/** @extends Factory<Investor> */
class InvestorFactory extends Factory
{
protected $model = Investor::class;
public function definition(): array
{
return [
'source_system' => 'example',
'external_id' => (string) Str::uuid(),
'data_classification' => 'internal',
'legal_name' => 'Investidor fictício de teste',
'investor_type' => 'institutional',
'status' => 'prospect',
];
}
}
database/factories/ProjectFactory.php
<?php
namespace Database\Factories;
use App\Models\Project;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/** @extends Factory<Project> */
class ProjectFactory extends Factory
{
protected $model = Project::class;
public function definition(): array
{
return [
'source_system' => 'example',
'external_id' => (string) Str::uuid(),
'data_classification' => 'internal',
'code' => 'EXAMPLE-'.Str::uuid(),
'name' => 'Projecto fictício de teste',
'status' => 'draft',
'budget_amount' => '1000.00',
'budget_currency' => 'MZN',
];
}
}
database/seeders/DatabaseSeeder.php
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class DatabaseSeeder extends Seeder
{
use WithoutModelEvents;
/**
* Seed the application's database.
*/
public function run(): void
{
if (! app()->environment(['local', 'testing'])) {
return;
}
$this->call(InvestMozReferenceSeeder::class);
// User::factory(10)->create();
User::firstOrCreate(
['email' => 'test@example.com'],
[
'name' => 'Test User',
'password' => Hash::make(Str::random(48)),
],
);
}
}
database/seeders/InvestMozReferenceSeeder.php
<?php
namespace Database\Seeders;
use App\Models\Investor;
use App\Models\Project;
use Illuminate\Database\Seeder;
class InvestMozReferenceSeeder extends Seeder
{
public function run(): void
{
if (! app()->environment(['local', 'testing'])) {
throw new \RuntimeException('Reference fixtures are restricted to local/testing.');
}
Project::withTrashed()->updateOrCreate(
['source_system' => 'example', 'external_id' => 'PROJECT-001'],
[
'code' => 'EXAMPLE-PROJECT-001',
'name' => 'Projecto fictício para validação técnica',
'status' => 'draft',
'budget_amount' => '1000.00',
'budget_currency' => 'MZN',
'data_classification' => 'internal',
'deleted_at' => null,
],
);
Investor::withTrashed()->updateOrCreate(
['source_system' => 'example', 'external_id' => 'INVESTOR-001'],
[
'legal_name' => 'Entidade fictícia para validação técnica',
'investor_type' => 'institutional',
'status' => 'prospect',
'data_classification' => 'internal',
'deleted_at' => null,
],
);
}
}
Comandos Artisan e testes
Consultar runbook.md para pré-requisitos e protecção da base isolada.
php artisan migrate:fresh --seed
php artisan migrate:rollback
php artisan test --configuration=phpunit.investmoz.xml
tests/InvestMoz/SchemaLifecycleTest.php
<?php
namespace Tests\InvestMoz;
use App\Models\Investor;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class SchemaLifecycleTest extends TestCase
{
private function rejected(string $sql, array $bindings, string $sqlState): void
{
DB::beginTransaction();
try {
DB::statement($sql, $bindings);
$this->fail('The database accepted an invalid operation: '.$sql);
} catch (QueryException $exception) {
$this->assertSame($sqlState, $exception->errorInfo[0]);
} finally {
DB::rollBack();
}
}
public function test_schema_constraints_events_and_rollback_in_isolated_postgis(): void
{
if (getenv('INVESTMOZ_SCHEMA_TESTS') !== '1') {
$this->markTestSkipped('Set INVESTMOZ_SCHEMA_TESTS=1 only for an isolated disposable *_test database.');
}
$this->assertSame('testing', app()->environment());
$this->assertSame('pgsql', DB::connection()->getDriverName());
$this->assertStringEndsWith('_test', DB::connection()->getDatabaseName());
$this->assertSame(DB::connection()->getDatabaseName(), DB::selectOne('SELECT current_database() AS name')->name);
$this->assertFileDoesNotExist(base_path('bootstrap/cache/config.php'), 'Clear cached configuration before the destructive test.');
$this->artisan('migrate:fresh', ['--seed' => true, '--force' => true])->assertExitCode(0);
$manifest = json_decode(file_get_contents(base_path('docs/investmoz/schema.json')), true, 512, JSON_THROW_ON_ERROR);
$legacy = json_decode(file_get_contents(base_path('docs/investmoz/legacy-schema.json')), true, 512, JSON_THROW_ON_ERROR);
foreach (array_merge($manifest['tables'], $legacy['tables']) as $table) {
$actual = DB::select(
"SELECT a.attname AS column_name, CASE WHEN a.attnotnull THEN 'NO' ELSE 'YES' END AS is_nullable, format_type(a.atttypid,a.atttypmod) AS pg_type, pg_get_expr(d.adbin,d.adrelid) AS default_expression FROM pg_attribute a LEFT JOIN pg_attrdef d ON d.adrelid=a.attrelid AND d.adnum=a.attnum JOIN pg_class c ON c.oid=a.attrelid JOIN pg_namespace n ON n.oid=c.relnamespace WHERE n.nspname='public' AND c.relname=? AND a.attnum>0 AND NOT a.attisdropped ORDER BY a.attnum",
[$table['name']],
);
$this->assertSame(array_column($table['columns'], 'name'), array_column($actual, 'column_name'), $table['name']);
foreach ($actual as $position => $column) {
$this->assertSame($table['columns'][$position]['nullable'] ? 'YES' : 'NO', $column->is_nullable);
$expectedType = str_replace(['timestamptz', 'char('], ['timestamp with time zone', 'character('], $table['columns'][$position]['type']);
$this->assertSame($expectedType, $column->pg_type, $table['name'].'.'.$column->column_name);
$expectedDefault = $table['columns'][$position]['default'];
$actualDefault = $column->default_expression === null ? null : str_replace(['::text', '::character varying'], '', $column->default_expression);
$this->assertSame($expectedDefault, $actualDefault, $table['name'].'.'.$column->column_name.' default');
}
}
$expectedIndexes = array_merge(array_column($manifest['indexes'], 'name'), array_column($legacy['indexes'], 'name'));
foreach ($manifest['constraints'] as $constraint) {
if ($constraint['kind'] === 'PRIMARY KEY') {
$expectedIndexes[] = $constraint['name'];
}
}
foreach ($legacy['tables'] as $table) {
$expectedIndexes[] = $table['name'].'_pkey';
}
sort($expectedIndexes);
$actualIndexes = DB::table('pg_indexes')->where('schemaname', 'public')->whereIn('tablename', array_column(array_merge($manifest['tables'], $legacy['tables']), 'name'))->orderBy('indexname')->pluck('indexname')->all();
$this->assertSame($expectedIndexes, $actualIndexes);
foreach ($manifest['indexes'] as $index) {
$row = DB::selectOne("SELECT indexdef FROM pg_indexes WHERE schemaname='public' AND indexname=?", [$index['name']]);
$this->assertNotNull($row, $index['name']);
$this->assertStringContainsString('USING '.$index['method'], $row->indexdef);
}
foreach ($manifest['constraints'] as $constraint) {
$this->assertNotNull(DB::selectOne(
"SELECT oid FROM pg_constraint WHERE connamespace='public'::regnamespace AND conname=?",
[$constraint['name']],
), $constraint['name']);
}
$actions = ['CASCADE' => 'c', 'RESTRICT' => 'r', 'SET NULL' => 'n', 'NO ACTION' => 'a'];
foreach (array_merge($manifest['relationships'], $legacy['relationships']) as $relationship) {
$actualFk = DB::selectOne("SELECT confdeltype, confupdtype FROM pg_constraint WHERE connamespace='public'::regnamespace AND conname=?", [$relationship['name']]);
$this->assertNotNull($actualFk, $relationship['name']);
$this->assertSame($actions[$relationship['on_delete']], $actualFk->confdeltype);
$this->assertSame($actions[$relationship['on_update']], $actualFk->confupdtype);
}
foreach ($manifest['triggers'] as $trigger) {
$this->assertNotNull(DB::selectOne('SELECT oid FROM pg_trigger WHERE tgname=? AND NOT tgisinternal', [$trigger['name']]));
}
$project = DB::selectOne("INSERT INTO projects(code,name,status,source_system,external_id,budget_amount,budget_currency) VALUES ('TEST-P','Fictício','draft','test','P-1',123456789012345678.90,'MZN') RETURNING id,budget_amount");
$this->assertSame('123456789012345678.90', $project->budget_amount);
$this->rejected("INSERT INTO projects(code,name,status) VALUES ('TEST-P','Duplicado','draft')", [], '23505');
$this->rejected("INSERT INTO projects(code,name,status) VALUES ('BAD-S','Fictício','unknown')", [], '23514');
$this->rejected("INSERT INTO projects(code,name,status,budget_amount,budget_currency) VALUES ('BAD-M','Fictício','draft',-1,'MZN')", [], '23514');
$this->rejected("INSERT INTO projects(code,name,status,budget_amount) VALUES ('BAD-C','Fictício','draft',1)", [], '23514');
DB::update('UPDATE projects SET deleted_at=now() WHERE id=?', [$project->id]);
DB::insert("INSERT INTO projects(code,name,status) VALUES ('TEST-P','Código reutilizado','draft')");
$this->rejected("INSERT INTO projects(code,name,status,source_system,external_id) VALUES ('NEW-CODE','Fictício','draft','test','P-1')", [], '23505');
$location = DB::selectOne("INSERT INTO geo_locations(name,location_type,code) VALUES ('Local fictício','site','TEST-GEO') RETURNING id");
DB::insert("INSERT INTO geo_geometries(geo_location_id,geometry_type,geom) VALUES (?,'point',ST_GeomFromText('POINT(32 -25)',4326))", [$location->id]);
$this->rejected("INSERT INTO geo_geometries(geo_location_id,geometry_type,geom) VALUES (?,'line',ST_GeomFromText('POINT(32 -25)',4326))", [$location->id], '23514');
$this->rejected("INSERT INTO geo_geometries(geo_location_id,geometry_type,geom) VALUES (?,'polygon',ST_GeomFromText('POLYGON((0 0,1 1,1 0,0 1,0 0))',4326))", [$location->id], '23514');
$this->rejected("INSERT INTO geo_geometries(geo_location_id,geometry_type,geom) VALUES (?,'point',ST_GeomFromText('POINT EMPTY',4326))", [$location->id], '23514');
$this->rejected("INSERT INTO geo_geometries(geo_location_id,geometry_type,geom) VALUES (?,'point',ST_GeomFromText('POINT(181 0)',4326))", [$location->id], '23514');
$this->rejected("INSERT INTO geo_geometries(geo_location_id,geometry_type,geom) VALUES (?,'point',ST_GeomFromText('POINT(1 1)',3857))", [$location->id], '22023');
$this->rejected("INSERT INTO project_locations(project_id,geo_location_id,role) VALUES (gen_random_uuid(),?,'primary')", [$location->id], '23503');
$i1 = Investor::factory()->create();
$i2 = Investor::factory()->create();
$contact = DB::selectOne("INSERT INTO contacts(full_name) VALUES ('Contacto fictício') RETURNING id");
DB::insert('INSERT INTO investor_contacts(investor_id,contact_id) VALUES (?,?),(?,?)', [$i1->id, $contact->id, $i2->id, $contact->id]);
$this->rejected('INSERT INTO investor_contacts(investor_id,contact_id) VALUES (?,?)', [$i1->id, $contact->id], '23505');
$this->rejected('INSERT INTO project_documents(project_id,document_id) VALUES (?,gen_random_uuid())', [$project->id], '23503');
$audit = DB::selectOne("INSERT INTO audit_events(entity_type,action) VALUES ('test','created') RETURNING id");
$this->rejected("UPDATE audit_events SET action='tampered' WHERE id=?", [$audit->id], '42501');
$this->rejected('DELETE FROM audit_events WHERE id=?', [$audit->id], '42501');
$this->rejected('TRUNCATE audit_events', [], '42501');
$event = DB::selectOne("INSERT INTO outbox_events(aggregate_type,aggregate_id,event_type,payload,status) VALUES ('test',?,'test.created','{}','pending') RETURNING id", [$project->id]);
DB::update("UPDATE outbox_events SET status='published',published_at=now() WHERE id=?", [$event->id]);
$this->rejected("UPDATE outbox_events SET payload='{\"changed\":true}' WHERE id=?", [$event->id], '42501');
$this->rejected('DELETE FROM outbox_events WHERE id=?', [$event->id], '42501');
$this->rejected('TRUNCATE outbox_events', [], '42501');
DB::insert("INSERT INTO inbox_events(message_id,event_type,payload,status) VALUES ('TEST-MESSAGE','test','{}','received')");
$this->rejected("INSERT INTO inbox_events(message_id,event_type,payload,status) VALUES ('TEST-MESSAGE','test','{}','received')", [], '23505');
DB::statement("SET TIME ZONE 'Africa/Maputo'");
try {
DB::update("UPDATE projects SET name='Actualizado' WHERE id=?", [$project->id]);
$age = DB::selectOne('SELECT abs(extract(epoch FROM (CURRENT_TIMESTAMP-updated_at))) AS age FROM projects WHERE id=?', [$project->id]);
$this->assertLessThan(5.0, (float) $age->age);
} finally {
DB::statement("SET TIME ZONE 'UTC'");
}
// Index eligibility, not a latency/SLO claim on tiny fixtures.
DB::statement('SET enable_seqscan = off');
try {
$plan = json_encode(DB::select('EXPLAIN (FORMAT JSON) SELECT id FROM geo_geometries WHERE geom && ST_MakeEnvelope(31,-26,33,-24,4326)'));
$this->assertStringContainsString('imz_geo_geometries_geom_idx', $plan);
} finally {
DB::statement('RESET enable_seqscan');
}
$this->artisan('migrate')->assertExitCode(0); // Ledger idempotency.
$this->artisan('db:seed', ['--class' => 'InvestMozReferenceSeeder'])->assertExitCode(0);
$this->assertSame(1, DB::table('projects')->where('source_system', 'example')->where('external_id', 'PROJECT-001')->count());
$this->artisan('migrate:rollback', ['--step' => 15, '--force' => true])->assertExitCode(0);
foreach ($manifest['tables'] as $table) {
$this->assertFalse(Schema::hasTable($table['name']));
}
$this->assertTrue(Schema::hasTable('users'));
$this->assertTrue(Schema::hasTable('opportunities'));
$this->assertCount(2, DB::select("SELECT extname FROM pg_extension WHERE extname IN ('postgis','pgcrypto')"));
$this->artisan('migrate', ['--seed' => true, '--force' => true])->assertExitCode(0);
// This is a separate upgrade batch: ordinary rollback must now revert it.
$this->artisan('migrate:rollback', ['--force' => true])->assertExitCode(0);
$this->assertFalse(Schema::hasTable('projects'));
$this->assertTrue(Schema::hasTable('users'));
$this->artisan('migrate', ['--force' => true])->assertExitCode(0);
}
}
Consultas de verificação
-- Read-only verification after migrate, in isolated PostgreSQL.
SELECT version(), PostGIS_Full_Version();
SELECT extname,extversion FROM pg_extension WHERE extname IN ('postgis','pgcrypto');
SELECT table_name,column_name,data_type,udt_name,is_nullable,column_default,
character_maximum_length,numeric_precision,numeric_scale
FROM information_schema.columns WHERE table_schema='public' ORDER BY table_name,ordinal_position;
SELECT conrelid::regclass,conname,contype,pg_get_constraintdef(oid)
FROM pg_constraint WHERE connamespace='public'::regnamespace ORDER BY 1,2;
SELECT tablename,indexname,indexdef FROM pg_indexes WHERE schemaname='public' ORDER BY 1,2;
SELECT tgrelid::regclass,tgname,pg_get_triggerdef(oid)
FROM pg_trigger WHERE NOT tgisinternal AND tgname LIKE 'imz_%' ORDER BY 1,2;
SELECT * FROM pg_policies WHERE schemaname='public';
SELECT id FROM geo_geometries WHERE ST_SRID(geom)<>4326 OR ST_NDims(geom)<>2 OR ST_IsEmpty(geom) OR NOT ST_IsValid(geom);
SELECT p.id FROM project_locations p LEFT JOIN projects t ON t.id=p.project_id WHERE t.id IS NULL;
SELECT c.investor_id,c.contact_id FROM investor_contacts c LEFT JOIN investors i ON i.id=c.investor_id WHERE i.id IS NULL;
SELECT source_system,external_id,count(*) FROM projects
WHERE external_id IS NOT NULL GROUP BY source_system,external_id HAVING count(*)>1;
SELECT id FROM projects WHERE budget_amount<0 OR ((budget_amount IS NULL)<>(budget_currency IS NULL));
EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT id FROM outbox_events WHERE status='pending' AND available_at<=CURRENT_TIMESTAMP ORDER BY available_at LIMIT 100;
EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT id FROM geo_geometries WHERE ST_Intersects(geom,ST_MakeEnvelope(32,-26,33,-25,4326));
Plano de rollback
Execução, migração de dados e rollback
Pré-requisitos
PHP 8.4.1+ para o composer.lock instalado; composer.json declara ^8.3. Runtime compatível com composer.lock, pdo_pgsql, dependências Composer, PostgreSQL/PostGIS. Referência: PostgreSQL 16 com PostGIS 3.4 ou superior compatível; confirmar no servidor. Usar base isolada terminada em _test. Configurar DB_CONNECTION=pgsql, DB_DATABASE=investmoz_test, DB_HOST, DB_PORT, DB_USERNAME e DB_PASSWORD no ambiente seguro; nunca versionar credenciais. O administrador pode provisionar postgis/pgcrypto antes; caso contrário a conta de migrations necessita dessa capacidade.
Comandos Artisan
Os ficheiros já estão criados. Para futuras alterações: php artisan make:migration descricao_da_alteracao php artisan migrate --pretend php artisan migrate --seed php artisan migrate:status
Apenas numa base de desenvolvimento descartável: php artisan migrate:fresh --seed php artisan migrate:rollback php artisan migrate --seed
Idempotência é assegurada pelo ledger migrations; não se usa IF NOT EXISTS para esconder deriva de tabelas. Extensões partilhadas usam IF NOT EXISTS. Funções próprias investmoz_* usam CREATE OR REPLACE porque migrate:fresh remove tabelas, mas conserva funções PostgreSQL. Cada migration usa a transacção gerida pelo Laravel, sem BEGIN/COMMIT embutidos. Uma falha deixa o ficheiro pendente, preservando os anteriores.
Testes
php artisan config:clear
php artisan test
php artisan test --configuration=phpunit.investmoz.xml
python tools/investmoz/validate.py
python tools/investmoz/generate.py --source "caminho/do/documento.docx" --check
O ensaio dedicado exige INVESTMOZ_SCHEMA_TESTS=1 e base terminada em _test; executa migrate:fresh e elimina dados dessa base. As novas migrations rejeitam SQLite explicitamente. A suite principal deve usar PostgreSQL. Testes estáticos não equivalem a execução PostgreSQL/PostGIS. Desempenho usa EXPLAIN sem limiar inventado.
MySQL -> PostgreSQL
- Inventariar versão, charset, collation, contagens, moedas, fusos e ligações da origem real.
- Obter snapshot e backup com restauração verificada e manifesto SHA-256.
- Criar destino vazio e executar migrations sem seeds de demonstração.
- Preservar IDs bigint do legado; atribuir UUID às novas entidades com mapa persistente origem/ID/UUID. Resolver P-08 antes de mapear opportunities para projects/CRM.
- Transportar decimais como strings, sem float. Normalizar datas com fuso aprovado; colocar zero dates e datas inválidas em quarentena.
- Validar JSON e geometrias 2D SRID 4326; recusar correcções geográficas silenciosas.
- Importar por dependências em lotes transaccionais; deduplicar por source_system/external_id e comparar version_no atomicamente.
- Guardar checkpoint na transacção do lote; não colocar dados pessoais nos logs.
- Reconciliar contagens, somas, hashes canónicos, duplicados, órfãos e geometrias; tolerâncias ainda pendentes.
- Ajustar sequences bigint com setval após verificar MAX(id); guardar origem para reversão.
- Ensaiar corte, deltas e restauro antes de transferir tráfego. Esta entrega não executa importação.
Rollback
down remove triggers, índices avançados, FKs/checks/PKs e tabelas em ordem inversa, depois funções próprias. Não remove extensões nem usa DROP CASCADE. Reverter tabelas POPULADAS destrói os seus dados, mesmo sem CASCADE. Não é reversão sem perda. Antes de rollback fora do ensaio: suspender escritores, exportar tabelas, verificar restauração separada e guardar ledger. Preferir migration compensatória. Num upgrade, migrate:rollback reverte o lote novo. Após migrate:fresh, todas as migrations podem pertencer ao mesmo lote; rollback pode remover também o legado. RESTRICT deve bloquear dependências externas; não contornar com CASCADE. Manter aplicação compatível com o esquema restaurado. Rollback de esquema não reconverte automaticamente dados para MySQL.
Fontes técnicas
https://www.postgresql.org/docs/16/ddl-constraints.html https://postgis.net/docs/ST_IsValid.html https://postgis.net/docs/ST_IsEmpty.html
Checklist para cada ambiente
Consultar validation.md para as evidencias do ensaio local ja executado. Os itens seguintes devem ser repetidos no ambiente de destino.
- Reconciliação autorizada e migrations históricas preservadas.
- Catálogo, dicionário e SQL gerados da mesma representação.
- UUID novos, FKs compatíveis, decimais, geometrias e índices explícitos.
- Contactos N:N e documentos tipados.
- Extensões preservadas no rollback.
- Lacunas documentadas e fora do DDL.
- migrate:fresh --seed e rollback confirmados em PostgreSQL/PostGIS.
- Suite da aplicação executada em PostgreSQL.
- Matriz de permissões, importação real, reconciliação e restauro validados.
- Desempenho confirmado com volume e SLO aprovados.
Matriz de rastreabilidade
| Domínio | Tabela | Campo | Migration | Requisito/Fonte | Decisão |
|---|---|---|---|---|---|
| Aplicação existente | users | id | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | users | name | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | users | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 | |
| Aplicação existente | users | email_verified_at | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | users | password | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | users | remember_token | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | users | created_at | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | users | updated_at | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | users | two_factor_secret | database/migrations/2025_08_14_170933_add_two_factor_columns_to_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | users | two_factor_recovery_codes | database/migrations/2025_08_14_170933_add_two_factor_columns_to_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | users | two_factor_confirmed_at | database/migrations/2025_08_14_170933_add_two_factor_columns_to_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | password_reset_tokens | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 | |
| Aplicação existente | password_reset_tokens | token | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | password_reset_tokens | created_at | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sessions | id | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sessions | user_id | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sessions | ip_address | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sessions | user_agent | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sessions | payload | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sessions | last_activity | database/migrations/0001_01_01_000000_create_users_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | cache | key | database/migrations/0001_01_01_000001_create_cache_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | cache | value | database/migrations/0001_01_01_000001_create_cache_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | cache | expiration | database/migrations/0001_01_01_000001_create_cache_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | cache_locks | key | database/migrations/0001_01_01_000001_create_cache_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | cache_locks | owner | database/migrations/0001_01_01_000001_create_cache_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | cache_locks | expiration | database/migrations/0001_01_01_000001_create_cache_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | jobs | id | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | jobs | queue | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | jobs | payload | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | jobs | attempts | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | jobs | reserved_at | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | jobs | available_at | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | jobs | created_at | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | id | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | name | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | total_jobs | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | pending_jobs | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | failed_jobs | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | failed_job_ids | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | options | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | cancelled_at | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | created_at | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | job_batches | finished_at | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | failed_jobs | id | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | failed_jobs | uuid | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | failed_jobs | connection | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | failed_jobs | queue | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | failed_jobs | payload | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | failed_jobs | exception | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | failed_jobs | failed_at | database/migrations/0001_01_01_000002_create_jobs_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | passkeys | id | database/migrations/2024_01_01_000000_create_passkeys_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | passkeys | user_id | database/migrations/2024_01_01_000000_create_passkeys_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | passkeys | name | database/migrations/2024_01_01_000000_create_passkeys_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | passkeys | credential_id | database/migrations/2024_01_01_000000_create_passkeys_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | passkeys | credential | database/migrations/2024_01_01_000000_create_passkeys_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | passkeys | last_used_at | database/migrations/2024_01_01_000000_create_passkeys_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | passkeys | created_at | database/migrations/2024_01_01_000000_create_passkeys_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | passkeys | updated_at | database/migrations/2024_01_01_000000_create_passkeys_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | id | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | name | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | slug | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | short_description | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | description | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | icon | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | sort_order | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | is_active | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | published_at | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | created_at | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | updated_at | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | sectors | deleted_at | database/migrations/2026_01_01_000001_create_sectors_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | id | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | sector_id | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | reference | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | title | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | slug | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | summary | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | description | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | province | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | district | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | promoter_name | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | promoter_type | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | maturity_level | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | maturity_label | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | estimated_investment_amount | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | estimated_investment_currency | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | financing_modality | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | expected_impact | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | status | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | is_featured | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | published_at | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | last_validated_at | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | created_at | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | updated_at | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | opportunities | deleted_at | database/migrations/2026_01_01_000002_create_opportunities_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | id | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | opportunity_id | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | reference | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | full_name | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 | |
| Aplicação existente | interest_requests | phone | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | investor_type | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | country | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | sector_interest | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | opportunity_reference | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | investment_range | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | message | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | privacy_consent | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | consented_at | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | status | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | source_page | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | ip_address | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | user_agent | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | metadata | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | reviewed_at | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | reviewed_by | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | created_at | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | updated_at | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Aplicação existente | interest_requests | deleted_at | database/migrations/2026_01_01_000003_create_interest_requests_table.php | Migration instalada | COMPAT-01 |
| Identidade | organizations | id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | source_system | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | external_id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | version_no | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | data_classification | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | correlation_id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | created_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | updated_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | deleted_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | name | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | organizations | organization_type | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | source_system | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | external_id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | version_no | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | data_classification | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | correlation_id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | created_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | updated_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | deleted_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | user_id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | organization_id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | memberships | role | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | source_system | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | external_id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | version_no | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | data_classification | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | correlation_id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | created_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | updated_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | deleted_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | user_id | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | subject_ref | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | purpose | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | status | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | granted_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Identidade | consents | withdrawn_at | database/migrations/2026_09_24_001000_investmoz_identity.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | id | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | source_system | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | external_id | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | version_no | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | data_classification | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | correlation_id | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | created_at | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | updated_at | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | deleted_at | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | file_name | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | media_type | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | storage_key | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | sha256 | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Conteúdos | documents | status | database/migrations/2026_09_24_002000_investmoz_content.php | A.26; A.31.2 | RECON-01 |
| Geografia | geo_locations | id | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | source_system | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | external_id | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | version_no | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | data_classification | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | correlation_id | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | created_at | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | updated_at | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | deleted_at | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | name | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | location_type | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | parent_id | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_locations | code | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | id | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | source_system | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | external_id | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | version_no | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | data_classification | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | correlation_id | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | created_at | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | updated_at | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | deleted_at | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | geo_location_id | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | geometry_type | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | geom | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Geografia | geo_geometries | properties | database/migrations/2026_09_24_003000_investmoz_geography.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | id | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | source_system | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | external_id | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | version_no | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | data_classification | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | correlation_id | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | created_at | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | updated_at | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | deleted_at | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | code | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | name | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | status | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | description | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | budget_amount | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | budget_currency | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | start_date | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | end_date | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | projects | metadata | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | id | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | source_system | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | external_id | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | version_no | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | data_classification | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | correlation_id | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | created_at | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | updated_at | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | deleted_at | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | project_id | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | geo_location_id | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Projectos | project_locations | role | database/migrations/2026_09_24_004000_investmoz_projects.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | source_system | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | external_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | version_no | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | data_classification | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | correlation_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | created_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | updated_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | deleted_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | code | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | name | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | sector | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | status | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | economic_clusters | metadata | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | source_system | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | external_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | version_no | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | data_classification | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | correlation_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | created_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | updated_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | deleted_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | cluster_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | code | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | name | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chains | stage | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | source_system | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | external_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | version_no | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | data_classification | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | correlation_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | created_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | updated_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | deleted_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | from_value_chain_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | to_value_chain_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | value_chain_links | link_type | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | source_system | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | external_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | version_no | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | data_classification | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | correlation_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | created_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | updated_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | deleted_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | cluster_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | project_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | cluster_projects | role | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | source_system | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | external_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | version_no | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | data_classification | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | correlation_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | created_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | updated_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | deleted_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | anchor_project_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | cluster_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | anchor_project_links | rationale | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | source_system | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | external_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | version_no | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | data_classification | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | correlation_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | created_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | updated_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | deleted_at | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | anchor_project_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | complementary_project_id | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Clusters e cadeias | complementary_project_links | relation_type | database/migrations/2026_09_24_005000_investmoz_clusters.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | source_system | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | external_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | version_no | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | data_classification | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | correlation_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | created_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | updated_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | deleted_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | code | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | name | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | status | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | development_corridors | description | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | source_system | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | external_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | version_no | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | data_classification | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | correlation_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | created_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | updated_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | deleted_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | corridor_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | geo_location_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_locations | sequence_no | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | source_system | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | external_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | version_no | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | data_classification | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | correlation_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | created_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | updated_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | deleted_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | corridor_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_projects | project_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | source_system | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | external_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | version_no | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | data_classification | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | correlation_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | created_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | updated_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | deleted_at | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | corridor_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| Corredores | corridor_clusters | cluster_id | database/migrations/2026_09_24_006000_investmoz_corridors.php | A.25; A.31.2 | RECON-01 |
| CRM | investors | id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | source_system | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | external_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | version_no | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | data_classification | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | correlation_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | created_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | updated_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | deleted_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | organization_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | legal_name | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | investor_type | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investors | status | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | source_system | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | external_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | version_no | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | data_classification | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | correlation_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | created_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | updated_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | deleted_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | full_name | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | contacts | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 | |
| CRM | contacts | phone | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investor_contacts | investor_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investor_contacts | contact_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investor_contacts | is_primary | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investor_contacts | created_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | investor_contacts | updated_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | source_system | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | external_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | version_no | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | data_classification | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | correlation_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | created_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | updated_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | deleted_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | investor_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | owner_user_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | title | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | status | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | estimated_amount | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | leads | currency | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | source_system | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | external_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | version_no | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | data_classification | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | correlation_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | created_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | updated_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | deleted_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | lead_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | project_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | owner_user_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | stage | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | amount | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | currency | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | crm_opportunities | probability | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | source_system | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | external_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | version_no | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | data_classification | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | correlation_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | created_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | updated_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | deleted_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | investor_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | opportunity_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | actor_user_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | activity_type | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | occurred_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | activities | summary | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | source_system | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | external_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | version_no | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | data_classification | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | correlation_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | created_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | updated_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | deleted_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | assignee_user_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | opportunity_id | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | title | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | status | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| CRM | tasks | due_at | database/migrations/2026_09_24_007000_investmoz_crm.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | source_system | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | external_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | version_no | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | data_classification | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | correlation_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | created_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | updated_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | deleted_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | investor_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | opportunity_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | status | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | investor_journeys | started_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | source_system | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | external_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | version_no | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | data_classification | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | correlation_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | created_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | updated_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | deleted_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | journey_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | step_code | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | sequence_no | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | journey_steps | status | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | source_system | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | external_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | version_no | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | data_classification | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | correlation_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | created_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | updated_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | deleted_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | journey_step_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | submitted_by | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | status | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | payload | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | submissions | submitted_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | source_system | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | external_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | version_no | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | data_classification | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | correlation_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | created_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | updated_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | deleted_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | investor_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | project_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | owner_user_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | status | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | aftercare_plans | review_date | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | source_system | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | external_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | version_no | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | data_classification | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | correlation_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | created_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | updated_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | deleted_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | aftercare_plan_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | category | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | description | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | severity | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | constraints | status | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | source_system | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | external_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | version_no | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | data_classification | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | correlation_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | created_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | updated_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | deleted_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | constraint_id | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | escalated_by | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | level | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | status | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Jornada e aftercare | escalations | escalated_at | database/migrations/2026_09_24_008000_investmoz_journey_aftercare.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | source_system | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | external_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | version_no | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | data_classification | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | correlation_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | created_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | updated_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | deleted_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | code | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | skills | name | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | source_system | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | external_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | version_no | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | data_classification | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | correlation_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | created_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | updated_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | deleted_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | code | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | occupations | name | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | source_system | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | external_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | version_no | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | data_classification | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | correlation_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | created_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | updated_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | deleted_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | project_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | occupation_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | skill_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | quantity | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_needs | priority | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | source_system | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | external_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | version_no | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | data_classification | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | correlation_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | created_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | updated_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | deleted_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | organization_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | name | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | training_providers | status | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | source_system | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | external_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | version_no | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | data_classification | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | correlation_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | created_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | updated_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | deleted_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | provider_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | code | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | title | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | courses | status | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | source_system | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | external_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | version_no | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | data_classification | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | correlation_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | created_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | updated_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | deleted_at | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | course_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | geo_location_id | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | start_date | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | end_date | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | capacity | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Educação | education_opportunities | status | database/migrations/2026_09_24_009000_investmoz_education.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | project_documents | project_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | project_documents | document_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | project_documents | created_at | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | investor_documents | investor_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | investor_documents | document_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | investor_documents | created_at | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | journey_documents | journey_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | journey_documents | document_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | journey_documents | created_at | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | aftercare_documents | aftercare_plan_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | aftercare_documents | document_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | aftercare_documents | created_at | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | education_documents | education_opportunity_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | education_documents | document_id | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Conteúdos — ligações tipadas | education_documents | created_at | database/migrations/2026_09_24_009500_investmoz_document_links.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | id | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | source_system | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | external_id | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | data_classification | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | correlation_id | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | created_at | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | actor_user_id | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | entity_type | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | entity_id | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | action | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | occurred_at | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | before_data | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Governação e auditoria | audit_events | after_data | database/migrations/2026_09_24_010000_investmoz_governance_ai.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | source_system | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | external_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | version_no | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | data_classification | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | correlation_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | created_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | updated_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | aggregate_type | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | aggregate_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | event_type | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | payload | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | status | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | available_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | outbox_events | published_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | source_system | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | external_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | version_no | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | data_classification | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | correlation_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | created_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | updated_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | message_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | event_type | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | payload | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | status | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | received_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | inbox_events | processed_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | source_system | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | external_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | version_no | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | data_classification | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | correlation_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | created_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | updated_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | deleted_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | integration_name | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | direction | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | status | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | started_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | ended_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | sync_runs | totals | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | source_system | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | external_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | version_no | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | data_classification | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | correlation_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | created_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | updated_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | deleted_at | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | sync_run_id | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | entity_type | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | external_id_ref | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | issue_type | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | severity | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | status | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
| Integrações e eventos | reconciliation_issues | details | database/migrations/2026_09_24_011000_investmoz_integrations.php | A.26; A.31.2 | RECON-01 |
Checklist final de conformidade
A checklist e as limitações de execução estão em runbook.md. As evidencias locais estao em validation.md. Os ensaios PostgreSQL não foram marcados como executados pelo gerador.