Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 71bfac4317 | |||
| b37d114d4d | |||
| 8a15c62a48 | |||
| 098bf52822 | |||
| e9c9b8216e | |||
| 11e7863d02 |
Generated
+185
-2
@@ -14,8 +14,11 @@
|
|||||||
"@nestjs/core": "^11.0.1",
|
"@nestjs/core": "^11.0.1",
|
||||||
"@nestjs/mapped-types": "*",
|
"@nestjs/mapped-types": "*",
|
||||||
"@nestjs/platform-express": "^11.0.1",
|
"@nestjs/platform-express": "^11.0.1",
|
||||||
|
"@nestjs/swagger": "^11.1.0",
|
||||||
"@nestjs/typeorm": "^11.0.0",
|
"@nestjs/typeorm": "^11.0.0",
|
||||||
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.1",
|
"class-validator": "^0.14.1",
|
||||||
|
"mysql2": "^3.14.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"typeorm": "^0.3.21"
|
"typeorm": "^0.3.21"
|
||||||
@@ -1906,6 +1909,12 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@microsoft/tsdoc": {
|
||||||
|
"version": "0.15.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz",
|
||||||
|
"integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@napi-rs/nice": {
|
"node_modules/@napi-rs/nice": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.0.1.tgz",
|
||||||
@@ -2495,6 +2504,39 @@
|
|||||||
"tslib": "^2.1.0"
|
"tslib": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@nestjs/swagger": {
|
||||||
|
"version": "11.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-11.1.0.tgz",
|
||||||
|
"integrity": "sha512-+GQ+q1ASTBvGi0DYHukWi8NVVVLszedwLLqHdLRnJh8rjokt8YTDb7roImvT/YMmYgPvaWBv/4JYdZH4FueLPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@microsoft/tsdoc": "0.15.1",
|
||||||
|
"@nestjs/mapped-types": "2.1.0",
|
||||||
|
"js-yaml": "4.1.0",
|
||||||
|
"lodash": "4.17.21",
|
||||||
|
"path-to-regexp": "8.2.0",
|
||||||
|
"swagger-ui-dist": "5.20.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@fastify/static": "^8.0.0",
|
||||||
|
"@nestjs/common": "^11.0.1",
|
||||||
|
"@nestjs/core": "^11.0.1",
|
||||||
|
"class-transformer": "*",
|
||||||
|
"class-validator": "*",
|
||||||
|
"reflect-metadata": "^0.1.12 || ^0.2.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@fastify/static": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"class-transformer": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"class-validator": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@nestjs/testing": {
|
"node_modules/@nestjs/testing": {
|
||||||
"version": "11.0.12",
|
"version": "11.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.0.12.tgz",
|
||||||
@@ -2613,6 +2655,13 @@
|
|||||||
"url": "https://opencollective.com/unts"
|
"url": "https://opencollective.com/unts"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@scarf/scarf": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/@sec-ant/readable-stream": {
|
"node_modules/@sec-ant/readable-stream": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
|
||||||
@@ -4115,7 +4164,6 @@
|
|||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||||
"dev": true,
|
|
||||||
"license": "Python-2.0"
|
"license": "Python-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/array-timsort": {
|
"node_modules/array-timsort": {
|
||||||
@@ -4146,6 +4194,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/aws-ssl-profiles": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/b4a": {
|
"node_modules/b4a": {
|
||||||
"version": "1.6.7",
|
"version": "1.6.7",
|
||||||
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
|
||||||
@@ -4746,6 +4803,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/class-transformer": {
|
||||||
|
"version": "0.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
|
||||||
|
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/class-validator": {
|
"node_modules/class-validator": {
|
||||||
"version": "0.14.1",
|
"version": "0.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz",
|
||||||
@@ -5248,6 +5311,15 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/denque": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
@@ -6499,6 +6571,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/generate-function": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-property": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/gensync": {
|
"node_modules/gensync": {
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.2",
|
||||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||||
@@ -7077,6 +7158,12 @@
|
|||||||
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
|
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/is-property": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/is-stream": {
|
"node_modules/is-stream": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||||
@@ -7912,7 +7999,6 @@
|
|||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^2.0.1"
|
"argparse": "^2.0.1"
|
||||||
@@ -8125,6 +8211,12 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/long": {
|
||||||
|
"version": "5.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz",
|
||||||
|
"integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/lowercase-keys": {
|
"node_modules/lowercase-keys": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
|
||||||
@@ -8148,6 +8240,21 @@
|
|||||||
"yallist": "^3.0.2"
|
"yallist": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lru.min": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"bun": ">=1.0.0",
|
||||||
|
"deno": ">=1.30.0",
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/wellwelwel"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.17",
|
"version": "0.30.17",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
|
||||||
@@ -8464,6 +8571,59 @@
|
|||||||
"node": "^18.17.0 || >=20.5.0"
|
"node": "^18.17.0 || >=20.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mysql2": {
|
||||||
|
"version": "3.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.0.tgz",
|
||||||
|
"integrity": "sha512-8eMhmG6gt/hRkU1G+8KlGOdQi2w+CgtNoD1ksXZq9gQfkfDsX4LHaBwTe1SY0Imx//t2iZA03DFnyYKPinxSRw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"aws-ssl-profiles": "^1.1.1",
|
||||||
|
"denque": "^2.1.0",
|
||||||
|
"generate-function": "^2.3.1",
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
|
"long": "^5.2.1",
|
||||||
|
"lru.min": "^1.0.0",
|
||||||
|
"named-placeholders": "^1.1.3",
|
||||||
|
"seq-queue": "^0.0.5",
|
||||||
|
"sqlstring": "^2.3.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mysql2/node_modules/iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "^7.14.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders/node_modules/lru-cache": {
|
||||||
|
"version": "7.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||||
|
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/natural-compare": {
|
"node_modules/natural-compare": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||||
@@ -9637,6 +9797,11 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/seq-queue": {
|
||||||
|
"version": "0.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||||
|
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
|
||||||
|
},
|
||||||
"node_modules/serialize-javascript": {
|
"node_modules/serialize-javascript": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||||
@@ -9883,6 +10048,15 @@
|
|||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sqlstring": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/stack-utils": {
|
"node_modules/stack-utils": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
||||||
@@ -10220,6 +10394,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/swagger-ui-dist": {
|
||||||
|
"version": "5.20.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.20.1.tgz",
|
||||||
|
"integrity": "sha512-qBPCis2w8nP4US7SvUxdJD3OwKcqiWeZmjN2VWhq2v+ESZEXOP/7n4DeiOiiZcGYTKMHAHUUrroHaTsjUWTEGw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@scarf/scarf": "=1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/symbol-observable": {
|
"node_modules/symbol-observable": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz",
|
||||||
|
|||||||
@@ -25,8 +25,11 @@
|
|||||||
"@nestjs/core": "^11.0.1",
|
"@nestjs/core": "^11.0.1",
|
||||||
"@nestjs/mapped-types": "*",
|
"@nestjs/mapped-types": "*",
|
||||||
"@nestjs/platform-express": "^11.0.1",
|
"@nestjs/platform-express": "^11.0.1",
|
||||||
|
"@nestjs/swagger": "^11.1.0",
|
||||||
"@nestjs/typeorm": "^11.0.0",
|
"@nestjs/typeorm": "^11.0.0",
|
||||||
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.1",
|
"class-validator": "^0.14.1",
|
||||||
|
"mysql2": "^3.14.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"typeorm": "^0.3.21"
|
"typeorm": "^0.3.21"
|
||||||
|
|||||||
+10
-5
@@ -1,4 +1,4 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { forwardRef, Module } from '@nestjs/common';
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
import { CuestionarioModule } from './cuestionario/cuestionario.module';
|
import { CuestionarioModule } from './cuestionario/cuestionario.module';
|
||||||
@@ -15,6 +15,7 @@ import { CuestionarioRespondidoModule } from './cuestionario_respondido/cuestion
|
|||||||
import { RespuestaParticipanteAbiertaModule } from './respuesta_participante_abierta/respuesta_participante_abierta.module';
|
import { RespuestaParticipanteAbiertaModule } from './respuesta_participante_abierta/respuesta_participante_abierta.module';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { ParticipanteModule } from './participante/participante.module';
|
||||||
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
@@ -33,14 +34,18 @@ import { ConfigModule } from '@nestjs/config';
|
|||||||
autoLoadEntities: true, // Carga automáticamente las entidades
|
autoLoadEntities: true, // Carga automáticamente las entidades
|
||||||
|
|
||||||
}),
|
}),
|
||||||
CuestionarioModule,
|
forwardRef(() => CuestionarioModule),
|
||||||
|
forwardRef(() => SeccionModule),
|
||||||
|
forwardRef(() => PreguntaModule),
|
||||||
|
forwardRef(() => OpcionModule),
|
||||||
|
ParticipanteModule,
|
||||||
TipoCuestionarioModule,
|
TipoCuestionarioModule,
|
||||||
CuestionarioSeccionModule,
|
CuestionarioSeccionModule,
|
||||||
SeccionModule,
|
|
||||||
SeccionPreguntaModule,
|
SeccionPreguntaModule,
|
||||||
PreguntaModule,
|
|
||||||
TipoPreguntaModule,
|
TipoPreguntaModule,
|
||||||
OpcionModule, PreguntaOpcionModule,
|
PreguntaOpcionModule,
|
||||||
RespuestaParticipanteCerradaModule,
|
RespuestaParticipanteCerradaModule,
|
||||||
CuestionarioRespondidoModule,
|
CuestionarioRespondidoModule,
|
||||||
RespuestaParticipanteAbiertaModule],
|
RespuestaParticipanteAbiertaModule],
|
||||||
|
|||||||
@@ -1,34 +1,216 @@
|
|||||||
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
|
import {
|
||||||
|
Controller,
|
||||||
|
Post,
|
||||||
|
Body,
|
||||||
|
Get,
|
||||||
|
Param,
|
||||||
|
Put,
|
||||||
|
Delete,
|
||||||
|
HttpStatus,
|
||||||
|
HttpException,
|
||||||
|
Query,
|
||||||
|
} from '@nestjs/common';
|
||||||
import { CuestionarioService } from './cuestionario.service';
|
import { CuestionarioService } from './cuestionario.service';
|
||||||
import { CreateCuestionarioDto } from './dto/create-cuestionario.dto';
|
import { CreateCuestionarioDto } from './dto/create-cuestionario.dto';
|
||||||
import { UpdateCuestionarioDto } from './dto/update-cuestionario.dto';
|
import { UpdateCuestionarioDto } from './dto/update-cuestionario.dto';
|
||||||
|
import {
|
||||||
|
ApiTags,
|
||||||
|
ApiOperation,
|
||||||
|
ApiResponse,
|
||||||
|
ApiParam,
|
||||||
|
ApiBody,
|
||||||
|
ApiQuery,
|
||||||
|
} from '@nestjs/swagger';
|
||||||
|
import { SeccionExistenteCuestionarioDto } from './dto/seccion-existente-cuestionario.dto';
|
||||||
|
|
||||||
@Controller('cuestionario')
|
@ApiTags('Cuestionarios')
|
||||||
|
@Controller('cuestionarios')
|
||||||
export class CuestionarioController {
|
export class CuestionarioController {
|
||||||
constructor(private readonly cuestionarioService: CuestionarioService) {}
|
constructor(private readonly cuestionarioService: CuestionarioService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
create(@Body() createCuestionarioDto: CreateCuestionarioDto) {
|
@ApiOperation({ summary: 'Crear un nuevo cuestionario' })
|
||||||
return this.cuestionarioService.create(createCuestionarioDto);
|
@ApiBody({ type: CreateCuestionarioDto })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.CREATED,
|
||||||
|
description: 'Cuestionario creado exitosamente con sus secciones y preguntas',
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
description: 'Datos de entrada inválidos',
|
||||||
|
})
|
||||||
|
async create(@Body() createCuestionarioDto: CreateCuestionarioDto) {
|
||||||
|
try {
|
||||||
|
return await this.cuestionarioService.create(createCuestionarioDto);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
{
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
},
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
findAll() {
|
@ApiOperation({ summary: 'Obtener todos los cuestionarios' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'tipo',
|
||||||
|
required: false,
|
||||||
|
description: 'Filtrar por tipo de cuestionario',
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Lista de cuestionarios obtenida exitosamente',
|
||||||
|
})
|
||||||
|
async findAll(@Query('tipo') tipoCuestionarioId?: number) {
|
||||||
|
if (tipoCuestionarioId) {
|
||||||
|
return this.cuestionarioService.findAllByTipo(tipoCuestionarioId);
|
||||||
|
}
|
||||||
return this.cuestionarioService.findAll();
|
return this.cuestionarioService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findOne(@Param('id') id: string) {
|
@ApiOperation({ summary: 'Obtener un cuestionario específico con todas sus relaciones' })
|
||||||
return this.cuestionarioService.findOne(+id);
|
@ApiParam({ name: 'id', description: 'ID del cuestionario' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Cuestionario encontrado con todas sus secciones y preguntas',
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.NOT_FOUND,
|
||||||
|
description: 'Cuestionario no encontrado',
|
||||||
|
})
|
||||||
|
async findOne(@Param('id') id: string) {
|
||||||
|
const cuestionario = await this.cuestionarioService.findOneWithRelations(+id);
|
||||||
|
if (!cuestionario) {
|
||||||
|
throw new HttpException(
|
||||||
|
'Cuestionario no encontrado',
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return cuestionario;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Put(':id')
|
||||||
update(@Param('id') id: string, @Body() updateCuestionarioDto: UpdateCuestionarioDto) {
|
@ApiOperation({ summary: 'Actualizar los metadatos de un cuestionario' })
|
||||||
return this.cuestionarioService.update(+id, updateCuestionarioDto);
|
@ApiParam({ name: 'id', description: 'ID del cuestionario a actualizar' })
|
||||||
|
@ApiBody({ type: UpdateCuestionarioDto })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Cuestionario actualizado exitosamente',
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.NOT_FOUND,
|
||||||
|
description: 'Cuestionario no encontrado',
|
||||||
|
})
|
||||||
|
async update(
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Body() updateCuestionarioDto: UpdateCuestionarioDto,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
return await this.cuestionarioService.update(+id, updateCuestionarioDto);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
{
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
},
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
remove(@Param('id') id: string) {
|
@ApiOperation({ summary: 'Eliminar un cuestionario y todas sus relaciones' })
|
||||||
return this.cuestionarioService.remove(+id);
|
@ApiParam({ name: 'id', description: 'ID del cuestionario a eliminar' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Cuestionario eliminado exitosamente',
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.NOT_FOUND,
|
||||||
|
description: 'Cuestionario no encontrado',
|
||||||
|
})
|
||||||
|
async remove(@Param('id') id: string) {
|
||||||
|
try {
|
||||||
|
return await this.cuestionarioService.remove(+id);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
{
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
},
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post(':id/secciones')
|
||||||
|
@ApiOperation({ summary: 'Agregar una sección existente al cuestionario' })
|
||||||
|
@ApiParam({ name: 'id', description: 'ID del cuestionario' })
|
||||||
|
@ApiBody({ type: SeccionExistenteCuestionarioDto })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.CREATED,
|
||||||
|
description: 'Sección agregada al cuestionario exitosamente',
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.NOT_FOUND,
|
||||||
|
description: 'Cuestionario o sección no encontrada',
|
||||||
|
})
|
||||||
|
async agregarSeccion(
|
||||||
|
@Param('id') cuestionarioId: string,
|
||||||
|
@Body() seccionDto: SeccionExistenteCuestionarioDto,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
return await this.cuestionarioService.agregarSeccionExistente(
|
||||||
|
+cuestionarioId,
|
||||||
|
seccionDto.id_seccion,
|
||||||
|
seccionDto.posicion,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
{
|
||||||
|
status: error.status || HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
},
|
||||||
|
error.status || HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':cuestionarioId/secciones/:seccionId')
|
||||||
|
@ApiOperation({ summary: 'Remover una sección del cuestionario' })
|
||||||
|
@ApiParam({ name: 'cuestionarioId', description: 'ID del cuestionario' })
|
||||||
|
@ApiParam({ name: 'seccionId', description: 'ID de la sección a remover' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Sección removida del cuestionario exitosamente',
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.NOT_FOUND,
|
||||||
|
description: 'Relación no encontrada',
|
||||||
|
})
|
||||||
|
async removerSeccion(
|
||||||
|
@Param('cuestionarioId') cuestionarioId: string,
|
||||||
|
@Param('seccionId') seccionId: string,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
return await this.cuestionarioService.eliminarSeccionDeCuestionario(
|
||||||
|
+cuestionarioId,
|
||||||
|
+seccionId,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
{
|
||||||
|
status: error.status || HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
},
|
||||||
|
error.status || HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,20 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module, forwardRef } from '@nestjs/common';
|
||||||
import { CuestionarioService } from './cuestionario.service';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { CuestionarioController } from './cuestionario.controller';
|
import { CuestionarioController } from './cuestionario.controller';
|
||||||
|
import { CuestionarioService } from './cuestionario.service';
|
||||||
|
import { Cuestionario } from './entities/cuestionario.entity';
|
||||||
|
import { CuestionarioSeccion } from '../cuestionario_seccion/entities/cuestionario_seccion.entity';
|
||||||
|
import { SeccionModule } from '../seccion/seccion.module';
|
||||||
|
import { TipoCuestionarioModule } from '../tipo_cuestionario/tipo_cuestionario.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([Cuestionario, CuestionarioSeccion]),
|
||||||
|
forwardRef(() => SeccionModule),
|
||||||
|
TipoCuestionarioModule,
|
||||||
|
],
|
||||||
controllers: [CuestionarioController],
|
controllers: [CuestionarioController],
|
||||||
providers: [CuestionarioService],
|
providers: [CuestionarioService],
|
||||||
|
exports: [CuestionarioService],
|
||||||
})
|
})
|
||||||
export class CuestionarioModule {}
|
export class CuestionarioModule {}
|
||||||
@@ -1,26 +1,221 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||||
import { CreateCuestionarioDto } from './dto/create-cuestionario.dto';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
import { Cuestionario } from './entities/cuestionario.entity';
|
||||||
|
import { SeccionService } from '../seccion/seccion.service';
|
||||||
|
import { CreateCuestionarioDto, SeccionEnCuestionarioDto } from './dto/create-cuestionario.dto';
|
||||||
import { UpdateCuestionarioDto } from './dto/update-cuestionario.dto';
|
import { UpdateCuestionarioDto } from './dto/update-cuestionario.dto';
|
||||||
|
import { Seccion } from '../seccion/entities/seccion.entity';
|
||||||
|
import { CuestionarioSeccion } from 'src/cuestionario_seccion/entities/cuestionario_seccion.entity';
|
||||||
|
import { TipoCuestionario } from 'src/tipo_cuestionario/entities/tipo_cuestionario.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CuestionarioService {
|
export class CuestionarioService {
|
||||||
create(createCuestionarioDto: CreateCuestionarioDto) {
|
async findAllByTipo(tipoCuestionarioId: number): Promise<Cuestionario[]> {
|
||||||
return 'This action adds a new cuestionario';
|
return this.cuestionarioRepository.find({
|
||||||
|
where: { tipo_cuestionario: { id_tipo_cuestionario: tipoCuestionarioId } },
|
||||||
|
relations: ['tipo_cuestionario', 'cuestionarioSecciones'],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
findAll() {
|
obtenerResumen(arg0: number) {
|
||||||
return `This action returns all cuestionario`;
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(Cuestionario)
|
||||||
|
private readonly cuestionarioRepository: Repository<Cuestionario>,
|
||||||
|
@InjectRepository(TipoCuestionario)
|
||||||
|
private readonly tipoCuestionarioRepository: Repository<TipoCuestionario>,
|
||||||
|
@InjectRepository(CuestionarioSeccion)
|
||||||
|
private readonly cuestionarioSeccionRepository: Repository<CuestionarioSeccion>,
|
||||||
|
private readonly seccionService: SeccionService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async create(createCuestionarioDto: CreateCuestionarioDto) {
|
||||||
|
// Verificar tipo de cuestionario
|
||||||
|
const tipoCuestionario = await this.tipoCuestionarioRepository.findOne({
|
||||||
|
where: { id_tipo_cuestionario: createCuestionarioDto.id_tipo_cuestionario },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!tipoCuestionario) {
|
||||||
|
throw new NotFoundException('Tipo de cuestionario no encontrado');
|
||||||
}
|
}
|
||||||
|
|
||||||
findOne(id: number) {
|
// Crear cuestionario base
|
||||||
return `This action returns a #${id} cuestionario`;
|
const cuestionario = this.cuestionarioRepository.create({
|
||||||
|
nombre_form: createCuestionarioDto.nombre_form,
|
||||||
|
descripcion: createCuestionarioDto.descripcion,
|
||||||
|
editable: createCuestionarioDto.editable ?? true,
|
||||||
|
fecha_inicio: createCuestionarioDto.fecha_inicio,
|
||||||
|
fecha_fin: createCuestionarioDto.fecha_fin,
|
||||||
|
tipo_cuestionario: tipoCuestionario,
|
||||||
|
contador_secciones: createCuestionarioDto.secciones?.length || 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const cuestionarioGuardado = await this.cuestionarioRepository.save(cuestionario);
|
||||||
|
|
||||||
|
// Procesar secciones si existen
|
||||||
|
if (createCuestionarioDto.secciones && createCuestionarioDto.secciones.length > 0) {
|
||||||
|
await this.agregarSeccionesACuestionario(
|
||||||
|
cuestionarioGuardado.id_cuestionario,
|
||||||
|
createCuestionarioDto.secciones,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(id: number, updateCuestionarioDto: UpdateCuestionarioDto) {
|
return this.findOneWithRelations(cuestionarioGuardado.id_cuestionario);
|
||||||
return `This action updates a #${id} cuestionario`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(id: number) {
|
private async agregarSeccionesACuestionario(
|
||||||
return `This action removes a #${id} cuestionario`;
|
cuestionarioId: number,
|
||||||
|
secciones: SeccionEnCuestionarioDto[],
|
||||||
|
) {
|
||||||
|
await Promise.all(
|
||||||
|
secciones.map(async (seccionDto) => {
|
||||||
|
// Crear la sección usando el servicio existente
|
||||||
|
const seccionCreada = await this.seccionService.create(seccionDto.seccion);
|
||||||
|
|
||||||
|
// Crear la relación cuestionario-sección
|
||||||
|
const cuestionarioSeccion = this.cuestionarioSeccionRepository.create({
|
||||||
|
posicion: seccionDto.posicion,
|
||||||
|
cuestionario: { id_cuestionario: cuestionarioId },
|
||||||
|
seccion: { id_seccion: seccionCreada?.id_seccion },
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.cuestionarioSeccionRepository.save(cuestionarioSeccion);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOneWithRelations(id: number) {
|
||||||
|
return this.cuestionarioRepository.findOne({
|
||||||
|
where: { id_cuestionario: id },
|
||||||
|
relations: [
|
||||||
|
'tipo_cuestionario',
|
||||||
|
'cuestionarioSecciones',
|
||||||
|
'cuestionarioSecciones.seccion',
|
||||||
|
'cuestionarioSecciones.seccion.seccionPreguntas',
|
||||||
|
'cuestionarioSecciones.seccion.seccionPreguntas.pregunta',
|
||||||
|
'cuestionarioSecciones.seccion.seccionPreguntas.pregunta.tipo_pregunta',
|
||||||
|
'cuestionarioSecciones.seccion.seccionPreguntas.pregunta.opciones',
|
||||||
|
'cuestionarioSecciones.seccion.seccionPreguntas.pregunta.opciones.opcion',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAll() {
|
||||||
|
return this.cuestionarioRepository.find({
|
||||||
|
relations: ['tipo_cuestionario'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: number, updateCuestionarioDto: UpdateCuestionarioDto) {
|
||||||
|
const cuestionario = await this.cuestionarioRepository.findOne({
|
||||||
|
where: { id_cuestionario: id },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!cuestionario) {
|
||||||
|
throw new NotFoundException(`Cuestionario con ID ${id} no encontrado`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizar campos básicos
|
||||||
|
if (updateCuestionarioDto.nombre_form !== undefined) {
|
||||||
|
cuestionario.nombre_form = updateCuestionarioDto.nombre_form;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateCuestionarioDto.descripcion !== undefined) {
|
||||||
|
cuestionario.descripcion = updateCuestionarioDto.descripcion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateCuestionarioDto.editable !== undefined) {
|
||||||
|
cuestionario.editable = updateCuestionarioDto.editable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateCuestionarioDto.fecha_inicio !== undefined) {
|
||||||
|
cuestionario.fecha_inicio = updateCuestionarioDto.fecha_inicio;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateCuestionarioDto.fecha_fin !== undefined) {
|
||||||
|
cuestionario.fecha_fin = updateCuestionarioDto.fecha_fin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.cuestionarioRepository.save(cuestionario);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(id: number) {
|
||||||
|
// Eliminar relaciones cuestionario-sección primero
|
||||||
|
await this.cuestionarioSeccionRepository.delete({
|
||||||
|
cuestionario: { id_cuestionario: id },
|
||||||
|
});
|
||||||
|
|
||||||
|
// Luego eliminar el cuestionario
|
||||||
|
const result = await this.cuestionarioRepository.delete(id);
|
||||||
|
|
||||||
|
if (result.affected === 0) {
|
||||||
|
throw new NotFoundException(`Cuestionario con ID ${id} no encontrado`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { affected: result.affected };
|
||||||
|
}
|
||||||
|
|
||||||
|
async agregarSeccionExistente(
|
||||||
|
cuestionarioId: number,
|
||||||
|
seccionId: number,
|
||||||
|
posicion: number,
|
||||||
|
) {
|
||||||
|
// Verificar que existan ambos elementos
|
||||||
|
const cuestionario = await this.cuestionarioRepository.findOne({
|
||||||
|
where: { id_cuestionario: cuestionarioId },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!cuestionario) {
|
||||||
|
throw new NotFoundException(`Cuestionario con ID ${cuestionarioId} no encontrado`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const seccion = await this.seccionService.findOneWithRelations(seccionId);
|
||||||
|
if (!seccion) {
|
||||||
|
throw new NotFoundException(`Sección con ID ${seccionId} no encontrada`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear la relación
|
||||||
|
const cuestionarioSeccion = this.cuestionarioSeccionRepository.create({
|
||||||
|
posicion,
|
||||||
|
cuestionario: { id_cuestionario: cuestionarioId },
|
||||||
|
seccion: { id_seccion: seccionId },
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.cuestionarioSeccionRepository.save(cuestionarioSeccion);
|
||||||
|
|
||||||
|
// Actualizar contador de secciones
|
||||||
|
await this.cuestionarioRepository.increment(
|
||||||
|
{ id_cuestionario: cuestionarioId },
|
||||||
|
'contador_secciones',
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.findOneWithRelations(cuestionarioId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async eliminarSeccionDeCuestionario(cuestionarioId: number, seccionId: number) {
|
||||||
|
const relacion = await this.cuestionarioSeccionRepository.findOne({
|
||||||
|
where: {
|
||||||
|
cuestionario: { id_cuestionario: cuestionarioId },
|
||||||
|
seccion: { id_seccion: seccionId },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!relacion) {
|
||||||
|
throw new NotFoundException('La sección no está asociada a este cuestionario');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.cuestionarioSeccionRepository.remove(relacion);
|
||||||
|
|
||||||
|
// Actualizar contador de secciones
|
||||||
|
await this.cuestionarioRepository.decrement(
|
||||||
|
{ id_cuestionario: cuestionarioId },
|
||||||
|
'contador_secciones',
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
return { success: true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1 +1,46 @@
|
|||||||
export class CreateCuestionarioDto {}
|
import { IsNotEmpty, IsString, IsBoolean, IsDateString, IsNumber, IsOptional, IsArray, ValidateNested } from 'class-validator';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
import { CreateSeccionDto } from 'src/seccion/dto/create-seccion.dto';
|
||||||
|
|
||||||
|
export class CreateCuestionarioDto {
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
nombre_form: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
descripcion?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
editable?: boolean;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsDateString()
|
||||||
|
fecha_inicio: Date;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsDateString()
|
||||||
|
fecha_fin: Date;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsNumber()
|
||||||
|
id_tipo_cuestionario: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => SeccionEnCuestionarioDto)
|
||||||
|
secciones?: SeccionEnCuestionarioDto[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SeccionEnCuestionarioDto {
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsNumber()
|
||||||
|
posicion: number;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => CreateSeccionDto)
|
||||||
|
seccion: CreateSeccionDto;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { IsNotEmpty, IsNumber, Min } from 'class-validator';
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class SeccionExistenteCuestionarioDto {
|
||||||
|
@ApiProperty({
|
||||||
|
example: 1,
|
||||||
|
description: 'Posición de la sección dentro del cuestionario',
|
||||||
|
})
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1)
|
||||||
|
posicion: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 5,
|
||||||
|
description: 'ID de la sección existente a agregar',
|
||||||
|
})
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1)
|
||||||
|
id_seccion: number;
|
||||||
|
}
|
||||||
@@ -1,4 +1,23 @@
|
|||||||
import { PartialType } from '@nestjs/mapped-types';
|
import { IsOptional, IsString, IsBoolean, IsDateString } from 'class-validator';
|
||||||
import { CreateCuestionarioDto } from './create-cuestionario.dto';
|
|
||||||
|
|
||||||
export class UpdateCuestionarioDto extends PartialType(CreateCuestionarioDto) {}
|
export class UpdateCuestionarioDto {
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
nombre_form?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
descripcion?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
editable?: boolean;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsDateString()
|
||||||
|
fecha_inicio?: Date;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsDateString()
|
||||||
|
fecha_fin?: Date;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { CuestionarioRespondido } from 'src/cuestionario_respondido/entities/cuestionario_respondido.entity';
|
||||||
import { CuestionarioSeccion } from 'src/cuestionario_seccion/entities/cuestionario_seccion.entity';
|
import { CuestionarioSeccion } from 'src/cuestionario_seccion/entities/cuestionario_seccion.entity';
|
||||||
import { TipoCuestionario } from 'src/tipo_cuestionario/entities/tipo_cuestionario.entity';
|
import { TipoCuestionario } from 'src/tipo_cuestionario/entities/tipo_cuestionario.entity';
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, OneToMany, ManyToMany, ManyToOne } from 'typeorm';
|
import { Entity, PrimaryGeneratedColumn, Column, OneToMany, ManyToMany, ManyToOne, JoinColumn } from 'typeorm';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -27,18 +28,22 @@ export class Cuestionario {
|
|||||||
@Column({ type: 'datetime', nullable: true })
|
@Column({ type: 'datetime', nullable: true })
|
||||||
fecha_inicio: Date;
|
fecha_inicio: Date;
|
||||||
|
|
||||||
|
@OneToMany(() => CuestionarioRespondido, cuestionarioRespondido => cuestionarioRespondido.cuestionario)
|
||||||
|
cuestionariosRespondidos: CuestionarioRespondido[];
|
||||||
|
|
||||||
@OneToMany(() => CuestionarioSeccion,(cuestionario_seccion) => cuestionario_seccion.id_cuestionario)
|
|
||||||
|
@OneToMany(() => CuestionarioSeccion,(cuestionario_seccion) => cuestionario_seccion.seccion)
|
||||||
|
@JoinColumn()
|
||||||
cuestionarioSeccion:CuestionarioSeccion[]
|
cuestionarioSeccion:CuestionarioSeccion[]
|
||||||
|
|
||||||
@OneToMany(()=> Cuestionario, (cuestionario) => cuestionario.id_cuestionario)
|
@OneToMany(()=> Cuestionario, (cuestionario) => cuestionario.cuestionario_original)
|
||||||
@Column({ type: 'int' })
|
cuestionarioOriginal: Cuestionario[];
|
||||||
id_cuestionario_original: number;
|
|
||||||
|
|
||||||
@OneToMany(()=> TipoCuestionario, (tipo_cuestionario) => tipo_cuestionario.id_tipo_cuestionario )
|
@ManyToOne(() => TipoCuestionario, (tipo) => tipo.cuestionarios)
|
||||||
@Column({ type: 'int' })
|
@JoinColumn({ name: 'id_tipo_cuestionario' }) // Clave foránea en la base de datos
|
||||||
id_tipo_cuestionario: number;
|
tipo_cuestionario: TipoCuestionario;
|
||||||
|
|
||||||
@ManyToOne(()=> Cuestionario, (cuestionario) => cuestionario.id_cuestionario)
|
@ManyToOne(()=> Cuestionario, (cuestionario) => cuestionario.cuestionarioOriginal)
|
||||||
Cuestionario: Cuestionario[];
|
@JoinColumn({ name: 'id_cuestionario_original' })
|
||||||
|
cuestionario_original: Cuestionario;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { CuestionarioRespondidoService } from './cuestionario_respondido.service';
|
import { CuestionarioRespondidoService } from './cuestionario_respondido.service';
|
||||||
import { CuestionarioRespondidoController } from './cuestionario_respondido.controller';
|
import { CuestionarioRespondidoController } from './cuestionario_respondido.controller';
|
||||||
|
import { CuestionarioRespondido } from './entities/cuestionario_respondido.entity';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
|
||||||
|
imports: [TypeOrmModule.forFeature([CuestionarioRespondido])],
|
||||||
controllers: [CuestionarioRespondidoController],
|
controllers: [CuestionarioRespondidoController],
|
||||||
providers: [CuestionarioRespondidoService],
|
providers: [CuestionarioRespondidoService],
|
||||||
|
exports:[CuestionarioRespondidoService, TypeOrmModule]
|
||||||
})
|
})
|
||||||
export class CuestionarioRespondidoModule {}
|
export class CuestionarioRespondidoModule {}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColum
|
|||||||
import { Cuestionario } from 'src/cuestionario/entities/cuestionario.entity';
|
import { Cuestionario } from 'src/cuestionario/entities/cuestionario.entity';
|
||||||
import { RespuestaParticipanteCerrada } from 'src/respuesta_participante_cerrada/entities/respuesta_participante_cerrada.entity';
|
import { RespuestaParticipanteCerrada } from 'src/respuesta_participante_cerrada/entities/respuesta_participante_cerrada.entity';
|
||||||
import { RespuestaParticipanteAbierta } from 'src/respuesta_participante_abierta/entities/respuesta_participante_abierta.entity';
|
import { RespuestaParticipanteAbierta } from 'src/respuesta_participante_abierta/entities/respuesta_participante_abierta.entity';
|
||||||
|
import { Participante } from 'src/participante/participante.entity';
|
||||||
|
|
||||||
@Entity('cuestionario_respondido')
|
@Entity('cuestionario_respondido')
|
||||||
export class CuestionarioRespondido {
|
export class CuestionarioRespondido {
|
||||||
@@ -13,20 +14,20 @@ export class CuestionarioRespondido {
|
|||||||
fechaRespuesta: Date;
|
fechaRespuesta: Date;
|
||||||
|
|
||||||
// Relación con Participante
|
// Relación con Participante
|
||||||
@ManyToOne(() => Participante, participante => participante.cuestionariosRespondidos)
|
@ManyToOne(() => Participante, participante => participante.cuestionarioRespondidos)
|
||||||
@JoinColumn({ name: 'id_participante' })
|
@JoinColumn({ name: 'id_participante' })
|
||||||
id_participante: Participante;
|
participante: Participante;
|
||||||
|
|
||||||
// Relación con Cuestionario
|
// Relación con Cuestionario
|
||||||
@ManyToOne(() => Cuestionario, cuestionario => cuestionario.id_cuestionario)
|
@ManyToOne(() => Cuestionario, cuestionario => cuestionario.cuestionariosRespondidos)
|
||||||
@JoinColumn({ name: 'id_cuestionario' })
|
@JoinColumn({ name: 'id_cuestionario' })
|
||||||
id_cuestionario: Cuestionario;
|
cuestionario: Cuestionario;
|
||||||
|
|
||||||
// Relación con RespuestasCerradas
|
// Relación con RespuestasCerradas
|
||||||
@OneToMany(() => RespuestaParticipanteCerrada, respuestaCerrada => respuestaCerrada.id_cuestionario_respondido)
|
@OneToMany(() => RespuestaParticipanteCerrada, respuestaCerrada => respuestaCerrada.cuestionarioRespondido)
|
||||||
respuestasCerradas: RespuestaParticipanteCerrada[];
|
respuestasCerradas: RespuestaParticipanteCerrada[];
|
||||||
|
|
||||||
// Relación con RespuestasAbiertas
|
// Relación con RespuestasAbiertas
|
||||||
@OneToMany(() => RespuestaParticipanteAbierta, respuestaAbierta => respuestaAbierta.id_cuestionario_respondido)
|
@OneToMany(() => RespuestaParticipanteAbierta, respuestaAbierta => respuestaAbierta.cuestionarioRespondido)
|
||||||
respuestasAbiertas: RespuestaParticipanteAbierta[];
|
respuestasAbiertas: RespuestaParticipanteAbierta[];
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { CuestionarioSeccionService } from './cuestionario_seccion.service';
|
import { CuestionarioSeccionService } from './cuestionario_seccion.service';
|
||||||
import { CuestionarioSeccionController } from './cuestionario_seccion.controller';
|
import { CuestionarioSeccionController } from './cuestionario_seccion.controller';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { CuestionarioSeccion } from './entities/cuestionario_seccion.entity';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([CuestionarioSeccion])],
|
||||||
controllers: [CuestionarioSeccionController],
|
controllers: [CuestionarioSeccionController],
|
||||||
providers: [CuestionarioSeccionService],
|
providers: [CuestionarioSeccionService],
|
||||||
|
exports:[CuestionarioSeccionService, TypeOrmModule]
|
||||||
})
|
})
|
||||||
export class CuestionarioSeccionModule {}
|
export class CuestionarioSeccionModule {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
|
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
||||||
import { Cuestionario } from '../../cuestionario/entities/cuestionario.entity'; // Asegúrate de importar la entidad Cuestionario
|
import { Cuestionario } from '../../cuestionario/entities/cuestionario.entity'; // Asegúrate de importar la entidad Cuestionario
|
||||||
import { Seccion } from 'src/seccion/entities/seccion.entity';
|
import { Seccion } from 'src/seccion/entities/seccion.entity';
|
||||||
|
|
||||||
@@ -11,11 +11,11 @@ export class CuestionarioSeccion {
|
|||||||
posicion: number;
|
posicion: number;
|
||||||
|
|
||||||
|
|
||||||
@ManyToOne(() => Cuestionario, (cuestionario) => cuestionario.id_cuestionario)
|
@ManyToOne(() => Cuestionario, (cuestionario) => cuestionario.cuestionarioSeccion)
|
||||||
@Column({ type: 'int' })
|
@JoinColumn({name:'id_cuestionario'})
|
||||||
id_cuestionario: number;
|
cuestionario: Cuestionario;
|
||||||
|
|
||||||
@ManyToOne(() => Seccion, (seccion) => seccion.id_seccion)
|
@ManyToOne(() => Seccion, (seccion) => seccion.cuestionarioSeccion)
|
||||||
@Column({type:'int'})
|
@JoinColumn({name:'id_seccion'})
|
||||||
id_seccion:number;
|
seccion:Seccion;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { IsString, MaxLength } from "class-validator";
|
import { IsString, IsNumber, IsNotEmpty, IsOptional } from 'class-validator';
|
||||||
|
|
||||||
export class CreateOpcionDto {
|
export class CreateOpcionDto {
|
||||||
|
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@MaxLength(50)
|
@IsNotEmpty()
|
||||||
opcion: string;
|
opcion: string;
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
posicion?: number;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,11 @@
|
|||||||
import { PartialType } from '@nestjs/mapped-types';
|
import { IsString, IsNumber, IsOptional } from 'class-validator';
|
||||||
import { CreateOpcionDto } from './create-opcion.dto';
|
|
||||||
|
|
||||||
export class UpdateOpcionDto extends PartialType(CreateOpcionDto) {}
|
export class UpdateOpcionDto {
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
opcion?: string;
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
posicion?: number;
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ export class Opcion {
|
|||||||
@Column({ type: String, nullable: false, length: 200, default: '' })
|
@Column({ type: String, nullable: false, length: 200, default: '' })
|
||||||
opcion: string;
|
opcion: string;
|
||||||
|
|
||||||
@OneToMany(() => PreguntaOpcion, (preguntaOpcion) => preguntaOpcion.id_opcion)
|
@OneToMany(() => PreguntaOpcion, (preguntaOpcion) => preguntaOpcion.opcion)
|
||||||
Preguntas: PreguntaOpcion[];
|
Preguntas: PreguntaOpcion[];
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,33 +2,41 @@ import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/commo
|
|||||||
import { OpcionService } from './opcion.service';
|
import { OpcionService } from './opcion.service';
|
||||||
import { CreateOpcionDto } from './dto/create-opcion.dto';
|
import { CreateOpcionDto } from './dto/create-opcion.dto';
|
||||||
import { UpdateOpcionDto } from './dto/update-opcion.dto';
|
import { UpdateOpcionDto } from './dto/update-opcion.dto';
|
||||||
|
import { Pregunta } from 'src/pregunta/entities/pregunta.entity';
|
||||||
|
|
||||||
@Controller('opcion')
|
@Controller('opcion')
|
||||||
export class OpcionController {
|
export class OpcionController {
|
||||||
constructor(private readonly opcionService: OpcionService) {}
|
constructor(private readonly opcionService: OpcionService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
create(@Body() createOpcionDto: CreateOpcionDto) {
|
async create(
|
||||||
return this.opcionService.create(createOpcionDto);
|
@Param('PreguntaId')PreguntaId:number,
|
||||||
|
@Body() createOpcionDto: CreateOpcionDto) {
|
||||||
|
|
||||||
|
return this.opcionService.create(PreguntaId,createOpcionDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
findAll() {
|
async findAll(
|
||||||
return this.opcionService.findAll();
|
@Param('PreguntaId')PreguntaId:number
|
||||||
|
) {
|
||||||
|
return this.opcionService.findAllByPregunta(PreguntaId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findOne(@Param('id') id: string) {
|
async findOne(
|
||||||
return this.opcionService.findOne(+id);
|
@Param('preguntaId') preguntaId: number,
|
||||||
|
@Param('opcionId') OpcionId: number) {
|
||||||
|
return this.opcionService.findOne(preguntaId, OpcionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
update(@Param('id') id: string, @Body() updateOpcionDto: UpdateOpcionDto) {
|
async pdate(@Param('preguntaId') preguntaId:number ,@Param('opcionId') id: number, @Body() updateOpcionDto: UpdateOpcionDto) {
|
||||||
return this.opcionService.update(+id, updateOpcionDto);
|
return this.opcionService.update(preguntaId, id,updateOpcionDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
remove(@Param('id') id: string) {
|
async remove(@Param('preguntaId') preguntaId:number ,@Param('opcionId') id: number) {
|
||||||
return this.opcionService.remove(+id);
|
return this.opcionService.remove(preguntaId, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module, forwardRef } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { OpcionService } from './opcion.service';
|
import { OpcionService } from './opcion.service';
|
||||||
import { OpcionController } from './opcion.controller';
|
import { OpcionController } from './opcion.controller';
|
||||||
|
import { Opcion } from './entities/opcion.entity';
|
||||||
|
import { PreguntaOpcion } from '../pregunta_opcion/entities/pregunta_opcion.entity';
|
||||||
|
import { PreguntaModule } from '../pregunta/pregunta.module';
|
||||||
|
import { Pregunta } from '../pregunta/entities/pregunta.entity';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([Opcion, Pregunta, PreguntaOpcion]), // Importar todas las entidades necesarias
|
||||||
|
forwardRef(() => PreguntaModule), // Usar forwardRef para dependencia circular
|
||||||
|
],
|
||||||
controllers: [OpcionController],
|
controllers: [OpcionController],
|
||||||
providers: [OpcionService],
|
providers: [OpcionService],
|
||||||
|
exports: [OpcionService, TypeOrmModule], // Exportar TypeOrmModule si otros módulos necesitan los repositorios
|
||||||
})
|
})
|
||||||
export class OpcionModule {}
|
export class OpcionModule {}
|
||||||
+139
-17
@@ -1,36 +1,158 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||||
import { CreateOpcionDto } from './dto/create-opcion.dto';
|
|
||||||
import { UpdateOpcionDto } from './dto/update-opcion.dto';
|
|
||||||
import { Opcion } from './entities/opcion.entity';
|
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
import { Opcion } from './entities/opcion.entity';
|
||||||
|
import { Pregunta } from '../pregunta/entities/pregunta.entity';
|
||||||
|
import { CreateOpcionDto } from './dto/create-opcion.dto';
|
||||||
|
import { PreguntaOpcion } from 'src/pregunta_opcion/entities/pregunta_opcion.entity';
|
||||||
|
import { UpdateOpcionDto } from './dto/update-opcion.dto';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OpcionService {
|
export class OpcionService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Opcion)
|
@InjectRepository(Opcion)
|
||||||
private repository: Repository<Opcion>,
|
private readonly opcionRepository: Repository<Opcion>,
|
||||||
){}
|
@InjectRepository(Pregunta)
|
||||||
|
private readonly preguntaRepository: Repository<Pregunta>,
|
||||||
|
@InjectRepository(PreguntaOpcion)
|
||||||
|
private readonly preguntaOpcionRepository: Repository<PreguntaOpcion>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async create(preguntaId: number, createOpcionDto: CreateOpcionDto) {
|
||||||
|
// Verificar que la pregunta exista y sea cerrada
|
||||||
|
const pregunta = await this.preguntaRepository.findOne({
|
||||||
|
where: { id_pregunta: preguntaId },
|
||||||
|
relations: ['tipo_pregunta'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pregunta) {
|
||||||
create():Promise<Opcion> {
|
throw new NotFoundException('Pregunta no encontrada');
|
||||||
return this.repository.save(this.repository.create());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
findAll() {
|
if (pregunta.tipo_pregunta.tipo_pregunta !== 'Cerrada') {
|
||||||
return `This action returns all opcion`;
|
throw new Error('Solo se pueden agregar opciones a preguntas cerradas');
|
||||||
}
|
}
|
||||||
|
|
||||||
findOne(id: number) {
|
// Crear la opción
|
||||||
return `This action returns a #${id} opcion`;
|
const opcion = this.opcionRepository.create({
|
||||||
|
opcion: createOpcionDto.opcion,
|
||||||
|
});
|
||||||
|
|
||||||
|
const savedOpcion = await this.opcionRepository.save(opcion);
|
||||||
|
|
||||||
|
// Crear la relación entre pregunta y opción
|
||||||
|
const preguntaOpcion = this.preguntaOpcionRepository.create({
|
||||||
|
pregunta: { id_pregunta: preguntaId },
|
||||||
|
opcion: savedOpcion,
|
||||||
|
posicion: createOpcionDto.posicion || 0, // Asignar posición
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.preguntaOpcionRepository.save(preguntaOpcion);
|
||||||
|
|
||||||
|
// Actualizar el contador de opciones en la pregunta
|
||||||
|
await this.preguntaRepository.increment(
|
||||||
|
{ id_pregunta: preguntaId },
|
||||||
|
'contador_opcion',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
return savedOpcion;
|
||||||
}
|
}
|
||||||
|
|
||||||
update(id: number, updateOpcionDto: UpdateOpcionDto) {
|
async findAllByPregunta(preguntaId: number) {
|
||||||
return `This action updates a #${id} opcion`;
|
return this.preguntaOpcionRepository.find({
|
||||||
|
where: { pregunta: { id_pregunta: preguntaId } },
|
||||||
|
relations: ['opcion'],
|
||||||
|
order: { posicion: 'ASC' },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(id: number) {
|
async findOne(preguntaId: number, id: number) {
|
||||||
return `This action removes a #${id} opcion`;
|
const preguntaOpcion = await this.preguntaOpcionRepository.findOne({
|
||||||
|
where: {
|
||||||
|
pregunta: { id_pregunta: preguntaId },
|
||||||
|
opcion: { id_opcion: id },
|
||||||
|
},
|
||||||
|
relations: ['opcion'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!preguntaOpcion) {
|
||||||
|
throw new NotFoundException('Opción no encontrada para esta pregunta');
|
||||||
|
}
|
||||||
|
|
||||||
|
return preguntaOpcion.opcion;
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
preguntaId: number,
|
||||||
|
id: number,
|
||||||
|
updateOpcionDto: UpdateOpcionDto
|
||||||
|
) {
|
||||||
|
// Verificar que la relación exista
|
||||||
|
const preguntaOpcion = await this.preguntaOpcionRepository.findOne({
|
||||||
|
where: {
|
||||||
|
pregunta: { id_pregunta: preguntaId },
|
||||||
|
opcion: { id_opcion: id },
|
||||||
|
},
|
||||||
|
relations: ['opcion'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!preguntaOpcion) {
|
||||||
|
throw new NotFoundException('Opción no encontrada para esta pregunta');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizar posición si se proporciona
|
||||||
|
if (updateOpcionDto.posicion !== undefined) {
|
||||||
|
await this.preguntaOpcionRepository.update(
|
||||||
|
{ id_pregunta_opcion: preguntaOpcion.id_pregunta_opcion },
|
||||||
|
{ posicion: updateOpcionDto.posicion }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizar texto de la opción
|
||||||
|
if (updateOpcionDto.opcion) {
|
||||||
|
await this.opcionRepository.update(
|
||||||
|
{ id_opcion: id },
|
||||||
|
{ opcion: updateOpcionDto.opcion }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.findOne(preguntaId, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(preguntaId: number, id: number) {
|
||||||
|
// Verificar que la relación exista
|
||||||
|
const preguntaOpcion = await this.preguntaOpcionRepository.findOne({
|
||||||
|
where: {
|
||||||
|
pregunta: { id_pregunta: preguntaId },
|
||||||
|
opcion: { id_opcion: id },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!preguntaOpcion) {
|
||||||
|
throw new NotFoundException('Opción no encontrada para esta pregunta');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eliminar la relación primero
|
||||||
|
await this.preguntaOpcionRepository.remove(preguntaOpcion);
|
||||||
|
|
||||||
|
// Eliminar la opción (si no está siendo usada en otras preguntas)
|
||||||
|
const count = await this.preguntaOpcionRepository.count({
|
||||||
|
where: { opcion: { id_opcion: id } },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (count === 0) {
|
||||||
|
await this.opcionRepository.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizar el contador de opciones en la pregunta
|
||||||
|
await this.preguntaRepository.decrement(
|
||||||
|
{ id_pregunta: preguntaId },
|
||||||
|
'contador_opcion',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
return { message: 'Opción eliminada correctamente' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { CuestionarioRespondido } from "src/cuestionario_respondido/entities/cuestionario_respondido.entity";
|
||||||
import { ParticipanteEvento } from "src/participante_evento/participante_evento.entity";
|
import { ParticipanteEvento } from "src/participante_evento/participante_evento.entity";
|
||||||
import { TipoUser } from "src/tipo_user/tipo_user.entity";
|
import { TipoUser } from "src/tipo_user/tipo_user.entity";
|
||||||
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||||
@@ -13,6 +14,10 @@ export class Participante {
|
|||||||
@Column()
|
@Column()
|
||||||
id_tipo_user: number
|
id_tipo_user: number
|
||||||
|
|
||||||
|
|
||||||
|
@OneToMany(() => CuestionarioRespondido, cuestionarioRespondido => cuestionarioRespondido.participante )
|
||||||
|
cuestionarioRespondidos:CuestionarioRespondido[];
|
||||||
|
|
||||||
//Relacion con tipo usuario
|
//Relacion con tipo usuario
|
||||||
@ManyToOne(() => TipoUser, tipoUser => tipoUser.participante)
|
@ManyToOne(() => TipoUser, tipoUser => tipoUser.participante)
|
||||||
@JoinColumn({ name: 'participante_id' }) //nombre de la relacion
|
@JoinColumn({ name: 'participante_id' }) //nombre de la relacion
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ import { Participante } from './participante.entity';
|
|||||||
imports: [TypeOrmModule.forFeature([Participante])],
|
imports: [TypeOrmModule.forFeature([Participante])],
|
||||||
controllers: [ParticipanteController],
|
controllers: [ParticipanteController],
|
||||||
providers: [ParticipanteService],
|
providers: [ParticipanteService],
|
||||||
exports: [ParticipanteService],
|
exports: [ParticipanteService, TypeOrmModule],
|
||||||
})
|
})
|
||||||
export class ParticipanteModule {}
|
export class ParticipanteModule {}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
import { Participante } from './participante.entity';
|
import { Participante } from './participante.entity';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { CreateParticipanteDto } from './dto/create-participante.dto';
|
import { CreateParticipanteDto } from './dto/create-participante.dto';
|
||||||
import { UpdateAdminDto } from 'src/admin/dto/update.admin.dto';
|
|
||||||
import { UpdateParticipanteDto } from './dto/update.participante.dto';
|
import { UpdateParticipanteDto } from './dto/update.participante.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { Evento } from 'src/evento/evento.entity';
|
|||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([ParticipanteEvento]), Evento],
|
imports: [TypeOrmModule.forFeature([ParticipanteEvento]), Evento],
|
||||||
controllers: [ParticipanteEventoController],
|
controllers: [ParticipanteEventoController],
|
||||||
providers: [ParticipanteEventoService]
|
providers: [ParticipanteEventoService],
|
||||||
|
exports:[TypeOrmModule,ParticipanteEventoService]
|
||||||
})
|
})
|
||||||
export class ParticipanteEventoModule {}
|
export class ParticipanteEventoModule {}
|
||||||
|
|||||||
@@ -1 +1,23 @@
|
|||||||
export class CreatePreguntaDto {}
|
import { IsNotEmpty, IsString, IsBoolean, IsNumber, IsOptional, IsArray, ValidateNested } from 'class-validator';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
import { CreateOpcionDto } from '../../opcion/dto/create-opcion.dto';
|
||||||
|
|
||||||
|
export class CreatePreguntaDto {
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
pregunta: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
obligatoria?: boolean;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsNumber()
|
||||||
|
id_tipo_pregunta: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => CreateOpcionDto)
|
||||||
|
opciones?: CreateOpcionDto[];
|
||||||
|
}
|
||||||
@@ -1,4 +1,15 @@
|
|||||||
import { PartialType } from '@nestjs/mapped-types';
|
import { IsOptional, IsString, IsBoolean, IsNumber } from 'class-validator';
|
||||||
import { CreatePreguntaDto } from './create-pregunta.dto';
|
|
||||||
|
|
||||||
export class UpdatePreguntaDto extends PartialType(CreatePreguntaDto) {}
|
export class UpdatePreguntaDto {
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
pregunta?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
obligatoria?: boolean;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
id_tipo_pregunta?: number;
|
||||||
|
}
|
||||||
@@ -1,33 +1,38 @@
|
|||||||
import { PreguntaOpcion } from 'src/pregunta_opcion/entities/pregunta_opcion.entity';
|
import { PreguntaOpcion } from 'src/pregunta_opcion/entities/pregunta_opcion.entity';
|
||||||
|
import { RespuestaParticipanteAbierta } from 'src/respuesta_participante_abierta/entities/respuesta_participante_abierta.entity';
|
||||||
import { SeccionPregunta } from 'src/seccion_pregunta/entities/seccion_pregunta.entity';
|
import { SeccionPregunta } from 'src/seccion_pregunta/entities/seccion_pregunta.entity';
|
||||||
import { TipoPregunta } from 'src/tipo_pregunta/entities/tipo_pregunta.entity';
|
import { TipoPregunta } from 'src/tipo_pregunta/entities/tipo_pregunta.entity';
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColumn } from 'typeorm';
|
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColumn } from 'typeorm';
|
||||||
|
|
||||||
|
|
||||||
@Entity()
|
@Entity('pregunta')
|
||||||
export class Pregunta {
|
export class Pregunta {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn({ name: 'id_pregunta' })
|
||||||
id_pregunta: number;
|
id_pregunta: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ type: 'text' })
|
||||||
pregunta: string;
|
pregunta: string;
|
||||||
|
|
||||||
@Column({ default: 0 })
|
@Column({ name: 'contador_opcion', default: 0 })
|
||||||
contador_opcion: number;
|
contador_opcion: number;
|
||||||
|
|
||||||
@Column({ default: false })
|
@Column({ default: false })
|
||||||
obligatoria: boolean;
|
obligatoria: boolean;
|
||||||
|
|
||||||
@ManyToOne(() => TipoPregunta, tipo => tipo.preguntas)
|
// Relación con TipoPregunta
|
||||||
|
@ManyToOne(() => TipoPregunta, tipoPregunta => tipoPregunta.preguntas)
|
||||||
@JoinColumn({ name: 'id_tipo_pregunta' })
|
@JoinColumn({ name: 'id_tipo_pregunta' })
|
||||||
id_tipo_pregunta: TipoPregunta;
|
tipo_pregunta: TipoPregunta;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
// Relación con PreguntaOpcion (tabla intermedia para opciones)
|
||||||
id_opcion_dependiente: number;
|
@OneToMany(() => PreguntaOpcion, preguntaOpcion => preguntaOpcion.pregunta)
|
||||||
|
|
||||||
@OneToMany(() => SeccionPregunta, seccionPregunta => seccionPregunta.id_pregunta)
|
|
||||||
seccionPreguntas: SeccionPregunta[];
|
|
||||||
|
|
||||||
@OneToMany(() => PreguntaOpcion, preguntaOpcion => preguntaOpcion.id_pregunta)
|
|
||||||
opciones: PreguntaOpcion[];
|
opciones: PreguntaOpcion[];
|
||||||
|
|
||||||
|
// Relación con SeccionPregunta (tabla intermedia para secciones)
|
||||||
|
@OneToMany(() => SeccionPregunta, seccionPregunta => seccionPregunta.pregunta)
|
||||||
|
seccionesPregunta: SeccionPregunta[];
|
||||||
|
|
||||||
|
// Relación con RespuestasAbiertas
|
||||||
|
@OneToMany(() => RespuestaParticipanteAbierta, respuestaAbierta => respuestaAbierta.pregunta)
|
||||||
|
respuestasAbiertas: RespuestaParticipanteAbierta[];
|
||||||
}
|
}
|
||||||
@@ -1,34 +1,110 @@
|
|||||||
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
|
import {
|
||||||
|
Controller,
|
||||||
|
Post,
|
||||||
|
Body,
|
||||||
|
Get,
|
||||||
|
Param,
|
||||||
|
Put,
|
||||||
|
Delete,
|
||||||
|
HttpStatus,
|
||||||
|
HttpException,
|
||||||
|
Query
|
||||||
|
} from '@nestjs/common';
|
||||||
import { PreguntaService } from './pregunta.service';
|
import { PreguntaService } from './pregunta.service';
|
||||||
|
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from '@nestjs/swagger';
|
||||||
import { CreatePreguntaDto } from './dto/create-pregunta.dto';
|
import { CreatePreguntaDto } from './dto/create-pregunta.dto';
|
||||||
import { UpdatePreguntaDto } from './dto/update-pregunta.dto';
|
import { UpdatePreguntaDto } from './dto/update-pregunta.dto';
|
||||||
|
|
||||||
@Controller('pregunta')
|
@ApiTags('Preguntas')
|
||||||
|
@Controller('preguntas')
|
||||||
export class PreguntaController {
|
export class PreguntaController {
|
||||||
constructor(private readonly preguntaService: PreguntaService) {}
|
constructor(private readonly preguntaService: PreguntaService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
create(@Body() createPreguntaDto: CreatePreguntaDto) {
|
@ApiOperation({ summary: 'Crear una nueva pregunta' })
|
||||||
return this.preguntaService.create(createPreguntaDto);
|
@ApiResponse({ status: 201, description: 'Pregunta creada exitosamente' })
|
||||||
|
@ApiResponse({ status: 400, description: 'Datos de entrada inválidos' })
|
||||||
|
@ApiResponse({ status: 404, description: 'Tipo de pregunta no encontrado' })
|
||||||
|
async create(@Body() createPreguntaDto: CreatePreguntaDto) {
|
||||||
|
try {
|
||||||
|
return await this.preguntaService.create(createPreguntaDto);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException({
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
}, HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
findAll() {
|
@ApiOperation({ summary: 'Obtener todas las preguntas' })
|
||||||
|
@ApiQuery({ name: 'tipo', required: false, description: 'Filtrar por tipo de pregunta' })
|
||||||
|
@ApiResponse({ status: 200, description: 'Lista de preguntas' })
|
||||||
|
async findAll(@Query('tipo') tipoPreguntaId?: number) {
|
||||||
|
if (tipoPreguntaId) {
|
||||||
|
return this.preguntaService.findAllByTipo(tipoPreguntaId);
|
||||||
|
}
|
||||||
return this.preguntaService.findAll();
|
return this.preguntaService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findOne(@Param('id') id: string) {
|
@ApiOperation({ summary: 'Obtener una pregunta específica' })
|
||||||
return this.preguntaService.findOne(+id);
|
@ApiParam({ name: 'id', description: 'ID de la pregunta' })
|
||||||
|
@ApiResponse({ status: 200, description: 'Pregunta encontrada' })
|
||||||
|
@ApiResponse({ status: 404, description: 'Pregunta no encontrada' })
|
||||||
|
async findOne(@Param('id') id: string) {
|
||||||
|
const pregunta = await this.preguntaService.findOneWithRelations(+id);
|
||||||
|
if (!pregunta) {
|
||||||
|
throw new HttpException('Pregunta no encontrada', HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
return pregunta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Put(':id')
|
||||||
update(@Param('id') id: string, @Body() updatePreguntaDto: UpdatePreguntaDto) {
|
@ApiOperation({ summary: 'Actualizar una pregunta' })
|
||||||
return this.preguntaService.update(+id, updatePreguntaDto);
|
@ApiParam({ name: 'id', description: 'ID de la pregunta a actualizar' })
|
||||||
|
@ApiResponse({ status: 200, description: 'Pregunta actualizada' })
|
||||||
|
@ApiResponse({ status: 404, description: 'Pregunta no encontrada' })
|
||||||
|
async update(
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Body() updatePreguntaDto: UpdatePreguntaDto,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
return await this.preguntaService.update(+id, updatePreguntaDto);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException({
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
}, HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
remove(@Param('id') id: string) {
|
@ApiOperation({ summary: 'Eliminar una pregunta' })
|
||||||
return this.preguntaService.remove(+id);
|
@ApiParam({ name: 'id', description: 'ID de la pregunta a eliminar' })
|
||||||
|
@ApiResponse({ status: 200, description: 'Pregunta eliminada' })
|
||||||
|
@ApiResponse({ status: 404, description: 'Pregunta no encontrada' })
|
||||||
|
async remove(@Param('id') id: string) {
|
||||||
|
try {
|
||||||
|
return await this.preguntaService.remove(+id);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException({
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
}, HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id/opciones')
|
||||||
|
@ApiOperation({ summary: 'Obtener opciones de una pregunta' })
|
||||||
|
@ApiParam({ name: 'id', description: 'ID de la pregunta' })
|
||||||
|
@ApiResponse({ status: 200, description: 'Opciones de la pregunta' })
|
||||||
|
@ApiResponse({ status: 404, description: 'Pregunta no encontrada' })
|
||||||
|
async getOpciones(@Param('id') id: string) {
|
||||||
|
const pregunta = await this.preguntaService.findOneWithRelations(+id);
|
||||||
|
if (!pregunta) {
|
||||||
|
throw new HttpException('Pregunta no encontrada', HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
return pregunta.opciones;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,20 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module, forwardRef } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { Pregunta } from './entities/pregunta.entity';
|
||||||
import { PreguntaService } from './pregunta.service';
|
import { PreguntaService } from './pregunta.service';
|
||||||
import { PreguntaController } from './pregunta.controller';
|
import { PreguntaController } from './pregunta.controller';
|
||||||
|
import { OpcionModule } from '../opcion/opcion.module';
|
||||||
|
import { PreguntaOpcion } from '../pregunta_opcion/entities/pregunta_opcion.entity';
|
||||||
|
import { TipoPreguntaModule } from '../tipo_pregunta/tipo_pregunta.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([Pregunta, PreguntaOpcion]),
|
||||||
|
forwardRef(() => OpcionModule),
|
||||||
|
TipoPreguntaModule,
|
||||||
|
],
|
||||||
controllers: [PreguntaController],
|
controllers: [PreguntaController],
|
||||||
providers: [PreguntaService],
|
providers: [PreguntaService],
|
||||||
|
exports: [PreguntaService],
|
||||||
})
|
})
|
||||||
export class PreguntaModule {}
|
export class PreguntaModule {}
|
||||||
@@ -1,26 +1,157 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
import { Pregunta } from './entities/pregunta.entity';
|
||||||
|
import { OpcionService } from '../opcion/opcion.service';
|
||||||
import { CreatePreguntaDto } from './dto/create-pregunta.dto';
|
import { CreatePreguntaDto } from './dto/create-pregunta.dto';
|
||||||
import { UpdatePreguntaDto } from './dto/update-pregunta.dto';
|
import { CreateOpcionDto } from '../opcion/dto/create-opcion.dto';
|
||||||
|
import { TipoPregunta } from 'src/tipo_pregunta/entities/tipo_pregunta.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PreguntaService {
|
export class PreguntaService {
|
||||||
create(createPreguntaDto: CreatePreguntaDto) {
|
|
||||||
return 'This action adds a new pregunta';
|
constructor(
|
||||||
|
@InjectRepository(Pregunta)
|
||||||
|
private readonly preguntaRepository: Repository<Pregunta>,
|
||||||
|
@InjectRepository(TipoPregunta)
|
||||||
|
private readonly tipoPreguntaRepository: Repository<TipoPregunta>,
|
||||||
|
private readonly opcionService: OpcionService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async create(createPreguntaDto: CreatePreguntaDto) {
|
||||||
|
// Verificar que el tipo de pregunta exista
|
||||||
|
|
||||||
|
//Se espera que solo exista el ripo de pregunta abierta y cerrada
|
||||||
|
const tipoPregunta = await this.tipoPreguntaRepository.findOne({
|
||||||
|
where: { id_tipo: createPreguntaDto.id_tipo_pregunta },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!tipoPregunta) {
|
||||||
|
throw new NotFoundException(
|
||||||
|
`Tipo de pregunta con ID ${createPreguntaDto.id_tipo_pregunta} no encontrado`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear la pregunta base
|
||||||
|
const pregunta = this.preguntaRepository.create({
|
||||||
|
pregunta: createPreguntaDto.pregunta,
|
||||||
|
obligatoria: createPreguntaDto.obligatoria || false,
|
||||||
|
tipo_pregunta: tipoPregunta,
|
||||||
|
});
|
||||||
|
|
||||||
|
const preguntaGuardada = await this.preguntaRepository.save(pregunta);
|
||||||
|
|
||||||
|
// Si es pregunta cerrada y tiene opciones, crearlas
|
||||||
|
if (
|
||||||
|
tipoPregunta.tipo_pregunta === 'Cerrada' &&
|
||||||
|
createPreguntaDto.opciones &&
|
||||||
|
createPreguntaDto.opciones.length > 0
|
||||||
|
) {
|
||||||
|
await this.agregarOpcionesAPregunta(
|
||||||
|
preguntaGuardada.id_pregunta,
|
||||||
|
createPreguntaDto.opciones,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Actualizar el contador de opciones
|
||||||
|
await this.preguntaRepository.update(
|
||||||
|
{ id_pregunta: preguntaGuardada.id_pregunta },
|
||||||
|
{ contador_opcion: createPreguntaDto.opciones.length },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.findOneWithRelations(preguntaGuardada.id_pregunta);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async agregarOpcionesAPregunta(
|
||||||
|
preguntaId: number,
|
||||||
|
opciones: CreateOpcionDto[],
|
||||||
|
) {
|
||||||
|
for (const opcionDto of opciones) {
|
||||||
|
await this.opcionService.create(preguntaId, opcionDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOneWithRelations(id: number) {
|
||||||
|
return this.preguntaRepository.findOne({
|
||||||
|
where: { id_pregunta: id },
|
||||||
|
relations: [
|
||||||
|
'tipo_pregunta',
|
||||||
|
'opciones',
|
||||||
|
'opciones.opcion',
|
||||||
|
'seccionesPregunta',
|
||||||
|
'seccionesPregunta.seccion',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAllByTipo(tipoPreguntaId: number) {
|
||||||
|
return this.preguntaRepository.find({
|
||||||
|
where: { tipo_pregunta: { id_tipo: tipoPreguntaId } },
|
||||||
|
relations: ['opciones', 'opciones.opcion'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(id: number) {
|
||||||
|
const pregunta = await this.preguntaRepository.findOne({
|
||||||
|
where: { id_pregunta: id },
|
||||||
|
relations: ['opciones'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pregunta) {
|
||||||
|
throw new NotFoundException(`Pregunta con ID ${id} no encontrada`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eliminar opciones primero si existen
|
||||||
|
if (pregunta.opciones && pregunta.opciones.length > 0) {
|
||||||
|
for (const opcion of pregunta.opciones) {
|
||||||
|
await this.opcionService.remove(id, opcion.id_pregunta_opcion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eliminar la pregunta
|
||||||
|
await this.preguntaRepository.delete(id);
|
||||||
|
|
||||||
|
return { message: 'Pregunta eliminada correctamente' };
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: number, updatePreguntaDto: any) {
|
||||||
|
const pregunta = await this.preguntaRepository.findOne({
|
||||||
|
where: { id_pregunta: id },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pregunta) {
|
||||||
|
throw new NotFoundException(`Pregunta con ID ${id} no encontrada`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizar campos básicos
|
||||||
|
if (updatePreguntaDto.pregunta !== undefined) {
|
||||||
|
pregunta.pregunta = updatePreguntaDto.pregunta;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatePreguntaDto.obligatoria !== undefined) {
|
||||||
|
pregunta.obligatoria = updatePreguntaDto.obligatoria;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si se cambia el tipo de pregunta
|
||||||
|
if (updatePreguntaDto.id_tipo_pregunta !== undefined) {
|
||||||
|
const tipoPregunta = await this.tipoPreguntaRepository.findOne({
|
||||||
|
where: { id_tipo: updatePreguntaDto.id_tipo_pregunta },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!tipoPregunta) {
|
||||||
|
throw new NotFoundException(
|
||||||
|
`Tipo de pregunta con ID ${updatePreguntaDto.id_tipo_pregunta} no encontrado`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pregunta.tipo_pregunta = tipoPregunta;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.preguntaRepository.save(pregunta);
|
||||||
}
|
}
|
||||||
|
|
||||||
findAll() {
|
findAll() {
|
||||||
return `This action returns all pregunta`;
|
return this.preguntaRepository.find();
|
||||||
}
|
}
|
||||||
|
|
||||||
findOne(id: number) {
|
|
||||||
return `This action returns a #${id} pregunta`;
|
|
||||||
}
|
|
||||||
|
|
||||||
update(id: number, updatePreguntaDto: UpdatePreguntaDto) {
|
|
||||||
return `This action updates a #${id} pregunta`;
|
|
||||||
}
|
|
||||||
|
|
||||||
remove(id: number) {
|
|
||||||
return `This action removes a #${id} pregunta`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,31 @@
|
|||||||
import { Opcion } from 'src/opcion/entities/opcion.entity';
|
import { Opcion } from 'src/opcion/entities/opcion.entity';
|
||||||
import { Pregunta } from 'src/pregunta/entities/pregunta.entity';
|
import { Pregunta } from 'src/pregunta/entities/pregunta.entity';
|
||||||
import { RespuestaParticipanteCerrada } from 'src/respuesta_participante_cerrada/entities/respuesta_participante_cerrada.entity';
|
import { RespuestaParticipanteCerrada } from 'src/respuesta_participante_cerrada/entities/respuesta_participante_cerrada.entity';
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany } from 'typeorm';
|
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColumn } from 'typeorm';
|
||||||
|
|
||||||
|
|
||||||
@Entity()
|
@Entity('pregunta_opcion')
|
||||||
export class PreguntaOpcion {
|
export class PreguntaOpcion {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn({ name: 'id_pregunta_opcion' })
|
||||||
id_pregunta_opcion: number;
|
id_pregunta_opcion: number;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
posicion: number;
|
posicion: number;
|
||||||
|
|
||||||
@ManyToOne(() => Pregunta, pregunta => pregunta.id_pregunta)
|
// Relación con Pregunta
|
||||||
@Column()
|
@ManyToOne(() => Pregunta, pregunta => pregunta.opciones)
|
||||||
id_pregunta: Pregunta;
|
@JoinColumn({ name: 'id_pregunta' })
|
||||||
|
pregunta: Pregunta;
|
||||||
|
|
||||||
@ManyToOne(() => Opcion, opcion => opcion.id_opcion)
|
// Relación con Opcion
|
||||||
@Column()
|
@ManyToOne(() => Opcion, opcion => opcion.Preguntas)
|
||||||
id_opcion: Opcion;
|
@JoinColumn({ name: 'id_opcion' })
|
||||||
|
opcion: Opcion;
|
||||||
|
|
||||||
@OneToMany(()=> RespuestaParticipanteCerrada, respuestaParticipanteCerrada=>respuestaParticipanteCerrada.id_pregunta_opcion)
|
// Nueva relación con RespuestaParticipanteCerrada
|
||||||
respuestaParticipanteCerrada:RespuestaParticipanteCerrada[];
|
@OneToMany(
|
||||||
|
() => RespuestaParticipanteCerrada,
|
||||||
|
respuestaCerrada => respuestaCerrada.preguntaOpcion
|
||||||
|
)
|
||||||
|
respuestasCerradas: RespuestaParticipanteCerrada[];
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { PreguntaOpcionService } from './pregunta_opcion.service';
|
import { PreguntaOpcionService } from './pregunta_opcion.service';
|
||||||
import { PreguntaOpcionController } from './pregunta_opcion.controller';
|
import { PreguntaOpcionController } from './pregunta_opcion.controller';
|
||||||
|
import { PreguntaOpcion } from './entities/pregunta_opcion.entity';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([PreguntaOpcion])],
|
||||||
controllers: [PreguntaOpcionController],
|
controllers: [PreguntaOpcionController],
|
||||||
providers: [PreguntaOpcionService],
|
providers: [PreguntaOpcionService],
|
||||||
|
exports:[PreguntaOpcionService, TypeOrmModule]
|
||||||
})
|
})
|
||||||
export class PreguntaOpcionModule {}
|
export class PreguntaOpcionModule {}
|
||||||
|
|||||||
+27
-11
@@ -2,29 +2,45 @@ import { CuestionarioRespondido } from 'src/cuestionario_respondido/entities/cue
|
|||||||
import { Pregunta } from 'src/pregunta/entities/pregunta.entity';
|
import { Pregunta } from 'src/pregunta/entities/pregunta.entity';
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
||||||
|
|
||||||
|
|
||||||
@Entity('respuesta_participante_abierta')
|
@Entity('respuesta_participante_abierta')
|
||||||
export class RespuestaParticipanteAbierta {
|
export class RespuestaParticipanteAbierta {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn({
|
||||||
idRespuestaParticipanteAbierta: number;
|
name: 'id_respuesta_participante_abierta',
|
||||||
|
type: 'integer'
|
||||||
|
})
|
||||||
|
id: number;
|
||||||
|
|
||||||
@Column({ type: 'text' })
|
@Column({
|
||||||
|
type: 'text',
|
||||||
|
nullable: false
|
||||||
|
})
|
||||||
respuesta: string;
|
respuesta: string;
|
||||||
|
|
||||||
// Relación con CuestionarioRespondido
|
// Relación con CuestionarioRespondido
|
||||||
@ManyToOne(
|
@ManyToOne(
|
||||||
() => CuestionarioRespondido,
|
() => CuestionarioRespondido,
|
||||||
cuestionarioRespondido => cuestionarioRespondido.idCuestionarioRespondido
|
(cuestionarioRespondido) => cuestionarioRespondido.respuestasAbiertas
|
||||||
)
|
)
|
||||||
@JoinColumn({ name: 'id_cuestionario_respondido' })
|
@JoinColumn({
|
||||||
id_cuestionario_respondido: CuestionarioRespondido;
|
name: 'id_cuestionario_respondido'
|
||||||
|
})
|
||||||
|
cuestionarioRespondido: CuestionarioRespondido;
|
||||||
|
|
||||||
|
// Relación con Pregunta
|
||||||
@ManyToOne(
|
@ManyToOne(
|
||||||
() => Pregunta,
|
() => Pregunta,
|
||||||
pregunta => pregunta.id_pregunta
|
(pregunta) => pregunta.respuestasAbiertas
|
||||||
)
|
)
|
||||||
@JoinColumn({ name: 'id_pregunta' })
|
@JoinColumn({
|
||||||
id_pregunta: Pregunta;
|
name: 'id_pregunta'
|
||||||
|
})
|
||||||
|
pregunta: Pregunta;
|
||||||
|
|
||||||
|
/* Campo adicional para tracking
|
||||||
|
@Column({
|
||||||
|
name: 'fecha_respuesta',
|
||||||
|
type: 'timestamp',
|
||||||
|
default: () => 'CURRENT_TIMESTAMP'
|
||||||
|
})
|
||||||
|
fechaRespuesta: Date;*/
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { RespuestaParticipanteAbiertaService } from './respuesta_participante_abierta.service';
|
import { RespuestaParticipanteAbiertaService } from './respuesta_participante_abierta.service';
|
||||||
import { RespuestaParticipanteAbiertaController } from './respuesta_participante_abierta.controller';
|
import { RespuestaParticipanteAbiertaController } from './respuesta_participante_abierta.controller';
|
||||||
|
import { RespuestaParticipanteAbierta } from './entities/respuesta_participante_abierta.entity';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([RespuestaParticipanteAbierta]),
|
||||||
|
],
|
||||||
controllers: [RespuestaParticipanteAbiertaController],
|
controllers: [RespuestaParticipanteAbiertaController],
|
||||||
providers: [RespuestaParticipanteAbiertaService],
|
providers: [RespuestaParticipanteAbiertaService],
|
||||||
|
exports: [RespuestaParticipanteAbiertaService, TypeOrmModule],
|
||||||
})
|
})
|
||||||
export class RespuestaParticipanteAbiertaModule {}
|
export class RespuestaParticipanteAbiertaModule {}
|
||||||
|
|||||||
+3
-3
@@ -10,11 +10,11 @@ export class RespuestaParticipanteCerrada {
|
|||||||
|
|
||||||
@ManyToOne(() => CuestionarioRespondido, cuestionarioRespondido => cuestionarioRespondido.respuestasCerradas)
|
@ManyToOne(() => CuestionarioRespondido, cuestionarioRespondido => cuestionarioRespondido.respuestasCerradas)
|
||||||
@JoinColumn({ name: 'id_cuestionario_respondido' })
|
@JoinColumn({ name: 'id_cuestionario_respondido' })
|
||||||
id_cuestionario_respondido: CuestionarioRespondido;
|
cuestionarioRespondido: CuestionarioRespondido;
|
||||||
|
|
||||||
@ManyToOne(() => PreguntaOpcion, preguntaOpcion => preguntaOpcion.id_pregunta_opcion)
|
@ManyToOne(() => PreguntaOpcion, preguntaOpcion => preguntaOpcion.respuestasCerradas)
|
||||||
@JoinColumn({ name: 'id_pregunta_opcion' })
|
@JoinColumn({ name: 'id_pregunta_opcion' })
|
||||||
id_pregunta_opcion: PreguntaOpcion;
|
preguntaOpcion: PreguntaOpcion;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { RespuestaParticipanteCerradaService } from './respuesta_participante_cerrada.service';
|
import { RespuestaParticipanteCerradaService } from './respuesta_participante_cerrada.service';
|
||||||
import { RespuestaParticipanteCerradaController } from './respuesta_participante_cerrada.controller';
|
import { RespuestaParticipanteCerradaController } from './respuesta_participante_cerrada.controller';
|
||||||
|
import { RespuestaParticipanteCerrada } from './entities/respuesta_participante_cerrada.entity';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([RespuestaParticipanteCerrada])],
|
||||||
controllers: [RespuestaParticipanteCerradaController],
|
controllers: [RespuestaParticipanteCerradaController],
|
||||||
providers: [RespuestaParticipanteCerradaService],
|
providers: [RespuestaParticipanteCerradaService],
|
||||||
|
exports:[RespuestaParticipanteCerradaService, TypeOrmModule]
|
||||||
})
|
})
|
||||||
export class RespuestaParticipanteCerradaModule {}
|
export class RespuestaParticipanteCerradaModule {}
|
||||||
|
|||||||
@@ -1 +1,30 @@
|
|||||||
export class CreateSeccionDto {}
|
import { IsNotEmpty, IsString, IsOptional, IsArray, ValidateNested, IsInt } from 'class-validator';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
import { CreatePreguntaDto } from '../../pregunta/dto/create-pregunta.dto';
|
||||||
|
|
||||||
|
export class CreateSeccionDto {
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
titulo: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
descripcion?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => PreguntaEnSeccionDto)
|
||||||
|
preguntas?: PreguntaEnSeccionDto[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PreguntaEnSeccionDto {
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsInt()
|
||||||
|
posicion: number;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => CreatePreguntaDto)
|
||||||
|
pregunta: CreatePreguntaDto;
|
||||||
|
}
|
||||||
@@ -16,9 +16,9 @@ export class Seccion {
|
|||||||
@Column({ type: 'text', nullable: true })
|
@Column({ type: 'text', nullable: true })
|
||||||
titulo: string;
|
titulo: string;
|
||||||
|
|
||||||
@OneToMany(() => CuestionarioSeccion,(cuestionario_seccion) => cuestionario_seccion.id_seccion )
|
@OneToMany(() => CuestionarioSeccion,(cuestionario_seccion) => cuestionario_seccion.seccion )
|
||||||
seccion:CuestionarioSeccion[];
|
cuestionarioSeccion:CuestionarioSeccion[];
|
||||||
|
|
||||||
@OneToMany(()=> SeccionPregunta, (seccion_pregunta)=> seccion_pregunta.id_seccion)
|
@OneToMany(()=> SeccionPregunta, (seccion_pregunta)=> seccion_pregunta.seccion)
|
||||||
seccion_pregunta:SeccionPregunta[];
|
seccion_pregunta:SeccionPregunta[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,166 @@
|
|||||||
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
|
import {
|
||||||
|
Controller,
|
||||||
|
Post,
|
||||||
|
Body,
|
||||||
|
Get,
|
||||||
|
Param,
|
||||||
|
Put,
|
||||||
|
Delete,
|
||||||
|
HttpStatus,
|
||||||
|
HttpException,
|
||||||
|
Query,
|
||||||
|
} from '@nestjs/common';
|
||||||
import { SeccionService } from './seccion.service';
|
import { SeccionService } from './seccion.service';
|
||||||
import { CreateSeccionDto } from './dto/create-seccion.dto';
|
import { CreateSeccionDto, PreguntaEnSeccionDto } from './dto/create-seccion.dto';
|
||||||
import { UpdateSeccionDto } from './dto/update-seccion.dto';
|
import { UpdateSeccionDto } from './dto/update-seccion.dto';
|
||||||
|
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';
|
||||||
|
|
||||||
@Controller('seccion')
|
@ApiTags('Secciones')
|
||||||
|
@Controller('secciones')
|
||||||
export class SeccionController {
|
export class SeccionController {
|
||||||
constructor(private readonly seccionService: SeccionService) {}
|
constructor(private readonly seccionService: SeccionService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
create(@Body() createSeccionDto: CreateSeccionDto) {
|
@ApiOperation({ summary: 'Crear una nueva sección con preguntas' })
|
||||||
return this.seccionService.create(createSeccionDto);
|
@ApiBody({ type: CreateSeccionDto })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.CREATED,
|
||||||
|
description: 'Sección creada exitosamente con sus preguntas'
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
description: 'Datos de entrada inválidos'
|
||||||
|
})
|
||||||
|
async create(@Body() createSeccionDto: CreateSeccionDto) {
|
||||||
|
try {
|
||||||
|
return await this.seccionService.create(createSeccionDto);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException({
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
}, HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
findAll() {
|
@ApiOperation({ summary: 'Obtener todas las secciones' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Lista de secciones obtenida exitosamente'
|
||||||
|
})
|
||||||
|
async findAll() {
|
||||||
return this.seccionService.findAll();
|
return this.seccionService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findOne(@Param('id') id: string) {
|
@ApiOperation({ summary: 'Obtener una sección específica con sus preguntas' })
|
||||||
return this.seccionService.findOne(+id);
|
@ApiParam({ name: 'id', description: 'ID de la sección' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Sección encontrada con todas sus relaciones'
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.NOT_FOUND,
|
||||||
|
description: 'Sección no encontrada'
|
||||||
|
})
|
||||||
|
async findOne(@Param('id') id: string) {
|
||||||
|
const seccion = await this.seccionService.findOneWithRelations(+id);
|
||||||
|
if (!seccion) {
|
||||||
|
throw new HttpException('Sección no encontrada', HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
return seccion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Put(':id')
|
||||||
update(@Param('id') id: string, @Body() updateSeccionDto: UpdateSeccionDto) {
|
@ApiOperation({ summary: 'Actualizar los metadatos de una sección' })
|
||||||
return this.seccionService.update(+id, updateSeccionDto);
|
@ApiParam({ name: 'id', description: 'ID de la sección a actualizar' })
|
||||||
|
@ApiBody({ type: UpdateSeccionDto })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Sección actualizada exitosamente'
|
||||||
|
})
|
||||||
|
async update(
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Body() updateSeccionDto: UpdateSeccionDto,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
return await this.seccionService.update(+id, updateSeccionDto);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException({
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
}, HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
remove(@Param('id') id: string) {
|
@ApiOperation({ summary: 'Eliminar una sección y sus relaciones' })
|
||||||
return this.seccionService.remove(+id);
|
@ApiParam({ name: 'id', description: 'ID de la sección a eliminar' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Sección eliminada exitosamente'
|
||||||
|
})
|
||||||
|
async remove(@Param('id') id: string) {
|
||||||
|
try {
|
||||||
|
return await this.seccionService.remove(+id);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException({
|
||||||
|
status: HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
}, HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post(':id/preguntas')
|
||||||
|
@ApiOperation({ summary: 'Agregar una nueva pregunta a la sección' })
|
||||||
|
@ApiParam({ name: 'id', description: 'ID de la sección' })
|
||||||
|
@ApiBody({ type: PreguntaEnSeccionDto })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.CREATED,
|
||||||
|
description: 'Pregunta agregada a la sección exitosamente'
|
||||||
|
})
|
||||||
|
async agregarPregunta(
|
||||||
|
@Param('id') seccionId: string,
|
||||||
|
@Body() preguntaDto: PreguntaEnSeccionDto,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
return await this.seccionService.agregarPreguntaExistente(
|
||||||
|
+seccionId,
|
||||||
|
preguntaDto.pregunta.id_tipo_pregunta,
|
||||||
|
preguntaDto.posicion,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException({
|
||||||
|
status: error.status || HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
}, error.status || HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':seccionId/preguntas/:preguntaId')
|
||||||
|
@ApiOperation({ summary: 'Remover una pregunta de la sección' })
|
||||||
|
@ApiParam({ name: 'seccionId', description: 'ID de la sección' })
|
||||||
|
@ApiParam({ name: 'preguntaId', description: 'ID de la pregunta a remover' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: 'Pregunta removida de la sección exitosamente'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
async removerPregunta(
|
||||||
|
@Param('seccionId') seccionId: string,
|
||||||
|
@Param('preguntaId') preguntaId: string,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
return await this.seccionService.eliminarPreguntaDeSeccion(
|
||||||
|
+seccionId,
|
||||||
|
+preguntaId,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException({
|
||||||
|
status: error.status || HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
}, error.status || HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module, forwardRef } from '@nestjs/common';
|
||||||
import { SeccionService } from './seccion.service';
|
import { SeccionService } from './seccion.service';
|
||||||
import { SeccionController } from './seccion.controller';
|
import { SeccionController } from './seccion.controller';
|
||||||
|
import { Seccion } from './entities/seccion.entity';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { SeccionPregunta } from '../seccion_pregunta/entities/seccion_pregunta.entity';
|
||||||
|
import { PreguntaModule } from '../pregunta/pregunta.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([Seccion, SeccionPregunta]),
|
||||||
|
forwardRef(() => PreguntaModule)
|
||||||
|
],
|
||||||
controllers: [SeccionController],
|
controllers: [SeccionController],
|
||||||
providers: [SeccionService],
|
providers: [SeccionService],
|
||||||
|
exports: [SeccionService],
|
||||||
})
|
})
|
||||||
export class SeccionModule {}
|
export class SeccionModule {}
|
||||||
+163
-12
@@ -1,26 +1,177 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||||
import { CreateSeccionDto } from './dto/create-seccion.dto';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { DeleteResult, Repository } from 'typeorm';
|
||||||
|
import { Seccion } from './entities/seccion.entity';
|
||||||
|
import { PreguntaService } from '../pregunta/pregunta.service';
|
||||||
|
import { CreateSeccionDto, PreguntaEnSeccionDto } from './dto/create-seccion.dto';
|
||||||
|
import { Pregunta } from '../pregunta/entities/pregunta.entity';
|
||||||
|
import { SeccionPregunta } from 'src/seccion_pregunta/entities/seccion_pregunta.entity';
|
||||||
import { UpdateSeccionDto } from './dto/update-seccion.dto';
|
import { UpdateSeccionDto } from './dto/update-seccion.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SeccionService {
|
export class SeccionService {
|
||||||
create(createSeccionDto: CreateSeccionDto) {
|
constructor(
|
||||||
return 'This action adds a new seccion';
|
@InjectRepository(Seccion)
|
||||||
|
private readonly seccionRepository: Repository<Seccion>,
|
||||||
|
@InjectRepository(SeccionPregunta)
|
||||||
|
private readonly seccionPreguntaRepository: Repository<SeccionPregunta>,
|
||||||
|
private readonly preguntaService: PreguntaService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async create(createSeccionDto: CreateSeccionDto) {
|
||||||
|
// Crear la sección base
|
||||||
|
const seccion = this.seccionRepository.create({
|
||||||
|
titulo: createSeccionDto.titulo,
|
||||||
|
descripcion: createSeccionDto.descripcion,
|
||||||
|
contador_pregunta: createSeccionDto.preguntas?.length || 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const seccionGuardada = await this.seccionRepository.save(seccion);
|
||||||
|
|
||||||
|
// Si hay preguntas, crearlas y asociarlas
|
||||||
|
if (createSeccionDto.preguntas && createSeccionDto.preguntas.length > 0) {
|
||||||
|
await this.agregarPreguntasASeccion(
|
||||||
|
seccionGuardada.id_seccion,
|
||||||
|
createSeccionDto.preguntas,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
findAll() {
|
return this.findOneWithRelations(seccionGuardada.id_seccion);
|
||||||
return `This action returns all seccion`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
findOne(id: number) {
|
private async agregarPreguntasASeccion(
|
||||||
return `This action returns a #${id} seccion`;
|
seccionId: number,
|
||||||
|
preguntas: PreguntaEnSeccionDto[], // Tipo actualizado
|
||||||
|
) {
|
||||||
|
for (const { posicion, pregunta } of preguntas) {
|
||||||
|
const preguntaCreada = await this.preguntaService.create(pregunta);
|
||||||
|
|
||||||
|
const seccionPregunta = this.seccionPreguntaRepository.create({
|
||||||
|
posicion,
|
||||||
|
seccion: { id_seccion: seccionId },
|
||||||
|
pregunta: { id_pregunta: preguntaCreada?.id_pregunta },
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.seccionPreguntaRepository.save(seccionPregunta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(id: number, updateSeccionDto: UpdateSeccionDto) {
|
async findOneWithRelations(id: number) {
|
||||||
return `This action updates a #${id} seccion`;
|
return this.seccionRepository.findOne({
|
||||||
|
where: { id_seccion: id },
|
||||||
|
relations: [
|
||||||
|
'seccionPreguntas',
|
||||||
|
'seccionPreguntas.pregunta',
|
||||||
|
'seccionPreguntas.pregunta.tipoPregunta',
|
||||||
|
'seccionPreguntas.pregunta.opciones',
|
||||||
|
'seccionPreguntas.pregunta.opciones.opcion',
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(id: number) {
|
async agregarPreguntaExistente(
|
||||||
return `This action removes a #${id} seccion`;
|
seccionId: number,
|
||||||
|
preguntaId: number,
|
||||||
|
posicion: number,
|
||||||
|
) {
|
||||||
|
// Verificar que existan ambos elementos
|
||||||
|
const seccion = await this.seccionRepository.findOne({
|
||||||
|
where: { id_seccion: seccionId },
|
||||||
|
});
|
||||||
|
if (!seccion) {
|
||||||
|
throw new NotFoundException(`Sección con ID ${seccionId} no encontrada`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pregunta = await this.preguntaService.findOneWithRelations(preguntaId);
|
||||||
|
if (!pregunta) {
|
||||||
|
throw new NotFoundException(`Pregunta con ID ${preguntaId} no encontrada`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear la relación
|
||||||
|
const seccionPregunta = this.seccionPreguntaRepository.create({
|
||||||
|
posicion,
|
||||||
|
seccion: { id_seccion: seccionId },
|
||||||
|
pregunta: { id_pregunta: preguntaId },
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.seccionPreguntaRepository.save(seccionPregunta);
|
||||||
|
|
||||||
|
// Actualizar contador de preguntas
|
||||||
|
await this.seccionRepository.increment(
|
||||||
|
{ id_seccion: seccionId },
|
||||||
|
'contador_pregunta',
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.findOneWithRelations(seccionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async eliminarPreguntaDeSeccion(seccionId: number, preguntaId: number) {
|
||||||
|
const relacion = await this.seccionPreguntaRepository.findOne({
|
||||||
|
where: {
|
||||||
|
seccion: { id_seccion: seccionId },
|
||||||
|
pregunta: { id_pregunta: preguntaId },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!relacion) {
|
||||||
|
throw new NotFoundException(
|
||||||
|
'La pregunta no está asociada a esta sección',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.seccionPreguntaRepository.remove(relacion);
|
||||||
|
|
||||||
|
// Actualizar contador de preguntas
|
||||||
|
await this.seccionRepository.decrement(
|
||||||
|
{ id_seccion: seccionId },
|
||||||
|
'contador_pregunta',
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAll(): Promise<Seccion[]> {
|
||||||
|
return this.seccionRepository.find({
|
||||||
|
relations: ['seccionPreguntas', 'seccionPreguntas.pregunta'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: number, updateSeccionDto: UpdateSeccionDto): Promise<Seccion> {
|
||||||
|
const seccion = await this.seccionRepository.findOne({
|
||||||
|
where: { id_seccion: id }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!seccion) {
|
||||||
|
throw new NotFoundException(`Sección con ID ${id} no encontrada`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateSeccionDto.titulo !== undefined) {
|
||||||
|
seccion.titulo = updateSeccionDto.titulo;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateSeccionDto.descripcion !== undefined) {
|
||||||
|
seccion.descripcion = updateSeccionDto.descripcion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.seccionRepository.save(seccion);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(id: number): Promise<DeleteResult> {
|
||||||
|
// Primero eliminamos las relaciones con preguntas (esto sigue siendo asíncrono)
|
||||||
|
this.seccionPreguntaRepository.delete({ seccion: { id_seccion: id } })
|
||||||
|
.catch(err => {
|
||||||
|
throw new Error(`Error al eliminar relaciones: ${err.message}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Eliminación sincrónica usando delete (devuelve DeleteResult directamente)
|
||||||
|
const result = this.seccionRepository.delete(id);
|
||||||
|
|
||||||
|
if ((await result).affected === 0) {
|
||||||
|
throw new NotFoundException(`Sección con ID ${id} no encontrada`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
import { Pregunta } from 'src/pregunta/entities/pregunta.entity';
|
import { Pregunta } from 'src/pregunta/entities/pregunta.entity';
|
||||||
import { Seccion } from 'src/seccion/entities/seccion.entity';
|
import { Seccion } from 'src/seccion/entities/seccion.entity';
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
|
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
@Entity('seccion_pregunta')
|
|
||||||
export class SeccionPregunta {
|
export class SeccionPregunta {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id_seccion_pregunta: number;
|
id_seccion_pregunta: number;
|
||||||
|
|
||||||
@Column({ type: 'tinyint' })
|
@Column()
|
||||||
posicion: number;
|
posicion: number;
|
||||||
|
|
||||||
@ManyToOne(() => Pregunta, (pregunta) => pregunta.id_pregunta)
|
@ManyToOne(() => Seccion, seccion => seccion.seccion_pregunta)
|
||||||
@Column({ type: 'int' })
|
@JoinColumn({name:'id_seccion'})
|
||||||
id_pregunta: number;
|
seccion: Seccion;
|
||||||
|
|
||||||
@ManyToOne(() => Seccion, (seccion) => seccion.id_seccion)
|
@ManyToOne(() => Pregunta, pregunta => pregunta.seccionesPregunta)
|
||||||
@Column({ type: 'int' })
|
@JoinColumn({name:'id_pregunta'})
|
||||||
id_seccion: number;
|
pregunta: Pregunta;
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { SeccionPreguntaService } from './seccion_pregunta.service';
|
import { SeccionPreguntaService } from './seccion_pregunta.service';
|
||||||
import { SeccionPreguntaController } from './seccion_pregunta.controller';
|
import { SeccionPreguntaController } from './seccion_pregunta.controller';
|
||||||
|
import { SeccionPregunta } from './entities/seccion_pregunta.entity';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([SeccionPregunta])],
|
||||||
controllers: [SeccionPreguntaController],
|
controllers: [SeccionPreguntaController],
|
||||||
providers: [SeccionPreguntaService],
|
providers: [SeccionPreguntaService],
|
||||||
|
exports:[SeccionPreguntaService, TypeOrmModule]
|
||||||
})
|
})
|
||||||
export class SeccionPreguntaModule {}
|
export class SeccionPreguntaModule {}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Cuestionario } from 'src/cuestionario/entities/cuestionario.entity';
|
import { Cuestionario } from 'src/cuestionario/entities/cuestionario.entity';
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, ManyToOne } from 'typeorm';
|
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, ManyToOne, OneToMany } from 'typeorm';
|
||||||
|
|
||||||
@Entity('tipo_cuestionario')
|
@Entity('tipo_cuestionario')
|
||||||
export class TipoCuestionario {
|
export class TipoCuestionario {
|
||||||
@@ -9,6 +9,6 @@ export class TipoCuestionario {
|
|||||||
@Column({ type: 'varchar', length: 30 })
|
@Column({ type: 'varchar', length: 30 })
|
||||||
tipo_cuestionario: string;
|
tipo_cuestionario: string;
|
||||||
|
|
||||||
@ManyToOne(()=> Cuestionario,(cuestionario)=> cuestionario.id_tipo_cuestionario)
|
@OneToMany(()=> Cuestionario,(cuestionario)=> cuestionario.tipo_cuestionario)
|
||||||
cuestionario:Cuestionario[];
|
cuestionarios:Cuestionario[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TipoCuestionarioService } from './tipo_cuestionario.service';
|
import { TipoCuestionarioService } from './tipo_cuestionario.service';
|
||||||
import { TipoCuestionarioController } from './tipo_cuestionario.controller';
|
import { TipoCuestionarioController } from './tipo_cuestionario.controller';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { TipoCuestionario } from './entities/tipo_cuestionario.entity';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([TipoCuestionario])],
|
||||||
controllers: [TipoCuestionarioController],
|
controllers: [TipoCuestionarioController],
|
||||||
providers: [TipoCuestionarioService],
|
providers: [TipoCuestionarioService],
|
||||||
|
exports:[TipoCuestionarioService, TypeOrmModule]
|
||||||
})
|
})
|
||||||
export class TipoCuestionarioModule {}
|
export class TipoCuestionarioModule {}
|
||||||
|
|||||||
@@ -1 +1,9 @@
|
|||||||
export class CreateTipoPreguntaDto {}
|
import { IsNotEmpty, IsString, MaxLength, MinLength } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateTipoPreguntaDto {
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
@MinLength(3)
|
||||||
|
@MaxLength(50)
|
||||||
|
tipo_pregunta: string;
|
||||||
|
}
|
||||||
@@ -9,6 +9,6 @@ export class TipoPregunta {
|
|||||||
@Column()
|
@Column()
|
||||||
tipo_pregunta: string;
|
tipo_pregunta: string;
|
||||||
|
|
||||||
@OneToMany(() => Pregunta, pregunta => pregunta.id_tipo_pregunta)
|
@OneToMany(() => Pregunta, pregunta => pregunta.tipo_pregunta)
|
||||||
preguntas: Pregunta[];
|
preguntas: Pregunta[];
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { Controller, Post, Body, HttpStatus, HttpException } from '@nestjs/common';
|
||||||
|
import { ApiTags, ApiOperation, ApiResponse, ApiBody } from '@nestjs/swagger';
|
||||||
|
import { CreateTipoPreguntaDto } from './dto/create-tipo_pregunta.dto';
|
||||||
|
import { TipoPreguntaService } from './tipo_pregunta.service';
|
||||||
|
|
||||||
|
@ApiTags('Tipos de Pregunta')
|
||||||
|
@Controller('tipos-pregunta')
|
||||||
|
export class TipoPreguntaController {
|
||||||
|
constructor(private readonly tipoPreguntaService: TipoPreguntaService) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
@ApiOperation({ summary: 'Crear un nuevo tipo de pregunta' })
|
||||||
|
@ApiBody({ type: CreateTipoPreguntaDto })
|
||||||
|
@ApiResponse({
|
||||||
|
status: 201,
|
||||||
|
description: 'Tipo de pregunta creado exitosamente'
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: 409,
|
||||||
|
description: 'El tipo de pregunta ya existe'
|
||||||
|
})
|
||||||
|
async create(@Body() createTipoPreguntaDto: CreateTipoPreguntaDto) {
|
||||||
|
try {
|
||||||
|
return await this.tipoPreguntaService.create(createTipoPreguntaDto);
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException({
|
||||||
|
status: error.status || HttpStatus.BAD_REQUEST,
|
||||||
|
error: error.message,
|
||||||
|
}, error.status || HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,16 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TipoPreguntaService } from './tipo_pregunta.service';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { TipoPregunta } from './entities/tipo_pregunta.entity';
|
||||||
import { TipoPreguntaController } from './tipo_pregunta.controller';
|
import { TipoPreguntaController } from './tipo_pregunta.controller';
|
||||||
|
import { TipoPreguntaService } from './tipo_pregunta.service';
|
||||||
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([TipoPregunta]),
|
||||||
|
],
|
||||||
controllers: [TipoPreguntaController],
|
controllers: [TipoPreguntaController],
|
||||||
providers: [TipoPreguntaService],
|
providers: [TipoPreguntaService],
|
||||||
|
exports: [TipoPreguntaService, TypeOrmModule],
|
||||||
})
|
})
|
||||||
export class TipoPreguntaModule {}
|
export class TipoPreguntaModule {}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { Injectable, ConflictException } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
import { TipoPregunta } from './entities/tipo_pregunta.entity';
|
||||||
|
import { CreateTipoPreguntaDto } from './dto/create-tipo_pregunta.dto';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TipoPreguntaService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(TipoPregunta)
|
||||||
|
private readonly tipoPreguntaRepository: Repository<TipoPregunta>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
|
||||||
|
async create(createTipoPreguntaDto: CreateTipoPreguntaDto): Promise<TipoPregunta> {
|
||||||
|
// Verificar si ya existe un tipo con el mismo nombre
|
||||||
|
const tipoExistente = await this.tipoPreguntaRepository.findOne({
|
||||||
|
where: { tipo_pregunta: createTipoPreguntaDto.tipo_pregunta },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (tipoExistente) {
|
||||||
|
throw new ConflictException(
|
||||||
|
`El tipo de pregunta '${createTipoPreguntaDto.tipo_pregunta}' ya existe`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear y guardar el nuevo tipo
|
||||||
|
const nuevoTipo = this.tipoPreguntaRepository.create({
|
||||||
|
tipo_pregunta: createTipoPreguntaDto.tipo_pregunta,
|
||||||
|
});
|
||||||
|
|
||||||
|
return await this.tipoPreguntaRepository.save(nuevoTipo);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user