From 2f50428c34ee21c10c88b2d3bf4a42fb69e2cb45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Geraldo=20D=2E=20F?= Date: Thu, 30 May 2024 18:44:38 -0300 Subject: [PATCH 1/8] =?UTF-8?q?Feat:=20carrinho=20de=20doa=C3=A7=C3=B5es?= =?UTF-8?q?=20(#182)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/sos-rs.insomnia.json | 670 +++++++++++++++++- prisma/dev_dump.sql | 2 +- .../migrations/20240528182902_/migration.sql | 44 ++ prisma/schema.prisma | 61 +- src/app.module.ts | 4 +- .../dashboard/dashboard.controller.spec.ts | 12 +- .../dashboard/dashboard.controller.ts | 0 .../dashboard/dashboard.module.ts | 0 .../dashboard/dashboard.service.spec.ts | 12 +- .../dashboard/dashboard.service.ts | 82 ++- .../donation-order.controller.spec.ts | 30 + .../donation-order.controller.ts | 82 +++ src/donation-order/donation-order.module.ts | 12 + .../donation-order.service.spec.ts | 28 + src/donation-order/donation-order.service.ts | 143 ++++ src/donation-order/types.ts | 39 + .../shelter-supply-history/utils.ts | 32 +- .../shelter-supply.controller.ts | 22 - src/shelter-supply/shelter-supply.service.ts | 51 +- src/shelter-supply/types.ts | 6 - src/shelter/shelter.service.ts | 2 +- .../supplies-history.service.ts | 1 + src/users/users.controller.ts | 41 +- src/users/users.service.ts | 9 + 24 files changed, 1216 insertions(+), 169 deletions(-) create mode 100644 prisma/migrations/20240528182902_/migration.sql rename src/{modules => }/dashboard/dashboard.controller.spec.ts (67%) rename src/{modules => }/dashboard/dashboard.controller.ts (100%) rename src/{modules => }/dashboard/dashboard.module.ts (100%) rename src/{modules => }/dashboard/dashboard.service.spec.ts (61%) rename src/{modules => }/dashboard/dashboard.service.ts (73%) create mode 100644 src/donation-order/donation-order.controller.spec.ts create mode 100644 src/donation-order/donation-order.controller.ts create mode 100644 src/donation-order/donation-order.module.ts create mode 100644 src/donation-order/donation-order.service.spec.ts create mode 100644 src/donation-order/donation-order.service.ts create mode 100644 src/donation-order/types.ts diff --git a/docs/sos-rs.insomnia.json b/docs/sos-rs.insomnia.json index 52abb855..916ae0ac 100644 --- a/docs/sos-rs.insomnia.json +++ b/docs/sos-rs.insomnia.json @@ -1 +1,669 @@ -{"_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 +{ + "_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\": \"Administrador\",\n\t\"lastName\": \"WEB\",\n\t\"phone\": \"(31) 999999999\"\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\": \"31999999999\",\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" + } + ] +} diff --git a/prisma/dev_dump.sql b/prisma/dev_dump.sql index 211625a8..83b66b3b 100644 --- a/prisma/dev_dump.sql +++ b/prisma/dev_dump.sql @@ -93,7 +93,7 @@ INSERT INTO public.partners VALUES ('33fc6b9c-e9dd-446d-b0a1-f66dd8a45cda', 'Pai -- Data for Name: users; Type: TABLE DATA; Schema: public; Owner: doadmin -- -INSERT INTO public.users VALUES ('e0306bc0-8c29-429a-bbd2-384f48d4f993', 'Dinho', '31996675945', '$2b$10$V4hFTbT7MrskROc4TI2lNe6gAd0g7U1niziAPycFueLhPJRFIfoGm', '31996675945', '2024-05-05T22:04:59.468Z', '2024-05-09T17:56:55.037Z', 'Admin', 'Duarte'); +INSERT INTO public.users VALUES ('e0306bc0-8c29-429a-bbd2-384f48d4f993', 'Administrador', '31999999999', '$2b$10$V4hFTbT7MrskROc4TI2lNe6gAd0g7U1niziAPycFueLhPJRFIfoGm', '31999999999', '2024-05-05T22:04:59.468Z', '2024-05-09T17:56:55.037Z', 'Admin', 'Web'); INSERT INTO public.users VALUES ('e82f476a-1574-4dd2-a4c4-1c1f0117db12', 'Rhuam', '51992047974', '$2b$10$V4hFTbT7MrskROc4TI2lNe6gAd0g7U1niziAPycFueLhPJRFIfoGm', '51992047974', '2024-05-05T22:06:11.390Z', '2024-05-16T18:52:36.650Z', 'Admin', 'Estevam'); diff --git a/prisma/migrations/20240528182902_/migration.sql b/prisma/migrations/20240528182902_/migration.sql new file mode 100644 index 00000000..6d13c04d --- /dev/null +++ b/prisma/migrations/20240528182902_/migration.sql @@ -0,0 +1,44 @@ +-- CreateEnum +CREATE TYPE "SupplyMeasure" AS ENUM ('Unit', 'Kg', 'Litters', 'Box', 'Piece'); + +-- CreateEnum +CREATE TYPE "DonationOrderStatus" AS ENUM ('Pending', 'Canceled', 'Complete'); + +-- AlterTable +ALTER TABLE "supplies" ADD COLUMN "measure" "SupplyMeasure" NOT NULL DEFAULT 'Unit'; + +-- CreateTable +CREATE TABLE "donation_order_supplies" ( + "id" TEXT NOT NULL, + "donation_order_id" TEXT NOT NULL, + "supply_id" TEXT NOT NULL, + "quantity" INTEGER NOT NULL, + "created_at" VARCHAR(32) NOT NULL, + "updated_at" VARCHAR(32), + + CONSTRAINT "donation_order_supplies_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "donation_orders" ( + "id" TEXT NOT NULL, + "user_id" TEXT NOT NULL, + "shelter_id" TEXT NOT NULL, + "status" "DonationOrderStatus" NOT NULL DEFAULT 'Pending', + "created_at" VARCHAR(32) NOT NULL, + "updated_at" VARCHAR(32), + + CONSTRAINT "donation_orders_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "donation_order_supplies" ADD CONSTRAINT "donation_order_supplies_supply_id_fkey" FOREIGN KEY ("supply_id") REFERENCES "supplies"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "donation_order_supplies" ADD CONSTRAINT "donation_order_supplies_donation_order_id_fkey" FOREIGN KEY ("donation_order_id") REFERENCES "donation_orders"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "donation_orders" ADD CONSTRAINT "donation_orders_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "donation_orders" ADD CONSTRAINT "donation_orders_shelter_id_fkey" FOREIGN KEY ("shelter_id") REFERENCES "shelters"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 69d25067..57447c75 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -19,6 +19,20 @@ enum ShelterCategory { DistributionCenter } +enum SupplyMeasure { + Unit + Kg + Litters + Box + Piece +} + +enum DonationOrderStatus { + Pending + Canceled + Complete +} + model User { id String @id @default(uuid()) name String @@ -33,6 +47,7 @@ model User { sessions Session[] shelterManagers ShelterManagers[] suppliesHistory SupplyHistory[] + donationOrders DonationOrder[] @@map("users") } @@ -78,15 +93,17 @@ model ShelterSupply { } model Supply { - id String @id @default(uuid()) - supplyCategoryId String @map("supply_category_id") + id String @id @default(uuid()) + supplyCategoryId String @map("supply_category_id") name String - createdAt String @map("created_at") @db.VarChar(32) - updatedAt String? @map("updated_at") @db.VarChar(32) + measure SupplyMeasure @default(value: Unit) + createdAt String @map("created_at") @db.VarChar(32) + updatedAt String? @map("updated_at") @db.VarChar(32) - supplyCategory SupplyCategory @relation(fields: [supplyCategoryId], references: [id]) - shelterSupplies ShelterSupply[] - supplyHistories SupplyHistory[] + supplyCategory SupplyCategory @relation(fields: [supplyCategoryId], references: [id]) + shelterSupplies ShelterSupply[] + supplyHistories SupplyHistory[] + DonationOrderSupply DonationOrderSupply[] @@map("supplies") } @@ -117,6 +134,7 @@ model Shelter { shelterManagers ShelterManagers[] shelterSupplies ShelterSupply[] supplyHistories SupplyHistory[] + DonationOrder DonationOrder[] @@map("shelters") } @@ -175,3 +193,32 @@ model SupplyHistory { @@map("supplies_history") } + +model DonationOrderSupply { + id String @id @default(uuid()) + donationOrderId String @map("donation_order_id") + supplyId String @map("supply_id") + quantity Int + createdAt String @map("created_at") @db.VarChar(32) + updatedAt String? @map("updated_at") @db.VarChar(32) + + supply Supply @relation(fields: [supplyId], references: [id]) + donationOrder DonationOrder @relation(fields: [donationOrderId], references: [id]) + + @@map("donation_order_supplies") +} + +model DonationOrder { + id String @id @default(uuid()) + userId String @map("user_id") + shelterId String @map("shelter_id") + status DonationOrderStatus @default(value: Pending) + createdAt String @map("created_at") @db.VarChar(32) + updatedAt String? @map("updated_at") @db.VarChar(32) + + user User @relation(fields: [userId], references: [id]) + shelter Shelter @relation(fields: [shelterId], references: [id]) + donationOrderSupplies DonationOrderSupply[] + + @@map("donation_orders") +} diff --git a/src/app.module.ts b/src/app.module.ts index 3f814215..5f953f1a 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -12,9 +12,10 @@ 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 { DashboardModule } from './modules/dashboard/dashboard.module'; +import { DashboardModule } from './dashboard/dashboard.module'; import { SupportersModule } from './supporters/supporters.module'; import { SuppliesHistoryModule } from './supplies-history/supplies-history.module'; +import { DonationOrderModule } from './donation-order/donation-order.module'; @Module({ imports: [ @@ -30,6 +31,7 @@ import { SuppliesHistoryModule } from './supplies-history/supplies-history.modul DashboardModule, SupportersModule, SuppliesHistoryModule, + DonationOrderModule, ], controllers: [], providers: [ diff --git a/src/modules/dashboard/dashboard.controller.spec.ts b/src/dashboard/dashboard.controller.spec.ts similarity index 67% rename from src/modules/dashboard/dashboard.controller.spec.ts rename to src/dashboard/dashboard.controller.spec.ts index 9ae8da71..312a8e2a 100644 --- a/src/modules/dashboard/dashboard.controller.spec.ts +++ b/src/dashboard/dashboard.controller.spec.ts @@ -1,15 +1,25 @@ import { Test, TestingModule } from '@nestjs/testing'; + import { DashboardController } from './dashboard.controller'; import { DashboardService } from './dashboard.service'; +import { PrismaService } from '../../prisma/prisma.service'; +import { PrismaModule } from '../../prisma/prisma.module'; describe('DashboardController', () => { let controller: DashboardController; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ + imports: [PrismaModule], controllers: [DashboardController], providers: [DashboardService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get(DashboardController); }); diff --git a/src/modules/dashboard/dashboard.controller.ts b/src/dashboard/dashboard.controller.ts similarity index 100% rename from src/modules/dashboard/dashboard.controller.ts rename to src/dashboard/dashboard.controller.ts diff --git a/src/modules/dashboard/dashboard.module.ts b/src/dashboard/dashboard.module.ts similarity index 100% rename from src/modules/dashboard/dashboard.module.ts rename to src/dashboard/dashboard.module.ts diff --git a/src/modules/dashboard/dashboard.service.spec.ts b/src/dashboard/dashboard.service.spec.ts similarity index 61% rename from src/modules/dashboard/dashboard.service.spec.ts rename to src/dashboard/dashboard.service.spec.ts index dc3993ae..d02863a9 100644 --- a/src/modules/dashboard/dashboard.service.spec.ts +++ b/src/dashboard/dashboard.service.spec.ts @@ -1,13 +1,23 @@ import { Test, TestingModule } from '@nestjs/testing'; + import { DashboardService } from './dashboard.service'; +import { PrismaService } from '../../prisma/prisma.service'; +import { PrismaModule } from '../../prisma/prisma.module'; describe('DashboardService', () => { let service: DashboardService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ + imports: [PrismaModule], providers: [DashboardService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(DashboardService); }); diff --git a/src/modules/dashboard/dashboard.service.ts b/src/dashboard/dashboard.service.ts similarity index 73% rename from src/modules/dashboard/dashboard.service.ts rename to src/dashboard/dashboard.service.ts index 22952e26..25d29883 100644 --- a/src/modules/dashboard/dashboard.service.ts +++ b/src/dashboard/dashboard.service.ts @@ -46,6 +46,7 @@ export class DashboardService { priority: true, supply: { select: { + measure: true, supplyCategory: { select: { name: true, @@ -58,34 +59,35 @@ export class DashboardService { }, }); - const categoriesWithPriorities = await this.prismaService.supplyCategory.findMany({ - select: { - id: true, - name: true, - supplies: { - select: { - shelterSupplies: { - select: { - priority: true, - shelterId: true - } - } - } - } - } - }); - - const result = categoriesWithPriorities.map(category => { + const categoriesWithPriorities = + await this.prismaService.supplyCategory.findMany({ + select: { + id: true, + name: true, + supplies: { + select: { + shelterSupplies: { + select: { + priority: true, + shelterId: true, + }, + }, + }, + }, + }, + }); + + const result = categoriesWithPriorities.map((category) => { const priorityCounts = { priority100: 0, priority10: 0, priority1: 0, }; - + const countedShelters = new Set(); - - category.supplies.forEach(supply => { - supply.shelterSupplies.forEach(shelterSupply => { + + category.supplies.forEach((supply) => { + supply.shelterSupplies.forEach((shelterSupply) => { if (!countedShelters.has(shelterSupply.shelterId)) { switch (shelterSupply.priority) { case 100: @@ -124,30 +126,40 @@ export class DashboardService { } }, 0); - const numSheltersAvailable = allShelters.filter(shelter => { - if (shelter.actived && shelter.capacity !== null && shelter.capacity > 0) { - return (shelter.shelteredPeople ?? 0) < shelter.capacity; + const numSheltersAvailable = allShelters.filter((shelter) => { + if ( + shelter.actived && + shelter.capacity !== null && + shelter.capacity > 0 + ) { + return (shelter.shelteredPeople ?? 0) < shelter.capacity; } - return false; - }).length; + return false; + }).length; const numSheltersFull = allShelters.reduce((count, shelter) => { - if (shelter.actived && shelter.capacity !== null && shelter.capacity > 0) { - if ((shelter.shelteredPeople ?? 0) >= shelter.capacity) { - return count + 1; - } + if ( + shelter.actived && + shelter.capacity !== null && + shelter.capacity > 0 + ) { + if ((shelter.shelteredPeople ?? 0) >= shelter.capacity) { + return count + 1; + } } return count; }, 0); const shelterWithoutInformation = allShelters.reduce((count, shelter) => { - if (shelter.shelteredPeople === null || shelter.shelteredPeople === undefined) { - return count + 1; + if ( + shelter.shelteredPeople === null || + shelter.shelteredPeople === undefined + ) { + return count + 1; } return count; }, 0); - - + return { allShelters: allShelters.length, allPeopleSheltered: allPeopleSheltered, diff --git a/src/donation-order/donation-order.controller.spec.ts b/src/donation-order/donation-order.controller.spec.ts new file mode 100644 index 00000000..9f734f1f --- /dev/null +++ b/src/donation-order/donation-order.controller.spec.ts @@ -0,0 +1,30 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { DonationOrderController } from './donation-order.controller'; +import { PrismaService } from '../prisma/prisma.service'; +import { PrismaModule } from '../prisma/prisma.module'; +import { DonationOrderService } from './donation-order.service'; + +describe('DonationOrderController', () => { + let controller: DonationOrderController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [PrismaModule], + providers: [DonationOrderService], + controllers: [DonationOrderController], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); + + controller = module.get(DonationOrderController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/donation-order/donation-order.controller.ts b/src/donation-order/donation-order.controller.ts new file mode 100644 index 00000000..52997ecc --- /dev/null +++ b/src/donation-order/donation-order.controller.ts @@ -0,0 +1,82 @@ +import { + Body, + Controller, + Get, + HttpException, + Logger, + Param, + Post, + Put, + Query, + Request, + UseGuards, +} from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; + +import { DonationOrderService } from './donation-order.service'; +import { ServerResponse } from '../utils'; +import { UserGuard } from '@/guards/user.guard'; + +@ApiTags('Doações') +@Controller('donation/order') +export class DonationOrderController { + private logger = new Logger(DonationOrderController.name); + + constructor(private readonly donationOrderService: DonationOrderService) {} + + @Post('') + @UseGuards(UserGuard) + async store(@Body() body, @Request() req) { + try { + const { userId } = req.user; + const data = await this.donationOrderService.store({ ...body, userId }); + return new ServerResponse(200, 'Successfully store donation order', data); + } catch (err: any) { + this.logger.error(`Failed to store donation order: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } + + @Put(':orderId') + @UseGuards(UserGuard) + async update(@Param('orderId') orderId: string, @Body() body) { + try { + await this.donationOrderService.update(orderId, body); + return new ServerResponse(200, 'Successfully updated donation order'); + } catch (err: any) { + this.logger.error(`Failed to update donation order: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } + + @Get('') + @UseGuards(UserGuard) + async index(@Query() query, @Request() req) { + try { + const { userId } = req.user; + const data = await this.donationOrderService.index(userId, query); + return new ServerResponse( + 200, + 'Successfully get all donation orders', + data, + ); + } catch (err: any) { + this.logger.error(`Failed to get all donation orders: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } + + @Get(':id') + @UseGuards(UserGuard) + async show(@Param('id') id: string, @Request() req) { + try { + const { userId } = req.user; + const data = await this.donationOrderService.show(id, userId); + if (!data) throw new HttpException('Not founded donation order', 404); + return new ServerResponse(200, 'Successfully get donation order', data); + } catch (err: any) { + this.logger.error(`Failed to get donation order: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } +} diff --git a/src/donation-order/donation-order.module.ts b/src/donation-order/donation-order.module.ts new file mode 100644 index 00000000..cf1191b0 --- /dev/null +++ b/src/donation-order/donation-order.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { DonationOrderService } from './donation-order.service'; +import { DonationOrderController } from './donation-order.controller'; +import { PrismaModule } from '../prisma/prisma.module'; + +@Module({ + imports: [PrismaModule], + providers: [DonationOrderService], + controllers: [DonationOrderController], +}) +export class DonationOrderModule {} diff --git a/src/donation-order/donation-order.service.spec.ts b/src/donation-order/donation-order.service.spec.ts new file mode 100644 index 00000000..aa1e49f7 --- /dev/null +++ b/src/donation-order/donation-order.service.spec.ts @@ -0,0 +1,28 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { DonationOrderService } from './donation-order.service'; +import { PrismaService } from '../prisma/prisma.service'; +import { PrismaModule } from '../prisma/prisma.module'; + +describe('DonationOrderService', () => { + let service: DonationOrderService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [PrismaModule], + providers: [DonationOrderService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); + + service = module.get(DonationOrderService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/donation-order/donation-order.service.ts b/src/donation-order/donation-order.service.ts new file mode 100644 index 00000000..6bcb11d1 --- /dev/null +++ b/src/donation-order/donation-order.service.ts @@ -0,0 +1,143 @@ +import { z } from 'zod'; +import { Injectable } from '@nestjs/common'; +import { Prisma } from '@prisma/client'; +import { DefaultArgs } from '@prisma/client/runtime/library'; + +import { PrismaService } from '../prisma/prisma.service'; +import { CreateDonationOrderScheme, UpdateDonationOrderScheme } from './types'; +import { SearchSchema } from '../types'; + +@Injectable() +export class DonationOrderService { + constructor(private readonly prismaService: PrismaService) {} + + async index(userId: string, query: any) { + const { shelterId } = query; + const { order, orderBy, page, perPage } = SearchSchema.parse(query); + + const where: Prisma.DonationOrderWhereInput = { + shelterId, + userId, + }; + + const count = await this.prismaService.donationOrder.count({ where }); + + const take = perPage; + const skip = perPage * (page - 1); + + const whereData: Prisma.DonationOrderFindManyArgs = { + take, + skip, + orderBy: { [orderBy]: order }, + where, + }; + + const results = await this.prismaService.donationOrder.findMany({ + ...whereData, + select: { + id: true, + status: true, + userId: true, + shelter: { + select: { + id: true, + name: true, + }, + }, + donationOrderSupplies: { + select: { + quantity: true, + supply: { + select: { + name: true, + measure: true, + }, + }, + }, + }, + createdAt: true, + updatedAt: true, + }, + orderBy: { + createdAt: 'desc', + }, + }); + + return { + page, + perPage, + count, + results, + }; + } + + async show(id: string, userId: string) { + const data = await this.prismaService.donationOrder.findUnique({ + where: { id, userId }, + select: { + id: true, + status: true, + userId: true, + shelter: { + select: { + id: true, + name: true, + }, + }, + donationOrderSupplies: { + select: { + quantity: true, + supply: { + select: { + name: true, + measure: true, + }, + }, + }, + }, + createdAt: true, + updatedAt: true, + }, + }); + return data; + } + + async store(body: z.infer) { + const { supplies, shelterId, userId } = + CreateDonationOrderScheme.parse(body); + const donation = await this.prismaService.donationOrder.create({ + data: { + shelterId, + userId, + createdAt: new Date().toISOString(), + donationOrderSupplies: { + createMany: { + data: supplies.map((s) => ({ + supplyId: s.id, + quantity: s.quantity, + createdAt: new Date().toISOString(), + })), + }, + }, + }, + }); + + return donation; + } + + async update( + orderId: string, + body: z.infer, + ) { + const { status } = UpdateDonationOrderScheme.parse(body); + await this.prismaService.donationOrder.update({ + where: { + id: orderId, + }, + data: { + status, + updatedAt: new Date().toISOString(), + }, + }); + } +} diff --git a/src/donation-order/types.ts b/src/donation-order/types.ts new file mode 100644 index 00000000..f0c524c0 --- /dev/null +++ b/src/donation-order/types.ts @@ -0,0 +1,39 @@ +import { DonationOrderStatus } from '@prisma/client'; +import z from 'zod'; + +const DonationOrderScheme = z.object({ + id: z.string(), + userId: z.string(), + shelterId: z.string(), + status: z.enum([ + DonationOrderStatus.Canceled, + DonationOrderStatus.Complete, + DonationOrderStatus.Pending, + ]), + createdAt: z.string(), + updatedAt: z.string().nullish(), +}); + +const CreateDonationOrderScheme = DonationOrderScheme.omit({ + id: true, + status: true, + createdAt: true, + updatedAt: true, +}).extend({ + supplies: z.array( + z.object({ + id: z.string(), + quantity: z.number().min(1), + }), + ), +}); + +const UpdateDonationOrderScheme = DonationOrderScheme.pick({ + status: true, +}); + +export { + DonationOrderScheme, + CreateDonationOrderScheme, + UpdateDonationOrderScheme, +}; diff --git a/src/interceptors/interceptors/shelter-supply-history/utils.ts b/src/interceptors/interceptors/shelter-supply-history/utils.ts index 46119734..2bcfee53 100644 --- a/src/interceptors/interceptors/shelter-supply-history/utils.ts +++ b/src/interceptors/interceptors/shelter-supply-history/utils.ts @@ -4,14 +4,12 @@ import { Logger } from '@nestjs/common'; import { CreateShelterSupplySchema, - UpdateManyShelterSupplySchema, UpdateShelterSupplySchema, } from '../../../shelter-supply/types'; import { PrismaService } from '../../../prisma/prisma.service'; import { CreateSupplyHistorySchema } from '../../../supplies-history/types'; -import { SupplyPriority } from '../../../supply/types'; import { ShelterSupplyHistoryAction, UserIdentity } from './types'; -import { getSessionData } from '@/utils/utils'; +import { getSessionData } from '@/utils'; function registerSupplyLog( body: z.infer, @@ -80,25 +78,6 @@ function registerUpdateSupplyLog( ); } -function registerUpdateManySupplyLog( - body: z.infer, - user: UserIdentity, -) { - const { ids, shelterId } = UpdateManyShelterSupplySchema.parse(body); - - ids.forEach((id) => - registerSupplyLog( - { - shelterId, - supplyId: id, - priority: SupplyPriority.UnderControl, - quantity: 0, - }, - user, - ), - ); -} - function handler( prismaService: PrismaService, action: ShelterSupplyHistoryAction, @@ -129,15 +108,6 @@ function handler( user, ); break; - case ShelterSupplyHistoryAction.UpdateMany: - registerUpdateManySupplyLog( - { - shelterId: (request.params as any).shelterId, - ids: (request.body as any).ids, - }, - user, - ); - break; } } diff --git a/src/shelter-supply/shelter-supply.controller.ts b/src/shelter-supply/shelter-supply.controller.ts index d052579f..226d0796 100644 --- a/src/shelter-supply/shelter-supply.controller.ts +++ b/src/shelter-supply/shelter-supply.controller.ts @@ -7,13 +7,11 @@ 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'; import { RegisterShelterSupplyHistory } from '@/decorators/RegisterShelterSupplyHistory'; import { ShelterSupplyHistoryAction } from '@/interceptors/interceptors/shelter-supply-history/types'; @@ -73,24 +71,4 @@ export class ShelterSupplyController { throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); } } - - @Put(':shelterId/supplies/many') - @UseGuards(DistributionCenterGuard) - @RegisterShelterSupplyHistory(ShelterSupplyHistoryAction.UpdateMany) - 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 ef4cf97a..5c9b2a77 100644 --- a/src/shelter-supply/shelter-supply.service.ts +++ b/src/shelter-supply/shelter-supply.service.ts @@ -2,11 +2,7 @@ import { z } from 'zod'; import { Injectable } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; -import { - CreateShelterSupplySchema, - UpdateManyShelterSupplySchema, - UpdateShelterSupplySchema, -} from './types'; +import { CreateShelterSupplySchema, UpdateShelterSupplySchema } from './types'; import { SupplyPriority } from '../supply/types'; @Injectable() @@ -79,50 +75,6 @@ export class ShelterSupplyService { }); } - async updateMany(body: z.infer) { - const { ids, shelterId } = UpdateManyShelterSupplySchema.parse(body); - - const supplies = await this.prismaService.shelterSupply.findMany({ - where: { - shelterId, - supplyId: { - in: ids, - }, - }, - }); - - 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) { return await this.prismaService.shelterSupply.findMany({ where: { @@ -135,6 +87,7 @@ export class ShelterSupplyService { select: { id: true, name: true, + measure: true, supplyCategory: { select: { id: true, diff --git a/src/shelter-supply/types.ts b/src/shelter-supply/types.ts index f683bf68..0de6cc72 100644 --- a/src/shelter-supply/types.ts +++ b/src/shelter-supply/types.ts @@ -44,14 +44,8 @@ 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/shelter.service.ts b/src/shelter/shelter.service.ts index 058db35f..757acdba 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -104,7 +104,7 @@ export class ShelterService implements OnModuleInit { select: { id: true, name: true, - + measure: true, supplyCategory: { select: { id: true, diff --git a/src/supplies-history/supplies-history.service.ts b/src/supplies-history/supplies-history.service.ts index 3505ebf9..4bfd0a02 100644 --- a/src/supplies-history/supplies-history.service.ts +++ b/src/supplies-history/supplies-history.service.ts @@ -36,6 +36,7 @@ export class SuppliesHistoryService { id: true, supply: { select: { + measure: true, name: true, }, }, diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 18baf4b6..586290e1 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -1,6 +1,7 @@ import { Body, Controller, + Get, HttpException, Logger, Param, @@ -24,7 +25,6 @@ export class UsersController { constructor(private readonly userServices: UsersService) {} @Post('') - @UseGuards(AdminGuard) @ApiBearerAuth() @ApiOperation({ summary: 'Cria um novo usuário', @@ -43,9 +43,9 @@ export class UsersController { examples: { 'Exemplo 1': { value: { - name: 'Dinho', - lastName: 'Duarte', - phone: '(31) 996675945', + name: 'Administrador', + lastName: 'Web', + phone: '(31) 999999999', }, }, }, @@ -83,10 +83,10 @@ export class UsersController { examples: { 'Exemplo 1': { value: { - name: 'Dinho', - lastName: 'Duarte', - phone: '(31) 996675945', - login: 'dinho duarte', + name: 'Administrador', + lastName: 'Web', + phone: '(31) 999999999', + login: 'admin', password: '123456', }, }, @@ -125,11 +125,11 @@ export class UsersController { examples: { 'Exemplo 1': { value: { - name: 'Dinho', - lastName: 'Duarte', - phone: '(31) 996675945', - login: 'dinho duarte', - password: '123456', + name: 'João', + lastName: 'Neves', + phone: '(11) 99999-9999', + login: 'joaodasneves', + password: '12345678', }, }, }, @@ -144,4 +144,19 @@ export class UsersController { throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); } } + + @Get('find/:field/:value') + async find(@Param('field') field: string, @Param('value') value: string) { + try { + const result = await this.userServices.checkIfUserExists({ + [field]: value, + }); + return new ServerResponse(201, 'Successfully searched user', { + exists: result, + }); + } catch (err: any) { + this.logger.error(`Failed to find user: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } } diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 49e5df91..339b468a 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { CreateUserSchema, UpdateUserSchema } from './types'; +import { User } from '@prisma/client'; @Injectable() export class UsersService { @@ -33,4 +34,12 @@ export class UsersService { }, }); } + + async checkIfUserExists(payload: Partial): Promise { + const result = await this.prismaService.user.findFirst({ + where: payload, + }); + + return !!result; + } } From b5ba7b355708ae8b7bee74dbb2acf140e4bebe92 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sat, 1 Jun 2024 20:58:08 -0300 Subject: [PATCH 2/8] Update - removendo limite de supplies na listagem de abrigos (#136) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Melhorar a descoberta de que existem mais itens depois que o limite de 10 é excedido no card Conforme solicitado na issue [#257](https://github.com/SOS-RS/frontend/issues/257) foi removido o limite no retorno dos supplies de abrigo. PR do Frontend: https://github.com/SOS-RS/frontend/pull/249 --- src/shelter/ShelterSearch.ts | 33 +++++++------------------------ src/shelter/types/search.types.ts | 2 +- 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/src/shelter/ShelterSearch.ts b/src/shelter/ShelterSearch.ts index d921dbf8..3434413f 100644 --- a/src/shelter/ShelterSearch.ts +++ b/src/shelter/ShelterSearch.ts @@ -12,9 +12,9 @@ import { } from './types/search.types'; const defaultTagsData: ShelterTagInfo = { - NeedDonations: 10, - NeedVolunteers: 10, - RemainingSupplies: 10, + NeedDonations: true, + NeedVolunteers: true, + RemainingSupplies: true, }; class ShelterSearch { @@ -204,27 +204,17 @@ function parseTagResponse( }; 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'); - } + supplyTags.push('NeedDonations'); } if ( tags.NeedVolunteers && @@ -233,24 +223,15 @@ function parseTagResponse( shelterSupply.priority, ) ) { - if (qtd.NeedVolunteers < tags.NeedVolunteers) { - qtd.NeedVolunteers++; - tagged = true; - supplyTags.push('NeedVolunteers'); - } + supplyTags.push('NeedVolunteers'); } if ( tags.RemainingSupplies && [SupplyPriority.Remaining].includes(shelterSupply.priority) ) { - if (qtd.RemainingSupplies < tags.RemainingSupplies) { - qtd.RemainingSupplies++; - tagged = true; - supplyTags.push('RemainingSupplies'); - } + supplyTags.push('RemainingSupplies'); } - if (tagged) return [...prev, { ...shelterSupply, tags: supplyTags }]; - else return prev; + return [...prev, { ...shelterSupply, tags: supplyTags }]; }, [] as any), }; }); diff --git a/src/shelter/types/search.types.ts b/src/shelter/types/search.types.ts index ab5e6a18..1e5f2733 100644 --- a/src/shelter/types/search.types.ts +++ b/src/shelter/types/search.types.ts @@ -14,7 +14,7 @@ const ShelterTagTypeSchema = z.enum([ const ShelterTagInfoSchema = z.record( ShelterTagTypeSchema, - z.number().optional(), + z.boolean().optional(), ); export type ShelterTagType = z.infer; From cdad22ab2f2b69c74f42259dd0e5405ac1e5c001 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi <334958+giggio@users.noreply.github.com> Date: Tue, 4 Jun 2024 19:30:39 -0300 Subject: [PATCH 3/8] Run e2e tests on build (#168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adicionei o serviço de pg no build, um script de pre pra rodar as migrations, e retirei o npx do run delas. --- .env.test | 3 + .github/workflows/ci.yml | 17 +- package-lock.json | 773 +++++++++++++++++++++++++++++++++++++++ package.json | 8 +- 4 files changed, 797 insertions(+), 4 deletions(-) create mode 100644 .env.test diff --git a/.env.test b/.env.test new file mode 100644 index 00000000..79057e63 --- /dev/null +++ b/.env.test @@ -0,0 +1,3 @@ +DB_HOST=localhost +DB_DATABASE_NAME=sos_rs_test +DATABASE_URL="postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE_NAME}?schema=public" \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 150e2e9f..c81067fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,10 +11,24 @@ on: branches: - main - develop + - staging jobs: build: runs-on: ubuntu-latest + services: + db: + image: postgres:16.3 + ports: + - 5432:5432 + env: + POSTGRES_PASSWORD: root + POSTGRES_USER: root + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 steps: # Check out the source @@ -36,6 +50,7 @@ jobs: # Build App - name: Build App run: npm run build - - name: Test run: npm test + - name: Test e2e + run: npm run test:e2e diff --git a/package-lock.json b/package-lock.json index 65c13732..71a4ebb0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "zod": "^3.23.6" }, "devDependencies": { + "@dotenvx/dotenvx": "^0.44.0", "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", @@ -50,6 +51,10 @@ "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", "typescript": "^5.1.3" + }, + "engines": { + "node": ">=18.18", + "npm": ">=10.5.0" } }, "node_modules/@ampproject/remapping": { @@ -848,6 +853,110 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dev": true, + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@dotenvx/dotenvx": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-0.44.0.tgz", + "integrity": "sha512-K8JXCGI2QwupCeEW17/RaXF9+q+5DgVWiVKgm7TryM3h9QnuFYexf/2XaAS728RZkzikqH4Ylq9GgsYSNBwS7Q==", + "dev": true, + "dependencies": { + "@inquirer/confirm": "^2.0.17", + "arch": "^2.1.1", + "chalk": "^4.1.2", + "commander": "^11.1.0", + "conf": "^10.2.0", + "diff": "^5.2.0", + "dotenv": "^16.4.5", + "dotenv-expand": "^11.0.6", + "eciesjs": "^0.4.6", + "execa": "^5.1.1", + "glob": "^10.3.10", + "ignore": "^5.3.0", + "is-wsl": "^2.1.1", + "object-treeify": "1.1.33", + "open": "^8.4.2", + "ora": "^5.4.1", + "semver": "^7.3.4", + "undici": "^5.28.3", + "which": "^4.0.0", + "winston": "^3.11.0", + "xxhashjs": "^0.2.2" + }, + "bin": { + "dotenvx": "src/cli/dotenvx.js", + "git-dotenvx": "src/cli/dotenvx.js" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/dotenv-expand": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "dev": true, + "dependencies": { + "dotenv": "^16.4.4" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -966,6 +1075,15 @@ "fast-uri": "^2.0.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@fastify/cors": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-9.0.1.tgz", @@ -1112,6 +1230,81 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "node_modules/@inquirer/confirm": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-2.0.17.tgz", + "integrity": "sha512-EqzhGryzmGpy2aJf6LxJVhndxYmFs+m8cxXzf8nejb1DE3sabf6mUgBcp4J0jAUEiAcYzqmkqRr7LPFh/WdnXA==", + "dev": true, + "dependencies": { + "@inquirer/core": "^6.0.0", + "@inquirer/type": "^1.1.6", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/core": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", + "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", + "dev": true, + "dependencies": { + "@inquirer/type": "^1.1.6", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.10.7", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "figures": "^3.2.0", + "mute-stream": "^1.0.0", + "run-async": "^3.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/core/node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@inquirer/core/node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@inquirer/core/node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/@inquirer/type": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.3.2.tgz", + "integrity": "sha512-5Frickan9c89QbPkSu6I6y8p+9eR6hZkdPahGmNDsTFX8FHLPAozyzCZMKUeW8FyYwnlCKUjqIEqxY+UctARiw==", + "dev": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2259,6 +2452,39 @@ } } }, + "node_modules/@noble/ciphers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.4.1.tgz", + "integrity": "sha512-QCOA9cgf3Rc33owG0AYBB9wszz+Ul2kramWN8tXG44Gyciud/tbkEqvxRF/IpqQaBpRBNi9f4jdNxqB2CQCIXg==", + "dev": true, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", + "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "dev": true, + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2583,6 +2809,15 @@ "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", "dev": true }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.12.8", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.8.tgz", @@ -2634,6 +2869,18 @@ "@types/superagent": "^8.1.0" } }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "dev": true + }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -3214,6 +3461,26 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -3283,6 +3550,12 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3297,6 +3570,15 @@ "node": ">=8.0.0" } }, + "node_modules/atomically": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", + "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==", + "dev": true, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/avvio": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.3.0.tgz", @@ -3924,6 +4206,16 @@ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3940,6 +4232,16 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", @@ -3948,6 +4250,31 @@ "color-support": "bin.js" } }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dev": true, + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -4015,6 +4342,30 @@ "typedarray": "^0.0.6" } }, + "node_modules/conf": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/conf/-/conf-10.2.0.tgz", + "integrity": "sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==", + "dev": true, + "dependencies": { + "ajv": "^8.6.3", + "ajv-formats": "^2.1.1", + "atomically": "^1.7.0", + "debounce-fn": "^4.0.0", + "dot-prop": "^6.0.1", + "env-paths": "^2.2.1", + "json-schema-typed": "^7.0.3", + "onetime": "^5.1.2", + "pkg-up": "^3.1.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", @@ -4168,6 +4519,12 @@ "node": ">= 8" } }, + "node_modules/cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==", + "dev": true + }, "node_modules/date-fns": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", @@ -4177,6 +4534,30 @@ "url": "https://github.com/sponsors/kossnocorp" } }, + "node_modules/debounce-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz", + "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/debounce-fn/node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -4260,6 +4641,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4362,6 +4752,33 @@ "node": ">=6.0.0" } }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -4375,6 +4792,20 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/eciesjs": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.6.tgz", + "integrity": "sha512-t0qLzGVKeATAA6X19hIeToxBVG8yvn/be/4XyJvTCBD53m2CK22cgzk+WW+pNYjEw5FGWZLNFoJte8lyZS/A/w==", + "dev": true, + "dependencies": { + "@noble/ciphers": "^0.4.0", + "@noble/curves": "^1.2.0", + "@noble/hashes": "^1.3.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4405,6 +4836,12 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "dev": true + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -4428,6 +4865,15 @@ "node": ">=10.13.0" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -5089,6 +5535,12 @@ "bser": "2.1.1" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "dev": true + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -5291,6 +5743,12 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "dev": true + }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -5935,6 +6393,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -5991,6 +6464,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -6024,6 +6506,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -6860,6 +7354,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, + "node_modules/json-schema-typed": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz", + "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==", + "dev": true + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -6954,6 +7454,12 @@ "node": ">=6" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "dev": true + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -7084,6 +7590,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/logform": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "dev": true, + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -7510,6 +8042,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-treeify": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz", + "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/obliterator": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", @@ -7544,6 +8085,15 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dev": true, + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -7559,6 +8109,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -7968,6 +8535,79 @@ "node": ">=8" } }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -8855,6 +9495,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -8932,6 +9587,15 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -9384,6 +10048,12 @@ "node": "*" } }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "dev": true + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -9473,6 +10143,15 @@ "tree-kill": "cli.js" } }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "dev": true, + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -9711,6 +10390,18 @@ "node": ">=8" } }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -9986,6 +10677,79 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, + "node_modules/winston": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.0.tgz", + "integrity": "sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==", + "dev": true, + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.7.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "dev": true, + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/winston/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -10060,6 +10824,15 @@ "node": ">=0.4" } }, + "node_modules/xxhashjs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", + "dev": true, + "dependencies": { + "cuint": "^0.2.2" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index a7caf97b..fadd051b 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,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.config.ts", - "migrations:run": "npx prisma migrate deploy", - "migrations:dev": "npx prisma migrate dev", + "pretest:e2e": "dotenvx run --overload -f .env.local -f .env.test -- prisma migrate deploy", + "test:e2e": "dotenvx run --overload -f .env.local -f .env.test -- jest --config ./test/jest.e2e.config.ts", + "migrations:run": "prisma migrate deploy", + "migrations:dev": "prisma migrate dev", "docker:compose": "docker-compose -f docker-compose.dev.yml up" }, "dependencies": { @@ -42,6 +43,7 @@ "zod": "^3.23.6" }, "devDependencies": { + "@dotenvx/dotenvx": "^0.44.0", "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", From 5c3b21abf6ef7e34eec70485796b6daae69bf338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Wed, 5 Jun 2024 14:20:37 -0300 Subject: [PATCH 4/8] refactor: donation history --- package-lock.json | 13 ++ .../migrations/20240605140756_/migration.sql | 14 ++ prisma/schema.prisma | 16 +- .../donation-order.controller.ts | 9 +- src/donation-order/donation-order.service.ts | 156 +++++++++++++----- 5 files changed, 168 insertions(+), 40 deletions(-) create mode 100644 prisma/migrations/20240605140756_/migration.sql diff --git a/package-lock.json b/package-lock.json index 71a4ebb0..7437ec41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2371,6 +2371,19 @@ "real-require": "^0.2.0" } }, + "node_modules/@nestjs/schedule": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-4.0.2.tgz", + "integrity": "sha512-po9oauE7fO0CjhDKvVC2tzEgjOUwhxYoIsXIVkgfu+xaDMmzzpmXY2s1LT4oP90Z+PaTtPoAHmhslnYmo4mSZg==", + "dependencies": { + "cron": "3.1.7", + "uuid": "9.0.1" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, "node_modules/@nestjs/schematics": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.1.1.tgz", diff --git a/prisma/migrations/20240605140756_/migration.sql b/prisma/migrations/20240605140756_/migration.sql new file mode 100644 index 00000000..3f596607 --- /dev/null +++ b/prisma/migrations/20240605140756_/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "shelter_users" ( + "user_id" TEXT NOT NULL, + "shelter_id" TEXT NOT NULL, + "created_at" VARCHAR(32) NOT NULL, + + CONSTRAINT "shelter_users_pkey" PRIMARY KEY ("user_id","shelter_id") +); + +-- AddForeignKey +ALTER TABLE "shelter_users" ADD CONSTRAINT "shelter_users_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "shelter_users" ADD CONSTRAINT "shelter_users_shelter_id_fkey" FOREIGN KEY ("shelter_id") REFERENCES "shelters"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 57447c75..1a4b82f5 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -48,6 +48,7 @@ model User { shelterManagers ShelterManagers[] suppliesHistory SupplyHistory[] donationOrders DonationOrder[] + shelterUsers ShelterUsers[] @@map("users") } @@ -134,7 +135,8 @@ model Shelter { shelterManagers ShelterManagers[] shelterSupplies ShelterSupply[] supplyHistories SupplyHistory[] - DonationOrder DonationOrder[] + donationOrders DonationOrder[] + shelterUsers ShelterUsers[] @@map("shelters") } @@ -222,3 +224,15 @@ model DonationOrder { @@map("donation_orders") } + +model ShelterUsers { + userId String @map("user_id") + shelterId String @map("shelter_id") + createdAt String @map("created_at") @db.VarChar(32) + + user User @relation(fields: [userId], references: [id]) + shelter Shelter @relation(fields: [shelterId], references: [id]) + + @@id([userId, shelterId]) + @@map("shelter_users") +} diff --git a/src/donation-order/donation-order.controller.ts b/src/donation-order/donation-order.controller.ts index 52997ecc..fea6327f 100644 --- a/src/donation-order/donation-order.controller.ts +++ b/src/donation-order/donation-order.controller.ts @@ -39,9 +39,14 @@ export class DonationOrderController { @Put(':orderId') @UseGuards(UserGuard) - async update(@Param('orderId') orderId: string, @Body() body) { + async update( + @Request() req, + @Param('orderId') orderId: string, + @Body() body, + ) { try { - await this.donationOrderService.update(orderId, body); + const { userId } = req.user; + await this.donationOrderService.update(orderId, userId, body); return new ServerResponse(200, 'Successfully updated donation order'); } catch (err: any) { this.logger.error(`Failed to update donation order: ${err}`); diff --git a/src/donation-order/donation-order.service.ts b/src/donation-order/donation-order.service.ts index 6bcb11d1..5738c545 100644 --- a/src/donation-order/donation-order.service.ts +++ b/src/donation-order/donation-order.service.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { Injectable } from '@nestjs/common'; +import { HttpException, Injectable } from '@nestjs/common'; import { Prisma } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; @@ -9,16 +9,44 @@ import { SearchSchema } from '../types'; @Injectable() export class DonationOrderService { + private donationOrderVisibleFields: Prisma.DonationOrderSelect = { + id: true, + status: true, + userId: true, + shelter: { + select: { + id: true, + name: true, + }, + }, + donationOrderSupplies: { + select: { + quantity: true, + supply: { + select: { + name: true, + measure: true, + }, + }, + }, + }, + createdAt: true, + updatedAt: true, + }; + constructor(private readonly prismaService: PrismaService) {} async index(userId: string, query: any) { - const { shelterId } = query; + const { shelterId, op } = query; const { order, orderBy, page, perPage } = SearchSchema.parse(query); - const where: Prisma.DonationOrderWhereInput = { - shelterId, - userId, - }; + let where = {}; + + if (op === 'received') { + where = await this.getAllReceivedDonations(userId); + } else { + where = this.getAllDonationsMade(userId, shelterId); + } const count = await this.prismaService.donationOrder.count({ where }); @@ -34,30 +62,7 @@ export class DonationOrderService { const results = await this.prismaService.donationOrder.findMany({ ...whereData, - select: { - id: true, - status: true, - userId: true, - shelter: { - select: { - id: true, - name: true, - }, - }, - donationOrderSupplies: { - select: { - quantity: true, - supply: { - select: { - name: true, - measure: true, - }, - }, - }, - }, - createdAt: true, - updatedAt: true, - }, + select: this.donationOrderVisibleFields, orderBy: { createdAt: 'desc', }, @@ -127,17 +132,94 @@ export class DonationOrderService { async update( orderId: string, + userId: string, body: z.infer, ) { const { status } = UpdateDonationOrderScheme.parse(body); - await this.prismaService.donationOrder.update({ - where: { - id: orderId, - }, - data: { - status, - updatedAt: new Date().toISOString(), + const order = await this.prismaService.donationOrder.findFirst({ + where: { id: orderId }, + select: { + shelterId: true, + userId: true, + donationOrderSupplies: true, }, }); + + if (!order) return new HttpException('Donation not found', 404); + + if (order.userId !== userId) { + const isEmployer = await this.prismaService.shelterUsers.findFirst({ + where: { + userId, + shelterId: order.shelterId, + }, + }); + + if (!isEmployer) + return new HttpException( + 'User not allowed to update this donation', + 404, + ); + } + + await this.prismaService.$transaction([ + ...order.donationOrderSupplies.map((d) => + this.prismaService.shelterSupply.update({ + where: { + shelterId_supplyId: { + shelterId: order.shelterId, + supplyId: d.supplyId, + }, + }, + data: { + quantity: { + decrement: d.quantity, + }, + }, + }), + ), + this.prismaService.donationOrder.update({ + where: { + id: orderId, + }, + data: { + status, + updatedAt: new Date().toISOString(), + }, + }), + ]); + } + + private async getAllReceivedDonations(userId: string, shelterId?: string) { + const where: Prisma.DonationOrderWhereInput = { + shelterId, + }; + + if (!shelterId) { + const sheltersByUser = await this.prismaService.shelterUsers.findMany({ + where: { + userId, + }, + select: { + shelterId: true, + }, + }); + + const shelterIds = sheltersByUser.map((s) => s.shelterId); + where.shelterId = { + in: shelterIds, + }; + } + + return where; + } + + private getAllDonationsMade(userId: string, shelterId?: string) { + const where: Prisma.DonationOrderWhereInput = { + userId, + shelterId, + }; + + return where; } } From 50b68c6b155a57e8fdc8144703b86fe35b4d9dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Wed, 5 Jun 2024 14:27:54 -0300 Subject: [PATCH 5/8] fix: dashboard tests --- src/dashboard/dashboard.controller.spec.ts | 4 ++-- src/dashboard/dashboard.service.spec.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dashboard/dashboard.controller.spec.ts b/src/dashboard/dashboard.controller.spec.ts index 312a8e2a..57765394 100644 --- a/src/dashboard/dashboard.controller.spec.ts +++ b/src/dashboard/dashboard.controller.spec.ts @@ -2,8 +2,8 @@ import { Test, TestingModule } from '@nestjs/testing'; import { DashboardController } from './dashboard.controller'; import { DashboardService } from './dashboard.service'; -import { PrismaService } from '../../prisma/prisma.service'; -import { PrismaModule } from '../../prisma/prisma.module'; +import { PrismaService } from '../prisma/prisma.service'; +import { PrismaModule } from '../prisma/prisma.module'; describe('DashboardController', () => { let controller: DashboardController; diff --git a/src/dashboard/dashboard.service.spec.ts b/src/dashboard/dashboard.service.spec.ts index d02863a9..674d7664 100644 --- a/src/dashboard/dashboard.service.spec.ts +++ b/src/dashboard/dashboard.service.spec.ts @@ -1,8 +1,8 @@ import { Test, TestingModule } from '@nestjs/testing'; import { DashboardService } from './dashboard.service'; -import { PrismaService } from '../../prisma/prisma.service'; -import { PrismaModule } from '../../prisma/prisma.module'; +import { PrismaService } from '../prisma/prisma.service'; +import { PrismaModule } from '../prisma/prisma.module'; describe('DashboardService', () => { let service: DashboardService; From abd355f1f9d34205e41b851ca022d026081a78a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Wed, 5 Jun 2024 14:52:45 -0300 Subject: [PATCH 6/8] fix: decretment supplies when update donation order --- src/donation-order/donation-order.service.ts | 37 +++++++++++--------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/donation-order/donation-order.service.ts b/src/donation-order/donation-order.service.ts index 5738c545..cc7fb2fd 100644 --- a/src/donation-order/donation-order.service.ts +++ b/src/donation-order/donation-order.service.ts @@ -1,6 +1,6 @@ import { z } from 'zod'; import { HttpException, Injectable } from '@nestjs/common'; -import { Prisma } from '@prisma/client'; +import { DonationOrderStatus, Prisma } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; import { PrismaService } from '../prisma/prisma.service'; @@ -162,22 +162,27 @@ export class DonationOrderService { ); } + const updatePromises = + status === DonationOrderStatus.Complete + ? order.donationOrderSupplies.map((d) => + this.prismaService.shelterSupply.update({ + where: { + shelterId_supplyId: { + shelterId: order.shelterId, + supplyId: d.supplyId, + }, + }, + data: { + quantity: { + decrement: d.quantity, + }, + }, + }), + ) + : []; + await this.prismaService.$transaction([ - ...order.donationOrderSupplies.map((d) => - this.prismaService.shelterSupply.update({ - where: { - shelterId_supplyId: { - shelterId: order.shelterId, - supplyId: d.supplyId, - }, - }, - data: { - quantity: { - decrement: d.quantity, - }, - }, - }), - ), + ...updatePromises, this.prismaService.donationOrder.update({ where: { id: orderId, From be7ac542939c5a8f936cde32a4466fca7edabb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Thu, 6 Jun 2024 10:32:32 -0300 Subject: [PATCH 7/8] feat: added more fields to donation order response to use in print response --- src/donation-order/donation-order.service.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/donation-order/donation-order.service.ts b/src/donation-order/donation-order.service.ts index cc7fb2fd..73f93a45 100644 --- a/src/donation-order/donation-order.service.ts +++ b/src/donation-order/donation-order.service.ts @@ -12,11 +12,19 @@ export class DonationOrderService { private donationOrderVisibleFields: Prisma.DonationOrderSelect = { id: true, status: true, - userId: true, + user: { + select: { + id: true, + name: true, + lastName: true, + phone: true, + }, + }, shelter: { select: { id: true, name: true, + address: true, }, }, donationOrderSupplies: { From 85c4d8366b65c4592e39cf8609ffcd9b9dd01c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Fri, 7 Jun 2024 12:03:14 -0300 Subject: [PATCH 8/8] fix: shelter decay time and visible donation fields --- src/donation-order/donation-order.service.ts | 25 +------------------- src/shelter/shelter.service.ts | 4 ++-- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/src/donation-order/donation-order.service.ts b/src/donation-order/donation-order.service.ts index 73f93a45..6be75428 100644 --- a/src/donation-order/donation-order.service.ts +++ b/src/donation-order/donation-order.service.ts @@ -87,30 +87,7 @@ export class DonationOrderService { async show(id: string, userId: string) { const data = await this.prismaService.donationOrder.findUnique({ where: { id, userId }, - select: { - id: true, - status: true, - userId: true, - shelter: { - select: { - id: true, - name: true, - }, - }, - donationOrderSupplies: { - select: { - quantity: true, - supply: { - select: { - name: true, - measure: true, - }, - }, - }, - }, - createdAt: true, - updatedAt: true, - }, + select: this.donationOrderVisibleFields, }); return data; } diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 757acdba..9aee0f0d 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -316,7 +316,7 @@ export class ShelterService implements OnModuleInit { shelterSupplies .map(this.parseShelterSupply) .filter((f) => - this.canDecayShelterSupply(f, [SupplyPriority.Urgent], 12), + this.canDecayShelterSupply(f, [SupplyPriority.Urgent], 48), ), SupplyPriority.Needing, @@ -329,7 +329,7 @@ export class ShelterService implements OnModuleInit { this.canDecayShelterSupply( f, [SupplyPriority.Needing, SupplyPriority.Remaining], - 48, + 72, ), ), SupplyPriority.UnderControl,