@fayz-ai/db 0.18.2 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/migrations/136_a_baixa_do_espelho_e_do_porte_nao_do_v2.sql +204 -0
  2. package/migrations/137_a_retirada_e_um_canal_de_venda.sql +43 -0
  3. package/migrations/138_o_produto_tem_cor_e_a_conta_so_a_veste_se_pagar.sql +606 -0
  4. package/migrations/139_a_equipe_e_um_agrupamento_declarado.sql +50 -0
  5. package/migrations/140_a_unidade_se_escreve_pela_mesma_porta_que_se_le.sql +130 -0
  6. package/migrations/141_o_endereco_da_unidade_mora_na_tabela_de_enderecos.sql +203 -0
  7. package/migrations/142_a_coordenada_e_do_endereco_nao_da_unidade.sql +157 -0
  8. package/migrations/143_o_preset_para_de_nomear_telas_que_nao_existem.sql +29 -0
  9. package/migrations/144_marketing_e_um_botao_nao_uma_gaveta.sql +46 -0
  10. package/migrations/145_campanhas_e_templates_somem_em_toda_conta.sql +36 -0
  11. package/migrations/146_a_clinica_ve_as_proprias_analises.sql +31 -0
  12. package/migrations/147_tres_saloes_desligam_o_rh.sql +30 -0
  13. package/migrations/148_servicos_ganham_a_permissao_que_nunca_tiveram.sql +37 -0
  14. package/migrations/149_a_conta_do_fornecedor_nao_e_conta_da_casa.sql +131 -0
  15. package/migrations/150_todo_cadastro_tem_observacao_e_etiqueta.sql +62 -0
  16. package/migrations/151_a_parceria_e_uma_especie_de_pessoa.sql +35 -0
  17. package/migrations/152_a_profissao_e_a_especie_de_pet_sao_catalogos.sql +31 -0
  18. package/migrations/153_a_sala_nao_e_a_filial.sql +94 -0
  19. package/migrations/154_as_duas_tabelas_novas_dizem_de_quem_sao.sql +33 -0
  20. package/migrations/155_o_pacote_tem_observacao_e_etiqueta_e_diz_de_quem_e.sql +28 -0
  21. package/migrations/156_restaurante_nao_vende_servico.sql +44 -0
  22. package/migrations/157_o_que_a_porta_da_unidade_criou_tambem_se_revoga.sql +45 -0
  23. package/migrations/158_a_producao_e_do_restaurante_e_mora_no_estoque.sql +129 -0
  24. package/migrations/159_a_loja_tambem_confundia_o_que_vende_com_o_que_guarda.sql +98 -0
  25. package/migrations/161_vender_e_falar_com_quem_ainda_nao_comprou_sao_o_mesmo_assunto.sql +73 -0
  26. package/package.json +1 -1
