feat: vote for super admin role (#56)

[WIP] solve this ticket: 

https://app.ora.pm/p/fb56ed95daa7456b888d266a050b9afa?v=86662&s=29580&t=k&c=e2ed47d1b61a467bba6cbdd734665bdd
This commit is contained in:
VincentAlamelle 2023-08-01 12:13:48 +02:00 committed by GitHub
commit 77f24af33c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 916 additions and 107 deletions

185
package-lock.json generated
View File

@ -19,7 +19,7 @@
"cron": "^2.3.1",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.57",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.66",
"module-alias": "^2.2.2",
"multer": "^1.4.5-lts.1",
"next": "^13.1.5",
@ -1061,14 +1061,14 @@
}
},
"node_modules/@next/env": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.10.tgz",
"integrity": "sha512-3G1yD/XKTSLdihyDSa8JEsaWOELY+OWe08o0LUYzfuHp1zHDA8SObQlzKt+v+wrkkPcnPweoLH1ImZeUa0A1NQ=="
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.12.tgz",
"integrity": "sha512-RmHanbV21saP/6OEPBJ7yJMuys68cIf8OBBWd7+uj40LdpmswVAwe1uzeuFyUsd6SfeITWT3XnQfn6wULeKwDQ=="
},
"node_modules/@next/swc-darwin-arm64": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.10.tgz",
"integrity": "sha512-4bsdfKmmg7mgFGph0UorD1xWfZ5jZEw4kKRHYEeTK9bT1QnMbPVPlVXQRIiFPrhoDQnZUoa6duuPUJIEGLV1Jg==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.12.tgz",
"integrity": "sha512-deUrbCXTMZ6ZhbOoloqecnUeNpUOupi8SE2tx4jPfNS9uyUR9zK4iXBvH65opVcA/9F5I/p8vDXSYbUlbmBjZg==",
"cpu": [
"arm64"
],
@ -1081,9 +1081,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.10.tgz",
"integrity": "sha512-ngXhUBbcZIWZWqNbQSNxQrB9T1V+wgfCzAor2olYuo/YpaL6mUYNUEgeBMhr8qwV0ARSgKaOp35lRvB7EmCRBg==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.12.tgz",
"integrity": "sha512-WRvH7RxgRHlC1yb5oG0ZLx8F7uci9AivM5/HGGv9ZyG2Als8Ij64GC3d+mQ5sJhWjusyU6T6V1WKTUoTmOB0zQ==",
"cpu": [
"x64"
],
@ -1096,9 +1096,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.10.tgz",
"integrity": "sha512-SjCZZCOmHD4uyM75MVArSAmF5Y+IJSGroPRj2v9/jnBT36SYFTORN8Ag/lhw81W9EeexKY/CUg2e9mdebZOwsg==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.12.tgz",
"integrity": "sha512-YEKracAWuxp54tKiAvvq73PUs9lok57cc8meYRibTWe/VdPB2vLgkTVWFcw31YDuRXdEhdX0fWS6Q+ESBhnEig==",
"cpu": [
"arm64"
],
@ -1111,9 +1111,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.10.tgz",
"integrity": "sha512-F+VlcWijX5qteoYIOxNiBbNE8ruaWuRlcYyIRK10CugqI/BIeCDzEDyrHIHY8AWwbkTwe6GRHabMdE688Rqq4Q==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.12.tgz",
"integrity": "sha512-LhJR7/RAjdHJ2Isl2pgc/JaoxNk0KtBgkVpiDJPVExVWA1c6gzY57+3zWuxuyWzTG+fhLZo2Y80pLXgIJv7g3g==",
"cpu": [
"arm64"
],
@ -1126,9 +1126,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.10.tgz",
"integrity": "sha512-WDv1YtAV07nhfy3i1visr5p/tjiH6CeXp4wX78lzP1jI07t4PnHHG1WEDFOduXh3WT4hG6yN82EQBQHDi7hBrQ==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.12.tgz",
"integrity": "sha512-1DWLL/B9nBNiQRng+1aqs3OaZcxC16Nf+mOnpcrZZSdyKHek3WQh6j/fkbukObgNGwmCoVevLUa/p3UFTTqgqg==",
"cpu": [
"x64"
],
@ -1141,9 +1141,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.10.tgz",
"integrity": "sha512-zFkzqc737xr6qoBgDa3AwC7jPQzGLjDlkNmt/ljvQJ/Veri5ECdHjZCUuiTUfVjshNIIpki6FuP0RaQYK9iCRg==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.12.tgz",
"integrity": "sha512-kEAJmgYFhp0VL+eRWmUkVxLVunn7oL9Mdue/FS8yzRBVj7Z0AnIrHpTIeIUl1bbdQq1VaoOztnKicAjfkLTRCQ==",
"cpu": [
"x64"
],
@ -1156,9 +1156,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.10.tgz",
"integrity": "sha512-IboRS8IWz5mWfnjAdCekkl8s0B7ijpWeDwK2O8CdgZkoCDY0ZQHBSGiJ2KViAG6+BJVfLvcP+a2fh6cdyBr9QQ==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.12.tgz",
"integrity": "sha512-GMLuL/loR6yIIRTnPRY6UGbLL9MBdw2anxkOnANxvLvsml4F0HNIgvnU3Ej4BjbqMTNjD4hcPFdlEow4XHPdZA==",
"cpu": [
"arm64"
],
@ -1171,9 +1171,9 @@
}
},
"node_modules/@next/swc-win32-ia32-msvc": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.10.tgz",
"integrity": "sha512-bSA+4j8jY4EEiwD/M2bol4uVEu1lBlgsGdvM+mmBm/BbqofNBfaZ2qwSbwE2OwbAmzNdVJRFRXQZ0dkjopTRaQ==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.12.tgz",
"integrity": "sha512-PhgNqN2Vnkm7XaMdRmmX0ZSwZXQAtamBVSa9A/V1dfKQCV1rjIZeiy/dbBnVYGdj63ANfsOR/30XpxP71W0eww==",
"cpu": [
"ia32"
],
@ -1186,9 +1186,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.10.tgz",
"integrity": "sha512-g2+tU63yTWmcVQKDGY0MV1PjjqgZtwM4rB1oVVi/v0brdZAcrcTV+04agKzWtvWroyFz6IqtT0MoZJA7PNyLVw==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.12.tgz",
"integrity": "sha512-Z+56e/Ljt0bUs+T+jPjhFyxYBcdY2RIq9ELFU+qAMQMteHo7ymbV7CKmlcX59RI9C4YzN8PgMgLyAoi916b5HA==",
"cpu": [
"x64"
],
@ -1493,9 +1493,9 @@
}
},
"node_modules/@types/node": {
"version": "18.17.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.0.tgz",
"integrity": "sha512-GXZxEtOxYGFchyUzxvKI14iff9KZ2DI+A6a37o6EQevtg6uO9t+aUZKcaC1Te5Ng1OnLM7K9NVVj+FbecD9cJg=="
"version": "18.17.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz",
"integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw=="
},
"node_modules/@types/node-fetch": {
"version": "2.6.4",
@ -2049,9 +2049,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001516",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz",
"integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==",
"version": "1.0.30001517",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz",
"integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==",
"funding": [
{
"type": "opencollective",
@ -2335,9 +2335,9 @@
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
},
"node_modules/cron": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/cron/-/cron-2.3.1.tgz",
"integrity": "sha512-1eRRlIT0UfIqauwbG9pkg3J6CX9A6My2ytJWqAXoK0T9oJnUZTzGBNPxao0zjodIbPgf8UQWjE62BMb9eVllSQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/cron/-/cron-2.4.0.tgz",
"integrity": "sha512-Cx77ic1TyIAtUggr0oAhtS8MLzPBUqGNIvdDM7jE3oFIxfe8LXWI9q3iQN/H2CebAiMir53LQKWOhEKnzkJTAQ==",
"dependencies": {
"luxon": "^3.2.1"
}
@ -2467,9 +2467,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
},
"node_modules/electron-to-chromium": {
"version": "1.4.461",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz",
"integrity": "sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==",
"version": "1.4.473",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.473.tgz",
"integrity": "sha512-aVfC8+440vGfl06l8HKKn8/PD5jRfSnLkTTD65EFvU46igbpQRri1gxSzW9/+TeUlwYzrXk1sw867T96zlyECA==",
"dev": true
},
"node_modules/emittery": {
@ -3193,17 +3193,17 @@
}
},
"node_modules/istanbul-lib-report": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
"integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
"integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
"dev": true,
"dependencies": {
"istanbul-lib-coverage": "^3.0.0",
"make-dir": "^3.0.0",
"make-dir": "^4.0.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=8"
"node": ">=10"
}
},
"node_modules/istanbul-lib-source-maps": {
@ -3244,9 +3244,9 @@
"dev": true
},
"node_modules/istanbul-reports": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
"integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz",
"integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==",
"dev": true,
"dependencies": {
"html-escaper": "^2.0.0",
@ -3972,7 +3972,7 @@
}
},
"node_modules/le-coffre-resources": {
"resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#dffc2429ba6ceb4129deb56e308962799b9b572c",
"resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#e7916d516fe434c93ef13e765d8d63a7ce3c56b2",
"license": "MIT",
"dependencies": {
"class-transformer": "^0.5.1",
@ -3990,9 +3990,9 @@
}
},
"node_modules/libphonenumber-js": {
"version": "1.10.37",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.37.tgz",
"integrity": "sha512-Z10PCaOCiAxbUxLyR31DNeeNugSVP6iv/m7UrSKS5JHziEMApJtgku4e9Q69pzzSC9LnQiM09sqsGf2ticZnMw=="
"version": "1.10.38",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.38.tgz",
"integrity": "sha512-4NjVXVUmpZ9Zsqq6FXa2+MKI+KAI3tOqA0pxXgXGluhpj4ge5didmbWJpMBqGB3AVGv1SnEtKdGTbxjSEG1kCQ=="
},
"node_modules/lines-and-columns": {
"version": "1.2.4",
@ -4066,20 +4066,53 @@
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
"integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
"dev": true,
"dependencies": {
"semver": "^6.0.0"
"semver": "^7.5.3"
},
"engines": {
"node": ">=8"
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/make-dir/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/make-dir/node_modules/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/make-dir/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@ -4386,11 +4419,11 @@
}
},
"node_modules/next": {
"version": "13.4.10",
"resolved": "https://registry.npmjs.org/next/-/next-13.4.10.tgz",
"integrity": "sha512-4ep6aKxVTQ7rkUW2fBLhpBr/5oceCuf4KmlUpvG/aXuDTIf9mexNSpabUD6RWPspu6wiJJvozZREhXhueYO36A==",
"version": "13.4.12",
"resolved": "https://registry.npmjs.org/next/-/next-13.4.12.tgz",
"integrity": "sha512-eHfnru9x6NRmTMcjQp6Nz0J4XH9OubmzOa7CkWL+AUrUxpibub3vWwttjduu9No16dug1kq04hiUUpo7J3m3Xw==",
"dependencies": {
"@next/env": "13.4.10",
"@next/env": "13.4.12",
"@swc/helpers": "0.5.1",
"busboy": "1.6.0",
"caniuse-lite": "^1.0.30001406",
@ -4406,15 +4439,15 @@
"node": ">=16.8.0"
},
"optionalDependencies": {
"@next/swc-darwin-arm64": "13.4.10",
"@next/swc-darwin-x64": "13.4.10",
"@next/swc-linux-arm64-gnu": "13.4.10",
"@next/swc-linux-arm64-musl": "13.4.10",
"@next/swc-linux-x64-gnu": "13.4.10",
"@next/swc-linux-x64-musl": "13.4.10",
"@next/swc-win32-arm64-msvc": "13.4.10",
"@next/swc-win32-ia32-msvc": "13.4.10",
"@next/swc-win32-x64-msvc": "13.4.10"
"@next/swc-darwin-arm64": "13.4.12",
"@next/swc-darwin-x64": "13.4.12",
"@next/swc-linux-arm64-gnu": "13.4.12",
"@next/swc-linux-arm64-musl": "13.4.12",
"@next/swc-linux-x64-gnu": "13.4.12",
"@next/swc-linux-x64-musl": "13.4.12",
"@next/swc-win32-arm64-msvc": "13.4.12",
"@next/swc-win32-ia32-msvc": "13.4.12",
"@next/swc-win32-x64-msvc": "13.4.12"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
@ -5661,9 +5694,9 @@
}
},
"node_modules/tslib": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
"integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
},
"node_modules/type-detect": {
"version": "4.0.8",

View File

@ -52,7 +52,7 @@
"cron": "^2.3.1",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.63",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.66",
"module-alias": "^2.2.2",
"multer": "^1.4.5-lts.1",
"next": "^13.1.5",

View File

@ -0,0 +1,76 @@
import { Response, Request } from "express";
import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import AppointmentsService from "@Services/super-admin/AppointmentsService/AppointmentsService";
import { Service } from "typedi";
import { Appointment } from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler";
@Controller()
@Service()
export default class AppointmentsController extends ApiController {
constructor(private appointmentsService: AppointmentsService) {
super();
}
/**
* @description Get all appointments
*/
@Get("/api/v1/super-admin/appointments", [authHandler])
protected async get(req: Request, response: Response) {
try {
//get query
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
//call service to get prisma entity
const appointmentsEntities = await this.appointmentsService.get(query);
//Hydrate ressource with prisma entity
const appointments = Appointment.hydrateArray<Appointment>(appointmentsEntities, { strategy: "excludeAll" });
//success
this.httpSuccess(response, appointments);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/**
* @description Get a specific appointment by uid
*/
@Get("/api/v1/super-admin/appointments/:uid", [authHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
const appointmentEntity = await this.appointmentsService.getByUid(uid, query);
if (!appointmentEntity) {
this.httpNotFoundRequest(response, "appointment not found");
return;
}
//Hydrate ressource with prisma entity
const appointment = Appointment.hydrate<Appointment>(appointmentEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, appointment);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -0,0 +1,94 @@
import authHandler from "@App/middlewares/AuthHandler";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Controller, Post } from "@ControllerPattern/index";
import { EAppointmentStatus } from "@prisma/client";
import AppointmentService from "@Services/super-admin/AppointmentsService/AppointmentsService";
import LiveVoteService from "@Services/super-admin/LiveVoteService/LiveVoteService";
import UsersService from "@Services/super-admin/UsersService/UsersService";
import VotesService from "@Services/super-admin/VotesService/VotesService";
import { validateOrReject } from "class-validator";
import { Request, Response } from "express";
import { Vote } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Controller()
@Service()
export default class LiveVoteController extends ApiController {
constructor(
private liveVoteService: LiveVoteService,
private votesService: VotesService,
private usersService: UsersService,
private appointmentService: AppointmentService,
) {
super();
}
/**
* @description Create a new vote
*/
@Post("/api/v1/super-admin/live-votes", [authHandler])
protected async post(req: Request, response: Response) {
try {
const userId = req.body.user.userId;
//init IUser resource with request body values
const voteEntity = Vote.hydrate<Vote>(req.body);
//validate user
await validateOrReject(voteEntity, { groups: ["createVote"] });
let voteFound = [];
if (voteEntity.appointment.uid) {
const appointment = await this.appointmentService.getByUid(voteEntity.appointment.uid);
if (!appointment) {
this.httpNotFoundRequest(response, "Appointment not found");
return;
}
if (appointment.status === EAppointmentStatus.CLOSED) {
this.httpBadRequest(response, "Appointment is closed");
return;
}
voteFound = await this.votesService.get({
where: { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] },
});
} else {
voteFound = await this.votesService.get({
where: {
AND: [
{
appointment: {
AND: [{ user_uid: voteEntity.appointment.targeted_user.uid }, { status: EAppointmentStatus.OPEN }],
},
},
{ voter: { uid: userId } },
],
},
});
}
if (voteFound.length) {
this.httpBadRequest(response, "Voter already voted for this appointment");
return;
}
const voter = await this.usersService.getByUid(userId);
voteEntity.voter = voter!;
//call service to get prisma entity
const voteEntityCreated = await this.liveVoteService.create(voteEntity);
if (!voteEntityCreated) {
this.httpBadRequest(response, "Appointment choice is not valid");
return;
}
//Hydrate ressource with prisma entity
const vote = Vote.hydrate<Vote>(voteEntityCreated, {
strategy: "excludeAll",
});
//success
this.httpCreated(response, vote);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -90,12 +90,13 @@ export default class UsersController extends ApiController {
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
const userFound = await this.usersService.getByUid(uid);
const userFound = await this.usersService.getByUid(uid, {role: true, votes: true});
if (!userFound) {
this.httpNotFoundRequest(response, "user not found");
@ -104,12 +105,13 @@ export default class UsersController extends ApiController {
//init IUser resource with request body values
const userEntity = User.hydrate<User>(req.body);
const userFoundEntity = User.hydrate<User>(userFound, { strategy: "excludeAll" });
//validate user
await validateOrReject(userEntity, { groups: ["updateUser"] });
//call service to get prisma entity
const userEntityUpdated = await this.usersService.update(uid, userEntity);
const userEntityUpdated = await this.usersService.update(uid, userFoundEntity);
//Hydrate ressource with prisma entity
const user = User.hydrate<User>(userEntityUpdated, {

View File

@ -0,0 +1,110 @@
import { Response, Request } from "express";
import { Controller, Delete, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import VotesService from "@Services/super-admin/VotesService/VotesService";
import { Service } from "typedi";
import { Vote } from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler";
import { Votes } from "@prisma/client";
@Controller()
@Service()
export default class VotesController extends ApiController {
constructor(private votesService: VotesService) {
super();
}
/**
* @description Get all votes
*/
@Get("/api/v1/super-admin/votes", [authHandler])
protected async get(req: Request, response: Response) {
try {
//get query
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
//call service to get prisma entity
const votesEntities = await this.votesService.get(query);
//Hydrate ressource with prisma entity
const votes = Vote.hydrateArray<Vote>(votesEntities, { strategy: "excludeAll" });
//success
this.httpSuccess(response, votes);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/**
* @description Get a specific vote by uid
*/
@Get("/api/v1/super-admin/votes/:uid", [authHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
const voteEntity = await this.votesService.getByUid(uid, query);
if (!voteEntity) {
this.httpNotFoundRequest(response, "vote not found");
return;
}
//Hydrate ressource with prisma entity
const vote = Vote.hydrate<Vote>(voteEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, vote);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/**
* @description Delete a specific folder
*/
@Delete("/api/v1/super-admin/votes/:uid", [authHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
const voteFound = await this.votesService.getByUid(uid);
if (!voteFound) {
this.httpNotFoundRequest(response, "vote not found");
return;
}
//call service to get prisma entity
const votetEntity: Votes = await this.votesService.delete(uid);
//Hydrate ressource with prisma entity
const vote = Vote.hydrate<Vote>(votetEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, vote);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -40,6 +40,9 @@ import RolesControllerNotary from "./api/notary/RolesController";
import OfficeRolesControllerNotary from "./api/notary/OfficeRolesController";
import FilesControllerCustomer from "./api/customer/FilesController";
import DocumentsControllerCustomer from "./api/customer/DocumentsController";
import AppointmentsController from "./api/super-admin/AppointmentsController";
import VotesController from "./api/super-admin/VotesController";
import LiveVoteController from "./api/super-admin/LiveVoteController";
/**
@ -56,6 +59,9 @@ export default {
Container.get(DeedTypesControllerSuperAdmin);
Container.get(DocumentsControllerSuperAdmin);
Container.get(DocumentTypesControllerSuperAdmin);
Container.get(AppointmentsController);
Container.get(VotesController);
Container.get(LiveVoteController);
Container.get(IdNotUserController);
Container.get(FranceConnectCustomerController);
Container.get(FilesControllerSuperAdmin);

View File

@ -0,0 +1,38 @@
-- DropForeignKey
ALTER TABLE "users" DROP CONSTRAINT "users_contact_uid_fkey";
-- DropForeignKey
ALTER TABLE "users" DROP CONSTRAINT "users_office_role_uid_fkey";
-- DropForeignKey
ALTER TABLE "users" DROP CONSTRAINT "users_office_uid_fkey";
-- DropForeignKey
ALTER TABLE "users" DROP CONSTRAINT "users_roles_uid_fkey";
-- CreateTable
CREATE TABLE "votes" (
"uid" TEXT NOT NULL,
"user_uid" VARCHAR(255) NOT NULL,
"voters" TEXT[],
CONSTRAINT "votes_pkey" PRIMARY KEY ("uid")
);
-- CreateIndex
CREATE UNIQUE INDEX "votes_uid_key" ON "votes"("uid");
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_contact_uid_fkey" FOREIGN KEY ("contact_uid") REFERENCES "contacts"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_roles_uid_fkey" FOREIGN KEY ("roles_uid") REFERENCES "roles"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_office_role_uid_fkey" FOREIGN KEY ("office_role_uid") REFERENCES "office_roles"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_office_uid_fkey" FOREIGN KEY ("office_uid") REFERENCES "offices"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "votes" ADD CONSTRAINT "votes_user_uid_fkey" FOREIGN KEY ("user_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1,45 @@
/*
Warnings:
- You are about to drop the column `user_uid` on the `votes` table. All the data in the column will be lost.
- You are about to drop the column `voters` on the `votes` table. All the data in the column will be lost.
- Added the required column `appointment_uid` to the `votes` table without a default value. This is not possible if the table is not empty.
- Added the required column `voter_uid` to the `votes` table without a default value. This is not possible if the table is not empty.
*/
-- CreateEnum
CREATE TYPE "EVote" AS ENUM ('NOMINATE', 'DISMISS');
-- CreateEnum
CREATE TYPE "EAppointmentStatus" AS ENUM ('OPEN', 'CLOSED');
-- DropForeignKey
ALTER TABLE "votes" DROP CONSTRAINT "votes_user_uid_fkey";
-- AlterTable
ALTER TABLE "votes" DROP COLUMN "user_uid",
DROP COLUMN "voters",
ADD COLUMN "appointment_uid" VARCHAR(255) NOT NULL,
ADD COLUMN "choice" "EVote" NOT NULL DEFAULT 'NOMINATE',
ADD COLUMN "voter_uid" VARCHAR(255) NOT NULL;
-- CreateTable
CREATE TABLE "appointments" (
"uid" TEXT NOT NULL,
"user_uid" VARCHAR(255) NOT NULL,
"status" "EAppointmentStatus" NOT NULL DEFAULT 'OPEN',
CONSTRAINT "appointments_pkey" PRIMARY KEY ("uid")
);
-- CreateIndex
CREATE UNIQUE INDEX "appointments_uid_key" ON "appointments"("uid");
-- AddForeignKey
ALTER TABLE "appointments" ADD CONSTRAINT "appointments_user_uid_fkey" FOREIGN KEY ("user_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "votes" ADD CONSTRAINT "votes_appointment_uid_fkey" FOREIGN KEY ("appointment_uid") REFERENCES "appointments"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "votes" ADD CONSTRAINT "votes_voter_uid_fkey" FOREIGN KEY ("voter_uid") REFERENCES "users"("uid") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,11 @@
/*
Warnings:
- You are about to drop the column `choice` on the `votes` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "appointments" ADD COLUMN "choice" "EVote" NOT NULL DEFAULT 'NOMINATE';
-- AlterTable
ALTER TABLE "votes" DROP COLUMN "choice";

View File

@ -0,0 +1,8 @@
/*
Warnings:
- A unique constraint covering the columns `[user_uid,choice,status]` on the table `appointments` will be added. If there are existing duplicate values, this will fail.
*/
-- CreateIndex
CREATE UNIQUE INDEX "appointments_user_uid_choice_status_key" ON "appointments"("user_uid", "choice", "status");

View File

@ -65,6 +65,8 @@ model Users {
office_uid String @db.VarChar(255)
notifications Notifications[] @relation("UserHasNotifications")
office_folders OfficeFolders[] @relation("OfficeFolderHasStakeholders")
appointment Appointments[]
votes Votes[]
@@map("users")
}
@ -287,6 +289,28 @@ model Emails {
@@map("email")
}
model Appointments {
uid String @id @unique @default(uuid())
user Users @relation(fields: [user_uid], references: [uid], onDelete: Cascade)
user_uid String @db.VarChar(255)
choice EVote @default(NOMINATE)
status EAppointmentStatus @default(OPEN)
votes Votes[]
@@unique([user_uid, choice, status])
@@map("appointments")
}
model Votes {
uid String @id @unique @default(uuid())
appointment Appointments @relation(fields: [appointment_uid], references: [uid], onDelete: Cascade)
appointment_uid String @db.VarChar(255)
voter Users @relation(fields: [voter_uid], references: [uid])
voter_uid String @db.VarChar(255)
@@map("votes")
}
enum ECivility {
MALE
FEMALE
@ -321,3 +345,13 @@ enum EDocumentStatus {
ANCHORED
REFUSED
}
enum EVote {
NOMINATE
DISMISS
}
enum EAppointmentStatus {
OPEN
CLOSED
}

View File

@ -1,18 +1,7 @@
import { ECivility, ECustomerStatus, EFolderStatus, EOfficeStatus, Prisma, PrismaClient } from "@prisma/client";
import User, { Address, Contact, Customer, Deed, DeedType, DocumentType, Office, OfficeFolder, OfficeRole, Role, Rule } from "le-coffre-resources/dist/SuperAdmin";
import "module-alias/register";
import { EFolderStatus, EOfficeStatus, ECivility, ECustomerStatus, PrismaClient, Prisma } from "@prisma/client";
import User, {
Address,
Contact,
Customer,
Deed,
DeedType,
Office,
OfficeFolder,
OfficeRole,
Role,
Rule,
DocumentType,
} from "le-coffre-resources/dist/SuperAdmin";
export default async function main() {
try{
@ -605,7 +594,7 @@ export default async function main() {
updated_at: new Date(),
},
{
name: "PUT deedtypes",
name: "PUT deed-types",
created_at: new Date(),
updated_at: new Date(),
},
@ -665,7 +654,7 @@ export default async function main() {
updated_at: new Date(),
},
{
name: "POST deedtypes",
name: "POST deed-types",
created_at: new Date(),
updated_at: new Date(),
},
@ -862,26 +851,19 @@ export default async function main() {
rules: rules.slice(0, 40),
},
{
name: "notary",
name: "Notaire",
created_at: new Date(),
updated_at: new Date(),
office: offices[0]!,
rules: rules.slice(0, 33),
},
{
name: "deputy",
name: "Collaborateur",
created_at: new Date(),
updated_at: new Date(),
office: offices[0]!,
rules: rules.slice(0, 22),
},
{
name: "listener",
created_at: new Date(),
updated_at: new Date(),
office: offices[0]!,
rules: rules.slice(0, 11),
},
}
];
const users: User[] = [

View File

@ -0,0 +1,76 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { Appointments, EAppointmentStatus, Prisma } from "@prisma/client";
@Service()
export default class AppointmentsRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().appointments;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many appointments
*/
public async findMany(query: Prisma.AppointmentsFindManyArgs) {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Update data of a appointment
*/
public async update(uid: string, status: EAppointmentStatus): Promise<Appointments> {
const updateArgs: Prisma.AppointmentsUpdateArgs = {
where: {
uid: uid,
},
data: {
status: status,
},
};
return this.model.update(updateArgs);
}
/**
* @description : Find one appointment
*/
public async findOneByUid(uid: string, query?: Prisma.AppointmentsInclude) {
return this.model.findUnique({
where: {
uid: uid,
},
include: query,
});
}
/**
* @description : Find one appointment with votes
*/
public async findOneByUidWithVotes(uid: string) {
return this.model.findUnique({
where: {
uid: uid,
},
include: {votes: true},
});
}
/**
* @description : delete a appointment
*/
public async delete(uid: string): Promise<Appointments> {
return this.model.delete({
where: {
uid: uid,
},
});
}
}

View File

@ -2,7 +2,7 @@ import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { ECivility, Prisma, Users } from "@prisma/client";
import User from "le-coffre-resources/dist/SuperAdmin";
import User, { Role } from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class UsersRepository extends BaseRepository {
@ -196,6 +196,18 @@ export default class UsersRepository extends BaseRepository {
});
}
/**
* @description : Find one user with office
*/
public async findOneByUidWithRole(uid: string): Promise<((Users & {role: Role} )| null)> {
return this.model.findUnique({
where: {
uid: uid,
},
include: { role: true },
});
}
/**
* @description : Find one user
*/

View File

@ -0,0 +1,89 @@
import Database from "@Common/databases/database";
import { EAppointmentStatus, EVote, Prisma, Votes } from "@prisma/client";
import BaseRepository from "@Repositories/BaseRepository";
import { Vote } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Service()
export default class VotesRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().votes;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many votes
*/
public async findMany(query: Prisma.VotesFindManyArgs) {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create new vote
*/
public async create(vote: Vote): Promise<Votes> {
let whereArg: Prisma.AppointmentsWhereUniqueInput;
if(vote.appointment.targeted_user.uid) {
whereArg = {
user_uid_choice_status: {
user_uid: vote.appointment.targeted_user.uid,
choice: EVote[vote.appointment.choice as keyof typeof EVote],
status: EAppointmentStatus.OPEN,
}
};
} else {
whereArg = {
uid: vote.appointment.uid,
};
}
const createArgs: Prisma.VotesCreateArgs = {
data: {
appointment: {
connectOrCreate: {
where: whereArg,
create: {
choice: EVote[vote.appointment.choice as keyof typeof EVote],
user_uid: vote.appointment.targeted_user.uid!,
}
},
},
voter: {
connect: {
uid: vote.voter.uid,
},
},
}
};
return this.model.create({...createArgs, include: {appointment: {include: {votes: true}}}});
}
/**
* @description : Find one vote
*/
public async findOneByUid(uid: string, query?: Prisma.VotesInclude): Promise<Votes | null> {
return this.model.findUnique({
where: {
uid: uid,
},
include: query,
});
}
/**
* @description : delete a vote
*/
public async delete(uid: string): Promise<Votes> {
return this.model.delete({
where: {
uid: uid,
},
});
}
}

View File

@ -0,0 +1,53 @@
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import AppointmentsRepository from "@Repositories/AppointmentsRepository";
import { Prisma, Appointments, EAppointmentStatus } from "@prisma/client";
@Service()
export default class AppointmentService extends BaseService {
constructor(private appointmentRepository: AppointmentsRepository) {
super();
}
/**
* @description : Get all appointments
* @throws {Error} If appointments cannot be get
*/
public get(query: Prisma.AppointmentsFindManyArgs) {
return this.appointmentRepository.findMany(query);
}
/**
* @description : Modify a appointment
* @throws {Error} If appointment cannot be modified
*/
public async update(uid: string, status: EAppointmentStatus): Promise<Appointments> {
return this.appointmentRepository.update(uid, status);
}
/**
* @description : Get a appointment by uid
* @throws {Error} If appointment cannot be get by uid
*/
public getByUid(uid: string, query?: Prisma.AppointmentsInclude): Promise<Appointments | null> {
return this.appointmentRepository.findOneByUid(uid, query);
}
/**
* @description : Get a appointment by uid
* @throws {Error} If appointment cannot be get by uid
*/
public getByUidWithVotes(uid: string) {
return this.appointmentRepository.findOneByUidWithVotes(uid);
}
/**
* @description : delete a appointment by uid
* @throws {Error} If appointment cannot be get by uid
*/
public delete(uid: string) {
return this.appointmentRepository.delete(uid);
}
}

View File

@ -0,0 +1,97 @@
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import User, { Appointment, Role, Vote } from "le-coffre-resources/dist/SuperAdmin";
import VotesRepository from "@Repositories/VotesRepository";
import { Appointments, EAppointmentStatus, EVote, Votes } from "@prisma/client";
import AppointmentService from "../AppointmentsService/AppointmentsService";
import UsersService from "../UsersService/UsersService";
import RolesService from "../RolesService/RolesService";
@Service()
export default class LiveVoteService extends BaseService {
constructor(
private voteRepository: VotesRepository,
private appointmentService: AppointmentService,
private userService: UsersService,
private roleService: RolesService,
) {
super();
}
public async verifyVoterChoice(vote: Vote): Promise<boolean> {
const userWithRole = await this.userService.getByUidWithRole(vote.appointment.targeted_user.uid!);
if (userWithRole!.role.name === "super-admin" && vote.appointment.choice === EVote.DISMISS) {
return true;
}
if (userWithRole!.role.name !== "super-admin" && vote.appointment.choice === EVote.NOMINATE) {
return true;
}
return false;
}
public async getAppointmentWithVotes(vote: Vote): Promise<Appointments | null> {
if (vote.appointment.uid) {
return this.appointmentService.getByUidWithVotes(vote.appointment.uid);
}
const appointmentByUser = await this.appointmentService.get({
where: {
AND: [
{ user_uid: vote.appointment.targeted_user.uid },
{ status: EAppointmentStatus.OPEN },
{ choice: EVote[vote.appointment.choice as keyof typeof EVote] },
],
},
include: { votes: true },
});
if (appointmentByUser.length >= 1) {
return this.appointmentService.getByUidWithVotes(appointmentByUser[0]!.uid);
}
return null;
}
private async closeVote(appointment: Appointments, vote: Votes) {
await this.appointmentService.update(vote.appointment_uid, EAppointmentStatus.CLOSED);
const user = await this.userService.getByUid(appointment.user_uid, { role: true });
const userEntity = User.hydrate<User>(user!, { strategy: "excludeAll" });
return await this.updateRole(appointment, userEntity, vote);
}
private async updateRole(appointment: Appointments, userEntity: User, vote: Votes) {
if (appointment.choice === EVote.DISMISS) {
const roles = await this.roleService.get({ where: { name: "default" } });
const roleEntity = Role.hydrate<Role>(roles[0]!, { strategy: "excludeAll" });
userEntity.role = roleEntity;
await this.userService.update(appointment!.user_uid, userEntity);
return vote;
} else if (appointment.choice === EVote.NOMINATE) {
const roles = await this.roleService.get({ where: { name: "super-admin" } });
const roleEntity = Role.hydrate<Role>(roles[0]!, { strategy: "excludeAll" });
userEntity!.role = roleEntity;
await this.userService.update(appointment!.user_uid, userEntity);
return vote;
}
return vote;
}
/**
* @description : Create a vote
* @throws {Error} If vote couldn't be created
*/
public async create(vote: Vote): Promise<Votes | null> {
const appointment = await this.getAppointmentWithVotes(vote);
if (appointment) {
const appointmentEntity = Appointment.hydrate<Appointment>(appointment, { strategy: "excludeAll" });
if (appointmentEntity?.votes && appointmentEntity.votes.length >= 2) {
const voteCreated = await this.voteRepository.create(vote);
return this.closeVote(appointment, voteCreated);
}
}
const approvedChoice = await this.verifyVoterChoice(vote);
if(!approvedChoice) return null;
return this.voteRepository.create(vote);
}
}

View File

@ -51,6 +51,14 @@ export default class UsersService extends BaseService {
return this.userRepository.findOneByUidWithOffice(uid);
}
/**
* @description : Get a user by uid with role
* @throws {Error} If user cannot be get by uid
*/
public getByUidWithRole(uid: string) {
return this.userRepository.findOneByUidWithRole(uid);
}
/**
* @description : Get a user by uid
* @throws {Error} If user cannot be get by uid

View File

@ -0,0 +1,35 @@
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import VotesRepository from "@Repositories/VotesRepository";
import { Prisma } from "@prisma/client";
@Service()
export default class VoteService extends BaseService {
constructor(private voteRepository: VotesRepository) {
super();
}
/**
* @description : Get all votes
* @throws {Error} If votes cannot be get
*/
public get(query: Prisma.VotesFindManyArgs) {
return this.voteRepository.findMany(query);
}
/**
* @description : Get a vote by uid
* @throws {Error} If vote cannot be get by uid
*/
public getByUid(uid: string, query?: Prisma.VotesInclude) {
return this.voteRepository.findOneByUid(uid, query);
}
/**
* @description : delete a vote by uid
* @throws {Error} If vote cannot be get by uid
*/
public delete(uid: string) {
return this.voteRepository.delete(uid);
}
}