@fayz-ai/plugin-workforce 0.1.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 (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/dist/context.d.ts +57 -0
  4. package/dist/context.d.ts.map +1 -0
  5. package/dist/data/index.d.ts +4 -0
  6. package/dist/data/index.d.ts.map +1 -0
  7. package/dist/data/mock.d.ts +3 -0
  8. package/dist/data/mock.d.ts.map +1 -0
  9. package/dist/data/supabase.d.ts +5 -0
  10. package/dist/data/supabase.d.ts.map +1 -0
  11. package/dist/data/types.d.ts +81 -0
  12. package/dist/data/types.d.ts.map +1 -0
  13. package/dist/index.d.ts +98 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +6416 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/migrations/index.d.ts +12 -0
  18. package/dist/migrations/index.d.ts.map +1 -0
  19. package/dist/settings/usePayrollAccounts.d.ts +14 -0
  20. package/dist/settings/usePayrollAccounts.d.ts.map +1 -0
  21. package/dist/store.d.ts +32 -0
  22. package/dist/store.d.ts.map +1 -0
  23. package/dist/types.d.ts +330 -0
  24. package/dist/types.d.ts.map +1 -0
  25. package/dist/views/HrView.d.ts +5 -0
  26. package/dist/views/HrView.d.ts.map +1 -0
  27. package/dist/views/PayrollCostsView.d.ts +3 -0
  28. package/dist/views/PayrollCostsView.d.ts.map +1 -0
  29. package/dist/views/PeopleView.d.ts +8 -0
  30. package/dist/views/PeopleView.d.ts.map +1 -0
  31. package/dist/views/PeriodsView.d.ts +3 -0
  32. package/dist/views/PeriodsView.d.ts.map +1 -0
  33. package/dist/views/SchedulesView.d.ts +3 -0
  34. package/dist/views/SchedulesView.d.ts.map +1 -0
  35. package/dist/views/TemplatesView.d.ts +3 -0
  36. package/dist/views/TemplatesView.d.ts.map +1 -0
  37. package/dist/views/TimeEntriesView.d.ts +3 -0
  38. package/dist/views/TimeEntriesView.d.ts.map +1 -0
  39. package/dist/views/WorkforcePage.d.ts +18 -0
  40. package/dist/views/WorkforcePage.d.ts.map +1 -0
  41. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Faya Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # @fayz-ai/plugin-workforce
2
+
3
+ > Escala, ponto e fechamento de competência — o RH operacional de qualquer app Fayz.
4
+
5
+ [![npm](https://img.shields.io/npm/v/@fayz-ai/plugin-workforce.svg)](https://www.npmjs.com/package/@fayz-ai/plugin-workforce)
6
+ [![license](https://img.shields.io/npm/l/@fayz-ai/plugin-workforce.svg)](https://github.com/FayaLabs/fayz-sdk/blob/main/LICENSE)
7
+
8
+ **Status:** beta — pre-1.0. A camada de dados está escrita e validada; a superfície de UI pode mudar antes do 1.0.
9
+
10
+ Toda casa que tem gente na escala precisa responder três perguntas: quem está escalado, quem de fato veio, e o mês está fechado. `plugin-workforce` é o módulo que responde as três sem inventar um segundo cadastro de pessoa e sem uma segunda tabela de horário.
11
+
12
+ Três decisões sustentam o modelo, e estão no SQL antes de estarem na tela:
13
+
14
+ - **A batida é um EVENTO, append-only.** `kind ∈ (clock_in, break_start, break_end, clock_out)`, N por dia, agrupados por `(person_id, work_date)`. Intervalo de almoço e turno partido saem de graça, e "quais pontos estão em aberto?" tem resposta sem coluna derivada.
15
+ - **O ajuste é uma LINHA, com autor e motivo obrigatório.** Nunca um UPDATE na batida — o horário real fica intocado, que é o que torna o ponto prova.
16
+ - **O previsto mora em `public.schedules`**, com `kind = 'work_shift'`. A escala publicada materializa a linha e guarda o id; o cruzamento previsto × realizado vira uma chave, e não um casamento por nome e hora.
17
+
18
+ ## O que tem dentro
19
+ - Um módulo `/workforce` com seis telas: Escalas, Templates, Registros de Ponto, Fechamento, Pessoas & Documentos, Encargos e Honorários
20
+ - Escala do dia a partir de um molde, com SNAPSHOT do turno — mudar o molde não reescreve o passado
21
+ - Folha de ponto agrupada por dia, com o crachá previsto × realizado lendo `v_workforce_day` (`absent` = falta, `outside_schedule` = fora da escala)
22
+ - Fechamento de competência por RPC (`workforce_period_close` / `workforce_period_reopen`), com motivo obrigatório para reabrir
23
+ - A ficha do colaborador vem do arquétipo de pessoa do `@fayz-ai/admin` — documentos, endereços, unidades e horário inclusos
24
+ - Custo de pessoal LIDO do razão do Financeiro (`plg_financial_rep_dre`, a mesma view do relatório de DRE), desenhado como DEMONSTRATIVO — árvore do plano de contas, uma coluna por mês de competência; este plugin não escreve nenhuma despesa
25
+ - **Qual ramo do plano é pessoal é uma DECLARAÇÃO da casa**, em `workforce.payroll_account_codes` (`tenants.settings`, migration 006). Sem escolha a tela mostra todas as despesas classificadas e avisa que é o que está fazendo — deduzir o ramo pelo nome da conta erraria no primeiro plano que numera diferente
26
+ - Provider plugável: memória por padrão, Supabase quando há cliente registrado
27
+
28
+ ## Install
29
+ ```bash
30
+ npm install @fayz-ai/plugin-workforce
31
+ ```
32
+ Peer deps: `@fayz-ai/core`, `@fayz-ai/ui`, `@fayz-ai/admin`, mais `react` / `react-dom`.
33
+
34
+ ## Usage
35
+ ```tsx
36
+ import { defineSaas } from '@fayz-ai/admin'
37
+ import { createWorkforcePlugin } from '@fayz-ai/plugin-workforce'
38
+
39
+ export const app = defineSaas({
40
+ // ...
41
+ plugins: [
42
+ createWorkforcePlugin({
43
+ currency: { code: 'BRL', locale: 'pt-BR', symbol: 'R$' },
44
+ labels: { pageTitle: 'RH', pageSubtitle: 'Escala, ponto e fechamento da equipe' },
45
+ // O SQL da jornada não guarda remuneração. Sem isto a folha mostra horas e
46
+ // um traço no lugar do valor, em vez de inventar um número.
47
+ hourlyRate: 22.5,
48
+ }),
49
+ ],
50
+ })
51
+ ```
52
+
53
+ ## Permissões
54
+ O baseline semeia oito chaves, e duas delas são segregação de função de propósito:
55
+ `workforce.adjust_time` (corrigir a batida de outra pessoa é prova, não edição) e
56
+ `workforce.close_period` (quem aponta não é quem fecha o mês).
@@ -0,0 +1,57 @@
1
+ import { formatCurrency, type CurrencyConfig, type EntityLookup } from '@fayz-ai/admin';
2
+ import type { WorkforcePluginLabels } from './index';
3
+ import type { WorkforceDataProvider } from './data/types';
4
+ import type { WorkforceUIState } from './store';
5
+ export interface WorkforceModules {
6
+ /** Escalas: o calendário mensal e o dia. */
7
+ schedules: boolean;
8
+ /** Templates: o molde da escala. */
9
+ templates: boolean;
10
+ /** Registros de Ponto: a folha, com ajuste auditado. */
11
+ timeEntries: boolean;
12
+ /** Fechamento: a competência mensal. */
13
+ periods: boolean;
14
+ /** Pessoas & Documentos: a ficha do colaborador. */
15
+ people: boolean;
16
+ /** Encargos e Honorários: o custo de pessoal, lido do Financeiro. */
17
+ payrollCosts: boolean;
18
+ /**
19
+ * Ficha de RH: vínculo, férias, afastamentos e pendências.
20
+ *
21
+ * Passa pela permissão `workforce_hr.*`, separada de `workforce.*` — quem vê
22
+ * escala e ponto não vê salário nem CID. É o conserto do V1-069, e o FLOW da
23
+ * Ficha diz que ele tinha de ser resolvido ANTES de portar.
24
+ */
25
+ hr: boolean;
26
+ }
27
+ export type WorkforceCurrency = CurrencyConfig;
28
+ export interface ResolvedWorkforceConfig {
29
+ modules: WorkforceModules;
30
+ labels: WorkforcePluginLabels;
31
+ currency: WorkforceCurrency;
32
+ /** Ver WorkforcePluginOptions.moduleNav. */
33
+ moduleNav?: 'rail' | 'tabs' | 'sidebar';
34
+ /**
35
+ * O valor da hora, quando o app souber dizer.
36
+ *
37
+ * O SQL da jornada NÃO guarda remuneração em lugar nenhum — nem na batida,
38
+ * nem no turno, nem em `public.people`. Sem isto a coluna "Valor" da folha
39
+ * não tem de onde sair, e a tela mostra "—" em vez de inventar um número.
40
+ */
41
+ hourlyRate?: number;
42
+ /** Busca de pessoa para escalar, quando o app quiser oferecer uma. */
43
+ staffLookup?: EntityLookup;
44
+ /** Item de nav → feature de acesso, exatamente como o APP declarou. */
45
+ navFeatureMap: Record<string, string>;
46
+ }
47
+ export declare const WorkforceContextProvider: import("react").FC<{
48
+ config: ResolvedWorkforceConfig;
49
+ provider: WorkforceDataProvider;
50
+ store: import("zustand").StoreApi<WorkforceUIState>;
51
+ children?: React.ReactNode;
52
+ }>;
53
+ export declare const useWorkforceConfig: () => ResolvedWorkforceConfig;
54
+ export declare const useWorkforceProvider: () => WorkforceDataProvider;
55
+ export declare const useWorkforceStore: <T>(selector: (state: WorkforceUIState) => T) => T;
56
+ export { formatCurrency };
57
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC5G,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AACpD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAM/C,MAAM,WAAW,gBAAgB;IAC/B,4CAA4C;IAC5C,SAAS,EAAE,OAAO,CAAA;IAClB,oCAAoC;IACpC,SAAS,EAAE,OAAO,CAAA;IAClB,wDAAwD;IACxD,WAAW,EAAE,OAAO,CAAA;IACpB,wCAAwC;IACxC,OAAO,EAAE,OAAO,CAAA;IAChB,oDAAoD;IACpD,MAAM,EAAE,OAAO,CAAA;IACf,qEAAqE;IACrE,YAAY,EAAE,OAAO,CAAA;IACrB;;;;;;OAMG;IACH,EAAE,EAAE,OAAO,CAAA;CACZ;AAED,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAA;AAE9C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,gBAAgB,CAAA;IACzB,MAAM,EAAE,qBAAqB,CAAA;IAC7B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACvC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,YAAY,CAAA;IAC1B,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACtC;AAID,eAAO,MAAM,wBAAwB;;;;;EAAsB,CAAA;AAC3D,eAAO,MAAM,kBAAkB,+BAAgB,CAAA;AAC/C,eAAO,MAAM,oBAAoB,6BAAkB,CAAA;AACnD,eAAO,MAAM,iBAAiB,oDAAe,CAAA;AAE7C,OAAO,EAAE,cAAc,EAAE,CAAA"}
@@ -0,0 +1,4 @@
1
+ export type { WorkforceDataProvider } from './types';
2
+ export { createMockWorkforceProvider } from './mock';
3
+ export { createSupabaseWorkforceProvider, WORK_SHIFT_KIND } from './supabase';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AACpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,QAAQ,CAAA;AACpD,OAAO,EAAE,+BAA+B,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { WorkforceDataProvider } from './types';
2
+ export declare function createMockWorkforceProvider(): WorkforceDataProvider;
3
+ //# sourceMappingURL=mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/data/mock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAiCpD,wBAAgB,2BAA2B,IAAI,qBAAqB,CAgSnE"}
@@ -0,0 +1,5 @@
1
+ import type { WorkforceDataProvider } from './types';
2
+ /** A espécie de horário que o RH oferta. Semeada pela migration 000. */
3
+ export declare const WORK_SHIFT_KIND = "work_shift";
4
+ export declare function createSupabaseWorkforceProvider(): WorkforceDataProvider;
5
+ //# sourceMappingURL=supabase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAYpD,wEAAwE;AACxE,eAAO,MAAM,eAAe,eAAe,CAAA;AA6F3C,wBAAgB,+BAA+B,IAAI,qBAAqB,CA8pBvE"}
@@ -0,0 +1,81 @@
1
+ import type { TimeEntry, TimeEntryQuery, TimeAdjustmentInput, PunchPhoto, WorkDay, WorkforcePeriod, ScheduleTemplate, SaveTemplateInput, SaveShiftInput, SaveRequirementInput, DaySchedule, ScheduleQuery, CreateScheduleInput, WorkforcePerson, PayrollCostRow, PayrollCostQuery, Employment, Vacation, Absence, PendingItem, HrOverview, HrUpcoming } from '../types';
2
+ /**
3
+ * O contrato de dados da jornada.
4
+ *
5
+ * Duas implementações: `createSupabaseWorkforceProvider` (o cluster) e
6
+ * `createMockWorkforceProvider` (memória, para quem monta o app sem banco).
7
+ * A escolha é do `createSafeDataProvider` do core, uma vez, na fábrica.
8
+ */
9
+ export interface WorkforceDataProvider {
10
+ getHrOverview(): Promise<HrOverview | null>;
11
+ getHrUpcoming(): Promise<HrUpcoming[]>;
12
+ getEmployment(personId: string): Promise<Employment | null>;
13
+ saveEmployment(input: Employment): Promise<void>;
14
+ getVacations(personId: string): Promise<Vacation[]>;
15
+ saveVacation(input: Vacation): Promise<void>;
16
+ getAbsences(personId: string): Promise<Absence[]>;
17
+ saveAbsence(input: Absence): Promise<void>;
18
+ getPendingItems(personId: string): Promise<PendingItem[]>;
19
+ savePendingItem(input: PendingItem): Promise<void>;
20
+ /** Marca resolvida, ou desmarca. Um ato, não uma edição de texto. */
21
+ resolvePendingItem(id: string, resolved: boolean): Promise<void>;
22
+ /** Lê `v_workforce_time_entries` — a batida com a hora que vale. */
23
+ getTimeEntries(query: TimeEntryQuery): Promise<TimeEntry[]>;
24
+ /** Lê `v_workforce_day` — previsto × realizado por pessoa e dia. */
25
+ getWorkDays(query: TimeEntryQuery): Promise<WorkDay[]>;
26
+ /**
27
+ * Grava UMA LINHA em `plg_workforce_time_adjustments`. Nunca um UPDATE na
28
+ * batida: a tabela de batidas é append-only por trigger, e o histórico de
29
+ * correções é o que torna o ponto prova.
30
+ */
31
+ adjustTimeEntry(input: TimeAdjustmentInput): Promise<void>;
32
+ /**
33
+ * URLs assinadas para as fotos das batidas — curtas, e EM LOTE.
34
+ *
35
+ * Assinar é obrigatório: o bucket é privado porque a foto é biometria facial
36
+ * de um funcionário, com hora e coordenada ao lado, e o V1 já a tratava assim.
37
+ *
38
+ * O lote não é otimização prematura. Uma assinatura por foto é uma requisição
39
+ * por LINHA da tabela — trinta dias do Pertinho do Céu são 261 linhas, logo
40
+ * 261 idas ao storage antes de a primeira cara aparecer. Em lote é uma ida por
41
+ * página.
42
+ *
43
+ * A chave do retorno é `bucket + '/' + path`, e uma foto que não pôde ser
44
+ * assinada simplesmente não aparece nele — a tela cai nas iniciais, que é a
45
+ * resposta honesta.
46
+ */
47
+ signPunchPhotos(photos: PunchPhoto[], expiresInSeconds?: number): Promise<Record<string, string>>;
48
+ getPeriods(): Promise<WorkforcePeriod[]>;
49
+ /** RPC `workforce_period_close`. Escrever a linha direto não é permitido. */
50
+ closePeriod(competenceMonth: string, notes?: string): Promise<void>;
51
+ /** RPC `workforce_period_reopen`. O motivo é obrigatório. */
52
+ reopenPeriod(competenceMonth: string, reason: string): Promise<void>;
53
+ getTemplates(): Promise<ScheduleTemplate[]>;
54
+ saveTemplate(input: SaveTemplateInput): Promise<string>;
55
+ deleteTemplate(id: string): Promise<void>;
56
+ saveShift(input: SaveShiftInput): Promise<string>;
57
+ deleteShift(id: string): Promise<void>;
58
+ saveRequirement(input: SaveRequirementInput): Promise<string>;
59
+ deleteRequirement(id: string): Promise<void>;
60
+ getSchedules(query: ScheduleQuery): Promise<DaySchedule[]>;
61
+ /**
62
+ * Cria a escala do dia a partir de um molde, copiando o SNAPSHOT do turno
63
+ * para cada atribuição — é assim que mudar o molde não reescreve o passado.
64
+ */
65
+ createSchedule(input: CreateScheduleInput): Promise<string>;
66
+ /**
67
+ * Publica: marca a escala e materializa cada titular como uma linha de
68
+ * `public.schedules` com `kind = 'work_shift'`, guardando o id em
69
+ * `schedule_row_id`. É a ponte com a agenda, e é o que torna o cruzamento
70
+ * previsto × realizado uma chave em vez de um casamento por nome e hora.
71
+ */
72
+ publishSchedule(scheduleId: string): Promise<void>;
73
+ /** `public.people` com papel de equipe — quem pode ser escalado. */
74
+ getStaff(): Promise<WorkforcePerson[]>;
75
+ /**
76
+ * Opcional: um cluster sem o Financeiro instalado não tem razão para ler, e a
77
+ * tela diz isso em vez de quebrar.
78
+ */
79
+ getPayrollCosts?(query: PayrollCostQuery): Promise<PayrollCostRow[]>;
80
+ }
81
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/data/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import type { EntityDef, PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core';
2
+ import type { EntityLookup } from '@fayz-ai/admin';
3
+ import type { WorkforceDataProvider } from './data/types';
4
+ /**
5
+ * O provider da jornada, resolvido tarde: Supabase quando há cliente, memória
6
+ * quando não há. Público porque um app que queira compartilhar UM provider
7
+ * entre o módulo e uma ponte (o totem de ponto, por exemplo) precisa do mesmo.
8
+ */
9
+ export declare function createSafeWorkforceProvider(): WorkforceDataProvider;
10
+ export interface WorkforcePluginLabels {
11
+ pageTitle: string;
12
+ pageSubtitle: string;
13
+ schedules: string;
14
+ templates: string;
15
+ timeEntries: string;
16
+ hr: string;
17
+ periods: string;
18
+ people: string;
19
+ payrollCosts: string;
20
+ }
21
+ export interface WorkforcePluginOptions {
22
+ /** Onde a sub-navegação do módulo mora. Padrão: o que a shell decidir. */
23
+ moduleNav?: 'rail' | 'tabs' | 'sidebar';
24
+ modules?: {
25
+ schedules?: boolean;
26
+ templates?: boolean;
27
+ timeEntries?: boolean;
28
+ hr?: boolean;
29
+ periods?: boolean;
30
+ people?: boolean;
31
+ payrollCosts?: boolean;
32
+ };
33
+ labels?: Partial<WorkforcePluginLabels>;
34
+ currency?: {
35
+ code?: string;
36
+ locale?: string;
37
+ symbol?: string;
38
+ };
39
+ navPosition?: number;
40
+ navSection?: 'main' | 'secondary';
41
+ scope?: PluginScope;
42
+ verticalId?: VerticalId;
43
+ /** Provider de dados. Padrão: Supabase-ou-memória. */
44
+ dataProvider?: WorkforceDataProvider;
45
+ /**
46
+ * Quanto vale a hora, para a folha mostrar valor.
47
+ *
48
+ * NÃO existe coluna de remuneração no SQL da jornada — nem na batida, nem no
49
+ * turno, nem em `public.people`. Sem esta opção a tela mostra "—" em vez de
50
+ * inventar um número, e o relatório do módulo diz isso.
51
+ */
52
+ hourlyRate?: number;
53
+ /** A entidade de pessoa que a aba "Pessoas & Documentos" edita. Padrão: o
54
+ * recorte de `people` com papel de equipe (ver views/PeopleView). */
55
+ staffEntity?: EntityDef;
56
+ /** Busca de pessoa, quando o app quiser oferecer uma para escalar. */
57
+ staffLookup?: EntityLookup;
58
+ /**
59
+ * Onde mora a página de UMA pessoa da equipe neste app — `'/staff'`.
60
+ *
61
+ * O nome na lista de Registros de Ponto é um `PersonLink`, e ele resolve a
62
+ * rota pelo registro compartilhado de caminhos. O padrão daquele registro é
63
+ * `/registry/staff`, que é herança do app veterinário: num app que monta a
64
+ * equipe em `/staff` o nome viraria um link para uma rota inexistente — pior
65
+ * que texto puro, porque parece clicável e não é.
66
+ *
67
+ * O plugin não adivinha: quem sabe onde a página está é o app que a montou.
68
+ * Sem esta opção o registro fica como está, e o link cai onde o padrão
69
+ * aponta.
70
+ */
71
+ staffRoute?: string;
72
+ /**
73
+ * Qual link interno ESTE app cobra, como `id do item de nav → id da feature`.
74
+ * Vazio por padrão: empacotamento é decisão do app, não do plugin.
75
+ */
76
+ navFeatureMap?: Record<string, string>;
77
+ }
78
+ /**
79
+ * Preset OPCIONAL de ids de feature para as subtelas — uma convenção oferecida
80
+ * aos apps, NÃO um padrão. Nada aqui vale sem `options.navFeatureMap`.
81
+ */
82
+ export declare const WORKFORCE_NAV_FEATURES: {
83
+ readonly schedules: "wf_schedules";
84
+ readonly templates: "wf_templates";
85
+ readonly 'time-entries': "wf_time_entries";
86
+ readonly hr: "wf_hr";
87
+ readonly periods: "wf_periods";
88
+ readonly people: "wf_people";
89
+ readonly 'payroll-costs': "wf_payroll_costs";
90
+ };
91
+ export declare function createWorkforcePlugin(options?: WorkforcePluginOptions): PluginManifest;
92
+ export type { WorkforceDataProvider } from './data/types';
93
+ export type { ResolvedWorkforceConfig } from './context';
94
+ export type { TimeEntry, TimeEntryKind, TimeEntryQuery, TimeAdjustmentAction, TimeAdjustmentInput, WorkDay, WorkforcePeriod, ScheduleTemplate, ScheduleShift, ScheduleRequirement, DaySchedule, ScheduleAssignment, ScheduleQuery, CreateScheduleInput, WorkforcePerson, PayrollCostRow, PayrollCostQuery, } from './types';
95
+ export { createMockWorkforceProvider } from './data/mock';
96
+ export { createSupabaseWorkforceProvider, WORK_SHIFT_KIND } from './data/supabase';
97
+ export { DEFAULT_STAFF_ENTITY } from './views/PeopleView';
98
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAEvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAIlD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AAMzD;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,qBAAqB,CAKnE;AAMD,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACvC,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,EAAE,CAAC,EAAE,OAAO,CAAA;QACZ,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,YAAY,CAAC,EAAE,OAAO,CAAA;KACvB,CAAA;IACD,MAAM,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAA;IACvC,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;IACjC,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IAEvB,sDAAsD;IACtD,YAAY,CAAC,EAAE,qBAAqB,CAAA;IAEpC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;0EACsE;IACtE,WAAW,CAAC,EAAE,SAAS,CAAA;IAEvB,sEAAsE;IACtE,WAAW,CAAC,EAAE,YAAY,CAAA;IAE1B;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACvC;AAoBD;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;CAQQ,CAAA;AA4B3C,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,cAAc,CA2HtF;AAMD,YAAY,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACzD,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AACxD,YAAY,EACV,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,oBAAoB,EAAE,mBAAmB,EACnF,OAAO,EAAE,eAAe,EACxB,gBAAgB,EAAE,aAAa,EAAE,mBAAmB,EACpD,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,mBAAmB,EACnE,eAAe,EAAE,cAAc,EAAE,gBAAgB,GAClD,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,EAAE,+BAA+B,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA"}