@@ -0,0 +1,129 @@
1
+ -- ---------------------------------------------------------------------------
2
+ -- 158_a_producao_e_do_restaurante_e_mora_no_estoque.sql
3
+ -- ---------------------------------------------------------------------------
4
+ -- Produção é um módulo de quem FABRICA o que vende — e, na frota de hoje, isso
5
+ -- é o ChefControl. Uma clínica, um salão, uma escola e uma loja compilam o
6
+ -- mesmo pacote e não têm o que produzir.
7
+ --
8
+ -- ── A porta é a OFERTA, não uma consulta na tela ────────────────────────────
9
+ -- `preset.modules` é o que este ofício oferece (079): `resolvePluginRuntime`
10
+ -- recebe a união do que os aplicativos da conta oferecem e deixa FORA todo
11
+ -- plugin que ninguém ofereceu, mesmo o que nasce ligado. É a mesma porta que
12
+ -- já mantém cozinha, mesa e reserva longe de um consultório — e o motivo de
13
+ -- não haver `if (tenant.temResto)` em componente nenhum.
14
+ --
15
+ -- ── E o rail: «Estoque» passa a abrir em dois ───────────────────────────────
16
+ -- Hoje o ChefControl põe o Estoque dentro de «Produtos», ao lado do Cardápio.
17
+ -- Com a Produção ao lado, o Estoque vira rubrica própria com duas telas:
18
+ --
19
+ -- Estoque
20
+ -- Geral → /inventory
21
+ -- Produção → /production
22
+ --
23
+ -- «Produtos» fica com o Cardápio, que é o que ela sempre foi na cabeça de quem
24
+ -- usa: o que se VENDE. Estoque é o que se GUARDA.
25
+ --
26
+ -- O `full` (aplicativo central) ganha a mesma rubrica por simetria, e nele ela
27
+ -- se recolhe sozinha: sem a Produção oferecida, uma rubrica com um destino só
28
+ -- VIRA o destino e volta a ser a linha «Estoque» de hoje (ver applyRailPreset).
29
+ -- Nenhuma conta sem `resto` muda de menu.
30
+ --
31
+ -- Idempotente: recalcula rail, modules e labels a partir do que está lá.
32
+ -- ---------------------------------------------------------------------------
33
+
34
+ -- ── 1. A oferta: só o ChefControl oferece Produção ──────────────────────────
35
+ UPDATE app.apps
36
+ SET preset = jsonb_set(
37
+ preset,
38
+ '{modules}',
39
+ (
40
+ SELECT to_jsonb(array_agg(m ORDER BY m))
41
+ FROM (
42
+ SELECT jsonb_array_elements_text(coalesce(preset -> 'modules', '[]'::jsonb)) AS m
43
+ UNION
44
+ SELECT 'production'
45
+ ) AS mods
46
+ ),
47
+ true
48
+ )
49
+ WHERE id = 'resto';
50
+
51
+ -- ── 2. O vocabulário: dentro da rubrica, o Estoque chama-se «Geral» ─────────
52
+ -- Fora dela o nome continua sendo o do plugin: a rubrica leva o próprio nome
53
+ -- quando se recolhe, então uma conta sem Produção nunca lê «Geral» sozinho.
54
+ UPDATE app.apps
55
+ SET preset = jsonb_set(
56
+ preset,
57
+ '{labels}',
58
+ coalesce(preset -> 'labels', '{}'::jsonb)
59
+ || jsonb_build_object('/inventory', 'Geral', '/production', 'Produção'),
60
+ true
61
+ )
62
+ WHERE id IN ('resto', 'full');
63
+
64
+ -- ── 3. «Produtos» não existe: o que sobra dela é o Cardápio ─────────────────
65
+ -- A rubrica juntava o que se VENDE (/menu) e o que se GUARDA (/inventory) sob
66
+ -- um nome que não é nenhum dos dois. Tirado o Estoque, o que resta é uma
67
+ -- rubrica de um destino só — e `applyRailPreset` recolhe essas, mantendo o
68
+ -- nome da RUBRICA e não o do destino. Por isso o nome muda aqui: sem esta
69
+ -- linha o rail leria «Produtos» apontando para o cardápio, que é o mal-entendido
70
+ -- de partida com uma tela a menos.
71
+ UPDATE app.apps
72
+ SET preset = jsonb_set(
73
+ preset,
74
+ '{rail}',
75
+ (
76
+ SELECT jsonb_agg(
77
+ CASE
78
+ WHEN entrada -> 'under' IS NOT NULL AND entrada ->> 'label' = 'Produtos'
79
+ THEN jsonb_build_object('label', 'Cardápio', 'icon', 'BookOpen',
80
+ 'under', jsonb_build_array('/menu'))
81
+ ELSE entrada
82
+ END
83
+ ORDER BY ord
84
+ )
85
+ FROM jsonb_array_elements(preset -> 'rail') WITH ORDINALITY AS r(entrada, ord)
86
+ ),
87
+ true
88
+ )
89
+ WHERE id = 'resto'
90
+ AND preset -> 'rail' IS NOT NULL;
91
+
92
+ -- ── 4. A rubrica «Estoque», nos dois aplicativos ────────────────────────────
93
+ -- Ela entra ENCOSTADA no vizinho certo, e não no fim: no ChefControl logo
94
+ -- depois do «Cardápio» (o que se vende e o que se guarda leem-se juntos), e no
95
+ -- aplicativo central logo depois da última rubrica antes de «Cadastros» — que
96
+ -- é sempre a última de todo preset.
97
+ --
98
+ -- As posições são multiplicadas por dez para a nova caber no meio sem renumerar
99
+ -- as vizinhas; `+5` é o «logo depois daquela».
100
+ UPDATE app.apps a
101
+ SET preset = jsonb_set(
102
+ a.preset,
103
+ '{rail}',
104
+ (
105
+ WITH atual AS (
106
+ SELECT entrada, ord
107
+ FROM jsonb_array_elements(a.preset -> 'rail') WITH ORDINALITY AS r(entrada, ord)
108
+ WHERE entrada ->> 'label' IS DISTINCT FROM 'Estoque'
109
+ AND NOT (entrada ? 'under' AND entrada -> 'under' @> '["/inventory"]'::jsonb)
110
+ ),
111
+ vizinha AS (
112
+ SELECT coalesce(
113
+ (SELECT ord FROM atual WHERE entrada -> 'under' @> '["/menu"]'::jsonb ORDER BY ord LIMIT 1),
114
+ (SELECT max(ord) FROM atual WHERE entrada ->> 'label' IS DISTINCT FROM 'Cadastros')
115
+ ) AS ord
116
+ )
117
+ SELECT jsonb_agg(entrada ORDER BY ord)
118
+ FROM (
119
+ SELECT entrada, ord * 10 AS ord FROM atual
120
+ UNION ALL
121
+ SELECT jsonb_build_object('label', 'Estoque', 'icon', 'Package',
122
+ 'under', jsonb_build_array('/inventory', '/production')),
123
+ (SELECT ord FROM vizinha) * 10 + 5
124
+ ) AS reordenado
125
+ ),
126
+ true
127
+ )
128
+ WHERE a.id IN ('resto', 'full')
129
+ AND a.preset -> 'rail' IS NOT NULL;
@@ -0,0 +1,98 @@
1
+ -- ---------------------------------------------------------------------------
2
+ -- 159_a_loja_tambem_confundia_o_que_vende_com_o_que_guarda.sql
3
+ -- ---------------------------------------------------------------------------
4
+ -- A 158 separou Cardápio de Estoque no ChefControl e parou aí. Mas quem
5
+ -- empresta o rail a uma conta é o PRIMEIRO aplicativo de `app_config()` — e
6
+ -- numa churrascaria que roda StoreControl + FullControl + FiscalControl o
7
+ -- primeiro é o StoreControl, porque `commerce` é ofício e `generic` não é.
8
+ -- O menu que a Artorius lê nunca foi o do `full`.
9
+ --
10
+ -- E o StoreControl trazia o mesmo mal-entendido ao contrário:
11
+ --
12
+ -- Estoque → /inventory + /menu
13
+ --
14
+ -- O cardápio DENTRO do estoque. Vender e guardar são dois trabalhos; quem
15
+ -- procura o que a casa oferece hoje e quem procura quanto ainda há na câmara
16
+ -- não estão fazendo a mesma coisa.
17
+ --
18
+ -- Depois desta:
19
+ --
20
+ -- Cardápio → /menu
21
+ -- Estoque → /inventory + /production
22
+ --
23
+ -- A Produção entra aqui como entrou no `full`: pela porta que já existe. Sem
24
+ -- o app `resto` ninguém a OFERECE, `resolvePluginRuntime` a descarta, e uma
25
+ -- rubrica de um destino só vira o destino (applyRailPreset) — a loja que não
26
+ -- fabrica continua lendo a linha «Estoque» de sempre. Numa conta que também
27
+ -- rode ChefControl, ela abre em Geral | Produção.
28
+ --
29
+ -- Idempotente: reescreve as duas rubricas a partir do que está lá.
30
+ -- ---------------------------------------------------------------------------
31
+
32
+ -- ── 1. O Estoque solta o Cardápio e recebe a Produção ───────────────────────
33
+ UPDATE app.apps
34
+ SET preset = jsonb_set(
35
+ preset,
36
+ '{rail}',
37
+ (
38
+ SELECT jsonb_agg(
39
+ CASE
40
+ WHEN entrada ? 'under' AND entrada -> 'under' @> '["/inventory"]'::jsonb
41
+ THEN jsonb_build_object('label', 'Estoque', 'icon', 'Package',
42
+ 'under', jsonb_build_array('/inventory', '/production'))
43
+ ELSE entrada
44
+ END
45
+ ORDER BY ord
46
+ )
47
+ FROM jsonb_array_elements(preset -> 'rail') WITH ORDINALITY AS r(entrada, ord)
48
+ ),
49
+ true
50
+ )
51
+ WHERE id = 'shop'
52
+ AND preset -> 'rail' IS NOT NULL;
53
+
54
+ -- ── 2. O Cardápio ganha rubrica própria, logo antes do Estoque ──────────────
55
+ -- Encostado e não no fim: o que se vende e o que se guarda leem-se juntos.
56
+ -- Posições ×10 para a nova caber no meio sem renumerar as vizinhas; `-5` é o
57
+ -- «logo antes daquela».
58
+ UPDATE app.apps a
59
+ SET preset = jsonb_set(
60
+ a.preset,
61
+ '{rail}',
62
+ (
63
+ WITH atual AS (
64
+ SELECT entrada, ord
65
+ FROM jsonb_array_elements(a.preset -> 'rail') WITH ORDINALITY AS r(entrada, ord)
66
+ WHERE entrada ->> 'label' IS DISTINCT FROM 'Cardápio'
67
+ AND NOT (entrada ? 'under' AND entrada -> 'under' @> '["/menu"]'::jsonb)
68
+ ),
69
+ vizinha AS (
70
+ SELECT (SELECT ord FROM atual
71
+ WHERE entrada -> 'under' @> '["/inventory"]'::jsonb
72
+ ORDER BY ord LIMIT 1) AS ord
73
+ )
74
+ SELECT jsonb_agg(entrada ORDER BY ord)
75
+ FROM (
76
+ SELECT entrada, ord * 10 AS ord FROM atual
77
+ UNION ALL
78
+ SELECT jsonb_build_object('label', 'Cardápio', 'icon', 'BookOpen',
79
+ 'under', jsonb_build_array('/menu')),
80
+ (SELECT ord FROM vizinha) * 10 - 5
81
+ WHERE (SELECT ord FROM vizinha) IS NOT NULL
82
+ ) AS reordenado
83
+ ),
84
+ true
85
+ )
86
+ WHERE a.id = 'shop'
87
+ AND a.preset -> 'rail' IS NOT NULL;
88
+
89
+ -- ── 3. O vocabulário dentro da rubrica ──────────────────────────────────────
90
+ UPDATE app.apps
91
+ SET preset = jsonb_set(
92
+ preset,
93
+ '{labels}',
94
+ coalesce(preset -> 'labels', '{}'::jsonb)
95
+ || jsonb_build_object('/inventory', 'Geral', '/production', 'Produção'),
96
+ true
97
+ )
98
+ WHERE id = 'shop';
@@ -0,0 +1,73 @@
1
+ -- ---------------------------------------------------------------------------
2
+ -- 161_vender_e_falar_com_quem_ainda_nao_comprou_sao_o_mesmo_assunto.sql
3
+ -- ---------------------------------------------------------------------------
4
+ -- No rail de hoje «CRM» e «Marketing» são duas linhas vizinhas e soltas. Quem
5
+ -- usa não separa as duas coisas: a campanha existe para gerar o lead, e o lead
6
+ -- é o começo do funil. No V1 elas nem são dois módulos — o `CRMSidebar` do
7
+ -- beautyplace desenha as views de venda E as de marketing na mesma barra, com
8
+ -- os prefixos `mkt-` misturados no mesmo `CRMView`.
9
+ --
10
+ -- Depois desta:
11
+ --
12
+ -- CRM
13
+ -- Vendas → /sales
14
+ -- Marketing → /marketing
15
+ --
16
+ -- Onde só um dos dois está ligado, `applyRailPreset` recolhe a rubrica no
17
+ -- destino que sobrou e ela volta a ser a linha de hoje — o `beauty`, que tem
18
+ -- CRM no rail e não tem Marketing, não muda de menu.
19
+ --
20
+ -- «Vendas» e não «CRM» no filho: o pai já se chama CRM, e pai e filho com o
21
+ -- mesmo nome é uma linha que não diz para onde leva (a mesma correção que o
22
+ -- Funil levou no plugin, onde o modo «Funil» virou «Quadro»).
23
+ --
24
+ -- Idempotente: reescreve a rubrica a partir do que está lá.
25
+ -- ---------------------------------------------------------------------------
26
+
27
+ -- ── 1. O vocabulário dentro da rubrica ──────────────────────────────────────
28
+ UPDATE app.apps
29
+ SET preset = jsonb_set(
30
+ preset,
31
+ '{labels}',
32
+ coalesce(preset -> 'labels', '{}'::jsonb)
33
+ || jsonb_build_object('/sales', 'Vendas', '/marketing', 'Marketing'),
34
+ true
35
+ )
36
+ WHERE preset -> 'rail' @> '["crm"]'::jsonb;
37
+
38
+ -- ── 2. As duas linhas viram uma rubrica, no lugar da primeira delas ─────────
39
+ -- No lugar da PRIMEIRA e não no fim: o CRM já está posicionado no rail de cada
40
+ -- ofício (depois de Clientes no `full`, depois de Marketing no `shop`), e uma
41
+ -- rubrica que muda de altura muda o menu de quem já sabia onde clicar.
42
+ UPDATE app.apps a
43
+ SET preset = jsonb_set(
44
+ a.preset,
45
+ '{rail}',
46
+ (
47
+ WITH numerada AS (
48
+ SELECT entrada, ord
49
+ FROM jsonb_array_elements(a.preset -> 'rail') WITH ORDINALITY AS r(entrada, ord)
50
+ ),
51
+ alvo AS (
52
+ SELECT min(ord) AS ord
53
+ FROM numerada
54
+ WHERE entrada IN ('"crm"'::jsonb, '"marketing"'::jsonb)
55
+ ),
56
+ restante AS (
57
+ SELECT entrada, ord
58
+ FROM numerada
59
+ WHERE entrada NOT IN ('"crm"'::jsonb, '"marketing"'::jsonb)
60
+ AND entrada ->> 'label' IS DISTINCT FROM 'CRM'
61
+ )
62
+ SELECT jsonb_agg(entrada ORDER BY ord)
63
+ FROM (
64
+ SELECT entrada, ord * 10 AS ord FROM restante
65
+ UNION ALL
66
+ SELECT jsonb_build_object('label', 'CRM', 'icon', 'Filter',
67
+ 'under', jsonb_build_array('/sales', '/marketing')),
68
+ (SELECT ord FROM alvo) * 10 - 1
69
+ ) AS reordenado
70
+ ),
71
+ true
72
+ )
73
+ WHERE a.preset -> 'rail' @> '["crm"]'::jsonb;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "fayz": {
4
4
  "status": "beta"
5
5
  },
6
- "version": "0.18.2",
6
+ "version": "0.20.1",
7
7
  "description": "Fayz SDK database layer — Drizzle schema primitives, spine references, and migration helpers shared across plugins.",
8
8
  "type": "module",
9
9
  "sideEffects": false,