From b3b6544ca89b6ebac0db2c0ace340f050d9cc9ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Geraldo=20D=2E=20F?= Date: Sat, 11 May 2024 04:19:06 -0300 Subject: [PATCH 01/12] merge: develop in main (#56) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(shelter-supply): add quantity property * feat(shelter-supply): show quantity property at query results * fix: removed unintended filter * feat: improve readme file * Bug fix: added verified field to the query * fix: verified was required on create shelter controller * Fix linter issues * feat(shelter-supply): set quantity to null if priority is UnderControl * refact: index search * fix: fixed shelter OR and AND conditions * fix: donation tags * fix: parse tag response in shelter index * fix: qtd of shelter supplies tagged * fix: migration issue * feat: update many supplies * feat: created admin user role * Fix/develop bugs (#54) * feat: update many supplies * feat: created admin user role * README.md 2.0 (#52) Melhorias incluem a adição de emojis para destacar tecnologias e endpoints, reorganização do texto para melhor legibilidade e clareza, além de ajustes na formatação para uma apresentação visual mais atrativa. * Add license (#50) Closes #44. --------- Co-authored-by: Jhonatan David <82552187+jotahdavid@users.noreply.github.com> Co-authored-by: MatheusDubin Co-authored-by: Lipe Co-authored-by: Gustavo Clemente Co-authored-by: kelvinsb Co-authored-by: Tatiane Co-authored-by: AlbuquerqueRafael Co-authored-by: Arthur <40851238+4rthuurr@users.noreply.github.com> Co-authored-by: Giovanni Bassi <334958+giggio@users.noreply.github.com> --- .env.example | 2 +- .env.local | 1 + .eslintrc.js | 6 + LICENSE | 21 + README.md | 117 +++-- docker-compose.dev.yml | 2 +- docs/sos-rs.insomnia.json | 1 + package-lock.json | 135 ++++-- package.json | 6 +- prisma/dev_dump.sql | 410 ++++++++++++++++++ .../migrations/20240509235041_/migration.sql | 2 + .../migrations/20240510225124_/migration.sql | 2 + .../migrations/20240511054108_/migration.sql | 2 + prisma/schema.prisma | 3 + src/decorators/index.ts | 3 - src/decorators/search-query/index.ts | 3 - .../search-query/search-query.decorator.ts | 77 ---- src/decorators/search-query/types.ts | 55 --- src/guards/admin.guard.ts | 20 + src/guards/distribution-center.guard.ts | 23 + src/guards/staff.guard.ts | 5 +- src/guards/user.guard.ts | 4 +- src/prisma/hooks/shelter/index.ts | 0 src/prisma/hooks/shelter/shelter-hooks.ts | 0 src/prisma/hooks/user/index.ts | 0 src/prisma/hooks/user/user-hooks.ts | 0 .../shelter-managers.controller.spec.ts | 4 +- .../shelter-managers.controller.ts | 4 +- .../shelter-supply.controller.ts | 21 + src/shelter-supply/shelter-supply.service.ts | 33 +- src/shelter-supply/types.ts | 9 + src/shelter/ShelterSearch.ts | 210 +++++++++ src/shelter/shelter.controller.ts | 23 +- src/shelter/shelter.service.ts | 261 +++-------- src/shelter/types.ts | 76 ---- src/shelter/types/search.types.ts | 26 ++ src/shelter/types/types.ts | 49 +++ .../supply-categories.controller.spec.ts | 4 +- .../supply-categories.controller.ts | 6 +- src/types.ts | 14 + src/users/users.controller.ts | 6 +- src/utils/index.ts | 4 - src/utils/utils.ts | 67 --- 43 files changed, 1112 insertions(+), 605 deletions(-) create mode 100644 LICENSE create mode 100644 docs/sos-rs.insomnia.json create mode 100644 prisma/dev_dump.sql create mode 100644 prisma/migrations/20240509235041_/migration.sql create mode 100644 prisma/migrations/20240510225124_/migration.sql create mode 100644 prisma/migrations/20240511054108_/migration.sql delete mode 100644 src/decorators/index.ts delete mode 100644 src/decorators/search-query/index.ts delete mode 100644 src/decorators/search-query/search-query.decorator.ts delete mode 100644 src/decorators/search-query/types.ts create mode 100644 src/guards/admin.guard.ts create mode 100644 src/guards/distribution-center.guard.ts create mode 100644 src/prisma/hooks/shelter/index.ts create mode 100644 src/prisma/hooks/shelter/shelter-hooks.ts create mode 100644 src/prisma/hooks/user/index.ts create mode 100644 src/prisma/hooks/user/user-hooks.ts create mode 100644 src/shelter/ShelterSearch.ts delete mode 100644 src/shelter/types.ts create mode 100644 src/shelter/types/search.types.ts create mode 100644 src/shelter/types/types.ts create mode 100644 src/types.ts diff --git a/.env.example b/.env.example index 29781499..aedd7c2d 100644 --- a/.env.example +++ b/.env.example @@ -5,7 +5,7 @@ DB_PORT= DB_USER= DB_PASSWORD= DB_DATABASE_NAME= -DATABASE_URL="postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE_NAME}?schema=public&sslmode=require" +DATABASE_URL="postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE_NAME}?schema=public" SECRET_KEY= HOST=::0.0.0.0 diff --git a/.env.local b/.env.local index e42d35b0..9cd74618 100644 --- a/.env.local +++ b/.env.local @@ -6,6 +6,7 @@ DB_DATABASE_NAME=sos_rs DB_USER=root DB_PASSWORD=root DATABASE_URL="postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE_NAME}?schema=public" + SECRET_KEY=batata HOST=::0.0.0.0 diff --git a/.eslintrc.js b/.eslintrc.js index 259de13c..d8bc3457 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,5 +21,11 @@ module.exports = { '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'off', + "prettier/prettier": [ + "error", + { + "endOfLine": "auto" + } + ] }, }; diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..c87cbc15 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 SOS-RS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 04551c7f..6a231353 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,101 @@ -# README para o Backend do App de Ajuda em Enchentes +# 🌊 Backend para App de Ajuda em Enchentes 🌊 -Este repositório contém o backend de um aplicativo desenvolvido para organizar e distribuir suprimentos, bem como coordenar voluntários durante os alagamentos no Rio Grande do Sul. O backend fornece APIs para autenticação de usuários, gerenciamento de abrigos e suprimentos, entre outros. +Este repositório contém o backend de um aplicativo projetado para ajudar na organização e distribuição de suprimentos, bem como na coordenação de voluntários durante enchentes no Rio Grande do Sul. Ele fornece APIs essenciais para a autenticação de usuários, gerenciamento de abrigos e suprimentos, e muito mais. -## Sobre o Projeto +## 🛠 Tecnologias Utilizadas -O sistema backend é projetado para ser robusto e escalável, garantindo que possa lidar com o alto volume de acessos durante emergências. Ele opera com diversas APIs que permitem a interação com o frontend e outros serviços potenciais. +- **🟢 Node.js**: Ambiente de execução para JavaScript. +- **🔗 Prisma**: ORM para Node.js e TypeScript, facilitando o gerenciamento do banco de dados. +- **🐳 Docker**: Solução para desenvolvimento e execução de aplicativos em contêineres. +- **🐦 Nest**: Framework de alto desempenho para aplicações web em Node.js. +- **📦 PostgreSQL**: Banco de dados relacional robusto e eficiente. -## Tecnologias Utilizadas +## 🗂 Dump do Banco de Dados -- **Node.js**: Ambiente de execução para JavaScript. -- **Express**: Framework para aplicação web para Node.js. -- **MongoDB**: Banco de dados NoSQL para armazenar dados de forma eficiente. -- **JWT**: Para autenticação segura via tokens. +Para iniciar com dados de exemplo, utilize o dump do banco disponível em `prisma/migration/dev_dump.sql`. Este arquivo pode ser executado após as migrations estarem aplicadas. -## Backlog +Se estiver usando Docker, os comandos para carregar o dump são: -- [ ] **Importar abrigos**: Importar a lista de abrigos e suas necessidades em csv para facilitar integração com outros sistemas. -- [ ] **Criar sistema de notificação**: Notificar em algum canal (whatsapp, discord, telegram) sobre atualizações. +```bash +# Copiar o dump para a pasta temporária do Docker +docker exec -it cp backup.sql POSTGRES_CONTAINER_ID:/tmp/backup.sql +# Importar o dump para o banco +docker exec -i POSTGRES_CONTAINER_ID psql -U root -d DATABASE_NAME -f /tmp/backup.sql +``` -## API Endpoints +## 🐳 Configuração com Docker -### Usuários -- **POST /users** - Cadastrar um novo usuário. -- **PUT /users** - Atualizar um usuário existente. +Para desenvolvedores de frontend que não precisam executar localmente a API e o banco, siga estes passos: -### Sessões -- **POST /sessions** - Criar uma nova sessão de usuário (login). -- **GET /sessions/:sessionId** - Obter detalhes de uma sessão. -- **PUT /sessions/:sessionId** - Atualizar uma sessão específica. +1. Clone o arquivo `.env` de exemplo: + ```bash + cp .env.local .env + ``` -### Abrigos -- **POST /shelters** - Cadastrar um novo abrigo. -- **PUT /shelters/:shelterId** - Atualizar um abrigo existente. -- **GET /shelters** - Listar abrigos. +2. Use o seguinte comando para criar e iniciar o banco via Docker: + ```bash + docker-compose -f docker-compose.dev.yml up + ``` -### Suprimentos -- **POST /supply** - Cadastrar um novo item de suprimento. -- **PUT /supplies/:supplyId** - Atualizar um suprimento. -- **GET /supplies** - Listar suprimentos. +Adicione a porta do serviço de banco no `docker-compose.dev.yml` para acessos externos: -### Categorias de Suprimentos -- **POST /supply-categories** - Cadastrar uma nova categoria de suprimentos. -- **PUT /supply-categories/:categoryId** - Atualizar uma categoria de suprimentos. -- **GET /supply-categories** - Listar categorias de suprimentos. +```yaml +ports: + - '5432:5432' + - '4000:4000' +``` -## Configuração Inicial +## 🚀 Configuração Inicial Local 1. Clone o repositório: ```bash git clone https://github.com/seuusuario/projeto-enchentes-backend.git ``` -2. Entre no diretório do projeto: - ```bash - cd projeto-enchentes-backend - ``` -3. Instale as dependências: +2. Instale as dependências: ```bash - npm install + npm install + npx prisma generate + npx prisma migrate dev + npm run start:dev ``` -4. Inicie o servidor: +3. Inicie o servidor: ```bash npm start ``` - A API estará acessível via `http://localhost:4000`. + A API estará disponível em `http://localhost:4000`. + +## 📡 API Endpoints + +### 🧑‍💻 Usuários + +- **📝 POST /users** - Registra um novo usuário. +- **🔧 PUT /users** - Atualiza um usuário existente. + +### 🚪 Sessões + +- **📝 POST /sessions** - Inicia uma nova sessão de usuário. +- **👀 GET /sessions/:sessionId** - Retorna detalhes de uma sessão. +- **🔧 PUT /sessions/:sessionId** - Atualiza uma sessão. + +### 🏠 Abrigos + +- **📝 POST /shelters** - Registra um novo abrigo. +- **🔧 PUT /shelters/:shelterId** - Atualiza um abrigo. +- **👀 GET /shelters** - Lista abrigos. + +### 📦 Suprimentos + +- **📝 POST /supply** - Registra um novo item de suprimento. +- **🔧 PUT /supplies/:supplyId** - Atualiza um suprimento. +- **👀 GET /supplies** - Lista suprimentos. + +### 🏷️ Categorias de Suprimentos -## Contribuição +- **📝 POST /supply-categories** - Registra uma nova categoria de suprimentos. +- **🔧 PUT /supply-categories/:categoryId** - Atualiza uma categoria. -Contribuições são bem-vindas! Se quiser contribuir, por favor faça um fork do repositório, crie uma branch para suas modificações e depois envie um pull request. +## 🤝 Contribuição +Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas modificações, e envie um pull request. -Sua participação é essencial para ajudarmos a comunidade afetada pelas enchentes no Rio Grande do Sul! +Sua ajuda é crucial para apoiar a comunidade afetada pelas enchentes no Rio Grande do Sul! diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 27e85ddf..3b49bcff 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -24,7 +24,7 @@ services: sh -c "npm install && npx prisma generate && npx prisma migrate dev && - npm run start" + npm run start:dev" db: container_name: sos-rs-db image: postgres diff --git a/docs/sos-rs.insomnia.json b/docs/sos-rs.insomnia.json new file mode 100644 index 00000000..52abb855 --- /dev/null +++ b/docs/sos-rs.insomnia.json @@ -0,0 +1 @@ +{"_type":"export","__export_format":4,"__export_date":"2024-05-08T00:03:58.774Z","__export_source":"insomnia.desktop.app:v2023.5.8","resources":[{"_id":"req_2cec83a23bd8471691471135813f5c97","parentId":"fld_c4388cda095c4c39a43aafa32cefe2b8","modified":1714943748677,"created":1714936267905,"url":"{{ _.url }}/users","name":"Create","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"name\": \"Dinho\",\n\t\"lastName\": \"Duarte\",\n\t\"phone\": \"(31) 996675945\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714464599040,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_c4388cda095c4c39a43aafa32cefe2b8","parentId":"wrk_a61684b639de4828aadbeb27d5fb06c2","modified":1714940272493,"created":1714935778575,"name":"Users","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1714937058452,"_type":"request_group"},{"_id":"wrk_a61684b639de4828aadbeb27d5fb06c2","parentId":null,"modified":1714933336427,"created":1714933336427,"name":"SOS - RS","description":"","scope":"collection","_type":"workspace"},{"_id":"req_e21013e88a174768a98348955f72c132","parentId":"fld_c4388cda095c4c39a43aafa32cefe2b8","modified":1714937581205,"created":1714937048293,"url":"{{ _.url }}/users","name":"Update","description":"","method":"PUT","body":{"mimeType":"application/json","text":"{\n\t\"password\": \"{{ _.password }}\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{"type":"bearer","token":"{{ _.token }}"},"metaSortKey":-1714228783645,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_04870db7df8f4303a36816da619912a3","parentId":"fld_73a709cd6af74d3fbb4405084ec5e8ca","modified":1714948018434,"created":1714937067812,"url":"{{ _.url }}/sessions","name":"Login","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"login\": \"31996675945\",\n\t\"password\": \"{{ _.password }}\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714937071296,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_73a709cd6af74d3fbb4405084ec5e8ca","parentId":"wrk_a61684b639de4828aadbeb27d5fb06c2","modified":1714940270087,"created":1714937057951,"name":"Sessions","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1714937058352,"_type":"request_group"},{"_id":"req_af589f721bf64c3284282ba537363913","parentId":"fld_73a709cd6af74d3fbb4405084ec5e8ca","modified":1714937629632,"created":1714937602570,"url":"{{ _.url }}/sessions","name":"Show","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{"type":"bearer","token":"{{ _.token }}","disabled":false},"metaSortKey":-1714700835168,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_29c7dc3ac6d6499eaee070b9a16df23d","parentId":"fld_66073a1e9d6c415aa0ccf6c5fcfb5d7d","modified":1715027093193,"created":1714938746809,"url":"{{ _.url }}/shelters","name":"Index","description":"","method":"GET","body":{},"parameters":[{"id":"pair_ed301dbad729421a819cf291a5476e0d","name":"search","value":"address:contains:avenida,name:contains:abrigo","description":"","disabled":false},{"id":"pair_ff5b87c85c9f43cf8d949b7dcce34b8a","name":"perPage","value":"2","description":"","disabled":false},{"id":"pair_f1811cb5e0d74429b94592ec3695aa46","name":"page","value":"2","description":"","disabled":false},{"id":"pair_f577dad0d6fb4d90ba7f40a3024cae1c","name":"or","value":"true","description":"","disabled":false},{"id":"pair_612e6829b3ee4689b38269c704c351ba","name":"","value":"","description":""}],"headers":[{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714938160109,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_66073a1e9d6c415aa0ccf6c5fcfb5d7d","parentId":"wrk_a61684b639de4828aadbeb27d5fb06c2","modified":1714940263026,"created":1714937696393,"name":"Shelters","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1714937058152,"_type":"request_group"},{"_id":"req_3a33bb80e5f443e08da29f5402326698","parentId":"fld_66073a1e9d6c415aa0ccf6c5fcfb5d7d","modified":1715007005651,"created":1714971065261,"url":"{{ _.url }}/shelters/62a17be9-a744-42a6-a7dd-8ce2872c56c8","name":"Show","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714938160059,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_e752bbc19fa74ed4a2f98df209429042","parentId":"fld_66073a1e9d6c415aa0ccf6c5fcfb5d7d","modified":1714964882912,"created":1714938158398,"url":"{{ _.url }}/shelters","name":"Create","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"pix\": \"abrigo-test@gmail.com\",\n\t\"name\": \"Abrigo\",\n\t\"address\": \"Porto Alegre 123 - Rio Grande do Sul\",\n\t\"petFriendly\": true,\n\t\"shelteredPeople\": null,\n\t\"capacity\": 200,\n\t\"contact\": \"(51) 99999-9999\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{"type":"bearer","token":"{{ _.token }}"},"metaSortKey":-1714938160009,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_19a1b609ba8945918f1522f39f790aa4","parentId":"fld_66073a1e9d6c415aa0ccf6c5fcfb5d7d","modified":1714939354278,"created":1714939326458,"url":"{{ _.url }}/shelters/f48720c2-53c0-4ad7-8ecb-5d99715289ff","name":"Update","description":"","method":"PUT","body":{"mimeType":"application/json","text":"{\n\t\"petFriendly\": true,\n\t\"shelteredPeople\": null,\n\t\"capacity\": 100\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714937887830.75,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_73490676e9284d929c11a147ac08bc91","parentId":"fld_66073a1e9d6c415aa0ccf6c5fcfb5d7d","modified":1714940105497,"created":1714940087947,"url":"{{ _.url }}/shelters/f48720c2-53c0-4ad7-8ecb-5d99715289ff/admin","name":"Update Adm","description":"","method":"PUT","body":{"mimeType":"application/json","text":"{\n\t\"petFriendly\": true,\n\t\"shelteredPeople\": null,\n\t\"capacity\": 100,\n\t\"address\": \"Porto Alegre 252 - Rio Grande do Sul\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714937751741.625,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_f9f8be1faea348378c53e6dca51b27b4","parentId":"fld_43a721aaeef04e1386732d41c31a778a","modified":1714941828416,"created":1714941788002,"url":"{{ _.url }}/supply-categories","name":"Index","description":"","method":"GET","body":{},"parameters":[{"id":"pair_ed301dbad729421a819cf291a5476e0d","name":"search","value":"pix:contains:abrigo","description":"","disabled":true},{"id":"pair_ff5b87c85c9f43cf8d949b7dcce34b8a","name":"perPage","value":"1","description":"","disabled":true},{"id":"pair_f1811cb5e0d74429b94592ec3695aa46","name":"page","value":"2","description":"","disabled":true}],"headers":[{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714938160109,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_43a721aaeef04e1386732d41c31a778a","parentId":"wrk_a61684b639de4828aadbeb27d5fb06c2","modified":1714941792124,"created":1714941787999,"name":"Supply Category","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1714701034874.75,"_type":"request_group"},{"_id":"req_99ec7d50412242d58edf68ca7745d082","parentId":"fld_43a721aaeef04e1386732d41c31a778a","modified":1714948186876,"created":1714941788001,"url":"{{ _.url }}/supply-categories","name":"Create","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"name\": \"Roupas\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{"type":"bearer","token":"{{ _.token }}"},"metaSortKey":-1714938160009,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_71fea5194e9143a1adeccc1f9e751868","parentId":"fld_43a721aaeef04e1386732d41c31a778a","modified":1714944576289,"created":1714941788004,"url":"{{ _.url }}/supply-categories/8b684946-89b7-4741-81e5-cb679d94fae7","name":"Update","description":"","method":"PUT","body":{"mimeType":"application/json","text":"{\n\t\"name\": \"Roupas\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{"type":"bearer","token":"{{ _.token }}"},"metaSortKey":-1714937887830.75,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_e540a2a47e854964a90c85c954e3a5fa","parentId":"fld_2b4a4b05308748559e1abe82ec94d62c","modified":1714963807376,"created":1714941690618,"url":"{{ _.url }}/supplies","name":"Create","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"shelterId\": \"{{ _.shelterId }}\",\n\t\"supplyCategoryId\": \"236d72c4-66d1-4a06-8749-625dc16dc11a\",\n\t\"name\": \"Absorvente\",\n\t\"priority\": 0\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714938160009,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_2b4a4b05308748559e1abe82ec94d62c","parentId":"wrk_a61684b639de4828aadbeb27d5fb06c2","modified":1714941690616,"created":1714941690616,"name":"Supplies","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1714465011597.5,"_type":"request_group"},{"_id":"req_b0641cadd0604de7961042b83c84199d","parentId":"fld_2b4a4b05308748559e1abe82ec94d62c","modified":1714963287737,"created":1714941690622,"url":"{{ _.url }}/supplies/867584d6-f7b6-45c8-9f68-98190639a324","name":"Update","description":"","method":"PUT","body":{"mimeType":"application/json","text":"{\n\t\"priority\": 10\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714937887830.75,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_e6d2ab40315f4b40b1d7e5dc21bff09b","parentId":"fld_2b4a4b05308748559e1abe82ec94d62c","modified":1714948340128,"created":1714941690620,"url":"{{ _.url }}/supplies/{{ _.shelterId }}","name":"Index","description":"","method":"GET","body":{},"parameters":[{"id":"pair_ed301dbad729421a819cf291a5476e0d","name":"search","value":"pix:contains:abrigo","description":"","disabled":true},{"id":"pair_ff5b87c85c9f43cf8d949b7dcce34b8a","name":"perPage","value":"1","description":"","disabled":true},{"id":"pair_f1811cb5e0d74429b94592ec3695aa46","name":"page","value":"2","description":"","disabled":true}],"headers":[{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714937615652.5,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_b02963992a3546868c226e54c25e3499","parentId":"fld_c7f5b02294b44b20bce3de13b7f14710","modified":1715026104841,"created":1715025970336,"url":"{{ _.url }}/shelter/managers","name":"Create","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"shelterId\": \"{{ _.shelterId }}\",\n\t\"userId\": \"7f71d975-03d1-4a7d-859e-cf5f03845473\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{"type":"bearer","token":"{{ _.token }}"},"metaSortKey":-1714938160009,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_c7f5b02294b44b20bce3de13b7f14710","parentId":"wrk_a61684b639de4828aadbeb27d5fb06c2","modified":1715025970334,"created":1715025970334,"name":"Shelter Manager","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1714228988320.25,"_type":"request_group"},{"_id":"req_15404a5b37ea4872ac0bef869246a0e8","parentId":"fld_c7f5b02294b44b20bce3de13b7f14710","modified":1715026350701,"created":1715025970338,"url":"{{ _.url }}/shelter/managers/{{ _.shelterId }}","name":"Index","description":"","method":"GET","body":{},"parameters":[{"id":"pair_6463a0ccc83742c99202284e920784cb","name":"includes","value":"user","description":"","disabled":true}],"headers":[{"name":"User-Agent","value":"insomnia/2023.5.8"}],"authentication":{},"metaSortKey":-1714937615652.5,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"env_3f99728f85808417b4aa32432285d40a45688cee","parentId":"wrk_a61684b639de4828aadbeb27d5fb06c2","modified":1715126560949,"created":1714933336431,"name":"Base Environment","data":{"baseURL":"http://localhost:4000","externalURL":"https://api.sos-rs.com","url":"{{ _.baseURL }}","password":"12345678","shelterId":"01d7c6e8-f040-486e-bb26-968ec4e8c717","token":""},"dataPropertyOrder":{"&":["baseURL","externalURL","url","password","shelterId","token"]},"color":null,"isPrivate":false,"metaSortKey":1714933336431,"_type":"environment"},{"_id":"jar_3f99728f85808417b4aa32432285d40a45688cee","parentId":"wrk_a61684b639de4828aadbeb27d5fb06c2","modified":1714933336431,"created":1714933336431,"name":"Default Jar","cookies":[],"_type":"cookie_jar"}]} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 53744939..6c3ae692 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "@types/express": "^4.17.17", "@types/jest": "^29.5.2", "@types/node": "^20.3.1", + "@types/query-string": "^6.3.0", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", @@ -2568,6 +2569,16 @@ "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", "dev": true }, + "node_modules/@types/query-string": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@types/query-string/-/query-string-6.3.0.tgz", + "integrity": "sha512-yuIv/WRffRzL7cBW+sla4HwBZrEXRNf1MKQ5SklPEadth+BKbDxiVG8A3iISN5B3yC4EeSCzMZP8llHTcUhOzQ==", + "deprecated": "This is a stub types definition. query-string provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "query-string": "*" + } + }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", @@ -4151,6 +4162,15 @@ } } }, + "node_modules/decode-uri-component": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", + "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, "node_modules/dedent": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", @@ -5042,6 +5062,18 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -5257,21 +5289,6 @@ "node": ">= 6" } }, - "node_modules/formidable": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", - "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", - "dev": true, - "dependencies": { - "dezalgo": "^1.0.4", - "hexoid": "^1.0.0", - "once": "^1.4.0", - "qs": "^6.11.0" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -7997,6 +8014,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/query-string": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.0.0.tgz", + "integrity": "sha512-4EWwcRGsO2H+yzq6ddHcVqkCQ2EFUSfDMEjF8ryp8ReymyZhIuaFRGLomeOQLkrzacMHoyky2HW0Qe30UbzkKw==", + "dev": true, + "dependencies": { + "decode-uri-component": "^0.4.1", + "filter-obj": "^5.1.0", + "split-on-first": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -8726,6 +8760,18 @@ "node": ">=0.10.0" } }, + "node_modules/split-on-first": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", + "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -8883,29 +8929,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/superagent": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", - "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", - "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", + "node_modules/supertest": { + "version": "6.3.4", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz", + "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==", "dev": true, "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.1.2", "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.8" + "superagent": "^8.1.2" }, "engines": { - "node": ">=6.4.0 <13 || >=14" + "node": ">=6.4.0" + } + }, + "node_modules/supertest/node_modules/formidable": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "dev": true, + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" } }, - "node_modules/superagent/node_modules/mime": { + "node_modules/supertest/node_modules/mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", @@ -8917,17 +8969,26 @@ "node": ">=4.0.0" } }, - "node_modules/supertest": { - "version": "6.3.4", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz", - "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==", + "node_modules/supertest/node_modules/superagent": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", + "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", "dev": true, "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", "methods": "^1.1.2", - "superagent": "^8.1.2" + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" }, "engines": { - "node": ">=6.4.0" + "node": ">=6.4.0 <13 || >=14" } }, "node_modules/supports-color": { diff --git a/package.json b/package.json index daf9e2fe..5e154b46 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,10 @@ "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json" + "test:e2e": "jest --config ./test/jest-e2e.json", + "migrations:run": "npx prisma migrate deploy", + "migrations:dev": "npx prisma migrate dev", + "docker:compose": "docker-compose -f docker-compose.dev.yml up" }, "dependencies": { "@fastify/static": "^7.0.3", @@ -43,6 +46,7 @@ "@types/express": "^4.17.17", "@types/jest": "^29.5.2", "@types/node": "^20.3.1", + "@types/query-string": "^6.3.0", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/prisma/dev_dump.sql b/prisma/dev_dump.sql new file mode 100644 index 00000000..b530df8a --- /dev/null +++ b/prisma/dev_dump.sql @@ -0,0 +1,410 @@ +SET session_replication_role = 'replica'; +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('5c4325d7-3552-4062-8519-e73f711ab9ae', 'e66152ed01ccb466dec570dd854998d6ea575904c6c8a6b0a27bd5106bc22982', '2024-05-08 20:02:46.292560 +00:00', '20240507205058_', null, null, '2024-05-08 20:02:46.286110 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('f44f79d5-5f17-4c18-b0cd-08e40d98903d', '9b04acb1bc45aaff86e38d15d96b1dac094075cb7955c505c7ff86213569e5c5', '2024-05-08 20:02:46.244735 +00:00', '20240505182421_', null, null, '2024-05-08 20:02:46.216629 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('d26612d1-8706-4513-afe1-7de868d5698a', '3ba4eb668430d0ae4d7378871dffb75f9b68b20f4a9c5b40fc4922490faf26f4', '2024-05-08 20:02:46.246790 +00:00', '20240505185353_', null, null, '2024-05-08 20:02:46.245297 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('69cdcdcd-f7dc-4856-8dd8-c3cb7a7047f0', '86a52b407be81fea91f42aaa10873b43d92392356e5bffba9f4d5f4550ed0889', '2024-05-08 20:02:46.255573 +00:00', '20240505185534_', null, null, '2024-05-08 20:02:46.247209 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('e04a706c-cfdd-4231-b600-def0de1588ca', '255ccd8822da05e75c6c0d673b51b0de1152d2e5018be8727d3a054dbcba8d4b', '2024-05-08 20:02:46.293958 +00:00', '20240507221950_', null, null, '2024-05-08 20:02:46.292910 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('6c78196d-49b2-4101-9cfc-9a0096bcb5a9', '593f1900ce20253b540c3a086f72659a65cd026877504e488aa0e8430c947026', '2024-05-08 20:02:46.257917 +00:00', '20240505190155_', null, null, '2024-05-08 20:02:46.256127 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('adef43d7-7ceb-45d4-9761-40eae27949c4', '609d36c32acbb3c796c7d604570bd9a0f215635fff824985860367c7b9f1f047', '2024-05-08 20:02:46.259733 +00:00', '20240505191728_', null, null, '2024-05-08 20:02:46.258417 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('17618a81-bf08-4c7c-bb32-78a876985d31', '7fb685d93b6d82a9114b74ef6f6c01a9621367822905458ce9ade2a2badc0bcf', '2024-05-08 20:02:46.261160 +00:00', '20240505201711_', null, null, '2024-05-08 20:02:46.260084 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('e1bdaca8-d5d3-4262-b821-c2c02ccb571b', 'ffb7936d4e116cf081f57ca7297bdf6ddb9d5a2a1eece18733ddac7d96ef5694', '2024-05-08 20:02:46.295474 +00:00', '20240508022250_', null, null, '2024-05-08 20:02:46.294290 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('0f071376-15e2-414f-b2c4-094190e92c9e', '908fa353723b97a0f01fc923ce6ff8410cd5d8bae3c2b54dc1f8a10a32e82aee', '2024-05-08 20:02:46.264645 +00:00', '20240505203201_', null, null, '2024-05-08 20:02:46.261485 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('aefe9d5e-c122-4d74-b252-2bdf533eba03', 'b7370bfa5845bacf51247053ae4f6b1e089730a109c3b8231cd576178e727ccb', '2024-05-08 20:02:46.268312 +00:00', '20240505222048_', null, null, '2024-05-08 20:02:46.265113 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('58d527d9-5f1b-4460-bb64-aaa813c21eee', 'b695d6cdb619b2dae828741fe155ceae87ac5cb0231029300dbf3aa2c65985a4', '2024-05-08 20:02:46.269595 +00:00', '20240505222318_', null, null, '2024-05-08 20:02:46.268656 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('9759b8f6-1bb1-4d44-a73d-b773e0fdac08', 'ee1dba4c28b2ff1c40f7cbb77d43801c46e356de380f2b5ca9cb34d0e342bb3e', '2024-05-08 20:02:46.296952 +00:00', '20240508041443_', null, null, '2024-05-08 20:02:46.295823 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('b54986cb-3fc6-4e33-99b2-6db188d147cf', '49dafed132d6bef711e6062be59b4d50c3c190bef559ef8b8ba24cf334c313fa', '2024-05-08 20:02:46.272851 +00:00', '20240505224712_', null, null, '2024-05-08 20:02:46.269931 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('57cd9414-01ab-47f8-bff8-6f95583a8f1a', '1a1ff97189ea103b77e2877ecd9d382e1c5f1470876dada40cca5306234fd811', '2024-05-08 20:02:46.274890 +00:00', '20240505225104_20240505222318', null, null, '2024-05-08 20:02:46.273192 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('79c7c9c3-0e03-4ff0-8ae2-89eb2d27ecfb', '106d84f2f9ea360d071a62ea07768a29567864dc7aee671f80f1a42934cab4e7', '2024-05-08 20:02:46.276752 +00:00', '20240506015214_', null, null, '2024-05-08 20:02:46.275328 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('0fed8584-77f7-41ad-80a8-f722d6d1e25d', '49dafed132d6bef711e6062be59b4d50c3c190bef559ef8b8ba24cf334c313fa', '2024-05-08 20:02:46.300042 +00:00', '20240508050213_', null, null, '2024-05-08 20:02:46.297285 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('91138d0b-d6f6-4887-9e61-e6d344c3d7ce', 'f772d4d963ab1b5c35e68b528d1af55835cb27b9099f526d970b0dbdccf7a11a', '2024-05-08 20:02:46.278130 +00:00', '20240506021537_', null, null, '2024-05-08 20:02:46.277104 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('f99c0ba3-63e1-490d-9bf2-e921459aa184', 'e9b29fd9d436da2c2ceeb0129fabf45713d89862947a3913028bb9221623f7ab', '2024-05-08 20:02:46.285744 +00:00', '20240506195247_', null, null, '2024-05-08 20:02:46.278490 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('c255d7f5-c437-48ec-851f-e84a0e335774', '1a1ff97189ea103b77e2877ecd9d382e1c5f1470876dada40cca5306234fd811', '2024-05-08 20:02:46.301556 +00:00', '20240508150340_', null, null, '2024-05-08 20:02:46.300367 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('46c9f6d8-b1fa-4cad-b084-c394c1103816', 'c8b1aed5a604b5f70b7440c98703857c365836ec548b6207adf903c2b10a793c', '2024-05-07 20:52:15.384800 +00:00', '20240507205058_', null, null, '2024-05-07 20:52:14.752248 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('c32e2d26-2a88-4e86-9a5f-a71cc6835b15', 'bf6e10172d502fbb5e0f47bfc1c625ca9aa98f4693f02ae3e78e911ea26c88c2', '2024-05-05 20:22:17.431799 +00:00', '20240505182421_', null, null, '2024-05-05 20:22:16.656578 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('de1113f6-6956-4bbb-be3a-006df5d471f6', 'e331666e7c4172383cbae7c33f491c106bb463398f642fdc8a33236d49a354a5', '2024-05-05 20:22:18.279294 +00:00', '20240505185353_', null, null, '2024-05-05 20:22:17.672062 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('49230062-1cce-43af-b064-f860ad5e58b4', 'ba809dc40dfa8e87ef0a0ade7486fa798a2f4cdbfde26c83812434080ffa766b', '2024-05-05 20:22:19.140315 +00:00', '20240505185534_', null, null, '2024-05-05 20:22:18.523559 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('ebc8b56d-8830-4cbc-bfd7-41e1a8272698', 'a0605cded7bdd04d0b01de01ad3fdc50325cbfc8490bae7945890d6ceeb23bfb', '2024-05-05 20:22:20.703463 +00:00', '20240505190155_', null, null, '2024-05-05 20:22:19.401583 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('61c031f3-dea8-4d01-9817-5f1bd7a7a7a2', '03488ccbbafc2b3deb2577b10676cfd45c9568d5f0d897924ef08083e6541ce6', '2024-05-05 20:22:21.593700 +00:00', '20240505191728_', null, null, '2024-05-05 20:22:20.981103 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('f8586b60-915b-42ac-89c0-0babe258f2ae', '5e72eaf177fe5b8226d367c357eeb963a39b5a60234dfa68fde9b494d90f0ade', '2024-05-05 20:22:22.444490 +00:00', '20240505201711_', null, null, '2024-05-05 20:22:21.836043 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('096073cd-fef1-4746-8b0f-0c3e7fcd321b', '797a68ad2122eefd89adaa253dd7f400f624e195632d9385ee6bb95469a43a52', '2024-05-05 20:32:02.271858 +00:00', '20240505203201_', null, null, '2024-05-05 20:32:01.662749 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('9c95b187-db79-499d-8190-c9e796a80298', '44d800d051566b499ccffb4e4295ba13385862a1cb8aae391040e4bc793346e9', '2024-05-05 22:20:49.258657 +00:00', '20240505222048_', null, null, '2024-05-05 22:20:48.643942 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('c919ae19-6a32-4baf-8f79-ce0903214d47', '72ffaab9d43d1a6992cee20847ff8a47cd2e73ac79f6e18c2d846741b3450aff', '2024-05-05 22:23:19.772977 +00:00', '20240505222318_', null, null, '2024-05-05 22:23:19.157387 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('7428d514-1f2e-49cf-a654-7479e5abbf15', '1e53cc353bcc7f971c7b00915eaecef56c80b26bf87249a112419406f6238a59', '2024-05-05 23:32:31.056485 +00:00', '20240505224712_', null, null, '2024-05-05 23:32:31.046850 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('49852d2a-8ca5-4b21-8414-969ccd7997d8', '59bc37eb4d6004154538c9b838b475a7b87b298e7a77965fd30f84fa23a7d502', '2024-05-05 23:32:31.065232 +00:00', '20240505225104_20240505222318', null, null, '2024-05-05 23:32:31.057939 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('963af559-0efe-4730-8ae2-7806dd51ddf3', 'f4a3543948a2d97a169859bc21722f472efe714784a8490fa6ebfbe1c8001e5f', '2024-05-06 02:56:06.420701 +00:00', '20240506015214_', null, null, '2024-05-06 02:56:05.808613 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('5989ce82-3898-4048-b954-d237e4e047f7', '4f4f1ec52fa8dbc4b6c750eceba181324a52f074494803f85de8b0a7273855be', '2024-05-06 02:56:07.287433 +00:00', '20240506021537_', null, null, '2024-05-06 02:56:06.668098 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('3b71321e-f5fc-442e-8559-4f8e3c5bb79d', '58383ab8e1dec08ab30dec98485ba408225a22107fff4745aefbc1168f182f3a', '2024-05-06 20:14:26.109428 +00:00', '20240506195247_', null, null, '2024-05-06 20:14:25.497555 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('f73cd1ed-a4f6-4684-8cee-a6d04eeb7cd1', 'ae49a07be38b3fe5f46a256884a00ef7282ac902a5a86a23f632acdb98b392e7', '2024-05-08 16:16:12.773259 +00:00', '20240507221950_', null, null, '2024-05-08 16:16:12.147752 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('f2a3063f-0202-42f4-a3ee-c0245b7da718', '84793831ae6d961a645b723faf8a0312f25e2f8bab459cf47696241368aa60ff', '2024-05-08 16:16:13.646475 +00:00', '20240508022250_', null, null, '2024-05-08 16:16:13.023073 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('672d83b9-d210-45fd-97d9-ed38e82dfb4e', 'fee95684300f7e10edbbcec94ee0d43704c4b640bd46244b28e58b38f97eccff', '2024-05-08 16:16:14.527603 +00:00', '20240508041443_', null, null, '2024-05-08 16:16:13.897884 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('36d67440-3fad-4a69-b48e-f8aa48c3fb54', '1e53cc353bcc7f971c7b00915eaecef56c80b26bf87249a112419406f6238a59', '2024-05-08 16:16:15.407624 +00:00', '20240508050213_', null, null, '2024-05-08 16:16:14.776221 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('6eb4f6df-f362-43fc-a827-ddf3cbf1ccc6', '59bc37eb4d6004154538c9b838b475a7b87b298e7a77965fd30f84fa23a7d502', '2024-05-08 16:16:16.281169 +00:00', '20240508150340_', null, null, '2024-05-08 16:16:15.658073 +00:00', 1); +INSERT INTO public._prisma_migrations (id, checksum, finished_at, migration_name, logs, rolled_back_at, started_at, applied_steps_count) VALUES ('3d52cad0-a66f-4f07-9bfe-dd2076bedfd3', 'dd56572b40d8c370c82aa1a4a2d74ba59da5de87abcf9186499a93dd7ad042ee', '2024-05-08 20:45:08.751784 +00:00', '20240508193500_', null, null, '2024-05-08 20:45:08.748779 +00:00', 1); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('5c9b6767-5310-461b-977b-906fe16370ae', 'Medicamentos', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('03fdb0f2-6b50-4895-b970-5793cad80c86', 'Cuidados com Animais', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('b3a81a9d-a964-4413-9a33-974a3b4673d1', 'Especialistas e Profissionais', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Acomodações e Descanso', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Equipamentos de Emergência', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Voluntariado', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Itens Descartáveis', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('718d5be3-69c3-4216-97f1-12b690d0eb97', 'Higiene Pessoal', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Alimentos e Água', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Material de Limpeza', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Vestuário', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('05583098-5f2e-44e2-b874-452ec86d9d3e', 'Veículos de Resgate e Transporte', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES (e'4f95853f-d5e1-487d-8086-6ddfaf2bbab7 +', 'Eletrodomésticos e Eletrônicos', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES (e'be0e4018-ca46-44cd-b814-7681ba98c51a +', 'Mobílias', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES (e'c117dd37-82ab-43a6-bf66-d97acef97f6e +', 'Jogos e Passatempo', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.category_supplies (id, name, created_at, updated_at) VALUES ('8200759f-067f-4fda-8947-ff5896929fcd', 'Cosméticos', '2024-05-05T00:00:00.000Z', '2024-05-05T00:00:00.000Z'); +INSERT INTO public.shelter_supplies (shelter_id, supply_id, priority, created_at, updated_at) VALUES ('7f21ccc7-d1de-4a23-b710-260761213000', 'ceebd729-eecc-420e-8e90-f764a487b202', 100, '2024-05-09T16:20:28.294Z', null); +INSERT INTO public.shelter_supplies (shelter_id, supply_id, priority, created_at, updated_at) VALUES ('7f21ccc7-d1de-4a23-b710-260761213000', '3a2d5542-e160-4192-974e-c0b0938b6b98', 10, '2024-05-09T16:20:35.057Z', null); +INSERT INTO public.shelter_supplies (shelter_id, supply_id, priority, created_at, updated_at) VALUES ('7f21ccc7-d1de-4a23-b710-260761213000', '73a8e20b-2973-42a4-943f-ea96a8c5e773', 1, '2024-05-09T16:20:48.077Z', null); +INSERT INTO public.shelters (id, pix, address, pet_friendly, sheltered_people, capacity, contact, created_at, updated_at, name, priority_sum, latitude, longitude, verified) VALUES ('7f21ccc7-d1de-4a23-b710-260761213000', null, 'Rua Coronel Corte Real, 975 - Petrópolis, Porto Alegre', null, null, null, null, '2024-05-07T01:04:29.240Z', '2024-05-09T16:20:48.068Z', 'Simers', 861, null, null, true); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('377fdec9-9b17-4086-8986-3e04508c4917', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Banana', '2024-05-08T16:23:26.186Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('43a27a70-3ed5-4a3d-8428-623810c3f717', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas para adultos', '2024-05-06T03:04:40.468Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ceebd729-eecc-420e-8e90-f764a487b202', '5c9b6767-5310-461b-977b-906fe16370ae', 'Fraldas Geriatricas', '2024-05-07T10:51:23.876Z', '2024-05-08T05:07:57.203Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('606a9ed3-b5f7-4d63-8da9-c65adf0a927a', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas leves', '2024-05-07T02:19:28.533Z', '2024-05-07T02:40:33.000Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('62bd5d05-ba37-497a-a1a1-56795813790d', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Escova de dentes', '2024-05-06T03:04:51.666Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('578809ce-d533-43df-ad00-3e61af85d73c', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Pás', '2024-05-06T03:04:52.222Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8f2d2855-7c53-418f-929b-222e431be3b7', 'b3a81a9d-a964-4413-9a33-974a3b4673d1', 'Veterinários', '2024-05-06T03:04:54.479Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('1fde16af-ef8a-4686-b021-cafc1c5179cf', '5c9b6767-5310-461b-977b-906fe16370ae', 'Medicamentos prescritos', '2024-05-06T03:04:57.286Z', '2024-05-07T21:30:20.591Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8fe8f879-5cc8-4670-a13d-9d2d6bb24017', 'b3a81a9d-a964-4413-9a33-974a3b4673d1', 'Assistentes Sociais', '2024-05-06T03:04:57.286Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d7f296ff-11e1-45cf-a360-7989c69affb1', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Pano de prato', '2024-05-07T01:00:43.134Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b2f1c6ff-93dc-4d8d-8365-36bcfc0eb1fd', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Anti pulgas para gatos e cachorros', '2024-05-06T18:37:45.921Z', '2024-05-07T17:04:43.980Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ddd006a5-eac6-44de-ad77-b9386f25ef9c', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Copos', '2024-05-06T03:05:01.751Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5cac0471-262c-4408-8fd7-00e99f5a9869', '5c9b6767-5310-461b-977b-906fe16370ae', 'Kits de primeiros socorros', '2024-05-06T03:05:02.870Z', '2024-05-06T06:21:16.435Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('02d3da70-8a88-4c34-a195-50de839bba53', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Acetona', '2024-05-06T18:38:42.101Z', '2024-05-06T19:20:49.697Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a67daf19-d5c9-4021-a189-c89adc8cb051', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Lixa de unha', '2024-05-06T18:39:02.084Z', '2024-05-06T19:21:00.937Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7d077d4d-2f97-4c24-9e73-e64765a3b2f8', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Cama alta para cadeirante ', '2024-05-06T19:23:10.433Z', '2024-05-07T00:57:04.927Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3f9591df-328d-467f-b556-0872762b09a8', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Caixas de transporte para pets', '2024-05-06T19:21:42.638Z', '2024-05-07T01:00:55.601Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('edcb4032-d028-48ee-9811-b6004b277877', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Repelente ', '2024-05-06T18:13:49.217Z', '2024-05-07T23:58:02.815Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ddfd8cc9-02db-4c9c-b59c-c4f03459607c', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Algodão ', '2024-05-06T18:38:28.696Z', '2024-05-06T19:20:30.868Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('fcc2aee3-3a74-45a7-a590-961a2f78050d', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Lanches', '2024-05-06T21:06:37.666Z', '2024-05-07T23:33:34.888Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b7349827-482c-4c5c-b0eb-7627a8380c16', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas íntimas', '2024-05-07T01:04:09.440Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ddd88a43-eb5a-416a-9ed1-2be44c5982a8', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Marmita', '2024-05-06T21:06:26.336Z', '2024-05-07T23:32:42.141Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('9ac19410-0488-4c11-a99a-ca78dad3d6e0', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Aparelho depilador', '2024-05-06T22:35:47.421Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('94701e72-8ebc-43e7-885a-9e2a810ad1e7', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Pente', '2024-05-06T22:36:04.108Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('cf61184d-0ffb-4443-9a63-231432a3bed1', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Produtos de desinfecção (cloro, álcool)', '2024-05-06T03:04:39.334Z', '2024-05-06T05:21:34.414Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('bd742c5e-9257-4f16-a572-b4571d98db90', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Toalha de Banho', '2024-05-06T22:57:50.533Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('85e928ec-beaf-4097-b8f7-9199ce8e3e48', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Chinelo', '2024-05-06T22:58:28.916Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('dd565638-4773-4712-91e1-4a3478c8fa6a', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas Pluz Size', '2024-05-06T22:37:48.923Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('eb3caab6-6357-4757-86b2-efaf8d691de7', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Calçados Infantis', '2024-05-06T22:38:28.312Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b2b8fa95-19ba-47db-9cff-b80d6d08e1c9', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Short Feminino', '2024-05-06T22:38:48.966Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3e2c22be-5ac0-4b10-ba0c-150ee9f33100', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Cadeiras (tipo de praia)', '2024-05-06T06:25:17.677Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f51bc934-80c1-4fb6-858f-38f701e88dd9', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Bermuda Masculina', '2024-05-06T22:39:38.319Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3e85a0d3-2717-44bb-8b4b-8ce1a0d2374d', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Voluntário - Manhã', '2024-05-06T06:26:39.694Z', '2024-05-07T16:46:56.492Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ca0ef946-0de3-47a2-a0cb-df72de35aeec', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Prestobarba', '2024-05-06T22:51:29.224Z', '2024-05-06T22:51:38.321Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('38f2c85a-d46f-4cd4-92a6-70cd8b55851a', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Papel higiênico', '2024-05-06T06:28:41.690Z', '2024-05-07T12:12:59.464Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4f44cc87-8684-4327-9fb6-0a55d3464020', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Caixa de papelão ', '2024-05-06T23:03:28.667Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6a220720-6fa3-42cc-8101-621da51b521f', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas para frio', '2024-05-06T06:29:59.865Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a9c5cfe0-a05c-4e45-b38a-f5db5f837304', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Vassouras e rodos', '2024-05-06T06:29:59.865Z', '2024-05-06T15:41:53.232Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6d451ef8-e962-423c-8fc8-5fb0eb848766', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Fórmula infantil', '2024-05-06T06:40:57.551Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('18b45eb3-755c-4d38-a974-2857f6b30638', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Voluntário - Tarde', '2024-05-06T06:40:57.551Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4bd475d3-779b-45bb-b9f9-7a6052bc41fb', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Lenços umedecidos', '2024-05-06T13:07:37.962Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('924e9906-692e-460a-bfe4-de2a6c33a5f1', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Travesseiro', '2024-05-06T13:08:07.375Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b5e87f98-0f0b-44b3-bf9c-81b84bab76d4', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Extensão', '2024-05-06T13:08:44.782Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2cae8411-a435-44dc-89c0-9a547813f914', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Lixeiras', '2024-05-06T13:09:03.598Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('761e4265-2f75-46a2-8cf3-16b8a5a69963', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Lanterna', '2024-05-06T13:11:26.213Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6b1d5955-578e-4b7c-a66a-118060c94901', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Álcool em gel', '2024-05-06T13:12:57.281Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d25db3bc-0812-4d28-a03f-ff51419cf15d', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Tapete higiênico', '2024-05-06T13:13:20.027Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b8f75b02-c99d-4a54-91a2-01e66617b676', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Brinquedos para cães', '2024-05-06T13:13:37.196Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('13a4afa8-2b27-43c2-8ac1-0a2b29ce7832', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Papel toalha', '2024-05-06T13:13:55.587Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6763caea-7b53-466a-a9b3-40ebfac0f9bb', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Baldes', '2024-05-06T13:14:13.712Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('9e6662ae-0354-4bf7-a7cc-457bbe6ffe6e', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Pote para comida', '2024-05-06T13:18:31.597Z', '2024-05-07T19:05:03.881Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e82f2b29-1394-4325-a728-f3dd20f1c6bf', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Mamadeira', '2024-05-06T13:17:45.797Z', '2024-05-07T18:53:47.204Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('474cc566-0a60-4f1a-8e48-40558fe39170', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Leitos para animais', '2024-05-06T13:37:34.424Z', '2024-05-07T17:09:10.751Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7982a520-ecc8-4cf9-a8be-2bd40550bd31', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Pente/Escova de cabelo', '2024-05-07T03:58:23.847Z', '2024-05-07T14:23:28.103Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c38cb955-8acf-462f-baec-1fa555f92df9', '05583098-5f2e-44e2-b874-452ec86d9d3e', 'Barcos', '2024-05-06T13:39:34.827Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8f528aeb-d345-42a8-b01f-48156c9d589f', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Luvas para limpeza', '2024-05-07T03:57:55.605Z', '2024-05-07T17:30:34.281Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('65bc4ea4-a0db-4ac4-b343-b9d587be224b', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Pano de chão', '2024-05-07T00:59:52.551Z', '2024-05-07T12:15:06.926Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('14ce7f98-2cb3-46ce-bc13-d0f420c5921c', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Ração úmida', '2024-05-07T07:33:00.942Z', '2024-05-07T14:12:59.394Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('01b0f1a3-354a-4f7a-a724-c022801d0734', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Tapetes higiênicos', '2024-05-07T07:32:25.144Z', '2024-05-07T14:13:12.312Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c2d8b7f0-b0cc-4d81-b935-77c12baa9b0e', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Farinha de polenta', '2024-05-07T04:00:39.815Z', '2024-05-07T14:22:50.791Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7137cf53-9bea-4a5f-a70b-c2ae81202d90', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', '1 Notebook pode ser usado', '2024-05-07T15:30:49.948Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('bf7f0124-f552-4ab4-8db2-0db1fb4728d8', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Lanterna ', '2024-05-07T15:31:41.173Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f20e10e5-5a6e-4fb2-9ef3-23e691b8d2db', '5c9b6767-5310-461b-977b-906fe16370ae', 'Insulina', '2024-05-07T14:27:19.999Z', '2024-05-07T17:30:59.674Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3abbe32c-86f7-4c43-b25e-db0ecf12c713', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Mesa', '2024-05-07T11:53:13.749Z', '2024-05-07T22:51:10.893Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('93ab9821-1e65-418b-a36c-5548625bc1ab', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Comidas não perecíveis', '2024-05-06T06:28:41.690Z', '2024-05-07T12:12:17.910Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('eb1d5056-8b9b-455d-a179-172a747e3f20', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Óleo de cozinha', '2024-05-07T04:01:20.516Z', '2024-05-07T14:22:57.654Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('73d62b87-49ae-48d7-9001-868839648b25', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Vinagre', '2024-05-07T14:29:14.893Z', '2024-05-07T17:30:54.226Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('cf326612-2637-4e48-917f-a29b1df4344e', '5c9b6767-5310-461b-977b-906fe16370ae', 'LOCAL DESATIVADO - CB - nova local Graciliano Ramos 217', '2024-05-07T13:10:45.748Z', '2024-05-07T14:49:53.852Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c8d5bcc7-cbe3-4767-8724-2d9065d1824d', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'COLETES', '2024-05-07T15:32:31.821Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('1606cc85-7ef0-4864-8cf1-15e9722a8115', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Caixas de papelão ', '2024-05-07T14:24:23.432Z', '2024-05-07T16:45:16.155Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('38554698-fae0-469c-b8c5-e07cbadf4f30', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Luvas Descartáveis', '2024-05-07T14:30:15.257Z', '2024-05-07T17:31:40.328Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e30c8efd-29f1-4414-9f5e-080b7e1f6fa3', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'VETERINARIOS', '2024-05-07T14:24:08.809Z', '2024-05-07T21:23:58.316Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d246ce3d-165b-462b-a2f5-e6234b505067', '5c9b6767-5310-461b-977b-906fe16370ae', 'Remédio de controle especial', '2024-05-07T11:54:20.805Z', '2024-05-07T22:50:49.154Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('55bf190c-f2eb-4f80-89f0-76dec0843ad4', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Absorventes higiênicos', '2024-05-06T13:46:54.975Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('81e1553d-ffd4-4ab3-9c0b-87062aeda6a9', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Sabão em pó ', '2024-05-06T21:09:51.663Z', '2024-05-07T13:15:52.340Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('158fb67d-00f8-4752-be65-4108101bdd7f', '5c9b6767-5310-461b-977b-906fe16370ae', 'Enlatados (ervilha e milho)', '2024-05-07T12:27:25.425Z', '2024-05-07T14:23:53.668Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5bbee915-3405-41f1-a0f2-1a6dde8c5732', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Tapete antiderrapante para box', '2024-05-07T01:03:25.375Z', '2024-05-07T17:04:56.660Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4e619f2b-0e02-4842-8b1d-410ff44038cd', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Cortador de unhas', '2024-05-07T15:13:03.999Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('001e3bdc-a463-4cea-a4f1-6bb36cd67d5f', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Jornal (para xixi e coco)', '2024-05-07T15:13:38.029Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e162ec59-91e5-4621-8a2a-05848cd0f368', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Toalha', '2024-05-07T14:28:15.278Z', '2024-05-08T14:44:37.136Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('24a56430-28ea-465e-8287-af19639b18ce', '5c9b6767-5310-461b-977b-906fe16370ae', 'Suco', '2024-05-07T12:25:56.943Z', '2024-05-08T00:07:36.586Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('1df0c458-f5eb-470c-be45-5e3649ccbe25', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Prendedor ', '2024-05-07T15:14:04.471Z', '2024-05-08T14:22:34.692Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a08d8756-9721-40b8-8146-07bec3bbed9b', '5c9b6767-5310-461b-977b-906fe16370ae', 'Peiteira/Coleira Grande', '2024-05-07T06:59:57.279Z', '2024-05-07T13:11:05.290Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5a1ad7fc-c94e-4d69-9151-ee106ba29e1d', '5c9b6767-5310-461b-977b-906fe16370ae', 'Dipirona Injetável ', '2024-05-07T06:59:28.401Z', '2024-05-07T13:11:19.021Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d96c56b3-c948-4d94-af04-9a693759a1dd', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Caixas médias', '2024-05-07T13:41:18.472Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e95f427a-d290-44f2-a54b-81a6e3847252', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Casinha para cachorro ', '2024-05-07T13:50:27.956Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('84f83b15-aa13-4b74-8c81-b769f429a6db', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Pasta de dente ', '2024-05-07T12:29:23.801Z', '2024-05-07T14:26:19.590Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('fa856f0d-1f0a-4dd8-862e-1cf79bfbc082', '5c9b6767-5310-461b-977b-906fe16370ae', 'BRAVECTO', '2024-05-07T06:59:04.559Z', '2024-05-07T14:49:59.475Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5fb70f9a-6966-4274-8af4-de3e61bd39f8', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Baralhos', '2024-05-07T15:12:41.573Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6271fa97-16a9-4713-b26b-ab4fce1819e5', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Gazebo', '2024-05-07T07:00:19.092Z', '2024-05-07T21:49:21.046Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('84cad0e5-c559-471b-8fc3-de467afc4685', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Shampoo', '2024-05-07T13:38:28.737Z', '2024-05-08T11:33:20.259Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c905ca5a-0564-4d2a-b9b9-585cbce1cc62', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Gilete', '2024-05-07T13:38:56.167Z', '2024-05-08T11:33:37.402Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('0fc4d439-3e5d-460d-aefb-c54583690db3', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Papelão', '2024-05-06T14:02:17.547Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('90c6ddc2-a574-47eb-a2d3-3c79b801e4fb', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Lonas', '2024-05-06T14:02:30.223Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('04156fe1-e392-4283-a919-1e25908dbec1', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Creme para assaduras', '2024-05-06T13:51:04.758Z', '2024-05-08T11:33:51.168Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('39bc837b-b026-4a73-b987-efbba14a889f', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Travesseiros', '2024-05-06T17:47:34.865Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('68c9670c-99fb-438a-8169-66cc1ce66313', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Voluntário - Noite', '2024-05-06T03:04:46.078Z', '2024-05-07T02:33:38.167Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('73a8e20b-2973-42a4-943f-ea96a8c5e773', '5c9b6767-5310-461b-977b-906fe16370ae', 'Álcool', '2024-05-06T14:22:09.209Z', '2024-05-07T21:58:30.919Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('367ed746-6c87-41d9-a29e-bf3540360ccf', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Shampoo e Condicionador', '2024-05-06T18:13:25.687Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('0b478819-4e8c-4b0a-b96a-dc9e267b7dd9', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Meias', '2024-05-06T18:14:20.158Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('580c2fac-3c42-48d2-b79b-2fbc7b6fc7b0', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Chinelos', '2024-05-06T18:14:29.874Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a09441c5-46c4-426b-8da7-e356c731475b', '5c9b6767-5310-461b-977b-906fe16370ae', 'Termômetro', '2024-05-07T12:52:29.431Z', '2024-05-07T19:00:05.501Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6b3962b3-33dd-422e-bdda-35dbe0afa554', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Fraldas Adultas', '2024-05-06T18:12:40.033Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8a857622-cd08-4e3e-81c4-f464505c5ca1', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Escova de Cabelo', '2024-05-06T18:14:10.918Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('683a84ad-681b-4971-a3ba-59694387304b', '5c9b6767-5310-461b-977b-906fe16370ae', 'luvas', '2024-05-07T12:52:51.471Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d01c1d11-e401-4151-b0ec-52c26ce54b32', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Água potável', '2024-05-06T18:30:38.341Z', '2024-05-08T05:53:38.452Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6347a939-ad2c-458e-a097-17fdb7ef34b1', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Toalhas', '2024-05-07T10:10:11.988Z', '2024-05-08T00:31:52.381Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2ca22b44-7d15-4524-9999-290a2925af6f', 'b3a81a9d-a964-4413-9a33-974a3b4673d1', 'Médicos', '2024-05-06T18:35:41.360Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('77282a94-c627-46ab-a22d-3d19cc00d3c7', '5c9b6767-5310-461b-977b-906fe16370ae', 'máscaras', '2024-05-07T12:53:06.219Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('abe67b83-3fdc-4e39-82ec-a15c49630b4d', '5c9b6767-5310-461b-977b-906fe16370ae', 'Medidores de pressão arterial ', '2024-05-06T18:37:19.661Z', '2024-05-07T00:57:36.638Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('46bd3422-75e0-4d67-b492-97f0e14dd403', '5c9b6767-5310-461b-977b-906fe16370ae', 'Termômetro ', '2024-05-06T18:36:44.265Z', '2024-05-07T00:57:42.676Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c8a7e7ea-4f68-473c-862f-fa302bf544ec', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Chuveiro 110w', '2024-05-06T18:39:53.223Z', '2024-05-07T00:57:48.619Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5d7dee46-9a08-4faf-adf8-5b341231f09a', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Turnos de noite', '2024-05-07T01:04:16.726Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7edd1812-c62d-4742-919a-c9240b41a160', '05583098-5f2e-44e2-b874-452ec86d9d3e', 'Helicópteros', '2024-05-07T01:04:20.663Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b02cec28-dac2-42ec-a552-0558f598fa51', '5c9b6767-5310-461b-977b-906fe16370ae', 'Remédios básicos', '2024-05-07T01:04:29.815Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('76c0cb36-9ee0-422f-8050-b422ff53b9d3', 'b3a81a9d-a964-4413-9a33-974a3b4673d1', 'Psicólogos', '2024-05-07T01:04:26.394Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8e9067fe-0ca2-4e3f-95c6-d9177b6f3b51', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Ração para animais', '2024-05-07T01:04:28.092Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('14bb5f33-7c73-441d-a3b6-27fd7348dce3', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas para crianças', '2024-05-07T01:04:29.240Z', '2024-05-08T13:50:01.985Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('11c6d26d-d148-49c7-bcfd-cf2ce6be4022', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Malas de Viagem', '2024-05-07T12:54:02.766Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('35f6046a-c2a2-4e4b-a857-f8de763e229a', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Pratos', '2024-05-06T03:04:50.554Z', '2024-05-07T14:13:49.822Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7b1ffe8e-6cb1-46b9-b85c-dcb380da4aa4', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Roupas de Camas ', '2024-05-07T14:24:57.964Z', '2024-05-07T16:45:37.760Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('01d3d6df-cd76-4f62-9c39-ddd968a9a634', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Papel higiênico ', '2024-05-07T14:56:19.458Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('9e66cff1-37e1-4631-8251-c7b03b287ada', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Luvas', '2024-05-07T15:09:08.115Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a1f41da4-7c34-46c6-a6bf-446db9063b96', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'OCULOS DE PROTEÇÃO', '2024-05-07T15:32:05.485Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('328d3f80-abfe-4c86-ba31-9399e4d9f2a6', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'ALICATE DE CORTE', '2024-05-07T15:32:51.813Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d66cd87f-0651-472d-a3e3-74e7fe481760', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'MACAS COMPLETAS', '2024-05-07T15:33:09.807Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f88381ee-7e98-4806-9fb4-acd4f1c328ec', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'CORDAS 10 OU 11 ML', '2024-05-07T15:33:47.105Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('90d760be-3781-4bf7-ae91-5f74027bb1d8', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'TESOURÃO', '2024-05-07T15:34:10.520Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8a8e86cf-24e0-4a87-b660-1a8d884bbacc', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'CAPACETES COM MARTELETE COM BATERIA', '2024-05-07T15:34:35.893Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ae3c2c9b-44da-4c00-9755-74880c3f9da1', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'CAPAS DE CHUVA', '2024-05-07T15:35:05.106Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('19c492f1-da4d-4ee2-a523-f3db27c75be8', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'SERRASABRE', '2024-05-07T15:35:29.077Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('844fa0a8-93a3-481e-8221-d6d385274281', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'MACACÃO PARA RESGATE E ROUPA REVERSA', '2024-05-07T15:36:18.104Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e72d0dd5-e4f2-41ca-b690-4471bf7713ef', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Bermuda masculina', '2024-05-07T00:52:13.465Z', '2024-05-07T16:14:06.295Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2c98279b-bbd2-4645-96a3-51edb69cf509', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Lentilha', '2024-05-07T14:26:42.725Z', '2024-05-07T17:31:22.022Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f8ba58b3-6549-49b7-b400-81ce225d365d', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Farinha', '2024-05-07T13:40:11.092Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2b72c607-f5b6-4907-88e9-1a2d50045b18', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Açúcar', '2024-05-07T13:40:25.423Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('85132717-39a0-41bb-8409-6ecf6ec77019', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Vassouras', '2024-05-07T16:14:51.207Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a9b67a55-6742-4c3f-98ad-af8a69c05686', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Turnos de tarde', '2024-05-07T16:14:55.673Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('28114a40-6489-4712-b5ba-5968b0fc8fd9', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Turnos de manhã', '2024-05-07T16:14:59.073Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('524ad35e-7967-4ebf-96d8-cdf0f56d1e81', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Sabonetes', '2024-05-07T16:15:03.641Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('cd9c4c7a-b1d1-4b85-9a90-a1968b1dc420', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Pasta de dente', '2024-05-07T16:15:04.207Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e15b969f-d5fe-48cf-80ea-443be9dc5785', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Medicamentos veterinários', '2024-05-07T16:15:07.663Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ff30edb6-ad8b-4b10-80ba-da7d2ef786f7', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Talheres', '2024-05-07T16:15:08.236Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('790861c7-f54f-4579-8859-bfe139177c0b', '05583098-5f2e-44e2-b874-452ec86d9d3e', 'Carros', '2024-05-07T16:15:10.541Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('dd6c8774-52ca-4c3f-9125-06ad4b0e2747', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Cordas', '2024-05-07T16:15:15.125Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('12441ef6-2583-4e7e-9aae-8f3bf89147e6', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Lanternas', '2024-05-07T16:15:15.709Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('770fd1b3-e792-4127-88f9-7d7a47224363', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Colchões', '2024-05-07T16:15:17.493Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('39854bdb-bb2e-4dc4-a08e-d1fc9c280ebb', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Lençóis', '2024-05-07T16:15:18.057Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('cb69b4b0-b164-43ed-ad6e-c0c3ca3ad93e', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Sacos de lixo', '2024-05-07T16:15:18.057Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('63683e0b-eb4b-4e46-99f4-377ca5bb26f0', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Fraldas', '2024-05-07T16:15:22.152Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3a2d5542-e160-4192-974e-c0b0938b6b98', '05583098-5f2e-44e2-b874-452ec86d9d3e', 'Jetskis', '2024-05-07T16:15:26.829Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8e596eea-5ab7-480b-a22f-2af852198a92', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Coleiras', '2024-05-07T16:15:27.420Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e332e031-a18e-4407-81e9-660530260e64', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Cobertores', '2024-05-07T16:20:45.101Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a736cad0-9135-4ac2-bb96-d40350b52658', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Sal', '2024-05-07T16:39:42.208Z', '2024-05-08T05:19:07.187Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('0fe9ff90-4190-4341-b775-986d9dd18bd5', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Tênis', '2024-05-07T16:39:27.415Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c8642f4a-7ee0-49a7-aec8-e18eab2e2c69', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Enlatados', '2024-05-07T16:40:04.034Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d8b0c9ec-39a1-44e4-9ccf-36b439e39368', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Escova de cabelo', '2024-05-07T00:58:52.951Z', '2024-05-07T17:04:35.596Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3e1b644d-f32f-4715-a329-581c3cf022f5', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Palhetes', '2024-05-07T14:22:56.751Z', '2024-05-07T16:45:09.503Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('20d95bd9-0113-4b90-914e-7e1083cb5cd6', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Lona ', '2024-05-07T14:23:26.626Z', '2024-05-07T16:45:25.577Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2df34cb2-b419-4cd9-bac0-fee998327fd6', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Desinfetante', '2024-05-06T18:12:00.180Z', '2024-05-07T16:59:06.062Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('0a238fb4-a6f0-4d93-9a1b-02245afa2513', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Corda de varal', '2024-05-07T01:01:47.341Z', '2024-05-07T17:04:07.635Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3810ff6f-2c32-4a64-a1c6-37be86fdaec6', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Jogo de cartas, baralho, dama e dominó, etc', '2024-05-07T17:11:13.587Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('55b622c5-32e6-4c56-a8b3-d2baa3ac44e7', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Desodorante', '2024-05-07T16:22:23.518Z', '2024-05-08T02:58:24.692Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f3eb355a-4868-48af-befc-38a8a565c8e4', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Rodo', '2024-05-07T17:03:59.038Z', '2024-05-07T20:48:47.209Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('210430a0-e1df-4cb9-9ebf-a60ebccd79f0', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Ventilador ', '2024-05-07T17:02:44.447Z', '2024-05-07T20:49:18.928Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e4cfa4d9-183d-42a4-8c39-994c734d8b49', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Pomadas', '2024-05-07T16:41:00.761Z', '2024-05-07T22:09:16.657Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2d2a7f10-0aa2-4c87-b5a8-3441cb569f10', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Produtos de limpeza', '2024-05-07T17:28:20.834Z', '2024-05-07T23:57:30.045Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f92f19df-fcfc-4187-ba73-3457c765e71a', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Sachê de molho', '2024-05-07T04:00:20.696Z', '2024-05-07T17:30:18.941Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('83c733cc-e2b0-4d93-990e-e2e05bf5187c', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Filtro de Café', '2024-05-07T04:00:00.126Z', '2024-05-07T17:31:15.639Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4bccd468-7b89-49f0-93d5-c761ff91c6fb', '5c9b6767-5310-461b-977b-906fe16370ae', 'Pomada para assadura', '2024-05-07T17:32:59.808Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5b5efd8a-6467-4496-bc81-966fbc441b54', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Extensão de Fio', '2024-05-07T07:00:38.959Z', '2024-05-07T17:42:21.699Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5a7c7193-ac38-4376-8ee4-d18034315a7c', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Turno da madrugada', '2024-05-07T17:32:12.898Z', '2024-05-07T22:42:10.227Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7a8dbb8c-1eef-4027-b544-2a415e4864aa', 'b3a81a9d-a964-4413-9a33-974a3b4673d1', 'Máscara', '2024-05-07T14:28:31.884Z', '2024-05-07T17:31:29.132Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f78c85b4-fcac-4854-970b-d80f201d5aa3', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Produtos de higiene', '2024-05-07T17:33:29.768Z', '2024-05-08T02:58:34.522Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('0fe671e5-1f19-4370-ae9d-8e49afa92aba', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas grandes', '2024-05-07T17:32:49.810Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b3d663ed-c0db-441a-83e8-0e4b0db58825', 'b3a81a9d-a964-4413-9a33-974a3b4673d1', 'Fisioterapeutas', '2024-05-07T17:47:58.711Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('cc5459a2-9b43-486b-8c3f-99c507c68562', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Sucos', '2024-05-07T17:54:28.175Z', '2024-05-08T15:40:07.474Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('55884181-02a9-4036-94ac-c6c2645deaef', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Antibioticos - shotapen', '2024-05-07T18:13:42.153Z', '2024-05-08T15:18:07.045Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('69665e5c-b948-46ff-8c0a-d520047d21bd', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Tramadol', '2024-05-07T18:14:04.200Z', '2024-05-08T15:18:32.681Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('35da1e4a-c8d2-4d9f-bd0b-ceec81216994', '5c9b6767-5310-461b-977b-906fe16370ae', 'Ventilador', '2024-05-07T17:57:30.883Z', '2024-05-07T17:59:47.471Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('52634f35-73b2-4c60-99c9-1ec886f6e4b3', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Sabonete infantil ', '2024-05-07T18:54:26.469Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('53361f8d-ac10-44e6-934d-db1c9c374c92', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'SACOS DE AREIA ', '2024-05-07T18:58:33.307Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d98b2225-e6b9-4ba5-9085-ccdcc1d56af9', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'ROUPAS INTIMAS - CUECAS - G ', '2024-05-07T18:59:06.683Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('46862e71-22b7-4023-ba93-2936050c6f9f', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Toalhas de banho', '2024-05-07T19:44:31.500Z', '2024-05-07T19:51:17.148Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7d0f8cf5-9f10-4822-bcde-6b94d1738065', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'CALÇA DE MOLETOM MASC - G ', '2024-05-07T18:59:23.302Z', '2024-05-07T22:07:11.854Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('1822d9b2-10f4-4e0d-a39a-b987ed707fae', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'MOLETOM G/GG ', '2024-05-07T18:59:39.453Z', '2024-05-07T22:06:39.002Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8df22c40-25d7-4f96-8bc6-0fe734f948d3', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'sanduíches/ bolos/ sucos/ lanches fáceis para os recém resgatados.', '2024-05-07T19:01:34.488Z', '2024-05-08T00:05:43.458Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('115de606-b9d6-475b-953b-d838d8783dd6', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Pão', '2024-05-07T17:55:03.463Z', '2024-05-08T15:40:18.018Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('63aacfa9-9d2d-45b3-90c5-c59af6de6f12', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Garfo e faca', '2024-05-07T18:35:53.995Z', '2024-05-07T18:36:34.363Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8e865522-b70c-45f4-aee0-b97c18fbba5f', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'chinelos', '2024-05-07T18:43:55.779Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ceac0bdc-e2a4-467b-9774-c0e3e69fb52e', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'bermuda masculina', '2024-05-07T18:47:19.403Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('65437ee2-7b21-4796-a360-9ad17c50aef5', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'chinelos masculinos', '2024-05-07T18:47:32.409Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8ef123b0-d60f-49b5-b4ef-1e015247b760', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'sapatos masculinos - tênis', '2024-05-07T18:47:57.599Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('29a5dd12-fba3-49db-8c3a-13f706d195d7', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'JORNAL', '2024-05-07T18:58:47.125Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('1114f512-17b1-4c26-927e-5d9888029183', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Creme de pentear', '2024-05-07T19:01:22.550Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('869ed149-9375-4fac-a687-d5450b53ceb8', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas femininas G/GG', '2024-05-07T19:45:19.557Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('0eb6f7b8-4a6c-4e0d-a518-bfdf5c46fa22', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Prendedor de roupas', '2024-05-07T19:53:36.526Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d52b7643-1731-48cb-9859-797c159d67b7', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Areia de gato', '2024-05-07T18:36:13.682Z', '2024-05-07T20:58:38.430Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4ae4acec-ee0d-40f3-931c-37759e97ecff', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Café', '2024-05-07T18:17:19.515Z', '2024-05-08T13:53:07.673Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('27493e1f-4f5c-4149-aabf-9c4f6697a35f', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Macarrão', '2024-05-07T18:18:07.151Z', '2024-05-08T13:54:06.355Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4124cef6-ffc1-40b7-8cb0-8b4a89dab6f2', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Frios', '2024-05-07T20:39:29.055Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3aaefd40-754e-434d-b4af-180fdd60174c', '5c9b6767-5310-461b-977b-906fe16370ae', 'TATAMES', '2024-05-07T18:22:58.756Z', '2024-05-07T22:50:42.364Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('bd92845d-ebfc-4a62-94e8-881649dba98e', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Bermudas', '2024-05-07T18:44:09.774Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('cab34f52-bc3e-46d8-96f0-f5b20c7ca485', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'toalhas', '2024-05-07T18:46:46.309Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('27c3707c-4a0b-4b43-8f8c-1b4bba103aa9', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'travesseiro', '2024-05-07T18:46:56.688Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('9af075ac-8d39-4843-8907-02ccb6b5910b', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Marmitas', '2024-05-06T13:18:11.085Z', '2024-05-07T18:53:22.475Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('91c1ee8c-c4bc-4858-86cb-c47b80846004', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'COBERTAS PARA PETS', '2024-05-07T18:57:48.647Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2de8d7b7-2d63-4a05-bf0b-2aaa0c9e24f7', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'TELAS / CHIQUEIROS ', '2024-05-07T18:58:02.983Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('54ba7af2-d6a6-41e9-b0e7-8230479c1e5e', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'BERMUDA MASC G/GG', '2024-05-07T18:59:53.685Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b1d8f194-15ac-4490-b062-d45434d41966', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Fita adesiva (durex)', '2024-05-07T19:03:33.691Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d2123a82-91a0-4f30-896b-61ee15ade670', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Condicionador ', '2024-05-07T19:05:57.847Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('36294c41-22ed-4750-afdd-ce758eff8a26', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'MARMITAS PARA 6000 PESSOAS', '2024-05-07T19:11:51.938Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('59ce1afa-2583-4810-b726-e8fa4c7e5464', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Potes (marmitex)', '2024-05-07T19:47:18.039Z', '2024-05-07T19:52:55.413Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d4bfdb7f-b11d-405d-99c6-99c135eb89d4', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Casacos masculinos M/G/GG', '2024-05-07T19:46:35.349Z', '2024-05-07T22:06:56.156Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7baf0c84-7658-4f5d-829a-36f6194c154f', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Proteínas', '2024-05-07T20:37:14.193Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4c4b59cc-d639-4952-87e3-107c61c2a673', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Farinha de trigo', '2024-05-07T20:39:56.596Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('1b45a959-c141-4d5b-a112-49cc10985fa1', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Alimentos para consumo rápido (Leite, bolacha, suco, etc)', '2024-05-07T20:40:23.082Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c62388dd-1718-4acc-80f6-447a991ef685', '5c9b6767-5310-461b-977b-906fe16370ae', 'NÃO ESTAMOS ABERTOS AINDA', '2024-05-07T18:16:37.627Z', '2024-05-07T22:50:35.997Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c0510523-3ceb-4069-a7df-3c9cf65dda06', '5c9b6767-5310-461b-977b-906fe16370ae', 'CAIXAS DE PAPELÃO ', '2024-05-07T18:23:13.195Z', '2024-05-07T22:50:53.502Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e3f6bdb7-6e6a-4cf9-bb2b-e16c0bae5dfc', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'SOMENTE PARA FAMÍLIAS ATÍPICAS', '2024-05-07T18:20:45.859Z', '2024-05-07T22:50:58.814Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6e6b1dcf-00dc-4a8d-b16f-b99fdbedda27', '5c9b6767-5310-461b-977b-906fe16370ae', 'Teste', '2024-05-07T20:31:18.613Z', '2024-05-08T03:38:57.445Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('21ef7b82-d386-482e-811d-7de76fcd16bc', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Balde', '2024-05-07T17:03:33.026Z', '2024-05-07T20:48:39.163Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b813d3b5-bf55-443b-b1a4-be3d426af4e9', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Fralda RN', '2024-05-07T20:55:03.541Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('52bd1913-9ae1-413d-8258-205049df62e6', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Roupa íntima feminina', '2024-05-07T21:32:40.164Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('07249168-622c-442a-a00a-5264f3a26f74', '05583098-5f2e-44e2-b874-452ec86d9d3e', 'Caminhão Pipa', '2024-05-07T20:56:33.956Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2477f44f-2324-4eec-a191-10ad25b564e9', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'caixa de areia (gato)', '2024-05-07T18:36:00.053Z', '2024-05-07T20:58:52.736Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('60852499-daab-47a4-a8b1-330951fe3eb2', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Jornal/Papelão ', '2024-05-07T22:16:40.116Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('cc4fe301-5eaa-4792-bfd0-33ee4f4a64ad', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Desodorante roll-on sem álcool', '2024-05-07T21:31:40.304Z', '2024-05-08T14:26:58.669Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e904d182-a778-4fac-94fb-61cfc5b6a8ba', '5c9b6767-5310-461b-977b-906fe16370ae', 'Fita Durex larga', '2024-05-07T22:40:24.728Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5a4901b0-14eb-4c88-92ff-bb82aff88094', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Mascara', '2024-05-07T22:41:31.631Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ab8709c7-2655-4f0f-b1bc-68363acf5f87', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Fórmula/leite em pó ', '2024-05-07T22:57:09.823Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('43182ad9-083f-4b64-a53b-986e1a74d695', '5c9b6767-5310-461b-977b-906fe16370ae', 'EVACUADO', '2024-05-07T23:19:27.294Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('15121282-bdc8-4096-845b-974401b2e6aa', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Shampoo/condicionador ', '2024-05-07T15:34:57.838Z', '2024-05-07T23:57:51.857Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f3289ada-0435-4441-a89c-e3e290c1beff', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'DIPIRONA GOTAS E COMPRIMIDOS', '2024-05-07T18:58:18.753Z', '2024-05-08T00:07:11.384Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('caa77bd6-4cf9-44a5-aa24-2e68c899081a', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Arroz', '2024-05-07T22:35:15.159Z', '2024-05-08T00:17:04.836Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('01794c4c-0038-4330-a478-0d10c85fb2d0', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Feijão ', '2024-05-07T22:34:57.148Z', '2024-05-08T00:17:10.414Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f013501e-e9ea-478f-af0d-648f96244b14', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Roupa íntima masculina', '2024-05-07T21:33:03.055Z', '2024-05-08T14:22:34.274Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('85255f2d-f774-48bb-aeec-66b711ebcd2c', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'TATAME', '2024-05-07T18:57:34.515Z', '2024-05-07T22:00:03.748Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2a340b8d-52f2-4c15-9424-fc97bb70dc30', '05583098-5f2e-44e2-b874-452ec86d9d3e', 'Caminhões', '2024-05-07T22:12:30.701Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('39b95236-1136-4154-b79d-a03b7e04be02', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Voluntaruado Madrugada', '2024-05-07T21:59:55.400Z', '2024-05-08T02:47:00.501Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('74dc7f47-7298-418b-9b5b-04c47914721b', '5c9b6767-5310-461b-977b-906fe16370ae', 'Repelente', '2024-05-07T22:41:12.321Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f6692860-7384-4b9a-a4e6-1e1c73ec798b', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Chinelo ', '2024-05-07T22:47:47.032Z', '2024-05-07T22:48:22.773Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2f3a8fa1-713c-4e53-82c9-d95a0383c345', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Fralda geriátrica', '2024-05-07T22:53:43.814Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a1c072fc-9a1d-4f28-a543-b6f21a7863c0', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Luvas descartáveis ', '2024-05-07T23:01:21.080Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('47f6a9ff-9285-4814-8697-29045eb4ac49', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Plus Size/GG', '2024-05-07T23:30:40.840Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d7169b4a-e0ef-469b-8427-f2191ebe432b', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupa Masculina', '2024-05-07T23:33:14.902Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('fcfdeaeb-0760-4f93-bac9-76b804551ce9', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Suco de caixinha', '2024-05-06T18:20:45.034Z', '2024-05-07T23:58:12.123Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5992e29f-0982-4f26-b0fd-7b44fc6c08fd', '5c9b6767-5310-461b-977b-906fe16370ae', 'Oléo', '2024-05-07T22:35:34.804Z', '2024-05-08T00:17:33.694Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('1ca48fb5-6df6-4884-ac61-9c9760041ee1', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Lona', '2024-05-07T23:13:18.203Z', '2024-05-08T15:41:16.899Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('bbdd5c64-f80e-4233-9928-7931fe5e3703', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Seringas', '2024-05-08T00:13:21.171Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5e3faa0a-8bf7-4182-b057-cec38d4bed2d', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Travesseiros/almofada', '2024-05-08T00:33:52.817Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('b00827d0-bac9-4338-8afd-7fae5a79612f', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Luva de Latex Descartável', '2024-05-08T01:12:45.846Z', '2024-05-08T12:54:54.549Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ad9a4dad-3dc5-46b3-b387-889fc5b0b186', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupa Masculina Adulta', '2024-05-08T01:16:12.507Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8c4ed7fa-8b92-492e-bf05-94d2fd4f5016', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Detergente', '2024-05-08T01:16:53.833Z', '2024-05-08T01:17:04.276Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('eb01d39b-e347-4a3f-a0ea-f59f916a2236', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Sapato Masculino ', '2024-05-08T01:19:28.222Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6d965a4b-3b38-4418-a95e-b0aec0e0eb7a', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Leite em pó', '2024-05-08T01:20:13.517Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e4e767ff-be22-4c15-99a3-fac2b97683df', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Shampoo ', '2024-05-08T01:21:03.786Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3a9fc3a5-6dcb-423f-812e-3175b59ea51c', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Feijão', '2024-05-08T01:21:36.563Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('69732c83-e2ee-481f-b4c5-e55932e8d51f', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Azeite', '2024-05-08T01:21:45.114Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4fe297e6-4d45-445e-93a1-0f59f9fb5d68', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Sapato Infantil ', '2024-05-08T01:21:57.223Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c38e4aa6-bc90-4592-ae7d-95d93de12ec4', '5c9b6767-5310-461b-977b-906fe16370ae', 'Polenta', '2024-05-08T01:28:16.543Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c1e4ef3f-0d86-418f-9d9f-05f028246bed', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Fralda XG e XXG', '2024-05-08T01:35:51.498Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('603dec10-b1e7-4034-aa4b-b0362347387b', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Latas de lixo', '2024-05-08T01:38:27.257Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('3f4a6357-7a1b-4c64-a48b-7c6136e3f472', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Gatorade/Isotônico', '2024-05-08T01:39:16.288Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('eaeaef1a-3f8f-4610-81f3-8f070eb4b07d', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Chinelos (todos os tamanhos)', '2024-05-08T01:39:30.849Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('634649db-5f8b-47b8-a034-f3a78c53dbfe', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Voluntário - Madrugada', '2024-05-06T13:04:28.501Z', '2024-05-08T01:41:08.441Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('dbcb6fc3-02b4-4e31-8924-ed56f0e6ecc1', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Itens de higiena pessoal', '2024-05-08T01:44:33.184Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e4f030c3-a985-4cc0-8336-9b55e1acc79f', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Itens de limpeza', '2024-05-08T01:44:43.317Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('53743f4f-eded-4145-b56e-224eab9471ec', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Luz de Emergência', '2024-05-08T01:09:38.515Z', '2024-05-08T12:55:33.404Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4d57d380-9335-4127-83fc-a54c7feeb0aa', '5c9b6767-5310-461b-977b-906fe16370ae', 'Freezer para armazenar comida', '2024-05-08T01:47:36.020Z', '2024-05-08T01:48:06.476Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('24857c6e-7fe5-45e8-9cc5-c5858390c06d', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Molho de tomate', '2024-05-08T02:04:25.978Z', '2024-05-08T02:05:38.414Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a6d3299c-fa53-493d-999c-56050e230a2b', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Farinha Mandioca', '2024-05-08T02:03:02.013Z', '2024-05-08T12:46:56.511Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5c1839cf-e5e9-4963-9018-c4d6f9ac5aeb', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Plástico filme', '2024-05-08T02:04:43.531Z', '2024-05-08T15:41:02.235Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5e2c418e-729b-4f4f-bef7-db807ca37de3', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Ventiladores', '2024-05-08T02:03:21.070Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7937bae2-155c-4357-99fb-86200485c51f', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Chinelos ', '2024-05-08T02:32:57.305Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e219552a-516b-4008-8341-b850a0102d35', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Assento p vaso sanitário', '2024-05-08T02:43:02.010Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('0f0fffef-ec91-4dc1-b8ac-41d189b1b026', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Gelo', '2024-05-08T02:43:15.092Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('1cfbb391-a7a6-42d2-b585-3f4ec40bf764', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Bermudas masculina tecido leve', '2024-05-08T02:43:44.438Z', '2024-05-08T02:44:02.671Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('fc763265-b328-4fa5-9975-307e97ec35ca', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Calçado masculino', '2024-05-08T02:44:34.563Z', '2024-05-08T02:44:44.370Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5ea0fec2-32ed-4302-9ef1-1daac2556be9', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Máquina de lavar roupa', '2024-05-08T02:47:32.148Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('440b1d5b-4b68-4118-be94-5f8644c0c36f', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Ganchos para montar varal', '2024-05-08T02:48:24.592Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('785546df-e5cc-432a-ab64-a4888c935121', 'fd1f74c4-6723-4ffe-8657-773a943e65c4', 'Luminárias com pedestal para área saúde 1m altura pelo menos', '2024-05-08T02:49:05.807Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('496185c5-16e8-4576-9778-0514ca727dbc', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Aparelho de barbear', '2024-05-07T16:22:03.975Z', '2024-05-08T02:58:00.013Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('cac2375f-e9af-41e4-b88f-7002ee54cabe', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Muriel ', '2024-05-08T03:21:27.125Z', '2024-05-08T03:22:15.102Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('14274ddb-ffb6-429c-9aa2-e68ece7d1ab9', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Remédios para pets', '2024-05-08T04:30:16.167Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e99b7beb-668d-45f0-b368-6fad52f284a5', '5c9b6767-5310-461b-977b-906fe16370ae', 'Material de Limpeza Geral', '2024-05-07T10:53:21.931Z', '2024-05-08T05:08:02.387Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('1705650f-20a0-402d-bd82-cf61f4b58fb5', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'pix', '2024-05-08T05:18:22.106Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2a0e1ee4-1cfa-4e9b-a94a-8b3fa659595c', '5c9b6767-5310-461b-977b-906fe16370ae', '', '2024-05-08T05:25:11.070Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('112f1380-ebef-4697-87e8-7cb8a1e05cf7', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Sacolas ou sacos plásticos ', '2024-05-08T10:30:46.714Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('980732ea-cfd4-41a3-95df-4e7725f7c107', '6e6aaf88-b9fb-4a38-ab92-0db63c30e3f8', 'Caixas de Papelão', '2024-05-08T10:34:48.963Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('883fd833-4187-4b99-82a4-0afc665a899a', '5c9b6767-5310-461b-977b-906fe16370ae', 'Gás', '2024-05-08T10:42:44.915Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2c0eabfd-5c22-4174-b93d-b814a7706b9e', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Embalagem descartável para as marmitas', '2024-05-08T02:04:02.781Z', '2024-05-08T15:41:08.945Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('85e69daa-6471-44c1-9313-be546eda7bf9', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Escova de debte', '2024-05-08T10:44:01.161Z', '2024-05-08T10:44:54.611Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('251dcbe0-fcd2-47d9-9527-3de6aaf26281', '5c9b6767-5310-461b-977b-906fe16370ae', 'Azitotromicina', '2024-05-08T10:46:19.201Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d1afbc6f-fcab-421a-89fc-10bec2fdd4ff', '5c9b6767-5310-461b-977b-906fe16370ae', 'Colírio ', '2024-05-08T10:46:51.353Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a257142f-813f-4450-bf2c-8ce9a51d86ed', '5c9b6767-5310-461b-977b-906fe16370ae', 'Antibiótico ', '2024-05-08T10:47:09.989Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a75e630a-4b6f-4b5e-b013-12770df0a6f8', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Suco de caixinha ', '2024-05-08T10:49:05.414Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2d3cf6fc-8424-47d6-8908-903526827010', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Ração ', '2024-05-08T11:52:30.536Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('66329b48-ccaf-4fa1-a2f6-3ad4ff61b82d', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Saquinhos - para montar kits ', '2024-05-08T12:02:03.845Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('09939054-16f2-454f-82c8-d8a39cb138ad', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'Rolo Lona Preta 40m x 6m (mais grossa)', '2024-05-07T20:53:09.079Z', '2024-05-08T13:12:13.360Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('5b719a56-5bda-4c09-891e-f15c0cdfc51a', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Calçado masculino (principalmente chinelo)', '2024-05-08T13:25:43.188Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('88f0efe9-8a5d-4c4c-8f7e-42b3f0ce8feb', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Xampu', '2024-05-08T13:27:23.344Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('59991d33-10e6-48af-be3e-274fa5960fc2', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Itens para criança ', '2024-05-08T13:28:07.915Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('689c1d43-a7ee-4b95-97df-1558fbfcb863', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Desodorante ', '2024-05-08T13:28:40.632Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ffc9891b-43d3-4134-8e9c-7ada4690d076', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Sabonete glicerinado (para machucados)', '2024-05-08T13:29:09.801Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('063d43f1-9f08-4943-8f82-b51aa4e49924', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Pomada para assadura ', '2024-05-08T13:29:57.355Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('15129370-e9f5-4797-87cf-225625bc7642', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Guardanapo de papel', '2024-05-08T13:34:41.526Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('060bd404-4214-469e-bac3-ea801400ea5e', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Sacolinhas plasticas e saquinhos pra montar kit de comida', '2024-05-08T13:35:17.661Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('73fbacb1-0736-49ec-8873-80ddd65608a2', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupa íntima masculina e feminina', '2024-05-08T13:35:25.096Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c31acdf4-e0c4-44a1-b95f-ac267fa6b75f', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupa plus size', '2024-05-08T13:35:50.123Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('90a9b8d2-2a53-428b-82ff-03506fb54302', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Condicionador', '2024-05-08T13:38:06.398Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8980a8e1-5aa6-4168-8cd6-e06f6ab9275a', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Refri pequeno', '2024-05-08T10:49:37.352Z', '2024-05-08T13:44:39.386Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('60514d82-d54a-472f-b482-5e93f2873b26', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Focinheira', '2024-05-08T13:06:28.297Z', '2024-05-08T15:42:19.330Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a1f3cbac-ed68-4875-85a3-dae686767837', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Pá de lixo', '2024-05-08T13:38:46.819Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('9092081f-0160-44ed-bc7d-2aa1819390f5', '5c9b6767-5310-461b-977b-906fe16370ae', 'Hipoglós', '2024-05-08T13:39:38.007Z', '2024-05-08T13:41:09.036Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('92542ce7-d1b9-4da5-9c93-38698fd0f042', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas GG', '2024-05-08T13:42:27.646Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('9798cd10-1d06-42a0-921b-83e17b91a90c', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Bolachinha ', '2024-05-08T10:49:27.210Z', '2024-05-08T13:44:33.386Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f3c395aa-63af-4264-99e0-2bd29760c62e', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Lenço umedecido ', '2024-05-08T13:41:01.048Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('22d6eaff-3933-418f-9287-7e45c300bfad', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Cortador de unha', '2024-05-08T13:42:53.302Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('c8ce7a65-be98-4e38-beaa-b9907dc003e9', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'Fraldas Geriátricas', '2024-05-08T13:44:27.004Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('e6d4396b-4097-4acf-a4e8-aac46722ad68', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Pá de Lixo', '2024-05-08T13:40:00.766Z', '2024-05-08T13:50:30.458Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a8c18a44-ec60-4a19-8e96-785c49de9630', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Toddynho', '2024-05-08T10:48:50.546Z', '2024-05-08T13:44:16.982Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('f040d5f7-db89-4068-a735-9c0082f30710', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Sapato masculino 43/44', '2024-05-08T14:18:29.029Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('599bee49-16ea-4ea6-9a4a-ae3043926417', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Frutas', '2024-05-08T14:19:56.118Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('a3b72470-8acf-43e6-a60e-e81685fb330d', '03fdb0f2-6b50-4895-b970-5793cad80c86', 'Luvas de procedimento', '2024-05-08T14:20:56.180Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('8550fcc0-103c-46ee-a632-7cbb45f1b74a', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'Talher Descartável ', '2024-05-08T14:25:04.086Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('33ad04bc-0c6c-4137-98c2-4ad8ca9559ef', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Alimentos Diets', '2024-05-08T14:25:38.271Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('6ee709d9-f990-41e3-9f92-a75f8d5e4855', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Ração gato', '2024-05-08T14:37:05.612Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('31ed387d-9786-44eb-88fb-3e19e00ba53a', '037ac262-4f35-42e0-83e1-4cdcceedb39c', 'toucas', '2024-05-08T14:37:58.920Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4eb7c42e-8499-438d-9298-3ca063eca896', '60d6808e-9d13-484d-84a4-2ca35d42b3a6', 'pallets', '2024-05-08T14:38:08.709Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('4fa35b65-02e9-4077-bddb-91ad40210ead', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'agua potavel e para limpeza', '2024-05-08T14:38:51.589Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('7a8d33b7-5d02-4c6a-9df8-9cecd60e43ed', '718d5be3-69c3-4216-97f1-12b690d0eb97', 'tapete higienico', '2024-05-08T14:39:13.786Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('ecfa6079-84f1-41f8-a86f-cf0e133a135e', '5d50d3cf-4e36-4639-813d-d43de8886ac8', 'Sacolas Para Montar Kits', '2024-05-08T14:45:46.856Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('aa508257-4477-47e7-8c39-77b8b39fe8bb', '5c9b6767-5310-461b-977b-906fe16370ae', 'Remédio para piolho', '2024-05-08T15:03:41.319Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('70ca14b1-0240-4bc7-902c-903fbe74da31', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Filtro de café ', '2024-05-08T15:05:41.441Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('fea081c1-7939-4516-97a5-f2cd49177577', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupa íntima ', '2024-05-08T15:34:51.112Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('58c7d1c9-8e7f-4d68-8ede-da32a40500bc', 'a3e3bdf8-0be4-4bdc-a3b0-b40ba931be5f', 'Achocolatado pronto', '2024-05-07T17:54:39.064Z', '2024-05-08T15:40:13.834Z'); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('258deaa1-d4c1-4e51-9a29-9883f68d506d', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas plus size masculino', '2024-05-08T15:58:57.509Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('2fe71172-ab32-490e-91ae-0ec727bd3d52', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas plus size feminina', '2024-05-08T15:59:23.476Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('fcffd019-56c9-4949-8a10-6b6f5104291c', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas íntimas plus size feminina', '2024-05-08T15:59:59.447Z', null); +INSERT INTO public.supplies (id, supply_category_id, name, created_at, updated_at) VALUES ('d1a27ea2-0281-4c95-9154-6509ede0f2dd', 'bf8b5e09-544f-4eff-9bb7-6220aaa34a85', 'Roupas íntimas plus size masculina', '2024-05-08T16:00:15.861Z', null); +INSERT INTO public.users (id, name, login, password, phone, created_at, updated_at, "accessLevel", "lastName") VALUES ('e0306bc0-8c29-429a-bbd2-384f48d4f993', 'Dinho', '31996675945', '$2b$10$q1QlN.55ruK52W91HkxULuF0YltXlZNRj2vOiqEyVhNxqQ6zGrWia', '31996675945', '2024-05-05T22:04:59.468Z', '2024-05-05T22:05:40.820Z', 'User', 'Duarte'); +INSERT INTO public.users (id, name, login, password, phone, created_at, updated_at, "accessLevel", "lastName") VALUES ('e82f476a-1574-4dd2-a4c4-1c1f0117db12', 'Rhuam', '51992047974', '$2b$10$5OWVxBKIfRwvdMhRdO4QIuZrjDvtAwby33jUO4Q3LAHQ8pMW6eMhG', '51992047974', '2024-05-05T22:06:11.390Z', null, 'Staff', 'Rhuam'); +INSERT INTO public.users (id, name, login, password, phone, created_at, updated_at, "accessLevel", "lastName") VALUES ('90d1d707-3b34-4c9d-a025-b26dcc035304', 'Flávia', '51997522219', '$2b$10$QUEKmG.q/sQsW0HRzl/pkuG3Px.6kNJXGzIXJRLrqfKp5WVv3m8.K', '51997522219', '2024-05-08T16:30:13.413Z', null, 'User', 'Flávia'); +SET session_replication_role = 'origin'; diff --git a/prisma/migrations/20240509235041_/migration.sql b/prisma/migrations/20240509235041_/migration.sql new file mode 100644 index 00000000..6d7908dc --- /dev/null +++ b/prisma/migrations/20240509235041_/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "shelter_supplies" ADD COLUMN "quantity" INTEGER; diff --git a/prisma/migrations/20240510225124_/migration.sql b/prisma/migrations/20240510225124_/migration.sql new file mode 100644 index 00000000..51d051bf --- /dev/null +++ b/prisma/migrations/20240510225124_/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "AccessLevel" ADD VALUE 'DistributionCenter'; diff --git a/prisma/migrations/20240511054108_/migration.sql b/prisma/migrations/20240511054108_/migration.sql new file mode 100644 index 00000000..a443ede5 --- /dev/null +++ b/prisma/migrations/20240511054108_/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "AccessLevel" ADD VALUE 'Admin'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3fab817b..792b1f65 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -10,6 +10,8 @@ datasource db { enum AccessLevel { User Staff + DistributionCenter + Admin } model User { @@ -58,6 +60,7 @@ model ShelterSupply { shelterId String @map("shelter_id") supplyId String @map("supply_id") priority Int @default(value: 0) + quantity Int? createdAt String @map("created_at") @db.VarChar(32) updatedAt String? @map("updated_at") @db.VarChar(32) diff --git a/src/decorators/index.ts b/src/decorators/index.ts deleted file mode 100644 index 6d8386f7..00000000 --- a/src/decorators/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { SearchQuery } from './search-query'; - -export { SearchQuery }; diff --git a/src/decorators/search-query/index.ts b/src/decorators/search-query/index.ts deleted file mode 100644 index 65273983..00000000 --- a/src/decorators/search-query/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { SearchQuery } from './search-query.decorator'; - -export { SearchQuery }; diff --git a/src/decorators/search-query/search-query.decorator.ts b/src/decorators/search-query/search-query.decorator.ts deleted file mode 100644 index 94748253..00000000 --- a/src/decorators/search-query/search-query.decorator.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { createParamDecorator, ExecutionContext } from '@nestjs/common'; - -import { getSearchWhere, parseStringToObject } from '@/utils'; -import { - SeachQueryProps, - SeachQueryPropsWithoutSearch, - SearchQueryPropsOptions, - SearchSchema, -} from './types'; - -function handleSearch(props: SeachQueryPropsWithoutSearch) { - return async function (model: any, options?: SearchQueryPropsOptions) { - const { hooks, select } = options ?? {}; - const { - download, - order, - orderBy, - page, - perPage, - search, - include = '', - or, - } = props; - const { afterWhere, beforeWhere } = hooks ?? {}; - const where = {}; - - if (beforeWhere) Object.assign(where, beforeWhere(where)); - Object.assign(where, getSearchWhere(search, or)); - if (afterWhere) Object.assign(where, afterWhere(where)); - - const count = await model.count({ where }); - - const take = download ? undefined : perPage; - const skip = download ? undefined : perPage * (page - 1); - - const query = { - take, - skip, - orderBy: parseStringToObject(orderBy, order), - where, - }; - - const includeData = include - .split(',') - .reduce((prev, curr) => (curr ? { ...prev, [curr]: true } : prev), {}); - - if (Object.keys(includeData).length > 0) query['include'] = includeData; - else if (select) query['select'] = select; - - const results = await model.findMany(query); - - return { page, perPage, count, results }; - }; -} - -export const SearchQuery = createParamDecorator( - (_, ctx: ExecutionContext): SeachQueryProps => { - const request = ctx.switchToHttp().getRequest(); - const query = request.query; - - const searchQueryProps = SearchSchema.parse({ - perPage: query.perPage, - page: query.page, - search: query.search, - orderBy: query.orderBy, - order: query.order, - download: query.download, - include: query.include, - or: query.or, - }); - - return { - query: searchQueryProps, - handleSearch: handleSearch(searchQueryProps), - }; - }, -); diff --git a/src/decorators/search-query/types.ts b/src/decorators/search-query/types.ts deleted file mode 100644 index 3545673e..00000000 --- a/src/decorators/search-query/types.ts +++ /dev/null @@ -1,55 +0,0 @@ -import z from 'zod'; - -const SearchSchema = z.object({ - perPage: z.preprocess( - (v) => +((v ?? '20') as string), - z.number().min(1).max(100), - ), - page: z.preprocess((v) => +((v ?? '1') as string), z.number().min(1)), - search: z.string().default(''), - order: z.enum(['desc', 'asc']).default('desc'), - orderBy: z.string().default('createdAt'), - download: z.preprocess( - (v) => (v ?? 'false') === 'true', - z.boolean().default(false), - ), - include: z.string().optional(), - or: z.preprocess( - (v) => (v ?? 'false') === 'true', - z.boolean().default(false), - ), -}); - -const SearchResponseSchema = z.object({ - count: z.number().min(0), - results: z.array(z.any()), -}); - -type SeachQueryPropsWithoutSearch = z.infer; - -interface SeachQueryPropsHooks { - beforeWhere?: (where: Record) => Record; - afterWhere?: (where: Record) => Record; -} - -interface SearchQueryPropsOptions { - hooks?: SeachQueryPropsHooks; - select?: T; -} - -interface SeachQueryProps { - query: SeachQueryPropsWithoutSearch; - handleSearch( - model: any, - options?: SearchQueryPropsOptions, - ): Promise>; -} - -export { - SeachQueryProps, - SeachQueryPropsHooks, - SeachQueryPropsWithoutSearch, - SearchQueryPropsOptions, - SearchResponseSchema, - SearchSchema, -}; diff --git a/src/guards/admin.guard.ts b/src/guards/admin.guard.ts new file mode 100644 index 00000000..2ced18c4 --- /dev/null +++ b/src/guards/admin.guard.ts @@ -0,0 +1,20 @@ +import { ExecutionContext, HttpException, Injectable } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { AccessLevel } from '@prisma/client'; + +import { canActivate } from './utils'; + +@Injectable() +export class AdminGuard extends AuthGuard('jwt') { + constructor() { + super(); + } + + async canActivate(context: ExecutionContext): Promise { + await super.canActivate(context); + const ok = await canActivate(context, [AccessLevel.Admin]); + if (ok) return true; + + throw new HttpException('Acesso não autorizado', 401); + } +} diff --git a/src/guards/distribution-center.guard.ts b/src/guards/distribution-center.guard.ts new file mode 100644 index 00000000..c829f271 --- /dev/null +++ b/src/guards/distribution-center.guard.ts @@ -0,0 +1,23 @@ +import { ExecutionContext, HttpException, Injectable } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { AccessLevel } from '@prisma/client'; + +import { canActivate } from './utils'; + +@Injectable() +export class DistributionCenterGuard extends AuthGuard('jwt') { + constructor() { + super(); + } + + async canActivate(context: ExecutionContext): Promise { + await super.canActivate(context); + const ok = await canActivate(context, [ + AccessLevel.Admin, + AccessLevel.DistributionCenter, + ]); + if (ok) return true; + + throw new HttpException('Acesso não autorizado', 401); + } +} diff --git a/src/guards/staff.guard.ts b/src/guards/staff.guard.ts index 0e5d99d6..fcd838f3 100644 --- a/src/guards/staff.guard.ts +++ b/src/guards/staff.guard.ts @@ -12,7 +12,10 @@ export class StaffGuard extends AuthGuard('jwt') { async canActivate(context: ExecutionContext): Promise { await super.canActivate(context); - const ok = await canActivate(context, [AccessLevel.Staff]); + const ok = await canActivate(context, [ + AccessLevel.Admin, + AccessLevel.Staff, + ]); if (ok) return true; throw new HttpException('Acesso não autorizado', 401); diff --git a/src/guards/user.guard.ts b/src/guards/user.guard.ts index fb03254e..f5c7c13c 100644 --- a/src/guards/user.guard.ts +++ b/src/guards/user.guard.ts @@ -13,8 +13,10 @@ export class UserGuard extends AuthGuard('jwt') { async canActivate(context: ExecutionContext): Promise { await super.canActivate(context); const ok = await canActivate(context, [ - AccessLevel.Staff, AccessLevel.User, + AccessLevel.Staff, + AccessLevel.DistributionCenter, + AccessLevel.Admin, ]); if (ok) return true; throw new HttpException('Acesso não autorizado', 401); diff --git a/src/prisma/hooks/shelter/index.ts b/src/prisma/hooks/shelter/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/prisma/hooks/shelter/shelter-hooks.ts b/src/prisma/hooks/shelter/shelter-hooks.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/prisma/hooks/user/index.ts b/src/prisma/hooks/user/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/prisma/hooks/user/user-hooks.ts b/src/prisma/hooks/user/user-hooks.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/shelter-managers/shelter-managers.controller.spec.ts b/src/shelter-managers/shelter-managers.controller.spec.ts index 45704316..5bc76a94 100644 --- a/src/shelter-managers/shelter-managers.controller.spec.ts +++ b/src/shelter-managers/shelter-managers.controller.spec.ts @@ -9,7 +9,9 @@ describe('ShelterManagersController', () => { controllers: [ShelterManagersController], }).compile(); - controller = module.get(ShelterManagersController); + controller = module.get( + ShelterManagersController, + ); }); it('should be defined', () => { diff --git a/src/shelter-managers/shelter-managers.controller.ts b/src/shelter-managers/shelter-managers.controller.ts index 897c5c7b..adea36c2 100644 --- a/src/shelter-managers/shelter-managers.controller.ts +++ b/src/shelter-managers/shelter-managers.controller.ts @@ -13,7 +13,7 @@ import { ApiTags } from '@nestjs/swagger'; import { ShelterManagersService } from './shelter-managers.service'; import { ServerResponse } from '../utils'; -import { StaffGuard } from '@/guards/staff.guard'; +import { AdminGuard } from '@/guards/admin.guard'; @ApiTags('Admin de Abrigo') @Controller('shelter/managers') @@ -25,7 +25,7 @@ export class ShelterManagersController { ) {} @Post('') - @UseGuards(StaffGuard) + @UseGuards(AdminGuard) async store(@Body() body) { try { await this.shelterManagerServices.store(body); diff --git a/src/shelter-supply/shelter-supply.controller.ts b/src/shelter-supply/shelter-supply.controller.ts index 749e39d9..e2d3df69 100644 --- a/src/shelter-supply/shelter-supply.controller.ts +++ b/src/shelter-supply/shelter-supply.controller.ts @@ -7,11 +7,13 @@ import { Param, Post, Put, + UseGuards, } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { ShelterSupplyService } from './shelter-supply.service'; import { ServerResponse } from '../utils'; +import { DistributionCenterGuard } from '@/guards/distribution-center.guard'; @ApiTags('Suprimento de abrigos') @Controller('shelter/supplies') @@ -67,4 +69,23 @@ export class ShelterSupplyController { throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); } } + + @Put(':shelterId/supplies/many') + @UseGuards(DistributionCenterGuard) + async updateMany(@Body() body, @Param('shelterId') shelterId: string) { + try { + const data = await this.shelterSupplyService.updateMany({ + shelterId, + ...body, + }); + return new ServerResponse( + 200, + 'Successfully updated many shelter supplies', + data, + ); + } catch (err: any) { + this.logger.error(`Failed to update many shelter supplies: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } } diff --git a/src/shelter-supply/shelter-supply.service.ts b/src/shelter-supply/shelter-supply.service.ts index c2d7c9c6..73faddc4 100644 --- a/src/shelter-supply/shelter-supply.service.ts +++ b/src/shelter-supply/shelter-supply.service.ts @@ -2,7 +2,12 @@ import { z } from 'zod'; import { Injectable } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; -import { CreateShelterSupplySchema, UpdateShelterSupplySchema } from './types'; +import { + CreateShelterSupplySchema, + UpdateManyShelterSupplySchema, + UpdateShelterSupplySchema, +} from './types'; +import { SupplyPriority } from '../supply/types'; @Injectable() export class ShelterSupplyService { @@ -27,7 +32,7 @@ export class ShelterSupplyService { } async store(body: z.infer) { - const { shelterId, priority, supplyId } = + const { shelterId, priority, supplyId, quantity } = CreateShelterSupplySchema.parse(body); await this.handleUpdateShelterSum(shelterId, 0, priority); await this.prismaService.shelterSupply.create({ @@ -35,6 +40,7 @@ export class ShelterSupplyService { shelterId, priority, supplyId, + quantity: priority !== SupplyPriority.UnderControl ? quantity : null, createdAt: new Date().toISOString(), }, }); @@ -42,7 +48,7 @@ export class ShelterSupplyService { async update(body: z.infer) { const { data, where } = UpdateShelterSupplySchema.parse(body); - const { priority } = data; + const { priority, quantity } = data; if (priority !== null && priority !== undefined) { const shelterSupply = await this.prismaService.shelterSupply.findFirst({ where: { @@ -67,7 +73,25 @@ export class ShelterSupplyService { }, data: { ...data, - createdAt: new Date().toISOString(), + quantity: priority !== SupplyPriority.UnderControl ? quantity : null, + updatedAt: new Date().toISOString(), + }, + }); + } + + async updateMany(body: z.infer) { + const { ids, shelterId } = UpdateManyShelterSupplySchema.parse(body); + + await this.prismaService.shelterSupply.updateMany({ + where: { + shelterId: shelterId, + supplyId: { + in: ids, + }, + }, + data: { + priority: SupplyPriority.UnderControl, + updatedAt: new Date().toISOString(), }, }); } @@ -79,6 +103,7 @@ export class ShelterSupplyService { }, select: { priority: true, + quantity: true, supply: { select: { id: true, diff --git a/src/shelter-supply/types.ts b/src/shelter-supply/types.ts index 8ce77ee6..1ff25f90 100644 --- a/src/shelter-supply/types.ts +++ b/src/shelter-supply/types.ts @@ -12,6 +12,7 @@ const ShelterSupplySchema = z.object({ z.literal(SupplyPriority.Needing), z.literal(SupplyPriority.Urgent), ]), + quantity: z.number().gt(0).nullable().optional(), createdAt: z.string(), updatedAt: z.string().nullable().optional(), }); @@ -20,6 +21,7 @@ const CreateShelterSupplySchema = ShelterSupplySchema.pick({ shelterId: true, supplyId: true, priority: true, + quantity: true, }); const UpdateShelterSupplySchema = z.object({ @@ -31,6 +33,7 @@ const UpdateShelterSupplySchema = z.object({ z.literal(SupplyPriority.Needing), z.literal(SupplyPriority.Urgent), ]), + quantity: z.number().nullable().optional(), shelterId: z.string(), supplyId: z.string(), }) @@ -41,8 +44,14 @@ const UpdateShelterSupplySchema = z.object({ }), }); +const UpdateManyShelterSupplySchema = z.object({ + ids: z.array(z.string()), + shelterId: z.string(), +}); + export { ShelterSupplySchema, CreateShelterSupplySchema, UpdateShelterSupplySchema, + UpdateManyShelterSupplySchema, }; diff --git a/src/shelter/ShelterSearch.ts b/src/shelter/ShelterSearch.ts new file mode 100644 index 00000000..7598b8e0 --- /dev/null +++ b/src/shelter/ShelterSearch.ts @@ -0,0 +1,210 @@ +import { Prisma } from '@prisma/client'; + +import { PrismaService } from '../prisma/prisma.service'; +import { SupplyPriority } from 'src/supply/types'; +import { + IFilterFormProps, + SearchShelterTagResponse, + ShelterTagInfo, + ShelterTagType, +} from './types/search.types'; + +const defaultTagsData: ShelterTagInfo = { + NeedDonations: 10, + NeedVolunteers: 10, + RemainingSupplies: 10, +}; + +class ShelterSearch { + private formProps: Partial; + private prismaService: PrismaService; + + constructor( + prismaService: PrismaService, + props: Partial = {}, + ) { + this.prismaService = prismaService; + this.formProps = { ...props }; + } + + priority(supplyIds: string[] = []): Prisma.ShelterWhereInput { + if (this.formProps.priority) { + return { + shelterSupplies: { + some: { + priority: +this.formProps.priority, + supplyId: + supplyIds.length > 0 + ? { + in: supplyIds, + } + : undefined, + }, + }, + }; + } else return {}; + } + + get shelterStatus(): Prisma.ShelterWhereInput[] { + if (!this.formProps.shelterStatus) return []; + else { + return this.formProps.shelterStatus.map((status) => { + if (status === 'waiting') + return { + capacity: null, + }; + else if (status === 'available') + return { + capacity: { + gt: this.prismaService.shelter.fields.shelteredPeople, + }, + }; + else + return { + capacity: { + lte: this.prismaService.shelter.fields.shelteredPeople, + }, + }; + }); + } + } + + supplyCategoryIds( + priority?: SupplyPriority | null, + ): Prisma.ShelterWhereInput { + if (!this.formProps.supplyCategoryIds) return {}; + return { + shelterSupplies: { + some: { + priority: priority ? +priority : undefined, + supply: { + supplyCategoryId: { + in: this.formProps.supplyCategoryIds, + }, + }, + }, + }, + }; + } + + get supplyIds(): Prisma.ShelterWhereInput { + if (!this.formProps.supplyIds) return {}; + return { + shelterSupplies: { + some: { + supply: { + id: { + in: this.formProps.supplyIds, + }, + }, + }, + }, + }; + } + + get search(): Prisma.ShelterWhereInput[] { + if (!this.formProps.search) return []; + else + return [ + { + address: { + contains: this.formProps.search, + mode: 'insensitive', + }, + }, + { + name: { + contains: this.formProps.search, + mode: 'insensitive', + }, + }, + ]; + } + + get query(): Prisma.ShelterWhereInput { + if (Object.keys(this.formProps).length === 0) return {}; + const queryData = { + AND: [ + { OR: this.search }, + { OR: this.shelterStatus }, + this.priority(this.formProps.supplyIds), + this.supplyCategoryIds(this.formProps.priority), + ], + }; + + return queryData; + } +} + +/** + * + * @param formProps Uma interface do tipo ShelterTagInfo | null. Que indica a quantidade máxima de cada categoria deverá ser retornada + * @param results Resultado da query em `this.prismaService.shelter.findMany` + * @param voluntaryIds + * @returns Retorna a lista de resultados, adicionando o campo tags em cada supply para assim categoriza-los corretamente e limitar a quantidade de cada retornada respeitando os parametros em formProps + */ +function parseTagResponse( + tagProps: Partial> = {}, + results: SearchShelterTagResponse[], + voluntaryIds: string[], +): SearchShelterTagResponse[] { + const tags: ShelterTagInfo = { + ...defaultTagsData, + ...(tagProps?.tags ?? {}), + }; + + const parsed = results.map((result) => { + const qtd: Required = { + NeedDonations: 0, + NeedVolunteers: 0, + RemainingSupplies: 0, + }; + return { + ...result, + shelterSupplies: result.shelterSupplies.reduce((prev, shelterSupply) => { + const supplyTags: ShelterTagType[] = []; + let tagged: boolean = false; + if ( + tags.NeedDonations && + [SupplyPriority.Needing, SupplyPriority.Urgent].includes( + shelterSupply.priority, + ) + ) { + if (qtd.NeedDonations < tags.NeedDonations) { + qtd.NeedDonations++; + tagged = true; + supplyTags.push('NeedDonations'); + } + } + if ( + tags.NeedVolunteers && + voluntaryIds.includes(shelterSupply.supply.supplyCategoryId) && + [SupplyPriority.Urgent, SupplyPriority.Needing].includes( + shelterSupply.priority, + ) + ) { + if (qtd.NeedVolunteers < tags.NeedVolunteers) { + qtd.NeedVolunteers++; + tagged = true; + supplyTags.push('NeedVolunteers'); + } + } + if ( + tags.RemainingSupplies && + [SupplyPriority.Remaining].includes(shelterSupply.priority) + ) { + if (qtd.RemainingSupplies < tags.RemainingSupplies) { + qtd.RemainingSupplies++; + tagged = true; + supplyTags.push('RemainingSupplies'); + } + } + if (tagged) return [...prev, { ...shelterSupply, tags: supplyTags }]; + else return prev; + }, [] as any), + }; + }); + return parsed; +} + +export { ShelterSearch, parseTagResponse }; diff --git a/src/shelter/shelter.controller.ts b/src/shelter/shelter.controller.ts index 173d365d..097285e4 100644 --- a/src/shelter/shelter.controller.ts +++ b/src/shelter/shelter.controller.ts @@ -14,9 +14,7 @@ import { ApiTags } from '@nestjs/swagger'; import { ShelterService } from './shelter.service'; import { ServerResponse } from '../utils'; -import { SearchQuery } from '../decorators'; -import { SeachQueryProps } from '@/decorators/search-query/types'; -import { UserGuard } from '@/guards/user.guard'; +import { StaffGuard } from '@/guards/staff.guard'; @ApiTags('Abrigos') @Controller('shelters') @@ -26,20 +24,9 @@ export class ShelterController { constructor(private readonly shelterService: ShelterService) {} @Get('') - async index(@SearchQuery() searchQueryParams: SeachQueryProps) { + async index(@Query() query) { try { - const data = await this.shelterService.index(searchQueryParams); - return new ServerResponse(200, 'Successfully get shelters', data); - } catch (err: any) { - this.logger.error(`Failed to get shelters: ${err}`); - throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); - } - } - - @Get('/search') - async search(@Query() complexSearchQueryParams) { - try { - const data = await this.shelterService.search(complexSearchQueryParams); + const data = await this.shelterService.index(query); return new ServerResponse(200, 'Successfully get shelters', data); } catch (err: any) { this.logger.error(`Failed to get shelters: ${err}`); @@ -59,7 +46,7 @@ export class ShelterController { } @Post('') - @UseGuards(UserGuard) + @UseGuards(StaffGuard) async store(@Body() body) { try { const data = await this.shelterService.store(body); @@ -82,7 +69,7 @@ export class ShelterController { } @Put(':id/admin') - @UseGuards(UserGuard) + @UseGuards(StaffGuard) async fullUpdate(@Param('id') id: string, @Body() body) { try { const data = await this.shelterService.fullUpdate(id, body); diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 85af8147..a24aa7ab 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -1,21 +1,27 @@ import { z } from 'zod'; import { Injectable } from '@nestjs/common'; +import * as qs from 'qs'; import { Prisma } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; + import { PrismaService } from '../prisma/prisma.service'; import { - ComplexSearchSchema, CreateShelterSchema, FullUpdateShelterSchema, UpdateShelterSchema, -} from './types'; -import { SeachQueryProps } from '@/decorators/search-query/types'; -import { SupplyPriority } from 'src/supply/types'; - +} from './types/types'; +import { SearchSchema } from '../types'; +import { ShelterSearch, parseTagResponse } from './ShelterSearch'; +import { SupplyPriority } from '../supply/types'; +import { IFilterFormProps } from './types/search.types'; @Injectable() export class ShelterService { - constructor(private readonly prismaService: PrismaService) {} + private voluntaryIds: string[] = []; + + constructor(private readonly prismaService: PrismaService) { + this.loadVoluntaryIds(); + } async store(body: z.infer) { const payload = CreateShelterSchema.parse(body); @@ -71,13 +77,11 @@ export class ShelterService { prioritySum: true, latitude: true, longitude: true, + verified: true, shelterSupplies: { - where: { - priority: { - }, - }, select: { priority: true, + quantity: true, supply: { select: { id: true, @@ -103,91 +107,30 @@ export class ShelterService { return data; } - async index(props: SeachQueryProps) { - const { handleSearch } = props; - - return await handleSearch>( - this.prismaService.shelter, - { - select: { - id: true, - name: true, - pix: true, - address: true, - capacity: true, - contact: true, - petFriendly: true, - shelteredPeople: true, - prioritySum: true, - verified: true, - latitude: true, - longitude: true, - createdAt: true, - updatedAt: true, - shelterSupplies: { - where: { - priority: { - gt: SupplyPriority.UnderControl, - }, - }, - select: { - priority: true, - supply: { - select: { - id: true, - name: true, - supplyCategory: { - select: { - id: true, - name: true, - }, - }, - createdAt: true, - updatedAt: true, - }, - }, - }, - }, - }, - }, - ); - } - - async search(props: z.infer) { - const payload = ComplexSearchSchema.parse({ - ...props, - supplyCategories: - typeof props['supplyCategories[]'] === 'string' - ? [props['supplyCategories[]']] - : props['supplyCategories[]'], - supplies: - typeof props['supplies[]'] === 'string' - ? [props['supplies[]']] - : props['supplies[]'], - }); - - const shelterStatusFilter = this.addShelterStatusFilter(payload); - const where = this.mountWhereFilter(payload); - const take = payload.perPage; - const skip = payload.perPage * (payload.page - 1); - - if (shelterStatusFilter.length > 0) { - where['AND'].push({ - OR: shelterStatusFilter, - }); - } - - const count = await this.prismaService.shelter.count({ - where: where, - }); - - const results = await this.prismaService.shelter.findMany({ - where: where, - orderBy: { - prioritySum: 'desc', - }, + async index(query: any) { + const { + order, + orderBy, + page, + perPage, + search: searchQuery, + } = SearchSchema.parse(query); + const queryData = qs.parse(searchQuery) as unknown as IFilterFormProps; + const { query: where } = new ShelterSearch(this.prismaService, queryData); + const count = await this.prismaService.shelter.count({ where }); + + const take = perPage; + const skip = perPage * (page - 1); + + const whereData: Prisma.ShelterFindManyArgs = { take, skip, + orderBy: { [orderBy]: order }, + where, + }; + + const results = await this.prismaService.shelter.findMany({ + ...whereData, select: { id: true, name: true, @@ -195,10 +138,10 @@ export class ShelterService { address: true, capacity: true, contact: true, - verified: true, petFriendly: true, shelteredPeople: true, prioritySum: true, + verified: true, latitude: true, longitude: true, createdAt: true, @@ -206,126 +149,40 @@ export class ShelterService { shelterSupplies: { where: { priority: { - gt: SupplyPriority.UnderControl, + notIn: [SupplyPriority.UnderControl], }, }, - select: { - priority: true, - supply: { - select: { - id: true, - name: true, - supplyCategory: { - select: { - id: true, - name: true, - }, - }, - createdAt: true, - updatedAt: true, - }, - }, + orderBy: { + updatedAt: 'desc', + }, + include: { + supply: true, }, }, }, }); - return { perPage: payload.perPage, page: payload.page, count, results }; - } - private mountWhereFilter(payload: z.infer) { - const filter: any = { - AND: [ - { - OR: [ - { address: { contains: payload.search, mode: 'insensitive' } }, - { name: { contains: payload.search, mode: 'insensitive' } }, - ], - }, - ], - }; + const parsed = parseTagResponse(queryData, results, this.voluntaryIds); - const shelterSuppliesFilter = { - shelterSupplies: { - some: {}, - }, + return { + page, + perPage, + count, + results: parsed, }; - - if (payload.priority) { - shelterSuppliesFilter.shelterSupplies.some['priority'] = parseInt( - payload.priority, - ); - } - - if (payload?.supplyCategories && payload?.supplyCategories.length !== 0) { - shelterSuppliesFilter.shelterSupplies.some['supply'] = { - supplyCategoryId: { - in: payload.supplyCategories, - }, - }; - } - - if (payload?.supplies && payload?.supplies.length !== 0) { - shelterSuppliesFilter.shelterSupplies.some['supplyId'] = { - in: payload.supplies, - }; - } - - if (Object.keys(shelterSuppliesFilter.shelterSupplies.some).length !== 0) { - filter['AND'].push(shelterSuppliesFilter); - } - - return filter; } - private addShelterStatusFilter(payload: z.infer) { - const shelterStatusFilter: any = []; - - if (payload.filterAvailableShelter) { - shelterStatusFilter.push({ - AND: [ - { - capacity: { - gt: this.prismaService.shelter.fields.shelteredPeople, - }, + loadVoluntaryIds() { + this.prismaService.supplyCategory + .findMany({ + where: { + name: { + in: ['Especialistas e Profissionais', 'Voluntariado'], }, - { - capacity: { not: null }, - }, - { - shelteredPeople: { not: null }, - }, - ], - }); - } - - if (payload.filterUnavailableShelter) { - shelterStatusFilter.push({ - AND: [ - { - capacity: { - lte: this.prismaService.shelter.fields.shelteredPeople, - }, - }, - { - capacity: { not: null }, - }, - { - shelteredPeople: { not: null }, - }, - ], - }); - } - - if (payload.waitingShelterAvailability) { - shelterStatusFilter.push({ - capacity: null, - }); - - shelterStatusFilter.push({ - shelteredPeople: null, + }, + }) + .then((resp) => { + this.voluntaryIds.push(...resp.map((s) => s.id)); }); - } - - return shelterStatusFilter; } } diff --git a/src/shelter/types.ts b/src/shelter/types.ts deleted file mode 100644 index 8e4a3f4d..00000000 --- a/src/shelter/types.ts +++ /dev/null @@ -1,76 +0,0 @@ -import z from 'zod'; - -import { capitalize } from '../utils'; - -export interface DefaultSupplyProps { - category: string; - supply: string; -} - -const ShelterSchema = z.object({ - id: z.string(), - name: z.string().transform(capitalize), - pix: z.string().nullable().optional(), - address: z.string().transform(capitalize), - petFriendly: z.boolean().nullable().optional(), - shelteredPeople: z.number().nullable().optional(), - latitude: z.number().nullable().optional(), - longitude: z.number().nullable().optional(), - capacity: z.number().nullable().optional(), - contact: z.string().nullable().optional(), - verified: z.boolean(), - createdAt: z.string(), - updatedAt: z.string().nullable().optional(), -}); - -const ComplexSearchSchema = z.object({ - search: z.preprocess((v) => v ?? '', z.string()), - status: z.array(z.number()).nullable().optional(), - perPage: z.preprocess( - (v) => +((v ?? '20') as string), - z.number().min(1).max(100), - ), - filterAvailableShelter: z.preprocess( - (v) => (v === 'true' ? true : false), - z.boolean(), - ), - filterUnavailableShelter: z.preprocess( - (v) => (v === 'true' ? true : false), - z.boolean(), - ), - waitingShelterAvailability: z.preprocess( - (v) => (v === 'true' ? true : false), - z.boolean(), - ), - page: z.preprocess((v) => +((v ?? '1') as string), z.number().min(1)), - supplyCategories: z.array(z.string()).nullable().optional(), - supplies: z.array(z.string()).nullable().optional(), - priority: z.string().nullable().optional(), - order: z.string(), - orderBy: z.string().nullable().optional(), -}); - -const CreateShelterSchema = ShelterSchema.omit({ - id: true, - createdAt: true, - updatedAt: true, -}); - -const UpdateShelterSchema = ShelterSchema.pick({ - petFriendly: true, - shelteredPeople: true, -}).partial(); - -const FullUpdateShelterSchema = ShelterSchema.omit({ - id: true, - createdAt: true, - updatedAt: true, -}).partial(); - -export { - ShelterSchema, - CreateShelterSchema, - UpdateShelterSchema, - FullUpdateShelterSchema, - ComplexSearchSchema, -}; diff --git a/src/shelter/types/search.types.ts b/src/shelter/types/search.types.ts new file mode 100644 index 00000000..b80ca59d --- /dev/null +++ b/src/shelter/types/search.types.ts @@ -0,0 +1,26 @@ +import { Shelter, ShelterSupply, Supply } from '@prisma/client'; +import { SupplyPriority } from '../../supply/types'; + +export type ShelterAvailabilityStatus = 'available' | 'unavailable' | 'waiting'; + +export interface IFilterFormProps { + search: string; + priority: SupplyPriority | null; + supplyCategoryIds: string[]; + supplyIds: string[]; + shelterStatus: ShelterAvailabilityStatus[]; + tags: ShelterTagInfo | null; +} + +export type SearchShelterTagResponse = Shelter & { + shelterSupplies: (ShelterSupply & { supply: Supply })[]; +}; + +export type ShelterTagType = + | 'NeedVolunteers' + | 'NeedDonations' + | 'RemainingSupplies'; + +export type ShelterTagInfo = { + [key in ShelterTagType]?: number; +}; diff --git a/src/shelter/types/types.ts b/src/shelter/types/types.ts new file mode 100644 index 00000000..b3911c96 --- /dev/null +++ b/src/shelter/types/types.ts @@ -0,0 +1,49 @@ +import z from 'zod'; + +import { capitalize } from '../../utils'; + +export interface DefaultSupplyProps { + category: string; + supply: string; +} + +const ShelterSchema = z.object({ + id: z.string(), + name: z.string().transform(capitalize), + pix: z.string().nullable().optional(), + address: z.string().transform(capitalize), + petFriendly: z.boolean().nullable().optional(), + shelteredPeople: z.number().min(0).nullable().optional(), + latitude: z.number().nullable().optional(), + longitude: z.number().nullable().optional(), + capacity: z.number().min(0).nullable().optional(), + contact: z.string().nullable().optional(), + verified: z.boolean(), + createdAt: z.string(), + updatedAt: z.string().nullable().optional(), +}); + +const CreateShelterSchema = ShelterSchema.omit({ + id: true, + createdAt: true, + updatedAt: true, + verified: true, +}); + +const UpdateShelterSchema = ShelterSchema.pick({ + petFriendly: true, + shelteredPeople: true, +}).partial(); + +const FullUpdateShelterSchema = ShelterSchema.omit({ + id: true, + createdAt: true, + updatedAt: true, +}).partial(); + +export { + ShelterSchema, + CreateShelterSchema, + UpdateShelterSchema, + FullUpdateShelterSchema, +}; diff --git a/src/supply-categories/supply-categories.controller.spec.ts b/src/supply-categories/supply-categories.controller.spec.ts index 0065545f..e9e287a5 100644 --- a/src/supply-categories/supply-categories.controller.spec.ts +++ b/src/supply-categories/supply-categories.controller.spec.ts @@ -9,7 +9,9 @@ describe('SupplyCategoriesController', () => { controllers: [SupplyCategoriesController], }).compile(); - controller = module.get(SupplyCategoriesController); + controller = module.get( + SupplyCategoriesController, + ); }); it('should be defined', () => { diff --git a/src/supply-categories/supply-categories.controller.ts b/src/supply-categories/supply-categories.controller.ts index 0b1d3057..96106050 100644 --- a/src/supply-categories/supply-categories.controller.ts +++ b/src/supply-categories/supply-categories.controller.ts @@ -13,7 +13,7 @@ import { ApiTags } from '@nestjs/swagger'; import { SupplyCategoriesService } from './supply-categories.service'; import { ServerResponse } from '../utils'; -import { StaffGuard } from '@/guards/staff.guard'; +import { AdminGuard } from '@/guards/admin.guard'; @ApiTags('Categoria de Suprimentos') @Controller('supply-categories') @@ -40,7 +40,7 @@ export class SupplyCategoriesController { } @Post('') - @UseGuards(StaffGuard) + @UseGuards(AdminGuard) async store(@Body() body) { try { const data = await this.supplyCategoryServices.store(body); @@ -56,7 +56,7 @@ export class SupplyCategoriesController { } @Put(':id') - @UseGuards(StaffGuard) + @UseGuards(AdminGuard) async update(@Param('id') id: string, @Body() body) { try { const data = await this.supplyCategoryServices.update(id, body); diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..9e16b1d1 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,14 @@ +import z from 'zod'; + +const SearchSchema = z.object({ + perPage: z.preprocess( + (v) => +((v ?? '20') as string), + z.number().min(1).max(100), + ), + page: z.preprocess((v) => +((v ?? '1') as string), z.number().min(1)), + search: z.string().default(''), + order: z.enum(['desc', 'asc']).default('desc'), + orderBy: z.string().default('createdAt'), +}); + +export { SearchSchema }; diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 86cd030c..5d4a0dc2 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -11,10 +11,10 @@ import { } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { StaffGuard } from '@/guards/staff.guard'; import { UserGuard } from '@/guards/user.guard'; import { ServerResponse } from '../utils'; import { UsersService } from './users.service'; +import { AdminGuard } from '@/guards/admin.guard'; @ApiTags('Usuários') @Controller('users') @@ -24,7 +24,7 @@ export class UsersController { constructor(private readonly userServices: UsersService) {} @Post('') - @UseGuards(StaffGuard) + @UseGuards(AdminGuard) async store(@Body() body) { try { await this.userServices.store(body); @@ -36,7 +36,7 @@ export class UsersController { } @Put(':id') - @UseGuards(StaffGuard) + @UseGuards(AdminGuard) async update(@Body() body, @Param('id') id: string) { try { await this.userServices.update(id, body); diff --git a/src/utils/index.ts b/src/utils/index.ts index 18fae9b5..09934e74 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,8 +3,6 @@ import { removeNotNumbers, getSessionData, deepMerge, - getSearchWhere, - parseStringToObject, capitalize, } from './utils'; @@ -14,6 +12,4 @@ export { removeNotNumbers, getSessionData, deepMerge, - getSearchWhere, - parseStringToObject, }; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 4c6f0300..772b3e12 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -75,77 +75,10 @@ function deepMerge(target: Record, source: Record) { } } -function parseStringToObject(path: string, value: any) { - const keys = path.split('.'); - const currentObj = {}; - let temp = currentObj; - - keys.forEach((key, index) => { - if (index === keys.length - 1) { - temp[key] = value; - } else { - temp[key] = {}; - temp = temp[key]; - } - }); - - return currentObj; -} - -function getSearchWhere(search: string, or?: boolean) { - const where = {}; - if (search !== '') { - const terms = search.split(','); - const groups: Record = - terms.reduce((prev, current) => { - const [key, condition, value] = current.split(':'); - const isBoolean = ['true', 'false'].includes(value); - const mode = - isBoolean || ['in', 'notIn'].includes(condition) - ? undefined - : 'insensitive'; - const parsedValue = isBoolean ? value === 'true' : value; - - return { - ...prev, - [key]: [ - ...(prev[key] ?? []), - { - [condition]: ['in', 'notIn'].includes(condition) - ? [parsedValue] - : parsedValue, - mode, - }, - ], - }; - }, {}); - - const parsed = Object.entries(groups).reduce((prev, [key, current]) => { - if (current.length > 1) { - return { - ...prev, - AND: current.map((c) => parseStringToObject(key, c)), - }; - } else return deepMerge(prev, parseStringToObject(key, current[0])); - }, {}); - Object.assign(where, parsed); - } - if (or) { - return { - OR: Object.entries(where).reduce( - (prev, [key, value]) => [...prev, { [key]: value }], - [] as any[], - ), - }; - } else return where; -} - export { ServerResponse, removeNotNumbers, getSessionData, deepMerge, - parseStringToObject, - getSearchWhere, capitalize, }; From 375418eef3922294592b15ad7534c658315025b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Geraldo=20D=2E=20F?= Date: Sat, 11 May 2024 16:23:59 -0300 Subject: [PATCH 02/12] fix: priority sum update where (#72) --- src/shelter-supply/shelter-supply.service.ts | 39 +++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/shelter-supply/shelter-supply.service.ts b/src/shelter-supply/shelter-supply.service.ts index 73faddc4..ef4cf97a 100644 --- a/src/shelter-supply/shelter-supply.service.ts +++ b/src/shelter-supply/shelter-supply.service.ts @@ -82,18 +82,45 @@ export class ShelterSupplyService { async updateMany(body: z.infer) { const { ids, shelterId } = UpdateManyShelterSupplySchema.parse(body); - await this.prismaService.shelterSupply.updateMany({ + const supplies = await this.prismaService.shelterSupply.findMany({ where: { - shelterId: shelterId, + shelterId, supplyId: { in: ids, }, }, - data: { - priority: SupplyPriority.UnderControl, - updatedAt: new Date().toISOString(), - }, }); + + const prioritySum = supplies.reduce( + (prev, current) => prev + current.priority, + 0, + ); + + await this.prismaService.$transaction([ + this.prismaService.shelter.update({ + where: { + id: shelterId, + }, + data: { + prioritySum: { + decrement: prioritySum, + }, + updatedAt: new Date().toISOString(), + }, + }), + this.prismaService.shelterSupply.updateMany({ + where: { + shelterId, + supplyId: { + in: ids, + }, + }, + data: { + priority: SupplyPriority.UnderControl, + updatedAt: new Date().toISOString(), + }, + }), + ]); } async index(shelterId: string) { From 2954d7a9a8e052afeeab3598305a706b404499c5 Mon Sep 17 00:00:00 2001 From: Filipe Pacheco de Fraga Date: Tue, 14 May 2024 00:30:07 -0300 Subject: [PATCH 03/12] Release 0.0.1 (#94) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jhonatan David <82552187+jotahdavid@users.noreply.github.com> Co-authored-by: MatheusDubin Co-authored-by: Gustavo Clemente Co-authored-by: kelvinsb Co-authored-by: Tatiane Co-authored-by: Sombrio Co-authored-by: AlbuquerqueRafael Co-authored-by: José Fagundes Co-authored-by: Arthur <40851238+4rthuurr@users.noreply.github.com> Co-authored-by: Giovanni Bassi <334958+giggio@users.noreply.github.com> Co-authored-by: LeoFC97 Co-authored-by: Rogério Piatek <74259272+RogerioPiatek@users.noreply.github.com> Co-authored-by: Anderson Rocha <59173445+AndersonCRocha@users.noreply.github.com> Co-authored-by: Pedro Perrone --- .github/workflows/ci.yml | 32 +++++ .github/workflows/pull_request_template.md | 24 ++++ Dockerfile | 4 +- README.md | 13 +- docker-compose.dev.yml | 23 +-- package.json | 1 + .../migrations/20240512005246_/migration.sql | 6 + prisma/schema.prisma | 5 + .../UserDecorator/user.decorator.ts | 8 ++ src/guards/apply-user.guard.ts | 10 ++ src/guards/utils.ts | 38 +++-- src/shelter/ShelterSearch.ts | 134 +++++++++++------- src/shelter/shelter.controller.ts | 20 ++- src/shelter/shelter.service.ts | 50 +++++-- src/shelter/types/search.types.ts | 62 +++++--- src/shelter/types/types.ts | 5 + src/utils/utils.ts | 42 +++++- tsconfig.json | 3 + 18 files changed, 366 insertions(+), 114 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/pull_request_template.md create mode 100644 prisma/migrations/20240512005246_/migration.sql create mode 100644 src/decorators/UserDecorator/user.decorator.ts create mode 100644 src/guards/apply-user.guard.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..f03015e0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: CI + +on: + pull_request: + branches: + - master + - develop + +jobs: + build: + runs-on: ubuntu-latest + + steps: + # Check out the source + - name: Checkout Source + uses: actions/checkout@v4 + # Setup node.js and cache + - name: "Setup node.js" + uses: actions/setup-node@v4 + with: + node-version: "18.x" + cache: 'npm' + cache-dependency-path: ./package-lock.json + # Install dependencies + - name: Install dependencies + run: npm ci + # Lint App + - name: Lint App + run: npm run lint:ci + # Build App + - name: Build App + run: npm run build \ No newline at end of file diff --git a/.github/workflows/pull_request_template.md b/.github/workflows/pull_request_template.md new file mode 100644 index 00000000..d9d9ffd2 --- /dev/null +++ b/.github/workflows/pull_request_template.md @@ -0,0 +1,24 @@ +### 🔨 Tenho uma nova PR para vocês revisarem + +- 🤔 O que foi feito? +> Digite aqui... + + +### 📗 Checklist do desenvolvedor + +- [ ] Foi testado localmente? +- [ ] Foi adicionado documentação necessária (swagger, testes e etc)? + +### 👀 Checklist do revisor + +#### Revisor 1️⃣ + +- [ ] Você entendeu o propósito desse PR? +- [ ] Você entendeu o fluxo de negócio? +- [ ] Você entendeu o que e como foi desenvolvido tecnicamente a solução? +- [ ] Você analisou se os testes estão cobrindo a maioria dos casos? + + +### 🔗 Referênia + +[Issue XX](https://github.com/SOS-RS/backend/issues/XX) diff --git a/Dockerfile b/Dockerfile index 4c2dba54..a98af1c5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ -FROM node:18.18 as node +FROM node:18.18-alpine as node WORKDIR /usr/app COPY package.json package-lock.json ./ RUN npm install -COPY . . \ No newline at end of file +COPY . . diff --git a/README.md b/README.md index 6a231353..99e4c850 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # 🌊 Backend para App de Ajuda em Enchentes 🌊 -Este repositório contém o backend de um aplicativo projetado para ajudar na organização e distribuição de suprimentos, bem como na coordenação de voluntários durante enchentes no Rio Grande do Sul. Ele fornece APIs essenciais para a autenticação de usuários, gerenciamento de abrigos e suprimentos, e muito mais. +Este repositório contém o backend de um aplicativo projetado para ajudar na organização e distribuição de suprimentos, +bem como na coordenação de voluntários durante enchentes no Rio Grande do Sul. Ele fornece APIs essenciais para a +autenticação de usuários, gerenciamento de abrigos e suprimentos, e muito mais. + +Se você quiser discutir ideias, problemas ou contribuições, sinta-se à vontade para se juntar ao nosso servidor do +Discord [aqui](https://discord.gg/vjZS6BQXvM). ## 🛠 Tecnologias Utilizadas @@ -12,7 +17,8 @@ Este repositório contém o backend de um aplicativo projetado para ajudar na or ## 🗂 Dump do Banco de Dados -Para iniciar com dados de exemplo, utilize o dump do banco disponível em `prisma/migration/dev_dump.sql`. Este arquivo pode ser executado após as migrations estarem aplicadas. +Para iniciar com dados de exemplo, utilize o dump do banco disponível em `prisma/migration/dev_dump.sql`. Este arquivo +pode ser executado após as migrations estarem aplicadas. Se estiver usando Docker, os comandos para carregar o dump são: @@ -96,6 +102,7 @@ ports: ## 🤝 Contribuição -Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas modificações, e envie um pull request. +Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas +modificações, e envie um pull request. Sua ajuda é crucial para apoiar a comunidade afetada pelas enchentes no Rio Grande do Sul! diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 3b49bcff..ba40eebc 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -3,31 +3,34 @@ version: '3.8' services: api: container_name: sos-rs-api - image: node:18.18 + image: node:18.18-alpine restart: always tty: true depends_on: - db ports: - - '4000:4000' + - '${PORT}:${PORT}' volumes: - .:/usr/app - /usr/app/node_modules working_dir: '/usr/app' environment: - - DB_HOST=sos-rs-db - - DB_PORT=5432 - - DB_DATABASE_NAME=sos_rs - - DB_USER=root - - DB_PASSWORD=root + - DB_HOST=${DB_HOST} + - DB_PORT=${DB_PORT} + - DB_DATABASE_NAME=${DB_DATABASE_NAME} + - DB_USER=${DB_USER} + - DB_PASSWORD=${DB_PASSWORD} + - PORT=${PORT} command: > sh -c "npm install && npx prisma generate && npx prisma migrate dev && - npm run start:dev" + npm run start:dev -- --preserveWatchOutput" db: container_name: sos-rs-db image: postgres + ports: + - '${DB_PORT}:${DB_PORT}' environment: - - POSTGRES_PASSWORD=root - - POSTGRES_USER=root + - POSTGRES_PASSWORD=${DB_PASSWORD} + - POSTGRES_USER=${DB_USER} diff --git a/package.json b/package.json index 5e154b46..3212f2fd 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "lint:ci": "eslint \"{src,apps,libs,test}/**/*.ts\" --format=stylish", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", diff --git a/prisma/migrations/20240512005246_/migration.sql b/prisma/migrations/20240512005246_/migration.sql new file mode 100644 index 00000000..c57b86cf --- /dev/null +++ b/prisma/migrations/20240512005246_/migration.sql @@ -0,0 +1,6 @@ +-- AlterTable +ALTER TABLE "shelters" ADD COLUMN "city" TEXT, +ADD COLUMN "neighbourhood" TEXT, +ADD COLUMN "street" TEXT, +ADD COLUMN "street_number" TEXT, +ADD COLUMN "zip_code" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 792b1f65..b853d2b4 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -89,6 +89,11 @@ model Shelter { name String @unique pix String? @unique address String + street String? + neighbourhood String? + city String? + streetNumber String? @map("street_number") + zipCode String? @map("zip_code") petFriendly Boolean? @map("pet_friendly") shelteredPeople Int? @map("sheltered_people") capacity Int? diff --git a/src/decorators/UserDecorator/user.decorator.ts b/src/decorators/UserDecorator/user.decorator.ts new file mode 100644 index 00000000..67e5edcd --- /dev/null +++ b/src/decorators/UserDecorator/user.decorator.ts @@ -0,0 +1,8 @@ +import { createParamDecorator, ExecutionContext } from '@nestjs/common'; + +export const UserDecorator = createParamDecorator( + (data: unknown, ctx: ExecutionContext) => { + const request = ctx.switchToHttp().getRequest(); + return request?.user; + }, +); diff --git a/src/guards/apply-user.guard.ts b/src/guards/apply-user.guard.ts new file mode 100644 index 00000000..07e7a6de --- /dev/null +++ b/src/guards/apply-user.guard.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; + +@Injectable() +export class ApplyUser extends AuthGuard('jwt') { + handleRequest(err: any, user: any) { + if (user) return user; + return null; + } +} diff --git a/src/guards/utils.ts b/src/guards/utils.ts index 1e385a4c..f36066e3 100644 --- a/src/guards/utils.ts +++ b/src/guards/utils.ts @@ -11,22 +11,34 @@ async function canActivate(context: ExecutionContext, allowed: AccessLevel[]) { if (request.user) { const { userId, sessionId } = request.user; - const session = await service.session.findUnique({ - where: { id: sessionId, active: true, user: { id: userId } }, - include: { - user: true, - }, - }); - - if ( - session && - allowed.some((permission) => permission === session.user.accessLevel) - ) { - return true; - } + return isRightSessionRole(allowed, sessionId, userId); } return false; } +async function isRightSessionRole( + allowed: AccessLevel[], + sessionId?: string, + userId?: string, +) { + if (!sessionId) return false; + if (!userId) return false; + + const session = await service.session.findUnique({ + where: { id: sessionId, active: true, user: { id: userId } }, + include: { + user: true, + }, + }); + + if ( + session && + allowed.some((permission) => permission === session.user.accessLevel) + ) { + return true; + } + return false; +} + export { canActivate }; diff --git a/src/shelter/ShelterSearch.ts b/src/shelter/ShelterSearch.ts index 7598b8e0..5215d37c 100644 --- a/src/shelter/ShelterSearch.ts +++ b/src/shelter/ShelterSearch.ts @@ -1,10 +1,12 @@ import { Prisma } from '@prisma/client'; -import { PrismaService } from '../prisma/prisma.service'; +import { calculateGeolocationBounds } from '@/utils/utils'; import { SupplyPriority } from 'src/supply/types'; +import { PrismaService } from '../prisma/prisma.service'; import { - IFilterFormProps, SearchShelterTagResponse, + ShelterSearchProps, + ShelterStatus, ShelterTagInfo, ShelterTagType, } from './types/search.types'; @@ -16,57 +18,54 @@ const defaultTagsData: ShelterTagInfo = { }; class ShelterSearch { - private formProps: Partial; + private formProps: Partial; private prismaService: PrismaService; constructor( prismaService: PrismaService, - props: Partial = {}, + props: Partial = {}, ) { this.prismaService = prismaService; this.formProps = { ...props }; } priority(supplyIds: string[] = []): Prisma.ShelterWhereInput { - if (this.formProps.priority) { - return { - shelterSupplies: { - some: { - priority: +this.formProps.priority, - supplyId: - supplyIds.length > 0 - ? { - in: supplyIds, - } - : undefined, - }, + if (!this.formProps.priority) return {}; + + return { + shelterSupplies: { + some: { + priority: +this.formProps.priority, + supplyId: + supplyIds.length > 0 + ? { + in: supplyIds, + } + : undefined, }, - }; - } else return {}; + }, + }; } get shelterStatus(): Prisma.ShelterWhereInput[] { if (!this.formProps.shelterStatus) return []; - else { - return this.formProps.shelterStatus.map((status) => { - if (status === 'waiting') - return { - capacity: null, - }; - else if (status === 'available') - return { - capacity: { - gt: this.prismaService.shelter.fields.shelteredPeople, - }, - }; - else - return { - capacity: { - lte: this.prismaService.shelter.fields.shelteredPeople, - }, - }; - }); - } + + const clausesFromStatus: Record< + ShelterStatus, + Prisma.ShelterWhereInput['capacity'] | null + > = { + waiting: null, + available: { + gt: this.prismaService.shelter.fields.shelteredPeople, + }, + unavailable: { + lte: this.prismaService.shelter.fields.shelteredPeople, + }, + }; + + return this.formProps.shelterStatus.map((status) => ({ + capacity: clausesFromStatus[status], + })); } supplyCategoryIds( @@ -104,27 +103,58 @@ class ShelterSearch { get search(): Prisma.ShelterWhereInput[] { if (!this.formProps.search) return []; - else - return [ - { - address: { - contains: this.formProps.search, - mode: 'insensitive', - }, + + return [ + { + address: { + contains: this.formProps.search, + mode: 'insensitive', }, - { - name: { - contains: this.formProps.search, - mode: 'insensitive', - }, + }, + { + name: { + contains: this.formProps.search, + mode: 'insensitive', }, - ]; + }, + ]; + } + + get cities(): Prisma.ShelterWhereInput { + if (!this.formProps.cities) return {}; + + return { + city: { + in: this.formProps.cities, + }, + }; + } + + get geolocation(): Prisma.ShelterWhereInput { + if (!this.formProps.geolocation) return {}; + + const { minLat, maxLat, minLong, maxLong } = calculateGeolocationBounds( + this.formProps.geolocation, + ); + + return { + latitude: { + gte: minLat, + lte: maxLat, + }, + longitude: { + gte: minLong, + lte: maxLong, + }, + }; } get query(): Prisma.ShelterWhereInput { if (Object.keys(this.formProps).length === 0) return {}; const queryData = { AND: [ + this.cities, + this.geolocation, { OR: this.search }, { OR: this.shelterStatus }, this.priority(this.formProps.supplyIds), @@ -144,7 +174,7 @@ class ShelterSearch { * @returns Retorna a lista de resultados, adicionando o campo tags em cada supply para assim categoriza-los corretamente e limitar a quantidade de cada retornada respeitando os parametros em formProps */ function parseTagResponse( - tagProps: Partial> = {}, + tagProps: Partial> = {}, results: SearchShelterTagResponse[], voluntaryIds: string[], ): SearchShelterTagResponse[] { diff --git a/src/shelter/shelter.controller.ts b/src/shelter/shelter.controller.ts index 097285e4..24603857 100644 --- a/src/shelter/shelter.controller.ts +++ b/src/shelter/shelter.controller.ts @@ -15,6 +15,8 @@ import { ApiTags } from '@nestjs/swagger'; import { ShelterService } from './shelter.service'; import { ServerResponse } from '../utils'; import { StaffGuard } from '@/guards/staff.guard'; +import { ApplyUser } from '@/guards/apply-user.guard'; +import { UserDecorator } from '@/decorators/UserDecorator/user.decorator'; @ApiTags('Abrigos') @Controller('shelters') @@ -34,10 +36,24 @@ export class ShelterController { } } + @Get('cities') + async cities() { + try { + const data = await this.shelterService.getCities(); + return new ServerResponse(200, 'Successfully get shelters cities', data); + } catch (err: any) { + this.logger.error(`Failed to get shelters cities: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } + @Get(':id') - async show(@Param('id') id: string) { + @UseGuards(ApplyUser) + async show(@UserDecorator() user: any, @Param('id') id: string) { try { - const data = await this.shelterService.show(id); + const isLogged = + Boolean(user) && Boolean(user?.sessionId) && Boolean(user?.userId); + const data = await this.shelterService.show(id, isLogged); return new ServerResponse(200, 'Successfully get shelter', data); } catch (err: any) { this.logger.error(`Failed to get shelter: ${err}`); diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index a24aa7ab..e3883215 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -1,19 +1,19 @@ -import { z } from 'zod'; import { Injectable } from '@nestjs/common'; -import * as qs from 'qs'; import { Prisma } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; +import * as qs from 'qs'; +import { z } from 'zod'; import { PrismaService } from '../prisma/prisma.service'; +import { SupplyPriority } from '../supply/types'; +import { SearchSchema } from '../types'; +import { ShelterSearch, parseTagResponse } from './ShelterSearch'; +import { ShelterSearchPropsSchema } from './types/search.types'; import { CreateShelterSchema, FullUpdateShelterSchema, UpdateShelterSchema, } from './types/types'; -import { SearchSchema } from '../types'; -import { ShelterSearch, parseTagResponse } from './ShelterSearch'; -import { SupplyPriority } from '../supply/types'; -import { IFilterFormProps } from './types/search.types'; @Injectable() export class ShelterService { @@ -60,7 +60,7 @@ export class ShelterService { }); } - async show(id: string) { + async show(id: string, shouldShowContact: boolean) { const data = await this.prismaService.shelter.findFirst({ where: { id, @@ -69,10 +69,15 @@ export class ShelterService { id: true, name: true, address: true, + street: true, + neighbourhood: true, + city: true, + streetNumber: true, + zipCode: true, pix: true, shelteredPeople: true, capacity: true, - contact: true, + contact: shouldShowContact, petFriendly: true, prioritySum: true, latitude: true, @@ -115,7 +120,7 @@ export class ShelterService { perPage, search: searchQuery, } = SearchSchema.parse(query); - const queryData = qs.parse(searchQuery) as unknown as IFilterFormProps; + const queryData = ShelterSearchPropsSchema.parse(qs.parse(searchQuery)); const { query: where } = new ShelterSearch(this.prismaService, queryData); const count = await this.prismaService.shelter.count({ where }); @@ -136,8 +141,12 @@ export class ShelterService { name: true, pix: true, address: true, + street: true, + neighbourhood: true, + city: true, + streetNumber: true, + zipCode: true, capacity: true, - contact: true, petFriendly: true, shelteredPeople: true, prioritySum: true, @@ -172,7 +181,26 @@ export class ShelterService { }; } - loadVoluntaryIds() { + async getCities() { + const cities = await this.prismaService.shelter.groupBy({ + by: ['city'], + _count: { + id: true, + }, + orderBy: { + _count: { + id: 'desc', + }, + }, + }); + + return cities.map(({ city, _count: { id: sheltersCount } }) => ({ + city: city || 'Cidade não informada', + sheltersCount, + })); + } + + private loadVoluntaryIds() { this.prismaService.supplyCategory .findMany({ where: { diff --git a/src/shelter/types/search.types.ts b/src/shelter/types/search.types.ts index b80ca59d..b87e653a 100644 --- a/src/shelter/types/search.types.ts +++ b/src/shelter/types/search.types.ts @@ -1,26 +1,52 @@ import { Shelter, ShelterSupply, Supply } from '@prisma/client'; +import { z } from 'zod'; import { SupplyPriority } from '../../supply/types'; -export type ShelterAvailabilityStatus = 'available' | 'unavailable' | 'waiting'; +const ShelterStatusSchema = z.enum(['available', 'unavailable', 'waiting']); -export interface IFilterFormProps { - search: string; - priority: SupplyPriority | null; - supplyCategoryIds: string[]; - supplyIds: string[]; - shelterStatus: ShelterAvailabilityStatus[]; - tags: ShelterTagInfo | null; -} +export type ShelterStatus = z.infer; -export type SearchShelterTagResponse = Shelter & { - shelterSupplies: (ShelterSupply & { supply: Supply })[]; -}; +const ShelterTagTypeSchema = z.enum([ + 'NeedVolunteers', + 'NeedDonations', + 'RemainingSupplies', +]); + +const ShelterTagInfoSchema = z.record( + ShelterTagTypeSchema, + z.number().optional(), +); + +export type ShelterTagType = z.infer; + +export type ShelterTagInfo = z.infer; -export type ShelterTagType = - | 'NeedVolunteers' - | 'NeedDonations' - | 'RemainingSupplies'; +export const GeolocationFilterSchema = z.object({ + latitude: z.coerce.number(), + longitude: z.coerce.number(), + radiusInMeters: z.coerce.number(), +}); -export type ShelterTagInfo = { - [key in ShelterTagType]?: number; +export type GeolocationFilter = z.infer; + +export const ShelterSearchPropsSchema = z.object({ + search: z.string().optional(), + priority: z.preprocess( + (value) => Number(value) || undefined, + z.nativeEnum(SupplyPriority).optional(), + ), + supplyCategoryIds: z.array(z.string()).optional(), + supplyIds: z.array(z.string()).optional(), + shelterStatus: z.array(ShelterStatusSchema).optional(), + tags: ShelterTagInfoSchema.nullable().optional(), + cities: z.array(z.string()).optional(), + geolocation: GeolocationFilterSchema.optional(), +}); + +export type ShelterSearchProps = z.infer; + +type AllowedShelterFields = Omit; + +export type SearchShelterTagResponse = AllowedShelterFields & { + shelterSupplies: (ShelterSupply & { supply: Supply })[]; }; diff --git a/src/shelter/types/types.ts b/src/shelter/types/types.ts index b3911c96..0dc21bac 100644 --- a/src/shelter/types/types.ts +++ b/src/shelter/types/types.ts @@ -12,6 +12,11 @@ const ShelterSchema = z.object({ name: z.string().transform(capitalize), pix: z.string().nullable().optional(), address: z.string().transform(capitalize), + city: z.string().transform(capitalize).nullable().optional(), + neighbourhood: z.string().transform(capitalize).nullable().optional(), + street: z.string().transform(capitalize).nullable().optional(), + streetNumber: z.string().nullable().optional(), + zipCode: z.string().nullable().optional(), petFriendly: z.boolean().nullable().optional(), shelteredPeople: z.number().min(0).nullable().optional(), latitude: z.number().nullable().optional(), diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 772b3e12..dfcbc70f 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,4 +1,5 @@ import { Logger } from '@nestjs/common'; +import { GeolocationFilter } from 'src/shelter/types/search.types'; class ServerResponse { readonly message: string; @@ -75,10 +76,45 @@ function deepMerge(target: Record, source: Record) { } } +interface Coordinates { + maxLat: number; + minLat: number; + maxLong: number; + minLong: number; +} + +function calculateGeolocationBounds({ + latitude, + longitude, + radiusInMeters, +}: GeolocationFilter): Coordinates { + const earthRadius = 6371000; + + const latRad = (latitude * Math.PI) / 180; + + const radiusRad = radiusInMeters / earthRadius; + + const maxLat = latitude + radiusRad * (180 / Math.PI); + const minLat = latitude - radiusRad * (180 / Math.PI); + + const deltaLong = Math.asin(Math.sin(radiusRad) / Math.cos(latRad)); + + const maxLong = longitude + deltaLong * (180 / Math.PI); + const minLong = longitude - deltaLong * (180 / Math.PI); + + return { + maxLat, + minLat, + maxLong, + minLong, + }; +} + export { ServerResponse, - removeNotNumbers, - getSessionData, - deepMerge, + calculateGeolocationBounds, capitalize, + deepMerge, + getSessionData, + removeNotNumbers, }; diff --git a/tsconfig.json b/tsconfig.json index b5b552bd..acda4d9d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,5 +30,8 @@ "@/guards/*": ["./src/guards/*"], "@/guards": ["./src/guards"] } + }, + "watchOptions": { + "watchFile": "fixedPollingInterval" } } From ab3d792dc16d3c7ce3bce781c14f5a0aab6934e2 Mon Sep 17 00:00:00 2001 From: Filipe Pacheco de Fraga Date: Tue, 14 May 2024 01:47:31 -0300 Subject: [PATCH 04/12] Release 0.0.2 (#101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Geraldo D. F --- src/shelter/shelter.service.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index e3883215..74d03860 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -14,6 +14,7 @@ import { FullUpdateShelterSchema, UpdateShelterSchema, } from './types/types'; +import { subDays } from 'date-fns'; @Injectable() export class ShelterService { @@ -30,6 +31,7 @@ export class ShelterService { data: { ...payload, createdAt: new Date().toISOString(), + updatedAt: subDays(new Date(), 1).toISOString(), }, }); } From af6303ad65816a7fc4ace0556757ce9f1aad55ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Tue, 14 May 2024 11:35:47 -0300 Subject: [PATCH 05/12] hotfix: login issue --- src/sessions/sessions.service.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sessions/sessions.service.ts b/src/sessions/sessions.service.ts index 235d7f0d..200104b6 100644 --- a/src/sessions/sessions.service.ts +++ b/src/sessions/sessions.service.ts @@ -23,6 +23,9 @@ export class SessionsService { await this.prismaService.session.updateMany({ where: { + user: { + login, + }, active: true, }, data: { From 37e4d6a98600414dbb919fa13e9468291d4784ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Thu, 16 May 2024 15:48:34 -0300 Subject: [PATCH 06/12] feat: added stg and development actions --- .github/workflows/dev.yml | 34 ++++++++++++++++++++++++++++++++++ .github/workflows/staging.yml | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 .github/workflows/dev.yml create mode 100644 .github/workflows/staging.yml diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml new file mode 100644 index 00000000..c8eb5c7d --- /dev/null +++ b/.github/workflows/dev.yml @@ -0,0 +1,34 @@ +name: Deploy Backend in Development Enviroment + +on: + push: + branches: [develop] + +jobs: + build: + runs-on: dev + + steps: + - uses: actions/checkout@v4 + + - name: Create .env file + run: | + touch .env + echo TZ=${{ secrets.TZ }} >> .env + echo DB_HOST=${{ secrets.DB_HOST }} >> .env + echo DB_PORT=${{ secrets.DB_PORT }} >> .env + echo DB_USER=${{ secrets.DB_USER }} >> .env + echo DB_PASSWORD=${{ secrets.DB_PASSWORD }} >> .env + echo DB_DATABASE_NAME=${{ secrets.DEV_DB_DATABASE_NAME }} >> .env + echo DATABASE_URL=postgresql://${{ secrets.DB_USER }}:${{ secrets.DB_PASSWORD }}@${{ secrets.DB_HOST }}:${{ secrets.DB_PORT }}/${{ secrets.DEV_DB_DATABASE_NAME }}?schema=public >> .env + echo SECRET_KEY=${{ secrets.SECRET_KEY }} >> .env + echo HOST=${{ secrets.HOST }} >> .env + echo PORT=${{ secrets.PORT }} >> .env + echo SERVER_USER_PASSWORD=${{ secrets.SERVER_USER_PASSWORD }} >> .env + cat .env + + - name: Remove old docker image + run: echo ${{ secrets.SERVER_USER_PASSWORD }} | sudo -S docker compose down --rmi all + + - name: Create new docker image + run: echo ${{ secrets.SERVER_USER_PASSWORD }} | sudo -S docker compose up -d --force-recreate diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml new file mode 100644 index 00000000..56b875d3 --- /dev/null +++ b/.github/workflows/staging.yml @@ -0,0 +1,34 @@ +name: Deploy Backend in Development Enviroment + +on: + push: + branches: [staging] + +jobs: + build: + runs-on: stg + + steps: + - uses: actions/checkout@v4 + + - name: Create .env file + run: | + touch .env + echo TZ=${{ secrets.TZ }} >> .env + echo DB_HOST=${{ secrets.DB_HOST }} >> .env + echo DB_PORT=${{ secrets.DB_PORT }} >> .env + echo DB_USER=${{ secrets.DB_USER }} >> .env + echo DB_PASSWORD=${{ secrets.DB_PASSWORD }} >> .env + echo DB_DATABASE_NAME=${{ secrets.STG_DB_DATABASE_NAME }} >> .env + echo DATABASE_URL=postgresql://${{ secrets.DB_USER }}:${{ secrets.DB_PASSWORD }}@${{ secrets.DB_HOST }}:${{ secrets.DB_PORT }}/${{ secrets.STG_DB_DATABASE_NAME }}?schema=public >> .env + echo SECRET_KEY=${{ secrets.SECRET_KEY }} >> .env + echo HOST=${{ secrets.HOST }} >> .env + echo PORT=${{ secrets.PORT }} >> .env + echo SERVER_USER_PASSWORD=${{ secrets.SERVER_USER_PASSWORD }} >> .env + cat .env + + - name: Remove old docker image + run: echo ${{ secrets.SERVER_USER_PASSWORD }} | sudo -S docker compose down --rmi all + + - name: Create new docker image + run: echo ${{ secrets.SERVER_USER_PASSWORD }} | sudo -S docker compose up -d --force-recreate From d4b1e3586adf1408ba9f28d256aa8a34a8a7a69c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Thu, 16 May 2024 16:10:37 -0300 Subject: [PATCH 07/12] hotfix: start:prod command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b20634cd..70a6153f 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", - "start:prod": "node dist/main", + "start:prod": "node dist/src/main.js", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "lint:ci": "eslint \"{src,apps,libs,test}/**/*.ts\" --format=stylish", "test": "jest", From 032196349705fad212a7b3025ac3d27c7bf565cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Thu, 16 May 2024 19:42:04 -0300 Subject: [PATCH 08/12] wip --- .../migrations/20240516212629_/migration.sql | 14 ++++++ prisma/schema.prisma | 11 +++++ src/app.module.ts | 2 + src/partners/partners.controller.ts | 23 +++++++++- src/partners/partners.service.ts | 9 ++++ src/partners/types.ts | 17 ++++++++ src/supporters/supporters.controller.spec.ts | 18 ++++++++ src/supporters/supporters.controller.ts | 43 +++++++++++++++++++ src/supporters/supporters.module.ts | 12 ++++++ src/supporters/supporters.service.spec.ts | 18 ++++++++ src/supporters/supporters.service.ts | 21 +++++++++ src/supporters/types.ts | 18 ++++++++ 12 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20240516212629_/migration.sql create mode 100644 src/partners/types.ts create mode 100644 src/supporters/supporters.controller.spec.ts create mode 100644 src/supporters/supporters.controller.ts create mode 100644 src/supporters/supporters.module.ts create mode 100644 src/supporters/supporters.service.spec.ts create mode 100644 src/supporters/supporters.service.ts create mode 100644 src/supporters/types.ts diff --git a/prisma/migrations/20240516212629_/migration.sql b/prisma/migrations/20240516212629_/migration.sql new file mode 100644 index 00000000..7f623b3f --- /dev/null +++ b/prisma/migrations/20240516212629_/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "supporters" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "image_url" TEXT NOT NULL, + "link" TEXT NOT NULL, + "created_at" VARCHAR(32) NOT NULL, + "updated_at" VARCHAR(32), + + CONSTRAINT "supporters_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "supporters_name_key" ON "supporters"("name"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a43b535a..7c726855 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -133,3 +133,14 @@ model Partners { @@map("partners") } + +model Supporters { + id String @id @default(uuid()) + name String @unique + imageUrl String @map("image_url") + link String + createdAt String @map("created_at") @db.VarChar(32) + updatedAt String? @map("updated_at") @db.VarChar(32) + + @@map("supporters") +} diff --git a/src/app.module.ts b/src/app.module.ts index c08ea99f..82663d34 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -12,6 +12,7 @@ import { SupplyCategoriesModule } from './supply-categories/supply-categories.mo import { ShelterManagersModule } from './shelter-managers/shelter-managers.module'; import { ShelterSupplyModule } from './shelter-supply/shelter-supply.module'; import { PartnersModule } from './partners/partners.module'; +import { SupportersModule } from './supporters/supporters.module'; @Module({ imports: [ @@ -24,6 +25,7 @@ import { PartnersModule } from './partners/partners.module'; ShelterManagersModule, ShelterSupplyModule, PartnersModule, + SupportersModule, ], controllers: [], providers: [ diff --git a/src/partners/partners.controller.ts b/src/partners/partners.controller.ts index f1829171..b2f38edd 100644 --- a/src/partners/partners.controller.ts +++ b/src/partners/partners.controller.ts @@ -1,6 +1,15 @@ -import { Controller, Get, HttpException, Logger } from '@nestjs/common'; +import { + Body, + Controller, + Get, + HttpException, + Logger, + Post, + UseGuards, +} from '@nestjs/common'; import { PartnersService } from './partners.service'; import { ServerResponse } from '../utils'; +import { AdminGuard } from '@/guards/admin.guard'; @Controller('partners') export class PartnersController { @@ -18,4 +27,16 @@ export class PartnersController { throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); } } + + @Post('') + @UseGuards(AdminGuard) + async store(@Body() body) { + try { + await this.partnersService.store(body); + return new ServerResponse(200, 'Successfully created partner'); + } catch (err: any) { + this.logger.error(`Failed to create partner: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } } diff --git a/src/partners/partners.service.ts b/src/partners/partners.service.ts index 6b3f6c8a..05f2628f 100644 --- a/src/partners/partners.service.ts +++ b/src/partners/partners.service.ts @@ -2,6 +2,8 @@ import { Injectable } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { PrismaService } from '../prisma/prisma.service'; +import { z } from 'zod'; +import { CreatePartnerSchema } from './types'; @ApiTags('Parceiros') @Injectable() @@ -11,4 +13,11 @@ export class PartnersService { async index() { return await this.prismaService.partners.findMany({}); } + + async store(body: z.infer) { + const payload = CreatePartnerSchema.parse(body); + await this.prismaService.partners.create({ + data: { ...payload, createdAt: new Date().toISOString() }, + }); + } } diff --git a/src/partners/types.ts b/src/partners/types.ts new file mode 100644 index 00000000..8844bbc5 --- /dev/null +++ b/src/partners/types.ts @@ -0,0 +1,17 @@ +import z from 'zod'; + +const PartnerSchema = z.object({ + id: z.string(), + name: z.string(), + link: z.string(), + createdAt: z.string(), + updatedAt: z.string().nullable().optional(), +}); + +const CreatePartnerSchema = PartnerSchema.omit({ + id: true, + createdAt: true, + updatedAt: true, +}); + +export { PartnerSchema, CreatePartnerSchema }; diff --git a/src/supporters/supporters.controller.spec.ts b/src/supporters/supporters.controller.spec.ts new file mode 100644 index 00000000..bdd4f767 --- /dev/null +++ b/src/supporters/supporters.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { SupportersController } from './supporters.controller'; + +describe('SupportersController', () => { + let controller: SupportersController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [SupportersController], + }).compile(); + + controller = module.get(SupportersController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/supporters/supporters.controller.ts b/src/supporters/supporters.controller.ts new file mode 100644 index 00000000..81a27504 --- /dev/null +++ b/src/supporters/supporters.controller.ts @@ -0,0 +1,43 @@ +import { + Body, + Controller, + Get, + HttpException, + Logger, + Post, + UseGuards, +} from '@nestjs/common'; + +import { SupportersService } from './supporters.service'; +import { ServerResponse } from '../utils'; +import { AdminGuard } from '@/guards/admin.guard'; + +@Controller('supporters') +export class SupportersController { + private logger = new Logger(SupportersController.name); + + constructor(private readonly supportersService: SupportersService) {} + + @Get('') + async index() { + try { + const data = await this.supportersService.index(); + return new ServerResponse(200, 'Successfully get supporters', data); + } catch (err: any) { + this.logger.error(`Failed to get supporters: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } + + @Post('') + @UseGuards(AdminGuard) + async store(@Body() body) { + try { + await this.supportersService.store(body); + return new ServerResponse(200, 'Successfully created supporter'); + } catch (err: any) { + this.logger.error(`Failed to create supporter: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } +} diff --git a/src/supporters/supporters.module.ts b/src/supporters/supporters.module.ts new file mode 100644 index 00000000..6a449002 --- /dev/null +++ b/src/supporters/supporters.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { SupportersService } from './supporters.service'; +import { SupportersController } from './supporters.controller'; +import { PrismaModule } from '../prisma/prisma.module'; + +@Module({ + imports: [PrismaModule], + providers: [SupportersService], + controllers: [SupportersController], +}) +export class SupportersModule {} diff --git a/src/supporters/supporters.service.spec.ts b/src/supporters/supporters.service.spec.ts new file mode 100644 index 00000000..93b703e3 --- /dev/null +++ b/src/supporters/supporters.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { SupportersService } from './supporters.service'; + +describe('SupportersService', () => { + let service: SupportersService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [SupportersService], + }).compile(); + + service = module.get(SupportersService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/supporters/supporters.service.ts b/src/supporters/supporters.service.ts new file mode 100644 index 00000000..bc488ecc --- /dev/null +++ b/src/supporters/supporters.service.ts @@ -0,0 +1,21 @@ +import { z } from 'zod'; +import { Injectable } from '@nestjs/common'; + +import { PrismaService } from '../prisma/prisma.service'; +import { CreateSupporterSchema } from './types'; + +@Injectable() +export class SupportersService { + constructor(private readonly prismaService: PrismaService) {} + + async index() { + return await this.prismaService.supporters.findMany({}); + } + + async store(body: z.infer) { + const payload = CreateSupporterSchema.parse(body); + await this.prismaService.supporters.create({ + data: { ...payload, createdAt: new Date().toISOString() }, + }); + } +} diff --git a/src/supporters/types.ts b/src/supporters/types.ts new file mode 100644 index 00000000..ae08ce64 --- /dev/null +++ b/src/supporters/types.ts @@ -0,0 +1,18 @@ +import z from 'zod'; + +const SupporterSchema = z.object({ + id: z.string(), + name: z.string(), + imageUrl: z.string(), + link: z.string(), + createdAt: z.string(), + updatedAt: z.string().nullable().optional(), +}); + +const CreateSupporterSchema = SupporterSchema.omit({ + id: true, + createdAt: true, + updatedAt: true, +}); + +export { SupporterSchema, CreateSupporterSchema }; From d4a98b5c8b294c44807620620b5cd8bbbe2f84d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Thu, 16 May 2024 21:47:40 -0300 Subject: [PATCH 09/12] fix: supporters module tests --- src/supporters/supporters.controller.spec.ts | 14 +++++++++++++- src/supporters/supporters.service.spec.ts | 12 +++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/supporters/supporters.controller.spec.ts b/src/supporters/supporters.controller.spec.ts index bdd4f767..8d281a47 100644 --- a/src/supporters/supporters.controller.spec.ts +++ b/src/supporters/supporters.controller.spec.ts @@ -1,5 +1,8 @@ import { Test, TestingModule } from '@nestjs/testing'; + import { SupportersController } from './supporters.controller'; +import { PrismaService } from '../prisma/prisma.service'; +import { SupportersService } from './supporters.service'; describe('SupportersController', () => { let controller: SupportersController; @@ -7,7 +10,16 @@ describe('SupportersController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SupportersController], - }).compile(); + providers: [SupportersService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return { + supplyCategory: { findMany: jest.fn().mockResolvedValue(0) }, + }; + } + }) + .compile(); controller = module.get(SupportersController); }); diff --git a/src/supporters/supporters.service.spec.ts b/src/supporters/supporters.service.spec.ts index 93b703e3..e2e9cc81 100644 --- a/src/supporters/supporters.service.spec.ts +++ b/src/supporters/supporters.service.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; + import { SupportersService } from './supporters.service'; +import { PrismaService } from '../prisma/prisma.service'; describe('SupportersService', () => { let service: SupportersService; @@ -7,7 +9,15 @@ describe('SupportersService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [SupportersService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return { + supplyCategory: { findMany: jest.fn().mockResolvedValue(0) }, + }; + } + }) + .compile(); service = module.get(SupportersService); }); From 2d14d3aec255759829e72972459295645013e3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Fri, 17 May 2024 15:29:11 -0300 Subject: [PATCH 10/12] fix: accents on get all shelters --- .../migration.sql | 3 ++ src/shelter/ShelterSearch.ts | 34 +++++++++---------- src/shelter/shelter.service.ts | 4 ++- 3 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 prisma/migrations/20240517181431_add_unaccent_extension/migration.sql diff --git a/prisma/migrations/20240517181431_add_unaccent_extension/migration.sql b/prisma/migrations/20240517181431_add_unaccent_extension/migration.sql new file mode 100644 index 00000000..3c7c1164 --- /dev/null +++ b/prisma/migrations/20240517181431_add_unaccent_extension/migration.sql @@ -0,0 +1,3 @@ +-- This is an empty migration. + +CREATE EXTENSION IF NOT EXISTS unaccent; \ No newline at end of file diff --git a/src/shelter/ShelterSearch.ts b/src/shelter/ShelterSearch.ts index 3d1367e5..15a3ca4d 100644 --- a/src/shelter/ShelterSearch.ts +++ b/src/shelter/ShelterSearch.ts @@ -27,6 +27,7 @@ class ShelterSearch { ) { this.prismaService = prismaService; this.formProps = { ...props }; + this.getQuery = this.getQuery.bind(this); } priority(supplyIds: string[] = []): Prisma.ShelterWhereInput { @@ -102,23 +103,20 @@ class ShelterSearch { }; } - get search(): Prisma.ShelterWhereInput[] { - if (!this.formProps.search) return []; + async getSearch(): Promise { + if (!this.formProps.search) return {}; - return [ - { - address: { - contains: this.formProps.search, - mode: 'insensitive', - }, - }, - { - name: { - contains: this.formProps.search, - mode: 'insensitive', - }, + const search = `${this.formProps.search.toLowerCase()}`; + + const results = await this.prismaService.$queryRaw<{ id: string }[]>( + Prisma.sql`SELECT id, name FROM shelters WHERE lower(unaccent(address)) LIKE '%' || unaccent(${search}) || '%' OR lower(unaccent(name)) LIKE '%' || unaccent(${search}) || '%';`, + ); + + return { + id: { + in: results.map((r) => r.id), }, - ]; + }; } get cities(): Prisma.ShelterWhereInput { @@ -150,13 +148,15 @@ class ShelterSearch { }; } - get query(): Prisma.ShelterWhereInput { + async getQuery(): Promise { if (Object.keys(this.formProps).length === 0) return {}; + + const search = await this.getSearch(); const queryData = { AND: [ this.cities, this.geolocation, - { OR: this.search }, + search, { OR: this.shelterStatus }, this.priority(this.formProps.supplyIds), this.supplyCategoryIds(this.formProps.priority), diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index f9c853d8..dc7ab680 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -125,7 +125,9 @@ export class ShelterService implements OnModuleInit { search: searchQuery, } = SearchSchema.parse(query); const queryData = ShelterSearchPropsSchema.parse(qs.parse(searchQuery)); - const { query: where } = new ShelterSearch(this.prismaService, queryData); + const { getQuery } = new ShelterSearch(this.prismaService, queryData); + const where = await getQuery(); + const count = await this.prismaService.shelter.count({ where }); const take = perPage; From da491dcdfb6291c5daf37c116d0f82416e18d629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Fri, 17 May 2024 15:42:12 -0300 Subject: [PATCH 11/12] fix: removed unecessary name from query --- src/shelter/ShelterSearch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shelter/ShelterSearch.ts b/src/shelter/ShelterSearch.ts index 15a3ca4d..1b9c76cf 100644 --- a/src/shelter/ShelterSearch.ts +++ b/src/shelter/ShelterSearch.ts @@ -109,7 +109,7 @@ class ShelterSearch { const search = `${this.formProps.search.toLowerCase()}`; const results = await this.prismaService.$queryRaw<{ id: string }[]>( - Prisma.sql`SELECT id, name FROM shelters WHERE lower(unaccent(address)) LIKE '%' || unaccent(${search}) || '%' OR lower(unaccent(name)) LIKE '%' || unaccent(${search}) || '%';`, + Prisma.sql`SELECT id FROM shelters WHERE lower(unaccent(address)) LIKE '%' || unaccent(${search}) || '%' OR lower(unaccent(name)) LIKE '%' || unaccent(${search}) || '%';`, ); return { From a4be895f2751005a3aadfbc6489cd348a7c05b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Fri, 17 May 2024 17:14:44 -0300 Subject: [PATCH 12/12] feat: added shelter category column --- .../migrations/20240517192040_/migration.sql | 6 ++++ prisma/schema.prisma | 29 ++++++++++++------- src/shelter/shelter.service.ts | 4 +++ 3 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 prisma/migrations/20240517192040_/migration.sql diff --git a/prisma/migrations/20240517192040_/migration.sql b/prisma/migrations/20240517192040_/migration.sql new file mode 100644 index 00000000..96a868d6 --- /dev/null +++ b/prisma/migrations/20240517192040_/migration.sql @@ -0,0 +1,6 @@ +-- CreateEnum +CREATE TYPE "ShelterCategory" AS ENUM ('Shelter', 'DistributionCenter'); + +-- AlterTable +ALTER TABLE "shelters" ADD COLUMN "actived" BOOLEAN NOT NULL DEFAULT true, +ADD COLUMN "category" "ShelterCategory" NOT NULL DEFAULT 'Shelter'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7c726855..04d0ee48 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -14,6 +14,11 @@ enum AccessLevel { Admin } +enum ShelterCategory { + Shelter + DistributionCenter +} + model User { id String @id @default(uuid()) name String @@ -85,25 +90,27 @@ model Supply { } model Shelter { - id String @id @default(uuid()) - name String @unique - pix String? @unique + id String @id @default(uuid()) + name String @unique + pix String? @unique address String street String? neighbourhood String? city String? - streetNumber String? @map("street_number") - zipCode String? @map("zip_code") - petFriendly Boolean? @map("pet_friendly") - shelteredPeople Int? @map("sheltered_people") + streetNumber String? @map("street_number") + zipCode String? @map("zip_code") + petFriendly Boolean? @map("pet_friendly") + shelteredPeople Int? @map("sheltered_people") capacity Int? contact String? - prioritySum Int @default(value: 0) @map("priority_sum") + prioritySum Int @default(value: 0) @map("priority_sum") latitude Float? longitude Float? - verified Boolean @default(value: false) - createdAt String @map("created_at") @db.VarChar(32) - updatedAt String? @map("updated_at") @db.VarChar(32) + verified Boolean @default(value: false) + category ShelterCategory @default(value: Shelter) + actived Boolean @default(value: true) + createdAt String @map("created_at") @db.VarChar(32) + updatedAt String? @map("updated_at") @db.VarChar(32) shelterManagers ShelterManagers[] shelterSupplies ShelterSupply[] diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index dc7ab680..f79ac367 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -87,6 +87,8 @@ export class ShelterService implements OnModuleInit { latitude: true, longitude: true, verified: true, + actived: true, + category: true, shelterSupplies: { select: { priority: true, @@ -159,6 +161,8 @@ export class ShelterService implements OnModuleInit { verified: true, latitude: true, longitude: true, + actived: true, + category: true, createdAt: true, updatedAt: true, shelterSupplies: {