*Desafio M5 - Projeto de aplicativo de cobranças* **O que o usuário pode fazer ?** - Cadastrar-se - Logar-se - Recuperar senha - Ver cobranças pagas (Dados estáticos) - Ver cobranças vencidas (Dados estáticos) - Ver cobranças previstas (Dados estáticos) - Ver clientes inadimplentes (Dados estáticos) - Ver clientes em dia (Dados estáticos) - Editar cadastro - Listar clientes - Adicionar clientes - Adicionar cobranças para os clientes **O que o usuário não pode fazer ? (Nessa sprint)** - Cadastrar cobrança - Editar cobrança - Ver todas as cobranças - Ver todos clientes em dia - Ver todos clientes inadimplentes <h1>Sprint 1</h1> ***Endpoints*** **Cadastro - POST** ***URL:*** /cadastro ***Método:*** POST ***Dados de entrada*** ``` {"name":"Jose Silva", "email":"josesilva@email.com" "password":"hashSenha"} ``` ***Dados de saída*** *Sucesso* ``` {"Usuário cadastrado com sucesso"} ``` *Falha* ``` {"message":"email já cadastrado"} ``` *Validações / Regras de negócio* - Verficar se existe algum campo não informado - Verificar se o email informado não é igual ao de outro cliente. - Verificar se as senhas coincidem - Usar criptografia para envio da senha(hash) **Login - POST** ***URL:*** /login ***Método:*** POST *Dados de entrada* ``` { "email": "josesilva@email.com", "password": "hashSenha" } ``` *Dados de saída* *Sucesso* ``` { "user_id": "1", "name":"Jose Silva", "email":"josesilva@email.com", "token":"c0ce7f40-e12b-393e-bb7c-5ad1fc3c9841" } ``` *Falha* ``` {"message":"Usuário não existe"} ``` ``` {"message":"Senha incorreta"} ``` *Validações / Regras de negócio* - Verficar se existe algum campo não informado - Usar criptografia para envio da senha(hash) **Usuário - GET** ***Necessário autenticação*** ***Token no header da requisição*** ***URL:*** /usuario ***Método:*** GET *Dados de entrada* ```json {"token":"c0ce7f40-e12b-393e-bb7c-5ad1fc3c9841", "user_id":"1"} ``` *Dados de saída* *Sucesso* ```json {"name":"Jose Silva", "email":"josesilva@email.com"} ``` *Falha* {"mensagem":"O usuário informado não existe"} *Validações / Regras de negócio* - Verificar se o usuário informado existe no banco de dados - O token tem que ser passado no front no headers athorization **Usuário - PUT** ***Necessário autenticação*** ***Token no header da requisição*** ***URL:*** /usuario ***Método:*** PUT *Dados de entrada* ```json { "name": "Jose Silva Lima", "email": "josesl@email.com", "password": "hashSenha" } ``` *Falha* ```json {"message":"email já cadastrado"} ``` *Validações / Regras de negócio* -Verificar se o email informado não é igual ao de outro usuario. **Cadastro cliente - POST** ***Necessário autenticação*** ***Token no header da requisição*** ***URL:*** /clients ***Método:*** POST *Dados de entrada* ```json { "name": "Bruna", "email": "bruna.silahty@hotmail.com", "cpf": "1234567890", "phone_client": "7184958568", "cep": "52041550", "address": "Rua sem nome", "complement": "Apatarmento do lado esquerdo", "neighborhood": "Fim", "city": "Marte", "state": "sr" } ``` *Dados de saída* *Sucesso* ```json {"mensagem": "Usuário cadastrado com sucesso"} ``` *Falha* ```json {"message":"email já cadastrado"} ``` ```json {"message":"Telefone cadastrado por outro cliente"} ``` *Validações / Regras de negócio* -Verificar se o email informado não é igual ao de outro cliente. -Verificar se o telefone informado não é igual ao de outro cliente <h1>Sprint 2</h1> <h2>Listagem de clientes - GET</h2> Na posição de usuário do sistema, desejo visualizar uma listagem com todos os clientes cadastrados. **Obs:** O dados status tem que ser criado a parti da pesquisa do BD de charges e se houver alguma cobrança vencida (com status pendente e com data de vencimento anterior a data atual), deverá exibir true, caso contrário, deverá exibir false. ***Necessaário autenticação*** ***Token no header da requisição*** ***URL:*** /listclients ***Método:*** GET *Dados de saída* ```jsonl { "clientsWithStatus": [ { "id": 1, "name_client": "Bruna carla", "email_client": "bruna.silahty@hotmail.com", "cpf_client": "1234567890 ", "phone_client": "7184958568", "status": true }, { "id": 2, "name_client": "tayanna kelly", "email_client": "amorim.tayanna@gmail.com", "cpf_client": "10278487345", "phone_client": "546373838", "status": false }, { "id": 3, "name_client": "Thaysa Ketlen", "email_client": "thaysa.ketlen@hotmail.com", "cpf_client": "10290999 ", "phone_client": "85678900", "status": false } ], "totalPages": 1 } ``` <h2>Detalhamento do Cliente- GET</h2> Na posição de usuário do sistema, desejo visualizar todos os detalhes de um cliente cadastrado, a fim de consultar seus dados e suas respectivas cobranças. ***Necessaário autenticação*** ***Token no header da requisição*** ***URL:*** /detailclient/:id ***Método:*** GET *Dados de saída* ```json { "name_client": "Jose Silva", "cpf_client": "88051533461", "email_client": "josesilva@email.com", "phone_client": "1234567890", "address_complete": { "address": "rua sem nome", "cep": "52041550", "complement": "Grand Line", "neighborhood": "Barra de Jangada", "city": "São Paulo", "state": "São Paulo" }, "charges": [ { "id_charges": "1", "description ": "lorem ipsum, lorem ipsum, lorem ipsum, lorem ipsum", "due_date": "12/05/23", "amount": "5000", "status": true }, { "id_charges": "2", "description ": "lorem ipsum, lorem ipsum, lorem ipsum, lorem ipsum", "due_date": "12/05/23", "amount": "3000", "status": false } ] } ``` <h2>Atualização do cliente - PUT</h2> Na posição de usuário do sistema, desejo atualizar os dados de um cliente cadastrado. ***Necessaário autenticação*** ***Token no header da requisição*** ***URL:***/clients/:identification ***Método:*** PUT - Campos Obrigatórios - nome - email - cpf - phone *Dados de entrada* ```json { "name_client": "Bruna carla", "email_client": "bruna.silahty@hotmail.com", "cpf_client": "1234567890", "phone_client": "7184958568", "cep": "52041550", "address": "Rua sem nome", "complement": "Apatarmento do lado esquerdo", "neighborhood": "Fim", "city": "Marte", "state": "sr" } ``` *Dados de saída* *Sucesso* ```json { "id": 22, "id_user": 34, "name_client": "Wuso Pedro", "email_client": "jose.silahty@hotmail.com", "cpf_client": "01790525093", "phone_client": "81983498923", "cep": "65095205", "address": "Rua Doze", "complement": "Apatarmento do lado esquerdo", "neighborhood": "Tibiri", "city": "São Luís", "state": "PE" } ``` *Falha* ```json {"message":"Campos obrigatórios passados em branco"} ``` ```json {"message":"email já existe"} ``` *Mensagem de Erro em caso de:* - Campos obrigatórios passados em branco - E-mail informado for diferente do cliente em questão e já existir cadastrado para outro cliente. - CPF informado for diferente do cliente em questão e já existir cadastrado para outro cliente - Após realizado a atualização com sucesso o usuário deverá receber uma mensagem de confirmação <h2>Cadastro de cobranças - POST</h2> Na posição de usuário do sistema, desejo cadastrar cobranças para um cliente, afim de acessar suas informações no futuro. ***Necessário autenticação*** ***Token no header da requisição*** ***URL:*** /charges ***Método:*** POST - Todos os campos são obrigatórios - O id_customer é o do cliente em questão e não do usuário logado *Dados de entrada* ```json { "id_customer": "2", "name_client": "Heberty", "description": "Calça Jeans", "status": true, "amount": 26000, "due_date": "2023-10-01" } ``` *Dados de saída* ```json { "id_charges": 5, "id_customer": 2, "name_client": "Heberty", "amount": 26000, "due_date": "2023-10-01T03:00:00.000Z", "registration_date": "2023-09-23T03:00:00.000Z", "description": "Calça Jeans", "status": true } ``` *Observações:* - A validação para saber se está vencida pode ser feita no front - O valor da cobrança também deve ser persistida no banco como centavos *Mensagem de Erro em caso de:* - Campos obrigatórios em branco <h2>Listagem de cobranças - GET</h2> Na posição de usuário do sistema, desejo visualizar uma listagem com todos as cobranças cadastradas. ***Necessário autenticação*** ***Token no header da requisição*** ***URL:*** /cobranca ***Método:*** GET *Dados de saída* ```json { "id": "4234234", "id_customer": "id que vem do req.user", "name_client": "Juliana Paiva", "description": "lorem ipsum", "cpf_client": "1234567890", "due_date": "1695168000", "amount": "20000", "status_charge": true || false } ``` - A cobrança recebe Vencido (Caso o status seja pendente e a data de vencimento for anterior a data atual) <h1>Sprint 3</h1> <h2>Edição de Cobrança - PUT</h2> ### `Na posição de usuário do sistema, desejo atualizar os dados de uma cobrança cadastrada.` ***Necessário autenticação*** ***Token no header da requisição*** ***URL:*** /updatecharge ***Método:*** PUT - Campos Obrigatórios - Descrição (<b>\*</b>) - Status (<b>\*</b>) - Valor (<b>\*</b>) - Vencimento (<b>\*</b>) *Dados de entrada* ```json { "id_charges": 2, "name_client": "Heberty", "description": "Calça Jeans", "status": true, "amount": 26000, "due_date": "2023-10-01" } ``` *Dados de saída* ```json { "id_charges": 2, "name_client": "Heberty", "description": "Calça Jeans", "status": true, "amount": 26000, "due_date": "2023-10-01", "registration_date": "2023-09-27" } ``` *Mensagem de Erro em caso de:* - Campos obrigatórios passados em branco - Após realizado a atualização com sucesso o usuário deverá receber uma mensagem de confirmação (FRONT-END) <h2>Exclusão de cobranças - DELETE</h2> #### `Na posição de usuário do sistema, desejo excluir uma cobrança cadastrada.` ***Necessário autenticação*** ***Token no header da requisição*** ***URL:*** /deletecharge:idChages ***Método:*** DELETE - Só poderá excluir a cobrança, se: - A cobrança estiver com status <b>pendente</b> - A data de vencimento for <b>igual</b> ou <b>posterior a data atual</b> - Cobranças com status <b>"pagas"</b>, não poderão ser apagadas - OBS: Essa validações podem ser feitas no front e o back só receberia o id da cobrança que seria excluída. *Dados de saída* ```json { mensage: "Cobrança deletada com sucesso" } ``` <h2>[Cobranças/Clientes] Busca e ordenação</h2> #### `Na posição de usuário do sistema, desejo buscar cobranças e clientes a partir de suas respectivas listagens.` <h4> Listagem Cobrança: </h4> - Na listagem de cobranças deverá possibilitar a <b>ordenação dos registros</b> pelo <b>nome do cliente</b> ou <b>ID da Cobrança</b> (front-end) - Campo de busca que permitirá buscar cobranças pelos seguintes campos: - Nome do cliente - Id da cobrança - OBS: esse filtro pode ser adicionado como uma verificação na rota já criada de listagem de cobranças - Ex: Por exemplo, se na requisição existir um parâmetro de query que seja diferente de undefined para campos como id_charges ou name_client, a API realizará uma pesquisa correspondente com base no parâmetro fornecido. ***Lembre-se de que a pesquisa será sensível a maiúsculas e minúsculas, caso não seja definido nenhum critério de busca.*** ```javascript const { id_charges, name_client, page } = req.query; if (nome !== undefined) { try { const chargesList = // aqui você pode pegar o mesmo objeto de pequisa para o Bd para listar todas as cobranças, mas tirando a paginação const chargeFilter = chargesList.filter( (charge) => charge.name_client === nome ); return res.json(chargeFilter); } catch (error) { res.status(500).json({ mensagem: "Erro interno do servidor", detalhes: error.message, }); } } ``` <h4> Listagem Clientes: </h4> - Nas <b>listagens de clientes</b> deverá possibilitar a <b>ordenação</b> dos registros pelo <b>nome</b> (FRONT-END) - Campo de busca que permitirá bucasr Clientes pelos seguintes campos: - Nome do cliente - CPF do cliente - E-mail do cliente ```javascript const { name, email, cpf, page } = req.query; if (name !== undefined) { try { const clientsList = // aqui você pode pegar o mesmo objeto de pequisa para o Bd para listar todas as cobranças, mas tirando a paginação const clientsFilter = clientsFilter.filter( (client) => client.name_client === name ); return res.json(chargeFilter); } catch (error) { res.status(500).json({ mensagem: "Erro interno do servidor", detalhes: error.message, }); } } ``` - Em caso de não retornar <b>nenhum resultado</b> uma mensagem adequada deverá ser exibida.(FRONT-END) <h2> [Cobranças/Clientes] Botão "ver todos" - Home </h2> #### `Na posição de usuário do sistema, desejo visualizar um relatório personalizado de cobranças e clientes.` ***Necessário autenticação*** ***Token no header da requisição*** ***URL:*** /custom-report ***Método:*** GET - Nos dados de saída deverá retornar dois objetos, sendo eles - Objeto que contenha informação sobre todas as ***cobranças*** agrupadas em tres categorias - ***paid*** - se a cobrança possuir o ```status = false``` - ***preview*** - se o ```status = true``` e ```due_date > ``` que a data atual - ***Overdue*** - ```status = true``` e ``due_date < ``` que data atual *xemplo de objeto de Charges* ```json { "paid": [ { "amount": 6500 }, { "total": 7 }, { "charges": [ { "id_charges": 1, "name_client": "Bruna carla", "amount": 2000 }, { "id_charges": 2, "name_client": "tayanna kelly", "amount": 4500 } ] } ], "preview": [ { "amount": 24000 }, { "total": 8 }, { "charges": [ { "id_charges": 1, "name_client": "Bruna carla", "amount": 2000 }, { "id_charges": 2, "name_client": "tayanna kelly", "amount": 4500 } ] } ], "overdue": [ { "amount": 24000 }, { "total": 5 }, { "id_charges": 1, "name_client": "Bruna carla", "amount": 2000 }, { "id_charges": 2, "name_client": "tayanna kelly", "amount": 4500 } ], } ``` - Objeto que contenha informação sobre todas as ***clientes*** agrupadas pelo seu status - ***defaulters*** - se o cliente possuir o ```status = true``` - - ***compliant*** - se o cliente possuir o ```status = false``` *Exemplo de objeto de Clients* ```json { "defaulters": [ { "total": 4 }, { "clients": [ { "id": 16, "name_client": "Tayanna", "cpf_client": "123146456" }, { "id": 17, "name_client": "Oriana", "cpf_client": "123145353" } ] } ], "compliant": [ { "total": 6 }, { "clients": [ { "id": 17, "name_client": "Oriana", "cpf_client": "123145353" }, { "id": 17, "name_client": "Oriana", "cpf_client": "123145353" } ] } ] } ``` *Dados saída* ```json { "paid": [ { "amount": 6500 }, { "total": 7 }, { "charges": [ { "id_charges": 1, "name_client": "Bruna carla", "amount": 2000 }, { "id_charges": 2, "name_client": "tayanna kelly", "amount": 4500 } ] } ], "preview": [ { "amount": 24000 }, { "total": 8 }, { "charges": [ { "id_charges": 1, "name_client": "Bruna carla", "amount": 2000 }, { "id_charges": 2, "name_client": "tayanna kelly", "amount": 4500 } ] } ], "Overdue": [ { "amount": 24000 }, { "total": 5 }, { "id_charges": 1, "name_client": "Bruna carla", "amount": 2000 }, { "id_charges": 2, "name_client": "tayanna kelly", "amount": 4500 } ], "defaulters": [ { "total": 4 }, { "clients": [ { "id": 16, "name_client": "Tayanna", "cpf_client": "123146456" }, { "id": 17, "name_client": "Oriana", "cpf_client": "123145353" } ] } ], "compliant": [ { "total": 6 }, { "clients": [ { "id": 17, "name_client": "Oriana", "cpf_client": "123145353" }, { "id": 17, "name_client": "Oriana", "cpf_client": "123145353" } ] } ] } ``` ***OBS: Adicionar uma ordenação do maior para o menor id, e só precisa retornar para o front os 4 primeiros resultados, tanto do objeto de charge como do de clients***