@fayz-ai/db 0.17.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/migrations/120_o_servico_diz_se_ele_se_agenda.sql +76 -0
- package/migrations/121_a_liberacao_pergunta_uma_vez_e_nao_cento_e_vinte_mil.sql +109 -0
- package/migrations/122_o_email_da_pessoa_e_um_email_nao_uma_lista.sql +80 -0
- package/migrations/123_um_writer_para_a_tabela_que_ja_tem_a_forma_certa.sql +197 -0
- package/migrations/124_o_updated_at_so_pode_ser_atribuido_uma_vez.sql +155 -0
- package/migrations/125_a_data_que_fecha_nao_e_a_data_que_so_lembra.sql +160 -0
- package/migrations/126_o_telefone_procurado_nao_tem_parenteses.sql +62 -0
- package/migrations/127_a_configuracao_tambem_se_pergunta_por_unidade.sql +250 -0
- package/migrations/128_a_biblioteca_de_midia_tambem_precisa_de_porta.sql +97 -0
- package/migrations/129_o_login_diz_de_quem_ele_e.sql +83 -0
- package/migrations/130_o_aviso_leva_a_algum_lugar.sql +31 -0
- package/migrations/131_o_salao_fala_o_vocabulario_do_v1.sql +81 -0
- package/migrations/132_o_cadastro_do_salao_fala_como_o_v1.sql +91 -0
- package/migrations/133_a_agenda_do_salao_perde_o_que_nao_e_dela.sql +69 -0
- package/migrations/134_todo_oficio_agrupa_os_seus_cadastros.sql +123 -0
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- O aviso leva a ALGUM LUGAR
|
|
3
|
+
--
|
|
4
|
+
-- `public.notifications` guarda título, corpo, tipo e lido — e mais nada. Um
|
|
5
|
+
-- aviso que diz "a conta de Fulana está aberta" e não leva até ela obriga a
|
|
6
|
+
-- recepção a procurar o nome numa lista, que é o caminho que o aviso existia
|
|
7
|
+
-- para evitar.
|
|
8
|
+
--
|
|
9
|
+
-- Duas colunas: para ONDE ir, e SOBRE O QUE é (o par polimórfico que o resto do
|
|
10
|
+
-- schema já usa em `documents.subject_type/subject_id`). Com o assunto dá para
|
|
11
|
+
-- não avisar duas vezes sobre o mesmo atendimento.
|
|
12
|
+
-- ============================================================================
|
|
13
|
+
|
|
14
|
+
ALTER TABLE public.notifications
|
|
15
|
+
ADD COLUMN IF NOT EXISTS link text,
|
|
16
|
+
ADD COLUMN IF NOT EXISTS subject_type text,
|
|
17
|
+
ADD COLUMN IF NOT EXISTS subject_id uuid;
|
|
18
|
+
|
|
19
|
+
COMMENT ON COLUMN public.notifications.link IS
|
|
20
|
+
'Rota do app para onde o aviso leva (ex.: #/checkin). Sem isto o aviso informa e abandona.';
|
|
21
|
+
COMMENT ON COLUMN public.notifications.subject_type IS
|
|
22
|
+
'Sobre o que é o aviso (appointment, order…), no mesmo par polimórfico de documents.';
|
|
23
|
+
|
|
24
|
+
-- Um aviso por assunto e por pessoa: o mesmo atendimento finalizado duas vezes
|
|
25
|
+
-- (reabrir e fechar de novo) não enche o sino.
|
|
26
|
+
CREATE UNIQUE INDEX IF NOT EXISTS notifications_subject_user_uidx
|
|
27
|
+
ON public.notifications (user_id, subject_type, subject_id, type)
|
|
28
|
+
WHERE subject_id IS NOT NULL;
|
|
29
|
+
|
|
30
|
+
CREATE INDEX IF NOT EXISTS notifications_user_unread_idx
|
|
31
|
+
ON public.notifications (user_id, created_at DESC) WHERE NOT read;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
-- ---------------------------------------------------------------------------
|
|
2
|
+
-- 117_o_salao_fala_o_vocabulario_do_v1.sql — o rail do StudioControl passa a
|
|
3
|
+
-- dizer o que o BeautySoft dizia.
|
|
4
|
+
-- ---------------------------------------------------------------------------
|
|
5
|
+
-- Estes clientes usam o V1 ha anos e vao receber o V2 com a mesma equipe, sem
|
|
6
|
+
-- treinamento. Um rail que espalha Confirmacoes e Check-in como linhas soltas
|
|
7
|
+
-- onde la eles sao filhos de Agenda, e que deixa Fornecedores fora de Cadastros
|
|
8
|
+
-- tendo Cadastros logo abaixo, faz cada pessoa reaprender um menu que ela ja
|
|
9
|
+
-- sabe de cor. Esse custo nao aparece em teste nenhum; aparece no chamado.
|
|
10
|
+
--
|
|
11
|
+
-- -- O que foi medido, dos dois lados, em 21/09/2026 --------------------------
|
|
12
|
+
--
|
|
13
|
+
-- V1 (Espaco Facial, unidade Treinamento, perfil dono):
|
|
14
|
+
--
|
|
15
|
+
-- Dashboard . Agenda v . Clientes v . Estoque . CRM . Financeiro .
|
|
16
|
+
-- Cadastros v . Configuracoes . Relatorios
|
|
17
|
+
--
|
|
18
|
+
-- Agenda v Agendamentos . Confirmacoes . Check-in . Comunicacao
|
|
19
|
+
-- Cadastros v Contatos . Contas . Equipamentos . Fornecedores .
|
|
20
|
+
-- Funcionarios . Locais Operacionais . Origens . Parcerias .
|
|
21
|
+
-- Servicos . Profissionais . Recursos Humanos
|
|
22
|
+
--
|
|
23
|
+
-- V2 (`beauty`, lido do proprio rail):
|
|
24
|
+
--
|
|
25
|
+
-- / . /agenda . /agenda/confirmations . /checkin . /sales . /customers .
|
|
26
|
+
-- /suppliers . /financial . /inventory . /marketing . /analytics .
|
|
27
|
+
-- /clients . /registry . /settings
|
|
28
|
+
--
|
|
29
|
+
-- /registry v services . categories . locations . location-groups .
|
|
30
|
+
-- staff . contacts . suppliers . partnerships . equipment
|
|
31
|
+
--
|
|
32
|
+
-- Tres diferencas de FORMA saltam dessa comparacao, e sao o que este arquivo
|
|
33
|
+
-- conserta:
|
|
34
|
+
--
|
|
35
|
+
-- 1. "Clientes" sai DUAS vezes -- `/customers` e `/clients` sao a mesma
|
|
36
|
+
-- linha do ponto de vista de quem usa. O ofício fica com `/clients`, que
|
|
37
|
+
-- e a ficha que o salao abre; `/customers` some do rail.
|
|
38
|
+
-- 2. "Fornecedores" sai DUAS vezes -- solto em `/suppliers` e dentro de
|
|
39
|
+
-- Cadastros em `/registry/suppliers`. No V1 ele mora em Cadastros e so.
|
|
40
|
+
-- 3. Agenda, Confirmacoes e Check-in sao tres linhas soltas onde o V1 tem
|
|
41
|
+
-- uma gaveta.
|
|
42
|
+
--
|
|
43
|
+
-- -- O que o preset pode e o que ele nao pode --------------------------------
|
|
44
|
+
-- Ele AGRUPA e ORDENA; quem NOMEIA e o plugin (083/101). Entao este arquivo
|
|
45
|
+
-- nao escreve "Agendamentos" nem "Funcionarios" em lugar nenhum: diz quais
|
|
46
|
+
-- PREFIXOS DE ROTA moram sob cada rubrica, e os rotulos continuam sendo os que
|
|
47
|
+
-- cada plugin declara. Foi essa separacao que parou a briga entre a arvore de
|
|
48
|
+
-- SQL e o catalogo, e ela nao vai ser reaberta por causa de um rotulo.
|
|
49
|
+
--
|
|
50
|
+
-- Fica, por isso, uma divergencia de VOCABULARIO que so o app resolve, anotada
|
|
51
|
+
-- aqui para nao se perder: o V1 chama "Funcionarios" o que `/registry/staff`
|
|
52
|
+
-- chama "Equipe", "Locais Operacionais" o que `/registry/locations` chama
|
|
53
|
+
-- "Locais de Atendimento", e "CRM" o que `/sales` chama "Vendas".
|
|
54
|
+
--
|
|
55
|
+
-- `/resources` ja entra no `under` de Cadastros: a tabela de recursos (salas,
|
|
56
|
+
-- macas, cadeiras) esta sendo criada agora, e no V1 esse cadastro mora em
|
|
57
|
+
-- Cadastros. Prefixo que ainda nao serve rota nenhuma nao custa nada -- a
|
|
58
|
+
-- rubrica simplesmente nao o recolhe ate a tela existir.
|
|
59
|
+
--
|
|
60
|
+
-- `hide` tira do rail o vocabulario que o V1 nao tem. NAO desliga modulo
|
|
61
|
+
-- nenhum: as telas continuam existindo, roteadas e alcancaveis -- o que sai e
|
|
62
|
+
-- a LINHA.
|
|
63
|
+
-- ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
UPDATE app.apps SET preset = (preset - 'rail' - 'hide') || $$
|
|
66
|
+
{
|
|
67
|
+
"rail": [
|
|
68
|
+
"dashboard",
|
|
69
|
+
{ "label": "Agenda", "icon": "Calendar",
|
|
70
|
+
"under": ["/agenda", "/checkin", "/conversations"] },
|
|
71
|
+
{ "label": "Clientes", "icon": "Users", "under": ["/clients"] },
|
|
72
|
+
"inventory",
|
|
73
|
+
"crm",
|
|
74
|
+
"financial",
|
|
75
|
+
{ "label": "Cadastros", "icon": "ClipboardList",
|
|
76
|
+
"under": ["/registry", "/resources", "/company", "/staff"] },
|
|
77
|
+
"reports"
|
|
78
|
+
],
|
|
79
|
+
"hide": ["/customers", "/suppliers", "/marketing", "/analytics", "/tasks"]
|
|
80
|
+
}
|
|
81
|
+
$$::jsonb WHERE id = 'beauty';
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
-- ---------------------------------------------------------------------------
|
|
2
|
+
-- 118_o_cadastro_do_salao_fala_como_o_v1.sql — o Cadastros do Espaço Facial.
|
|
3
|
+
-- ---------------------------------------------------------------------------
|
|
4
|
+
-- A 117 pôs as telas de cadastro sob UMA rubrica, e foi metade do caminho. A
|
|
5
|
+
-- outra metade é o que a recepcionista lê quando abre o menu: ela vem de sete
|
|
6
|
+
-- anos de BeautySoft, e lá a lista se chama assim, nesta ordem —
|
|
7
|
+
--
|
|
8
|
+
-- Contatos · Contas · Equipamentos · Fornecedores · Funcionários ·
|
|
9
|
+
-- Locais Operacionais · Origens · Parcerias · Serviços ·
|
|
10
|
+
-- Profissionais · Recursos Humanos
|
|
11
|
+
--
|
|
12
|
+
-- Três coisas faltavam para dizer isso, e as três agora são dado:
|
|
13
|
+
--
|
|
14
|
+
-- ORDEM `under` passa a ser lida como sequência, não como conjunto. O
|
|
15
|
+
-- V1 abre em Contatos e fecha em Serviços; a ordem de POSIÇÃO dos
|
|
16
|
+
-- plugins não tem como saber disso. Um prefixo largo no fim
|
|
17
|
+
-- (`/registry`) continua sendo o pega-tudo.
|
|
18
|
+
--
|
|
19
|
+
-- NOME `labels` é um dicionário rota → nome. Não é a árvore paralela
|
|
20
|
+
-- que a 083 matou: não há rota, ícone nem posição aqui, então não
|
|
21
|
+
-- há como uma entrada desenhar uma linha que não existe. É só o
|
|
22
|
+
-- ofício dizendo que na casa DELE `/registry/staff` se chama
|
|
23
|
+
-- "Funcionários" — renomear isso no plugin renomearia a mesma tela
|
|
24
|
+
-- no restaurante e na loja.
|
|
25
|
+
--
|
|
26
|
+
-- ORIGENS a rota existe desde sempre, com rótulo vazio, e por isso nunca
|
|
27
|
+
-- desenhou: uma linha sem nome não tem como aparecer. Nomeada pelo
|
|
28
|
+
-- preset, ela volta ao menu sem o aplicativo mudar uma linha.
|
|
29
|
+
--
|
|
30
|
+
-- ── O que continua faltando, e por que não está aqui ───────────────────────
|
|
31
|
+
-- Contas existe DENTRO do Financeiro, como aba do módulo, não
|
|
32
|
+
-- como rota própria. Puxá-la para cá a tiraria de lá.
|
|
33
|
+
-- Profissionais o V1 separa quem TRABALHA na casa (Funcionários) de
|
|
34
|
+
-- quem ATENDE (Profissionais). O V2 tem uma pessoa só.
|
|
35
|
+
-- Eixo não modelado — não se inventa rubrica para ele.
|
|
36
|
+
-- Recursos Humanos é o plugin `workforce`, que este aplicativo não monta.
|
|
37
|
+
--
|
|
38
|
+
-- `modules` ganha `registry` junto: quem NÃO é oferecido não entra, mesmo
|
|
39
|
+
-- instalado — e uma rubrica sobre telas que não existem some em silêncio, que
|
|
40
|
+
-- foi exatamente o que aconteceu no aplicativo central.
|
|
41
|
+
--
|
|
42
|
+
-- Idempotente: reescreve `rail`, `hide` e `labels` por inteiro.
|
|
43
|
+
-- ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
UPDATE app.apps
|
|
46
|
+
SET preset = (preset - 'rail' - 'hide' - 'labels') || $$
|
|
47
|
+
{
|
|
48
|
+
"rail": [
|
|
49
|
+
"dashboard",
|
|
50
|
+
{ "label": "Agenda", "icon": "Calendar",
|
|
51
|
+
"under": ["/agenda", "/checkin", "/conversations"] },
|
|
52
|
+
{ "label": "Clientes", "icon": "Users", "under": ["/clients"] },
|
|
53
|
+
"inventory",
|
|
54
|
+
"crm",
|
|
55
|
+
"financial",
|
|
56
|
+
{ "label": "Cadastros", "icon": "ClipboardList",
|
|
57
|
+
"under": ["/registry/contacts",
|
|
58
|
+
"/registry/equipment",
|
|
59
|
+
"/registry/suppliers",
|
|
60
|
+
"/registry/staff",
|
|
61
|
+
"/registry/locations",
|
|
62
|
+
"/registry/location-groups",
|
|
63
|
+
"/registry/origins",
|
|
64
|
+
"/registry/partnerships",
|
|
65
|
+
"/registry/services",
|
|
66
|
+
"/registry/categories",
|
|
67
|
+
"/registry", "/resources", "/company", "/staff"] },
|
|
68
|
+
"reports"
|
|
69
|
+
],
|
|
70
|
+
"hide": ["/customers", "/suppliers", "/marketing", "/analytics", "/tasks"],
|
|
71
|
+
"labels": {
|
|
72
|
+
"/": "Dashboard",
|
|
73
|
+
"/sales": "CRM",
|
|
74
|
+
"/registry/staff": "Funcionários",
|
|
75
|
+
"/registry/locations": "Locais Operacionais",
|
|
76
|
+
"/registry/origins": "Origens",
|
|
77
|
+
"/registry/services": "Serviços",
|
|
78
|
+
"/registry/categories": "Categorias"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
$$::jsonb WHERE id = 'beauty';
|
|
82
|
+
|
|
83
|
+
-- O ofício passa a OFERECER os Cadastros. Sem isto o plugin fica instalado e
|
|
84
|
+
-- calado: `resolvePluginRuntime` só liga por padrão quem está na oferta.
|
|
85
|
+
UPDATE app.apps
|
|
86
|
+
SET preset = jsonb_set(
|
|
87
|
+
preset, '{modules}',
|
|
88
|
+
(SELECT jsonb_agg(DISTINCT m)
|
|
89
|
+
FROM jsonb_array_elements(
|
|
90
|
+
COALESCE(preset->'modules', '[]'::jsonb) || '["registry"]'::jsonb) AS m))
|
|
91
|
+
WHERE id = 'beauty';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
-- ---------------------------------------------------------------------------
|
|
2
|
+
-- 119_a_agenda_do_salao_perde_o_que_nao_e_dela.sql
|
|
3
|
+
-- ---------------------------------------------------------------------------
|
|
4
|
+
-- O grupo Agenda tinha recolhido `/conversations` inteiro, e com ele vieram
|
|
5
|
+
-- duas telas que não são da recepção: Campanhas (disparo em massa) e Templates
|
|
6
|
+
-- (modelos de mensagem). No V1 o grupo tem QUATRO linhas —
|
|
7
|
+
--
|
|
8
|
+
-- Agendamentos · Confirmações · Check-in · Comunicação
|
|
9
|
+
--
|
|
10
|
+
-- — e "Comunicação" é a régua: o que sai sozinho em torno de um horário
|
|
11
|
+
-- marcado. Campanha é do marketing e não pertence ao grupo; o que mais se
|
|
12
|
+
-- parece com a régua hoje é a tela de modelos, então ela passa a se chamar
|
|
13
|
+
-- Comunicação até a régua existir de fato.
|
|
14
|
+
--
|
|
15
|
+
-- ── Clientes volta ao rail ─────────────────────────────────────────────────
|
|
16
|
+
-- A 117 escondeu `/customers` porque o salão tinha `/clients`, e o aplicativo
|
|
17
|
+
-- central não tem — a rubrica ficava sem filho e sumia, e a conta abria sem a
|
|
18
|
+
-- tela mais usada do dia. `/customers` É a lista de clientes aqui; o `hide`
|
|
19
|
+
-- existia para não mostrar o mesmo módulo com dois nomes, e sem o segundo nome
|
|
20
|
+
-- ele não tem o que resolver.
|
|
21
|
+
--
|
|
22
|
+
-- `/customers` se chama "Listar" e não "Clientes": a rubrica já diz Clientes,
|
|
23
|
+
-- e o índice de um grupo herda o nome do pai — saía "Clientes > Clientes".
|
|
24
|
+
-- Ao lado dele entra "Inserir", que é o par do V1.
|
|
25
|
+
--
|
|
26
|
+
-- Idempotente: reescreve `rail`, `hide` e `labels` por inteiro.
|
|
27
|
+
-- ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
UPDATE app.apps
|
|
30
|
+
SET preset = (preset - 'rail' - 'hide' - 'labels') || $$
|
|
31
|
+
{
|
|
32
|
+
"rail": [
|
|
33
|
+
"dashboard",
|
|
34
|
+
{ "label": "Agenda", "icon": "Calendar",
|
|
35
|
+
"under": ["/agenda", "/checkin", "/conversations"] },
|
|
36
|
+
{ "label": "Clientes", "icon": "Users", "under": ["/clients", "/customers"] },
|
|
37
|
+
"inventory",
|
|
38
|
+
"crm",
|
|
39
|
+
"financial",
|
|
40
|
+
{ "label": "Cadastros", "icon": "ClipboardList",
|
|
41
|
+
"under": ["/registry/contacts",
|
|
42
|
+
"/registry/equipment",
|
|
43
|
+
"/registry/suppliers",
|
|
44
|
+
"/registry/staff",
|
|
45
|
+
"/registry/locations",
|
|
46
|
+
"/registry/location-groups",
|
|
47
|
+
"/registry/origins",
|
|
48
|
+
"/registry/partnerships",
|
|
49
|
+
"/registry/services",
|
|
50
|
+
"/registry/categories",
|
|
51
|
+
"/registry", "/resources", "/company", "/staff"] },
|
|
52
|
+
"reports"
|
|
53
|
+
],
|
|
54
|
+
"hide": ["/suppliers", "/marketing", "/analytics", "/tasks",
|
|
55
|
+
"/conversations/campaigns"],
|
|
56
|
+
"labels": {
|
|
57
|
+
"/": "Dashboard",
|
|
58
|
+
"/sales": "CRM",
|
|
59
|
+
"/customers": "Listar",
|
|
60
|
+
"/customers/new": "Inserir",
|
|
61
|
+
"/conversations/templates": "Comunicação",
|
|
62
|
+
"/registry/staff": "Funcionários",
|
|
63
|
+
"/registry/locations": "Locais Operacionais",
|
|
64
|
+
"/registry/origins": "Origens",
|
|
65
|
+
"/registry/services": "Serviços",
|
|
66
|
+
"/registry/categories": "Categorias"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
$$::jsonb WHERE id = 'beauty';
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
-- ---------------------------------------------------------------------------
|
|
2
|
+
-- 134_todo_oficio_agrupa_os_seus_cadastros.sql — Cadastros deixa de ser sorte.
|
|
3
|
+
-- ---------------------------------------------------------------------------
|
|
4
|
+
-- A 117 pôs as telas de cadastro sob uma rubrica e a 132 lhes deu a ordem e o
|
|
5
|
+
-- vocabulário do V1. As duas mexeram em `beauty`, e só nele. O resultado é o
|
|
6
|
+
-- que um tenant vê hoje:
|
|
7
|
+
--
|
|
8
|
+
-- Espaço Facial (beauty) Cadastros ▸ Contatos · Equipamentos · …
|
|
9
|
+
-- Crema Club (school) Serviço · Categorias de Serviço · Locais de
|
|
10
|
+
-- Atendimento · Grupos de Locais · Profissionais ·
|
|
11
|
+
-- Contatos · Fornecedores · Parcerias ·
|
|
12
|
+
-- Equipamentos · Origens
|
|
13
|
+
--
|
|
14
|
+
-- Onze linhas planas, empurrando Análises e Financeiro para fora da primeira
|
|
15
|
+
-- tela. Não é escolha de ofício nenhum: é `createRegistryPlugin()` entrando em
|
|
16
|
+
-- todo aplicativo — o que a 117 queria — e só um dos rails tendo sido ensinado
|
|
17
|
+
-- a recolhê-las.
|
|
18
|
+
--
|
|
19
|
+
-- ── o que muda ──────────────────────────────────────────────────────────────
|
|
20
|
+
--
|
|
21
|
+
-- `school`, `shop` e `ticket` ganham a rubrica. `resto` já tinha uma com o
|
|
22
|
+
-- nome certo, mas recolhendo só `/company` e `/staff` — as dez telas de
|
|
23
|
+
-- `/registry/*` ficavam de fora dela, o que é pior que não ter: a casa lê
|
|
24
|
+
-- "Cadastros" no menu e os cadastros estão do lado de fora.
|
|
25
|
+
--
|
|
26
|
+
-- `beauty` não é tocado. Ele tem a lista longa que a 132 escreveu para dizer a
|
|
27
|
+
-- ORDEM do BeautySoft, e essa ordem é dele; reescrevê-la aqui seria trocar
|
|
28
|
+
-- sete anos de hábito por uma uniformização que ninguém pediu.
|
|
29
|
+
--
|
|
30
|
+
-- `full` também não. Ele já tem `under: ["/registry"]`, e um prefixo largo
|
|
31
|
+
-- sozinho é o pega-tudo — a mesma regra que a 132 documenta.
|
|
32
|
+
--
|
|
33
|
+
-- ── por que o prefixo curto basta ───────────────────────────────────────────
|
|
34
|
+
--
|
|
35
|
+
-- `under` casa por PREFIXO de rota: `/registry` serve `/registry/contacts` do
|
|
36
|
+
-- mesmo jeito que `/financial` serve `/financial/payables`. A lista longa do
|
|
37
|
+
-- salão existe para ordenar, não para alcançar. Onde não há ordem herdada para
|
|
38
|
+
-- honrar, o prefixo curto diz a mesma coisa com uma linha, e um cadastro novo
|
|
39
|
+
-- que um plugin publique amanhã entra na rubrica sozinho em vez de nascer solto
|
|
40
|
+
-- embaixo dela.
|
|
41
|
+
--
|
|
42
|
+
-- `/company` e `/staff` entram junto porque são cadastro pela mesma pergunta —
|
|
43
|
+
-- a ficha da casa e a de quem trabalha nela. É o que o `resto` já dizia.
|
|
44
|
+
--
|
|
45
|
+
-- ── posição ─────────────────────────────────────────────────────────────────
|
|
46
|
+
--
|
|
47
|
+
-- Antes de `reports`, como em `beauty` e em `resto`. Cadastro é o que se visita
|
|
48
|
+
-- de vez em quando para corrigir uma ficha; fica no fim, perto do que também se
|
|
49
|
+
-- abre por exceção — e longe de Painel, Conversas e do módulo do ofício, que
|
|
50
|
+
-- são a primeira tela do dia.
|
|
51
|
+
--
|
|
52
|
+
-- Uma rubrica sem filho ativo não desenha (ver `applyRailPreset`), então uma
|
|
53
|
+
-- conta que não instalou o registry não ganha um cabeçalho vazio.
|
|
54
|
+
-- ---------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
-- Insere a rubrica imediatamente antes de `reports`, preservando o resto do
|
|
57
|
+
-- rail na ordem em que está. Feito em SQL sobre o array e não com um rail novo
|
|
58
|
+
-- escrito à mão por aplicativo: o que muda é UMA entrada, e reescrever os
|
|
59
|
+
-- quatro rails inteiros aqui é como a 083 criou uma árvore paralela que
|
|
60
|
+
-- discordava dos plugins.
|
|
61
|
+
WITH alvo AS (
|
|
62
|
+
SELECT id,
|
|
63
|
+
preset->'rail' AS rail,
|
|
64
|
+
-- A rubrica deste ofício. `resto` já tem uma e ela é SUBSTITUÍDA pela
|
|
65
|
+
-- versão que alcança `/registry`; os outros três recebem uma nova.
|
|
66
|
+
jsonb_build_object(
|
|
67
|
+
'label', 'Cadastros',
|
|
68
|
+
'icon', 'ClipboardList',
|
|
69
|
+
'under', jsonb_build_array('/registry', '/company', '/staff')
|
|
70
|
+
) AS rubrica
|
|
71
|
+
FROM app.apps
|
|
72
|
+
WHERE id IN ('school', 'shop', 'ticket', 'resto')
|
|
73
|
+
AND preset ? 'rail'
|
|
74
|
+
),
|
|
75
|
+
limpo AS (
|
|
76
|
+
-- Fora a rubrica antiga, onde houver: manter as duas daria "Cadastros" duas
|
|
77
|
+
-- vezes no menu, e a primeira venceria a corrida pelas rotas.
|
|
78
|
+
SELECT a.id, a.rubrica,
|
|
79
|
+
COALESCE(
|
|
80
|
+
(SELECT jsonb_agg(e ORDER BY ord)
|
|
81
|
+
FROM jsonb_array_elements(a.rail) WITH ORDINALITY AS t(e, ord)
|
|
82
|
+
WHERE NOT (jsonb_typeof(e) = 'object' AND e->>'label' = 'Cadastros')),
|
|
83
|
+
'[]'::jsonb
|
|
84
|
+
) AS rail
|
|
85
|
+
FROM alvo a
|
|
86
|
+
),
|
|
87
|
+
posicao AS (
|
|
88
|
+
SELECT l.id, l.rail, l.rubrica,
|
|
89
|
+
-- Onde `reports` está. Sem ele, a rubrica vai para o fim.
|
|
90
|
+
COALESCE(
|
|
91
|
+
(SELECT MIN(ord) - 1
|
|
92
|
+
FROM jsonb_array_elements(l.rail) WITH ORDINALITY AS t(e, ord)
|
|
93
|
+
WHERE jsonb_typeof(e) = 'string' AND e #>> '{}' = 'reports'),
|
|
94
|
+
jsonb_array_length(l.rail)
|
|
95
|
+
) AS corte
|
|
96
|
+
FROM limpo l
|
|
97
|
+
)
|
|
98
|
+
UPDATE app.apps a
|
|
99
|
+
SET preset = jsonb_set(
|
|
100
|
+
a.preset, '{rail}',
|
|
101
|
+
(SELECT COALESCE(jsonb_agg(e ORDER BY ord), '[]'::jsonb)
|
|
102
|
+
FROM jsonb_array_elements(p.rail) WITH ORDINALITY AS t(e, ord)
|
|
103
|
+
WHERE ord <= p.corte)
|
|
104
|
+
|| jsonb_build_array(p.rubrica)
|
|
105
|
+
|| (SELECT COALESCE(jsonb_agg(e ORDER BY ord), '[]'::jsonb)
|
|
106
|
+
FROM jsonb_array_elements(p.rail) WITH ORDINALITY AS t(e, ord)
|
|
107
|
+
WHERE ord > p.corte)
|
|
108
|
+
),
|
|
109
|
+
updated_at = now()
|
|
110
|
+
FROM posicao p
|
|
111
|
+
WHERE a.id = p.id;
|
|
112
|
+
|
|
113
|
+
-- O módulo `registry` declarado, como a 132 fez para o salão: sem ele a conta
|
|
114
|
+
-- pode não montar o plugin, e a rubrica não desenha por não ter filho.
|
|
115
|
+
UPDATE app.apps
|
|
116
|
+
SET preset = jsonb_set(
|
|
117
|
+
preset, '{modules}',
|
|
118
|
+
(SELECT jsonb_agg(DISTINCT m)
|
|
119
|
+
FROM jsonb_array_elements(
|
|
120
|
+
COALESCE(preset->'modules', '[]'::jsonb) || '["registry"]'::jsonb) AS m)),
|
|
121
|
+
updated_at = now()
|
|
122
|
+
WHERE id IN ('school', 'shop', 'ticket', 'resto')
|
|
123
|
+
AND preset ? 'modules';
|
package/package.json
CHANGED