Repertórios
Gerado pelo Writer (Reversa) em 2026-05-11
doc_level: detalhado | Granularidade: híbrida (módulo + casos de uso)
Visão Geral
Módulo responsável pela criação, edição, reordenação, compartilhamento, importação e duplicação de repertórios musicais. Um repertório é uma lista de músicas (ou termos livres) organizada pelo usuário, com metadados de data e dia litúrgico. É o módulo com maior complexidade de fluxo do app, envolvendo integração com auth, API remota, geração de PDF e compartilhamento nativo.
Responsabilidades
- Criar e editar repertórios localmente (CRUD SQLite)
- Gerenciar itens do repertório (adicionar, remover, editar
momento e tonalidade)
- Compartilhar um repertório via API Canta.app e dialog nativo do SO (WhatsApp, etc.)
- Importar um repertório de outra conta via link/slug
- Duplicar um repertório existente
- Gerar folheto PDF online a partir de um repertório
- Proteger repertórios padrão ("Músicas favoritas" e "Visto recentemente") contra exclusão
Regras de Negócio
- Título do repertório é limitado a 50 caracteres (CHECK SQL, migration v8) 🟢
termo de um item de repertório é limitado a 300 caracteres (CHECK SQL, migration v8) 🟢
- Deleção de repertório é soft-delete —
data_exclusao é preenchida; o registro permanece no banco 🟢
- Repertórios com
tipo_repertorio = 1 ("Músicas favoritas" id=1 e "Visto recentemente" id=2) não podem ser excluídos 🟢
- A ordem dos itens é armazenada como array JSON
ordem_musicas no registro do repertório, não pela posição na tabela item_repertorio 🟢
- Reordenação de itens está temporariamente desabilitada na UI (DT-08) 🟢
momento e tonalidade têm espaços nas extremidades automaticamente removidos ao salvar 🟢
momento e tonalidade têm sugestões automáticas baseadas no histórico de uso do usuário 🟡
- Compartilhar requer autenticação Google; a mensagem gerada é formatada em Markdown compatível com WhatsApp 🟢
- Ao duplicar um repertório, o
slug fica undefined até o usuário compartilhar novamente 🟢
slug.referencia guarda quem originou o repertório; slug.corrente reflete a versão após último compartilhamento 🟢
- Geração de folheto via
GerarFolhetoComSlugStrategy requer autenticação; GerarFolhetoBase64Strategy não requer 🟢
- Um item de repertório pode ser uma música do catálogo (
id_musica) ou um texto livre (termo), mas não ambos 🟢
Requisitos Funcionais
| ID |
Requisito |
Prioridade |
Critério de Aceite |
| RF-01 |
Listar todos os repertórios do usuário (excluídos ficam ocultos) |
Must |
Repertórios com data_exclusao não aparecem na lista |
| RF-02 |
Criar um novo repertório com título obrigatório |
Must |
Repertório é criado com Timestamp.now e aparece na lista; título vazio deve ser rejeitado |
| RF-03 |
Editar o título de um repertório |
Must |
Novo título (≤ 50 chars) é persistido; erro se exceder |
| RF-04 |
Excluir um repertório (soft-delete) |
Must |
data_exclusao é preenchida; repertórios padrão (id=1, id=2) não podem ser excluídos |
| RF-05 |
Adicionar música do catálogo a um repertório |
Must |
Música aparece na lista de itens; ordem_musicas é atualizado |
| RF-06 |
Adicionar texto livre (termo) a um repertório |
Should |
Termo (≤ 300 chars) é salvo como ItemRepertorio sem id_musica |
| RF-07 |
Remover item de um repertório |
Must |
Item é deletado do banco; ordem_musicas é atualizado |
| RF-08 |
Editar momento e tonalidade de um item de repertório |
Should |
Valores são salvos sem espaços nas extremidades; sugestões de últimos usados são exibidas |
| RF-09 |
Compartilhar um repertório via API + dialog nativo |
Must |
Autenticação ocorre se necessária; mensagem Markdown é gerada e o dialog nativo de compartilhamento abre |
| RF-10 |
Importar repertório de outra conta via link/slug |
Should |
Itens são copiados localmente; slug.referencia é preservado |
| RF-11 |
Duplicar repertório local |
Should |
Nova cópia é criada sem slug; métricas de duplicação são registradas |
| RF-12 |
Gerar folheto PDF do repertório (online) |
Should |
Folheto é aberto em livreto.canta.app via browser; requer autenticação (estratégia com slug) ou não (estratégia Base64) |
| RF-13 |
Exibir metadados de dia litúrgico no compartilhamento |
Could |
Data em formato longo pt-BR e nome do dia litúrgico aparecem na mensagem gerada |
| RF-14 |
Exibir índice e sigla do livro ao lado da música no repertório compartilhado |
Should |
Sigla + índice do livro aparecem na mensagem de compartilhamento quando disponíveis |
Requisitos Não Funcionais
| Tipo |
Requisito inferido |
Evidência no código |
Confiança |
| Integridade |
Títulos ≤ 50 chars e termos ≤ 300 chars são garantidos por CHECK SQL |
Migration v8, schema item_repertorio |
🟢 |
| Disponibilidade |
Criação e edição de repertórios funcionam offline; compartilhamento requer internet |
RepertoriosRepository (local) vs CompartilharService (API) |
🟢 |
| Segurança |
Compartilhamento exige Bearer JWT obtido via Google OAuth com PKCE |
CompartilharService.getToken → Auth.autenticar |
🟢 |
| Performance |
ordem_musicas como JSON array evita N queries de reordenação |
Repertorio.ordem_musicas |
🟢 |
| Rastreabilidade |
Eventos de criação, duplicação, compartilhamento e folheto são monitorados via Sentry |
Metricas — repertorio_criado, repertorio_duplicado etc |
🟢 |
Critérios de Aceitação
Dado que o usuário está na tela de repertórios
Quando ele cria um repertório com título "Missa de Domingo"
Então o repertório aparece na lista e contém `data_exclusao = null`
Dado que o usuário tenta excluir o repertório "Músicas favoritas"
Quando a ação de exclusão é acionada
Então o sistema rejeita a operação (tipo_repertorio = 1 é protegido)
Dado que o usuário edita o título de um repertório para uma string com 51 caracteres
Quando a validação é executada
Então o título é rejeitado com mensagem de erro e o banco não é atualizado
Dado que o usuário adiciona uma música a um repertório
Quando a adição é confirmada
Então o `id_musica` aparece no array `ordem_musicas` e um `ItemRepertorio` é criado no banco
Dado que o usuário quer compartilhar um repertório sem estar logado
Quando o botão de compartilhar é acionado
Então o fluxo OAuth Google é iniciado antes de prosseguir com o compartilhamento
Dado que o usuário compartilha um repertório com sucesso
Quando a API retorna `conta.slug` e `slug`
Então `slug.corrente` é atualizado localmente e o dialog nativo de compartilhamento abre com a mensagem Markdown
Dado que o usuário acessa um item de repertório e edita a tonalidade para " Lá menor "
Quando o valor é salvo
Então o valor persistido é "Lá menor" (espaços removidos)
Dado que o usuário duplica um repertório
Quando a duplicação é concluída
Então o novo repertório não tem `slug` e a métrica `repertorio_duplicado` é registrada no Sentry
Prioridade (MoSCoW)
| Requisito |
MoSCoW |
Justificativa |
| Listar repertórios (RF-01) |
Must |
Ponto de entrada do módulo |
| Criar repertório (RF-02) |
Must |
Funcionalidade básica do módulo |
| Editar título (RF-03) |
Must |
Corrigir erros de nomenclatura é essencial |
| Excluir repertório soft-delete (RF-04) |
Must |
Gestão do ciclo de vida dos repertórios |
| Adicionar música (RF-05) |
Must |
Sem isso o módulo não tem valor |
| Remover item (RF-07) |
Must |
Sem remoção, o módulo seria inutilizável em longo prazo |
| Compartilhar repertório (RF-09) |
Must |
Feature principal de valor do módulo; requer auth |
| Editar momento/tonalidade (RF-08) |
Should |
Enriquece a experiência mas não bloqueia uso básico |
| Adicionar texto livre (RF-06) |
Should |
Útil para itens não-musicais (ex.: "Abertura") mas não crítico |
| Duplicar repertório (RF-11) |
Should |
Poupa tempo, não é essencial |
| Gerar folheto (RF-12) |
Should |
Recurso avançado de alto valor para grupos litúrgicos |
| Importar repertório (RF-10) |
Should |
Habilita colaboração, mas requer API ativa |
| Metadados litúrgicos no compartilhamento (RF-13) |
Could |
Enriquece a mensagem, mas compartilhamento funciona sem isso |
| Índice/sigla do livro no compartilhamento (RF-14) |
Should |
Importante para usuários com livros físicos em mãos |
Rastreabilidade de Código
| Arquivo |
Função / Classe |
Cobertura |
src/model/repertorio/Repertorio.ts |
Repertorio, ItemRepertorio, RepertorioSlug |
🟢 |
src/repository/repertorios/RepertoriosRepository.ts |
findAllBy, createRepertorio, deactivateRepertorio |
🟢 |
src/store/Repertorios/ |
Thunks Redux, reducer EntityAdapter |
🟢 |
src/store/ItensRepertorio/ |
Estado de itens em edição ativa |
🟢 |
src/service/RepertorioService.ts |
gerarMensagemCompartilhamento |
🟢 |
src/service/CompartilharService.ts |
repertorio, getToken |
🟢 |
src/service/FolhetoService.ts |
GerarFolhetoComSlugStrategy, GerarFolhetoBase64Strategy |
🟢 |