Test Docker
This commit is contained in:
		
							
								
								
									
										752
									
								
								Elecciones-Web/frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										752
									
								
								Elecciones-Web/frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -9,11 +9,14 @@ | ||||
|       "version": "0.0.0", | ||||
|       "dependencies": { | ||||
|         "axios": "^1.11.0", | ||||
|         "d3": "^7.9.0", | ||||
|         "react": "^19.1.1", | ||||
|         "react-dom": "^19.1.1" | ||||
|       }, | ||||
|       "devDependencies": { | ||||
|         "@eslint/js": "^9.33.0", | ||||
|         "@types/d3": "^7.4.3", | ||||
|         "@types/geojson": "^7946.0.16", | ||||
|         "@types/react": "^19.1.10", | ||||
|         "@types/react-dom": "^19.1.7", | ||||
|         "@vitejs/plugin-react": "^5.0.0", | ||||
| @@ -1393,6 +1396,290 @@ | ||||
|         "@babel/types": "^7.28.2" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3": { | ||||
|       "version": "7.4.3", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", | ||||
|       "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-array": "*", | ||||
|         "@types/d3-axis": "*", | ||||
|         "@types/d3-brush": "*", | ||||
|         "@types/d3-chord": "*", | ||||
|         "@types/d3-color": "*", | ||||
|         "@types/d3-contour": "*", | ||||
|         "@types/d3-delaunay": "*", | ||||
|         "@types/d3-dispatch": "*", | ||||
|         "@types/d3-drag": "*", | ||||
|         "@types/d3-dsv": "*", | ||||
|         "@types/d3-ease": "*", | ||||
|         "@types/d3-fetch": "*", | ||||
|         "@types/d3-force": "*", | ||||
|         "@types/d3-format": "*", | ||||
|         "@types/d3-geo": "*", | ||||
|         "@types/d3-hierarchy": "*", | ||||
|         "@types/d3-interpolate": "*", | ||||
|         "@types/d3-path": "*", | ||||
|         "@types/d3-polygon": "*", | ||||
|         "@types/d3-quadtree": "*", | ||||
|         "@types/d3-random": "*", | ||||
|         "@types/d3-scale": "*", | ||||
|         "@types/d3-scale-chromatic": "*", | ||||
|         "@types/d3-selection": "*", | ||||
|         "@types/d3-shape": "*", | ||||
|         "@types/d3-time": "*", | ||||
|         "@types/d3-time-format": "*", | ||||
|         "@types/d3-timer": "*", | ||||
|         "@types/d3-transition": "*", | ||||
|         "@types/d3-zoom": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-array": { | ||||
|       "version": "3.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", | ||||
|       "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-axis": { | ||||
|       "version": "3.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", | ||||
|       "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-selection": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-brush": { | ||||
|       "version": "3.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", | ||||
|       "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-selection": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-chord": { | ||||
|       "version": "3.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", | ||||
|       "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-color": { | ||||
|       "version": "3.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", | ||||
|       "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-contour": { | ||||
|       "version": "3.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", | ||||
|       "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-array": "*", | ||||
|         "@types/geojson": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-delaunay": { | ||||
|       "version": "6.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", | ||||
|       "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-dispatch": { | ||||
|       "version": "3.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", | ||||
|       "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-drag": { | ||||
|       "version": "3.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", | ||||
|       "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-selection": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-dsv": { | ||||
|       "version": "3.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", | ||||
|       "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-ease": { | ||||
|       "version": "3.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", | ||||
|       "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-fetch": { | ||||
|       "version": "3.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", | ||||
|       "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-dsv": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-force": { | ||||
|       "version": "3.0.10", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", | ||||
|       "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-format": { | ||||
|       "version": "3.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", | ||||
|       "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-geo": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", | ||||
|       "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/geojson": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-hierarchy": { | ||||
|       "version": "3.1.7", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", | ||||
|       "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-interpolate": { | ||||
|       "version": "3.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", | ||||
|       "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-color": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-path": { | ||||
|       "version": "3.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", | ||||
|       "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-polygon": { | ||||
|       "version": "3.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", | ||||
|       "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-quadtree": { | ||||
|       "version": "3.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", | ||||
|       "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-random": { | ||||
|       "version": "3.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", | ||||
|       "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-scale": { | ||||
|       "version": "4.0.9", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", | ||||
|       "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-time": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-scale-chromatic": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", | ||||
|       "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-selection": { | ||||
|       "version": "3.0.11", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", | ||||
|       "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-shape": { | ||||
|       "version": "3.1.7", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", | ||||
|       "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-path": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-time": { | ||||
|       "version": "3.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", | ||||
|       "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-time-format": { | ||||
|       "version": "4.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", | ||||
|       "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-timer": { | ||||
|       "version": "3.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", | ||||
|       "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3-transition": { | ||||
|       "version": "3.0.9", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", | ||||
|       "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-selection": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/d3-zoom": { | ||||
|       "version": "3.0.8", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", | ||||
|       "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/d3-interpolate": "*", | ||||
|         "@types/d3-selection": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/estree": { | ||||
|       "version": "1.0.8", | ||||
|       "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", | ||||
| @@ -1400,6 +1687,13 @@ | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/geojson": { | ||||
|       "version": "7946.0.16", | ||||
|       "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", | ||||
|       "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/json-schema": { | ||||
|       "version": "7.0.15", | ||||
|       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", | ||||
| @@ -1956,6 +2250,15 @@ | ||||
|         "node": ">= 0.8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/commander": { | ||||
|       "version": "7.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", | ||||
|       "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/concat-map": { | ||||
|       "version": "0.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", | ||||
| @@ -1992,6 +2295,407 @@ | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/d3": { | ||||
|       "version": "7.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", | ||||
|       "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-array": "3", | ||||
|         "d3-axis": "3", | ||||
|         "d3-brush": "3", | ||||
|         "d3-chord": "3", | ||||
|         "d3-color": "3", | ||||
|         "d3-contour": "4", | ||||
|         "d3-delaunay": "6", | ||||
|         "d3-dispatch": "3", | ||||
|         "d3-drag": "3", | ||||
|         "d3-dsv": "3", | ||||
|         "d3-ease": "3", | ||||
|         "d3-fetch": "3", | ||||
|         "d3-force": "3", | ||||
|         "d3-format": "3", | ||||
|         "d3-geo": "3", | ||||
|         "d3-hierarchy": "3", | ||||
|         "d3-interpolate": "3", | ||||
|         "d3-path": "3", | ||||
|         "d3-polygon": "3", | ||||
|         "d3-quadtree": "3", | ||||
|         "d3-random": "3", | ||||
|         "d3-scale": "4", | ||||
|         "d3-scale-chromatic": "3", | ||||
|         "d3-selection": "3", | ||||
|         "d3-shape": "3", | ||||
|         "d3-time": "3", | ||||
|         "d3-time-format": "4", | ||||
|         "d3-timer": "3", | ||||
|         "d3-transition": "3", | ||||
|         "d3-zoom": "3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-array": { | ||||
|       "version": "3.2.4", | ||||
|       "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", | ||||
|       "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "internmap": "1 - 2" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-axis": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", | ||||
|       "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-brush": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", | ||||
|       "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-dispatch": "1 - 3", | ||||
|         "d3-drag": "2 - 3", | ||||
|         "d3-interpolate": "1 - 3", | ||||
|         "d3-selection": "3", | ||||
|         "d3-transition": "3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-chord": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", | ||||
|       "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-path": "1 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-color": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", | ||||
|       "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-contour": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", | ||||
|       "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-array": "^3.2.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-delaunay": { | ||||
|       "version": "6.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", | ||||
|       "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "delaunator": "5" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-dispatch": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", | ||||
|       "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-drag": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", | ||||
|       "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-dispatch": "1 - 3", | ||||
|         "d3-selection": "3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-dsv": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", | ||||
|       "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "commander": "7", | ||||
|         "iconv-lite": "0.6", | ||||
|         "rw": "1" | ||||
|       }, | ||||
|       "bin": { | ||||
|         "csv2json": "bin/dsv2json.js", | ||||
|         "csv2tsv": "bin/dsv2dsv.js", | ||||
|         "dsv2dsv": "bin/dsv2dsv.js", | ||||
|         "dsv2json": "bin/dsv2json.js", | ||||
|         "json2csv": "bin/json2dsv.js", | ||||
|         "json2dsv": "bin/json2dsv.js", | ||||
|         "json2tsv": "bin/json2dsv.js", | ||||
|         "tsv2csv": "bin/dsv2dsv.js", | ||||
|         "tsv2json": "bin/dsv2json.js" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-ease": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", | ||||
|       "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", | ||||
|       "license": "BSD-3-Clause", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-fetch": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", | ||||
|       "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-dsv": "1 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-force": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", | ||||
|       "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-dispatch": "1 - 3", | ||||
|         "d3-quadtree": "1 - 3", | ||||
|         "d3-timer": "1 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-format": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", | ||||
|       "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-geo": { | ||||
|       "version": "3.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", | ||||
|       "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-array": "2.5.0 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-hierarchy": { | ||||
|       "version": "3.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", | ||||
|       "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-interpolate": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", | ||||
|       "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-color": "1 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-path": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", | ||||
|       "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-polygon": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", | ||||
|       "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-quadtree": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", | ||||
|       "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-random": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", | ||||
|       "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-scale": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", | ||||
|       "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-array": "2.10.0 - 3", | ||||
|         "d3-format": "1 - 3", | ||||
|         "d3-interpolate": "1.2.0 - 3", | ||||
|         "d3-time": "2.1.1 - 3", | ||||
|         "d3-time-format": "2 - 4" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-scale-chromatic": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", | ||||
|       "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-color": "1 - 3", | ||||
|         "d3-interpolate": "1 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-selection": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", | ||||
|       "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-shape": { | ||||
|       "version": "3.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", | ||||
|       "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-path": "^3.1.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-time": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", | ||||
|       "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-array": "2 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-time-format": { | ||||
|       "version": "4.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", | ||||
|       "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-time": "1 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-timer": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", | ||||
|       "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-transition": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", | ||||
|       "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-color": "1 - 3", | ||||
|         "d3-dispatch": "1 - 3", | ||||
|         "d3-ease": "1 - 3", | ||||
|         "d3-interpolate": "1 - 3", | ||||
|         "d3-timer": "1 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       }, | ||||
|       "peerDependencies": { | ||||
|         "d3-selection": "2 - 3" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/d3-zoom": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", | ||||
|       "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "d3-dispatch": "1 - 3", | ||||
|         "d3-drag": "2 - 3", | ||||
|         "d3-interpolate": "1 - 3", | ||||
|         "d3-selection": "2 - 3", | ||||
|         "d3-transition": "2 - 3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/debug": { | ||||
|       "version": "4.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", | ||||
| @@ -2017,6 +2721,15 @@ | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/delaunator": { | ||||
|       "version": "5.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", | ||||
|       "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "robust-predicates": "^3.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/delayed-stream": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", | ||||
| @@ -2661,6 +3374,18 @@ | ||||
|         "node": ">= 0.4" | ||||
|       } | ||||
|     }, | ||||
|     "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/ignore": { | ||||
|       "version": "5.3.2", | ||||
|       "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", | ||||
| @@ -2698,6 +3423,15 @@ | ||||
|         "node": ">=0.8.19" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/internmap": { | ||||
|       "version": "2.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", | ||||
|       "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", | ||||
|       "license": "ISC", | ||||
|       "engines": { | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/is-extglob": { | ||||
|       "version": "2.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", | ||||
| @@ -3200,6 +3934,12 @@ | ||||
|         "node": ">=0.10.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/robust-predicates": { | ||||
|       "version": "3.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", | ||||
|       "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", | ||||
|       "license": "Unlicense" | ||||
|     }, | ||||
|     "node_modules/rollup": { | ||||
|       "version": "4.46.2", | ||||
|       "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", | ||||
| @@ -3264,6 +4004,18 @@ | ||||
|         "queue-microtask": "^1.2.2" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/rw": { | ||||
|       "version": "1.3.3", | ||||
|       "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", | ||||
|       "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", | ||||
|       "license": "BSD-3-Clause" | ||||
|     }, | ||||
|     "node_modules/safer-buffer": { | ||||
|       "version": "2.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", | ||||
|       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/scheduler": { | ||||
|       "version": "0.26.0", | ||||
|       "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", | ||||
|   | ||||
| @@ -11,11 +11,14 @@ | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "axios": "^1.11.0", | ||||
|     "d3": "^7.9.0", | ||||
|     "react": "^19.1.1", | ||||
|     "react-dom": "^19.1.1" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@eslint/js": "^9.33.0", | ||||
|     "@types/d3": "^7.4.3", | ||||
|     "@types/geojson": "^7946.0.16", | ||||
|     "@types/react": "^19.1.10", | ||||
|     "@types/react-dom": "^19.1.7", | ||||
|     "@vitejs/plugin-react": "^5.0.0", | ||||
|   | ||||
							
								
								
									
										150
									
								
								Elecciones-Web/frontend/public/buenos-aires-municipios.geojson
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								Elecciones-Web/frontend/public/buenos-aires-municipios.geojson
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										145
									
								
								Elecciones-Web/frontend/public/municipioIdMap.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								Elecciones-Web/frontend/public/municipioIdMap.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| { | ||||
|   "100": "100", | ||||
|   "101": "101", | ||||
|   "102": "102", | ||||
|   "103": "103", | ||||
|   "104": "104", | ||||
|   "105": "105", | ||||
|   "106": "106", | ||||
|   "107": "107", | ||||
|   "108": "108", | ||||
|   "109": "109", | ||||
|   "110": "110", | ||||
|   "111": "111", | ||||
|   "113": "113", | ||||
|   "114": "114", | ||||
|   "115": "115", | ||||
|   "116": "116", | ||||
|   "117": "117", | ||||
|   "118": "118", | ||||
|   "119": "119", | ||||
|   "120": "120", | ||||
|   "121": "121", | ||||
|   "122": "122", | ||||
|   "123": "123", | ||||
|   "124": "124", | ||||
|   "125": "125", | ||||
|   "126": "126", | ||||
|   "127": "127", | ||||
|   "128": "128", | ||||
|   "129": "129", | ||||
|   "130": "130", | ||||
|   "131": "131", | ||||
|   "132": "132", | ||||
|   "133": "133", | ||||
|   "134": "134", | ||||
|   "135": "135", | ||||
|   "136": "136", | ||||
|   "137": "137", | ||||
|   "309": "309", | ||||
|   "314": "314", | ||||
|   "338": "338", | ||||
|   "357": "357", | ||||
|   "387": "387", | ||||
|   "396": "396", | ||||
|   "398": "398", | ||||
|   "399": "399", | ||||
|   "045": "045", | ||||
|   "055": "055", | ||||
|   "070": "070", | ||||
|   "030": "030", | ||||
|   "074": "074", | ||||
|   "003": "003", | ||||
|   "086": "086", | ||||
|   "082": "082", | ||||
|   "063": "063", | ||||
|   "006": "006", | ||||
|   "047": "047", | ||||
|   "084": "084", | ||||
|   "026": "026", | ||||
|   "025": "025", | ||||
|   "007": "007", | ||||
|   "033": "033", | ||||
|   "076": "076", | ||||
|   "054": "054", | ||||
|   "072": "072", | ||||
|   "012": "012", | ||||
|   "004": "004", | ||||
|   "077": "077", | ||||
|   "087": "087", | ||||
|   "098": "098", | ||||
|   "015": "015", | ||||
|   "080": "080", | ||||
|   "046": "046", | ||||
|   "038": "038", | ||||
|   "032": "032", | ||||
|   "014": "014", | ||||
|   "064": "064", | ||||
|   "083": "083", | ||||
|   "049": "049", | ||||
|   "058": "058", | ||||
|   "023": "023", | ||||
|   "060": "060", | ||||
|   "018": "018", | ||||
|   "042": "042", | ||||
|   "062": "062", | ||||
|   "066": "066", | ||||
|   "041": "041", | ||||
|   "053": "053", | ||||
|   "057": "057", | ||||
|   "001": "001", | ||||
|   "005": "005", | ||||
|   "002": "002", | ||||
|   "031": "031", | ||||
|   "008": "008", | ||||
|   "009": "009", | ||||
|   "013": "013", | ||||
|   "010": "010", | ||||
|   "011": "011", | ||||
|   "019": "019", | ||||
|   "017": "017", | ||||
|   "097": "097", | ||||
|   "020": "020", | ||||
|   "016": "016", | ||||
|   "037": "037", | ||||
|   "021": "021", | ||||
|   "027": "027", | ||||
|   "022": "022", | ||||
|   "036": "036", | ||||
|   "029": "029", | ||||
|   "028": "028", | ||||
|   "035": "035", | ||||
|   "056": "056", | ||||
|   "044": "044", | ||||
|   "034": "034", | ||||
|   "040": "040", | ||||
|   "039": "039", | ||||
|   "043": "043", | ||||
|   "051": "051", | ||||
|   "052": "052", | ||||
|   "059": "059", | ||||
|   "065": "065", | ||||
|   "061": "061", | ||||
|   "024": "024", | ||||
|   "068": "068", | ||||
|   "050": "050", | ||||
|   "078": "078", | ||||
|   "079": "079", | ||||
|   "067": "067", | ||||
|   "096": "096", | ||||
|   "099": "099", | ||||
|   "075": "075", | ||||
|   "081": "081", | ||||
|   "069": "069", | ||||
|   "073": "073", | ||||
|   "089": "089", | ||||
|   "090": "090", | ||||
|   "085": "085", | ||||
|   "088": "088", | ||||
|   "091": "091", | ||||
|   "093": "093", | ||||
|   "071": "071", | ||||
|   "095": "095", | ||||
|   "092": "092", | ||||
|   "094": "094" | ||||
| } | ||||
| @@ -40,3 +40,7 @@ | ||||
| .read-the-docs { | ||||
|   color: #888; | ||||
| } | ||||
|  | ||||
| section { | ||||
|   margin-bottom: 2rem; | ||||
| } | ||||
| @@ -1,28 +1,100 @@ | ||||
| // src/App.tsx | ||||
| import { useState } from 'react'; | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { MunicipioWidget } from './components/MunicipioWidget'; | ||||
| import { MunicipioSelector } from './components/MunicipioSelector'; | ||||
| import { getMunicipios, type MunicipioSimple } from './services/api'; | ||||
| import './App.css'; | ||||
| import { ResumenProvincialWidget } from './components/ResumenProvincialWidget'; | ||||
| import { BancasWidget } from './components/BancasWidget'; | ||||
| import { TelegramasView } from './components/TelegramasView'; | ||||
| import { MapaD3Widget } from './components/MapaD3Widget'; | ||||
|  | ||||
| function App() { | ||||
|   const [selectedMunicipioId, setSelectedMunicipioId] = useState<string | null>(null); | ||||
|   const [listaMunicipios, setListaMunicipios] = useState<MunicipioSimple[]>([]); | ||||
|   const [loading, setLoading] = useState(true); | ||||
|  | ||||
|   useEffect(() => { | ||||
|     getMunicipios() | ||||
|       .then(setListaMunicipios) | ||||
|       .catch(err => console.error("Error al cargar la lista de municipios", err)) | ||||
|       .finally(() => setLoading(false)); | ||||
|   }, []); | ||||
|  | ||||
|   if (loading) return <h1>Cargando datos iniciales...</h1>; | ||||
|  | ||||
|   return ( | ||||
|     <> | ||||
|       <h1>Elecciones 2025 - Resultados en Vivo</h1> | ||||
|        | ||||
|       {/* Aquí podrías poner el widget del Resumen Provincial */} | ||||
|       <section> | ||||
|         <ResumenProvincialWidget distritoId="02" /> | ||||
|       </section> | ||||
|  | ||||
|       <hr /> | ||||
|        | ||||
|       <h2>Consulta por Municipio</h2> | ||||
|       <MunicipioSelector onMunicipioChange={setSelectedMunicipioId} /> | ||||
|  | ||||
|       {selectedMunicipioId && ( | ||||
|         <div style={{ marginTop: '20px' }}> | ||||
|           <MunicipioWidget municipioId={selectedMunicipioId} /> | ||||
|       <section style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: '20px' }}> | ||||
|         <div> | ||||
|           <h2>Mapa de Resultados</h2> | ||||
|           <MapaD3Widget | ||||
|             municipios={listaMunicipios}  | ||||
|             onMunicipioClick={setSelectedMunicipioId}  | ||||
|           /> | ||||
|         </div> | ||||
|       )} | ||||
|         <div> | ||||
|           <h2>Consulta por Municipio</h2> | ||||
|           <MunicipioSelector  | ||||
|             municipios={listaMunicipios}  | ||||
|             onMunicipioChange={setSelectedMunicipioId}  | ||||
|           /> | ||||
|           {selectedMunicipioId && ( | ||||
|             <div style={{ marginTop: '20px' }}> | ||||
|               <MunicipioWidget municipioId={selectedMunicipioId} /> | ||||
|             </div> | ||||
|           )} | ||||
|         </div> | ||||
|       </section> | ||||
|        | ||||
|       <section> | ||||
|         {/* Usamos el ID del distrito de Bs As ("02") */} | ||||
|         <ResumenProvincialWidget distritoId="02" /> | ||||
|       </section> | ||||
|  | ||||
|       <hr /> | ||||
|        | ||||
|       <section> | ||||
|         <h2>Consulta por Municipio</h2> | ||||
|         <MunicipioSelector onMunicipioChange={setSelectedMunicipioId} municipios={[]} /> | ||||
|         {selectedMunicipioId && ( | ||||
|           <div style={{ marginTop: '20px' }}> | ||||
|             <MunicipioWidget municipioId={selectedMunicipioId} /> | ||||
|           </div> | ||||
|         )} | ||||
|       </section> | ||||
|        | ||||
|       <section> | ||||
|         <h2>Proyección de Bancas</h2> | ||||
|         {/* Usamos el ID de la sección de La Plata ("0001") como ejemplo */} | ||||
|         <BancasWidget seccionId="0001" />  | ||||
|       </section> | ||||
|  | ||||
|       <hr /> | ||||
|        | ||||
|       <section> | ||||
|         <h2>Consulta de Resultados por Municipio</h2> | ||||
|         <MunicipioSelector onMunicipioChange={setSelectedMunicipioId} municipios={[]} /> | ||||
|         {selectedMunicipioId && ( | ||||
|           <div style={{ marginTop: '20px' }}> | ||||
|             <MunicipioWidget municipioId={selectedMunicipioId} /> | ||||
|           </div> | ||||
|         )} | ||||
|       </section> | ||||
|  | ||||
|       <hr /> | ||||
|  | ||||
|       <section> | ||||
|         <h2>Explorador de Telegramas</h2> | ||||
|         <TelegramasView /> | ||||
|       </section> | ||||
|     </> | ||||
|   ); | ||||
| } | ||||
|   | ||||
							
								
								
									
										52
									
								
								Elecciones-Web/frontend/src/components/BancasWidget.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								Elecciones-Web/frontend/src/components/BancasWidget.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| // src/components/BancasWidget.tsx | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { getBancasPorSeccion, type ProyeccionBancas } from '../services/api'; | ||||
|  | ||||
| interface Props { | ||||
|   seccionId: string; | ||||
| } | ||||
|  | ||||
| export const BancasWidget = ({ seccionId }: Props) => { | ||||
|   const [data, setData] = useState<ProyeccionBancas | null>(null); | ||||
|   const [loading, setLoading] = useState(true); | ||||
|  | ||||
|   useEffect(() => { | ||||
|     const fetchData = async () => { | ||||
|       try { | ||||
|         setLoading(true); | ||||
|         const proyeccion = await getBancasPorSeccion(seccionId); | ||||
|         setData(proyeccion); | ||||
|       } catch (err) { | ||||
|         console.error("Error cargando bancas", err); | ||||
|       } finally { | ||||
|         setLoading(false); | ||||
|       } | ||||
|     }; | ||||
|     fetchData(); | ||||
|   }, [seccionId]); | ||||
|  | ||||
|   if (loading) return <div>Cargando proyección de bancas...</div>; | ||||
|   if (!data) return <div>No hay datos de bancas disponibles.</div>; | ||||
|  | ||||
|   return ( | ||||
|     <div style={{ fontFamily: 'sans-serif', border: '1px solid #ccc', padding: '16px', borderRadius: '8px' }}> | ||||
|       <h3>Proyección de Bancas - {data.seccionNombre}</h3> | ||||
|       <table style={{ width: '100%', borderCollapse: 'collapse' }}> | ||||
|         <thead> | ||||
|           <tr> | ||||
|             <th style={{ textAlign: 'left' }}>Agrupación</th> | ||||
|             <th style={{ textAlign: 'right' }}>Bancas Obtenidas</th> | ||||
|           </tr> | ||||
|         </thead> | ||||
|         <tbody> | ||||
|           {data.proyeccion.map((partido) => ( | ||||
|             <tr key={partido.agrupacionNombre}> | ||||
|               <td>{partido.agrupacionNombre}</td> | ||||
|               <td style={{ textAlign: 'right' }}>{partido.bancas}</td> | ||||
|             </tr> | ||||
|           ))} | ||||
|         </tbody> | ||||
|       </table> | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
							
								
								
									
										112
									
								
								Elecciones-Web/frontend/src/components/MapaD3Widget.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								Elecciones-Web/frontend/src/components/MapaD3Widget.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| import { useEffect, useRef, useState } from 'react'; | ||||
| import * as d3 from 'd3'; | ||||
| // FIX: Usamos 'import type' para los tipos y quitamos la importación de 'MunicipioSimple' | ||||
| import type { FeatureCollection } from 'geojson'; | ||||
|  | ||||
| // --- Interfaces y Constantes --- | ||||
| interface MapaResultado { | ||||
|   municipioId: string; | ||||
|   agrupacionGanadoraId: string; | ||||
| } | ||||
| const COLOR_MAP: { [key: string]: string } = { "018": "#FFC107", "025": "#03A9F4", "031": "#4CAF50", "045": "#9C27B0", "default": "#E0E0E0" }; | ||||
|  | ||||
| interface Props { | ||||
|   onMunicipioClick: (municipioId: string) => void; | ||||
| } | ||||
|  | ||||
| export const MapaD3Widget = ({ onMunicipioClick }: Props) => { | ||||
|   const svgRef = useRef<SVGSVGElement | null>(null); | ||||
|   const containerRef = useRef<HTMLDivElement | null>(null); | ||||
|   const [tooltip, setTooltip] = useState<{ x: number; y: number; content: string } | null>(null); | ||||
|   const [loading, setLoading] = useState(true); | ||||
|  | ||||
|   useEffect(() => { | ||||
|     const svgElement = svgRef.current; | ||||
|     const containerElement = containerRef.current; | ||||
|     if (!svgElement || !containerElement) return; | ||||
|  | ||||
|     const drawMap = ( | ||||
|       geoData: FeatureCollection, // Usamos el tipo correcto | ||||
|       resultsMap: Map<string, MapaResultado>, | ||||
|       idMap: Record<string, string> | ||||
|     ) => { | ||||
|       const { width, height } = containerElement.getBoundingClientRect(); | ||||
|       if (width === 0 || height === 0) return; | ||||
|  | ||||
|       const svg = d3.select(svgElement); | ||||
|       svg.selectAll('*').remove(); | ||||
|       svg.attr('width', width).attr('height', height).attr('viewBox', `0 0 ${width} ${height}`); | ||||
|  | ||||
|       const projection = d3.geoMercator().fitSize([width, height], geoData); | ||||
|       const pathGenerator = d3.geoPath().projection(projection); | ||||
|  | ||||
|       const features = geoData.features; | ||||
|  | ||||
|       svg.append('g') | ||||
|         .selectAll('path') | ||||
|         .data(features) | ||||
|         .join('path') | ||||
|           .attr('d', pathGenerator as any) | ||||
|           .attr('stroke', '#FFFFFF') | ||||
|           .attr('stroke-width', 0.5) | ||||
|           .attr('fill', (d: any) => { | ||||
|             const geoJsonId = d.properties.cca; | ||||
|             const apiId = idMap[geoJsonId]; | ||||
|             const resultado = resultsMap.get(apiId); | ||||
|             return resultado ? COLOR_MAP[resultado.agrupacionGanadoraId] || COLOR_MAP.default : COLOR_MAP.default; | ||||
|           }) | ||||
|           .style('cursor', 'pointer') | ||||
|           .on('click', (_, d: any) => { | ||||
|             const apiId = idMap[d.properties.cca]; | ||||
|             if (apiId) onMunicipioClick(apiId); | ||||
|           }) | ||||
|           .on('mouseover', (event, d: any) => { | ||||
|             d3.select(event.currentTarget).attr('stroke', 'black').attr('stroke-width', 2); | ||||
|             setTooltip({ x: event.pageX, y: event.pageY, content: d.properties.nam }); | ||||
|           }) | ||||
|           .on('mouseout', (event) => { | ||||
|             d3.select(event.currentTarget).attr('stroke', '#FFFFFF').attr('stroke-width', 0.5); | ||||
|             setTooltip(null); | ||||
|           }); | ||||
|     }; | ||||
|  | ||||
|     (async () => { | ||||
|       try { | ||||
|         const [geoData, resultsData, idMap] = await Promise.all([ | ||||
|           d3.json<FeatureCollection>('/buenos-aires-municipios.geojson'), | ||||
|           d3.json<MapaResultado[]>('http://localhost:5217/api/resultados/mapa'), | ||||
|           d3.json<Record<string, string>>('/municipioIdMap.json') | ||||
|         ]); | ||||
|         if (geoData && resultsData && idMap) { | ||||
|           const resultsMap = new Map(resultsData.map(item => [item.municipioId, item])); | ||||
|           drawMap(geoData, resultsMap, idMap); | ||||
|         } else { | ||||
|           throw new Error("Faltan datos para renderizar el mapa."); | ||||
|         } | ||||
|       } catch (err) { | ||||
|         console.error("Error cargando datos para el mapa:", err); | ||||
|       } finally { | ||||
|         setLoading(false); | ||||
|       } | ||||
|     })(); | ||||
|   }, [onMunicipioClick]); | ||||
|  | ||||
|   if (loading) { | ||||
|     return <div ref={containerRef} style={{ width: '100%', height: '600px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>Cargando datos del mapa...</div>; | ||||
|   } | ||||
|  | ||||
|   return ( | ||||
|     <div ref={containerRef} style={{ width: '100%', height: '600px', border: '1px solid #eee' }}> | ||||
|       <svg ref={svgRef}></svg> | ||||
|       {tooltip && ( | ||||
|           <div style={{ | ||||
|               position: 'fixed', top: tooltip.y + 10, left: tooltip.x + 10, | ||||
|               backgroundColor: 'rgba(0, 0, 0, 0.75)', color: 'white', padding: '8px', | ||||
|               borderRadius: '4px', pointerEvents: 'none', fontSize: '14px', zIndex: 1000, | ||||
|           }}> | ||||
|               {tooltip.content} | ||||
|           </div> | ||||
|       )} | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
| @@ -1,31 +1,11 @@ | ||||
| // src/components/MunicipioSelector.tsx | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { getMunicipios, type MunicipioSimple } from '../services/api'; | ||||
| import { type MunicipioSimple } from '../services/api'; | ||||
|  | ||||
| interface Props { | ||||
|   municipios: MunicipioSimple[]; | ||||
|   onMunicipioChange: (municipioId: string) => void; | ||||
| } | ||||
|  | ||||
| export const MunicipioSelector = ({ onMunicipioChange }: Props) => { | ||||
|   const [municipios, setMunicipios] = useState<MunicipioSimple[]>([]); | ||||
|   const [loading, setLoading] = useState(true); | ||||
|  | ||||
|   useEffect(() => { | ||||
|     const loadMunicipios = async () => { | ||||
|       try { | ||||
|         const data = await getMunicipios(); | ||||
|         setMunicipios(data); | ||||
|       } catch (error) { | ||||
|         console.error("Error al cargar municipios", error); | ||||
|       } finally { | ||||
|         setLoading(false); | ||||
|       } | ||||
|     }; | ||||
|     loadMunicipios(); | ||||
|   }, []); | ||||
|  | ||||
|   if (loading) return <p>Cargando municipios...</p>; | ||||
|  | ||||
| export const MunicipioSelector = ({ municipios, onMunicipioChange }: Props) => { | ||||
|   return ( | ||||
|     <select onChange={(e) => onMunicipioChange(e.target.value)} defaultValue=""> | ||||
|       <option value="" disabled>Seleccione un municipio</option> | ||||
|   | ||||
| @@ -0,0 +1,52 @@ | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { getResumenProvincial, type ResumenProvincial } from '../services/api'; | ||||
|  | ||||
| interface Props { | ||||
|   distritoId: string; | ||||
| } | ||||
|  | ||||
| export const ResumenProvincialWidget = ({ distritoId }: Props) => { | ||||
|   const [data, setData] = useState<ResumenProvincial | null>(null); | ||||
|   const [loading, setLoading] = useState(true); | ||||
|  | ||||
|   useEffect(() => { | ||||
|     const fetchData = async () => { | ||||
|       try { | ||||
|         const resumen = await getResumenProvincial(distritoId); | ||||
|         setData(resumen); | ||||
|       } catch (err) { | ||||
|         console.error("Error cargando resumen provincial", err); | ||||
|       } finally { | ||||
|         setLoading(false); | ||||
|       } | ||||
|     }; | ||||
|  | ||||
|     fetchData(); | ||||
|     const intervalId = setInterval(fetchData, 15000); // Actualizamos cada 15s | ||||
|     return () => clearInterval(intervalId); | ||||
|   }, [distritoId]); | ||||
|  | ||||
|   if (loading) return <div>Cargando resumen provincial...</div>; | ||||
|   if (!data) return <div>No hay datos provinciales disponibles.</div>; | ||||
|  | ||||
|   return ( | ||||
|     <div style={{ fontFamily: 'sans-serif', border: '1px solid #ccc', padding: '16px', borderRadius: '8px', backgroundColor: '#f9f9f9' }}> | ||||
|       <h2>Resumen Provincial - {data.provinciaNombre}</h2> | ||||
|       <p><strong>Mesas Escrutadas:</strong> {data.porcentajeEscrutado.toFixed(2)}% | <strong>Participación:</strong> {data.porcentajeParticipacion.toFixed(2)}%</p> | ||||
|        | ||||
|       {data.resultados.map((partido) => ( | ||||
|         <div key={partido.nombre} style={{ margin: '10px 0' }}> | ||||
|           <span>{partido.nombre}</span> | ||||
|           <div style={{ display: 'flex', alignItems: 'center' }}> | ||||
|             <div style={{ backgroundColor: '#ddd', width: '100%', borderRadius: '4px', marginRight: '10px' }}> | ||||
|               <div style={{ width: `${partido.porcentaje}%`, backgroundColor: 'royalblue', color: 'white', padding: '4px', borderRadius: '4px', textAlign: 'right' }}> | ||||
|                 <strong>{partido.porcentaje.toFixed(2)}%</strong> | ||||
|               </div> | ||||
|             </div> | ||||
|             <span>{partido.votos.toLocaleString('es-AR')}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       ))} | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
							
								
								
									
										65
									
								
								Elecciones-Web/frontend/src/components/TelegramasView.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								Elecciones-Web/frontend/src/components/TelegramasView.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| // src/components/TelegramasView.tsx | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { getListaTelegramas, getTelegramaPorId, type TelegramaDetalle } from '../services/api'; | ||||
|  | ||||
| export const TelegramasView = () => { | ||||
|   const [listaIds, setListaIds] = useState<string[]>([]); | ||||
|   const [selectedTelegrama, setSelectedTelegrama] = useState<TelegramaDetalle | null>(null); | ||||
|   const [loadingList, setLoadingList] = useState(true); | ||||
|   const [loadingDetail, setLoadingDetail] = useState(false); | ||||
|  | ||||
|   useEffect(() => { | ||||
|     const loadList = async () => { | ||||
|       try { | ||||
|         const ids = await getListaTelegramas(); | ||||
|         setListaIds(ids); | ||||
|       } catch (error) { | ||||
|         console.error("Error al cargar lista de telegramas", error); | ||||
|       } finally { | ||||
|         setLoadingList(false); | ||||
|       } | ||||
|     }; | ||||
|     loadList(); | ||||
|   }, []); | ||||
|  | ||||
|   const handleSelectTelegrama = async (mesaId: string) => { | ||||
|     try { | ||||
|         setLoadingDetail(true); | ||||
|         const detalle = await getTelegramaPorId(mesaId); | ||||
|         setSelectedTelegrama(detalle); | ||||
|     } catch (error) { | ||||
|         console.error(`Error al cargar telegrama ${mesaId}`, error); | ||||
|     } finally { | ||||
|         setLoadingDetail(false); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   return ( | ||||
|     <div style={{ display: 'flex', gap: '20px', height: '500px' }}> | ||||
|       <div style={{ flex: 1, border: '1px solid #ccc', overflowY: 'auto' }}> | ||||
|         <h4>Telegramas Disponibles</h4> | ||||
|         {loadingList ? <p>Cargando...</p> : ( | ||||
|             <ul style={{ listStyle: 'none', padding: '10px' }}> | ||||
|                 {listaIds.map(id => ( | ||||
|                     <li key={id} onClick={() => handleSelectTelegrama(id)} style={{ cursor: 'pointer', padding: '5px', borderBottom: '1px solid #eee' }}> | ||||
|                         Mesa: {id} | ||||
|                     </li> | ||||
|                 ))} | ||||
|             </ul> | ||||
|         )} | ||||
|       </div> | ||||
|       <div style={{ flex: 3, border: '1px solid #ccc', display: 'flex', justifyContent: 'center', alignItems: 'center' }}> | ||||
|         {loadingDetail ? <p>Cargando telegrama...</p> :  | ||||
|          selectedTelegrama ? ( | ||||
|             <iframe  | ||||
|                 src={`data:application/pdf;base64,${selectedTelegrama.contenidoBase64}`}  | ||||
|                 width="100%"  | ||||
|                 height="100%"  | ||||
|                 title={selectedTelegrama.id} | ||||
|             /> | ||||
|          ) : <p>Seleccione un telegrama de la lista para visualizarlo.</p> | ||||
|         } | ||||
|       </div> | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
| @@ -39,6 +39,39 @@ export interface ResumenProvincial extends Omit<MunicipioResultados, 'municipioN | ||||
|     provinciaNombre: string; | ||||
| } | ||||
|  | ||||
| export interface BancaResultado { | ||||
|   agrupacionNombre: string; | ||||
|   bancas: number; | ||||
| } | ||||
|  | ||||
| export interface ProyeccionBancas { | ||||
|   seccionNombre: string; | ||||
|   proyeccion: BancaResultado[]; | ||||
| } | ||||
|  | ||||
| export interface TelegramaDetalle { | ||||
|     id: string; | ||||
|     ambitoGeograficoId: number; | ||||
|     contenidoBase64: string; | ||||
|     fechaEscaneo: string; | ||||
|     fechaTotalizacion: string; | ||||
| } | ||||
|  | ||||
| export const getBancasPorSeccion = async (seccionId: string): Promise<ProyeccionBancas> => { | ||||
|     const response = await apiClient.get<ProyeccionBancas>(`/resultados/bancas/${seccionId}`); | ||||
|     return response.data; | ||||
| }; | ||||
|  | ||||
| export const getListaTelegramas = async (): Promise<string[]> => { | ||||
|     const response = await apiClient.get<string[]>('/telegramas'); | ||||
|     return response.data; | ||||
| }; | ||||
|  | ||||
| export const getTelegramaPorId = async (mesaId: string): Promise<TelegramaDetalle> => { | ||||
|     const response = await apiClient.get<TelegramaDetalle>(`/telegramas/${mesaId}`); | ||||
|     return response.data; | ||||
| }; | ||||
|  | ||||
| export const getMunicipios = async (): Promise<MunicipioSimple[]> => { | ||||
|   const response = await apiClient.get<MunicipioSimple[]>('/catalogos/municipios'); | ||||
|   return response.data; | ||||
|   | ||||
| @@ -113,4 +113,78 @@ public class ResultadosController : ControllerBase | ||||
|  | ||||
|         return Ok(await Task.FromResult(respuestaSimulada)); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("bancas/{seccionId}")] | ||||
|     public async Task<IActionResult> GetBancasPorSeccion(string seccionId) | ||||
|     { | ||||
|         // 1. Buscamos el ámbito de la sección electoral | ||||
|         var seccion = await _dbContext.AmbitosGeograficos | ||||
|             .AsNoTracking() | ||||
|             .FirstOrDefaultAsync(a => a.SeccionId == seccionId && a.NivelId == 4); // Nivel 4 = Sección Electoral | ||||
|  | ||||
|         if (seccion == null) | ||||
|         { | ||||
|             return NotFound(new { message = $"No se encontró la sección electoral con ID {seccionId}" }); | ||||
|         } | ||||
|  | ||||
|         // 2. Buscamos todas las proyecciones para ese ámbito, incluyendo el nombre de la agrupación | ||||
|         var proyecciones = await _dbContext.ProyeccionesBancas | ||||
|             .AsNoTracking() | ||||
|             .Include(p => p.AgrupacionPolitica) // Incluimos el nombre del partido | ||||
|             .Where(p => p.AmbitoGeograficoId == seccion.Id) | ||||
|             .Select(p => new | ||||
|             { | ||||
|                 // Creamos un objeto anónimo para la respuesta, más limpio que un DTO para este caso simple | ||||
|                 AgrupacionNombre = p.AgrupacionPolitica.Nombre, | ||||
|                 Bancas = p.NroBancas | ||||
|             }) | ||||
|             .OrderByDescending(p => p.Bancas) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         if (!proyecciones.Any()) | ||||
|         { | ||||
|             return NotFound(new { message = $"No se han encontrado proyecciones de bancas para la sección {seccion.Nombre}" }); | ||||
|         } | ||||
|  | ||||
|         // 3. Devolvemos un objeto que contiene el nombre de la sección y la lista de resultados | ||||
|         return Ok(new | ||||
|         { | ||||
|             SeccionNombre = seccion.Nombre, | ||||
|             Proyeccion = proyecciones | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("mapa")] | ||||
|     public async Task<IActionResult> GetResultadosParaMapa() | ||||
|     { | ||||
|         // Esta consulta es mucho más eficiente y se traduce bien a SQL. | ||||
|         // Paso 1: Para cada ámbito, encontrar la cantidad máxima de votos. | ||||
|         var maxVotosPorAmbito = _dbContext.ResultadosVotos | ||||
|             .GroupBy(rv => rv.AmbitoGeograficoId) | ||||
|             .Select(g => new | ||||
|             { | ||||
|                 AmbitoId = g.Key, | ||||
|                 MaxVotos = g.Max(v => v.CantidadVotos) | ||||
|             }); | ||||
|  | ||||
|         // Paso 2: Unir los resultados originales con los máximos para encontrar el registro ganador. | ||||
|         // Esto nos da, para cada ámbito, el registro completo del partido que tuvo más votos. | ||||
|         var resultadosGanadores = await _dbContext.ResultadosVotos | ||||
|             .Join( | ||||
|                 maxVotosPorAmbito, | ||||
|                 voto => new { AmbitoId = voto.AmbitoGeograficoId, Votos = voto.CantidadVotos }, | ||||
|                 max => new { AmbitoId = max.AmbitoId, Votos = max.MaxVotos }, | ||||
|                 (voto, max) => voto // Nos quedamos con el objeto 'ResultadoVoto' completo | ||||
|             ) | ||||
|             .Include(rv => rv.AmbitoGeografico) // Incluimos el ámbito para obtener el MunicipioId | ||||
|             .Where(rv => rv.AmbitoGeografico.MunicipioId != null) | ||||
|             .Select(rv => new | ||||
|             { | ||||
|                 MunicipioId = rv.AmbitoGeografico.MunicipioId, | ||||
|                 AgrupacionGanadoraId = rv.AgrupacionPoliticaId | ||||
|             }) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         return Ok(resultadosGanadores); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,62 @@ | ||||
| using Elecciones.Core.DTOs.ApiResponses; | ||||
| using Elecciones.Database; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace Elecciones.Api.Controllers; | ||||
|  | ||||
| [ApiController] | ||||
| [Route("api/[controller]")] | ||||
| public class TelegramasController : ControllerBase | ||||
| { | ||||
|   private readonly EleccionesDbContext _dbContext; | ||||
|  | ||||
|   public TelegramasController(EleccionesDbContext dbContext) | ||||
|   { | ||||
|     _dbContext = dbContext; | ||||
|   } | ||||
|  | ||||
|   /// <summary> | ||||
|   /// Obtiene la lista de IDs de todos los telegramas que han sido totalizados y descargados. | ||||
|   /// </summary> | ||||
|   [HttpGet] | ||||
|   public async Task<IActionResult> GetListaTelegramas() | ||||
|   { | ||||
|     var ids = await _dbContext.Telegramas | ||||
|         .AsNoTracking() | ||||
|         .OrderBy(t => t.Id) | ||||
|         .Select(t => t.Id) | ||||
|         .ToListAsync(); | ||||
|  | ||||
|     return Ok(ids); | ||||
|   } | ||||
|  | ||||
|   /// <summary> | ||||
|   /// Obtiene el contenido completo de un telegrama específico, incluyendo la imagen en Base64. | ||||
|   /// </summary> | ||||
|   /// <param name="mesaId">El ID único de la mesa/telegrama (ej. "0200100001M").</param> | ||||
|   [HttpGet("{mesaId}")] | ||||
|   public async Task<IActionResult> GetTelegramaPorId(string mesaId) | ||||
|   { | ||||
|     var telegrama = await _dbContext.Telegramas | ||||
|         .AsNoTracking() | ||||
|         .FirstOrDefaultAsync(t => t.Id == mesaId); | ||||
|  | ||||
|     if (telegrama == null) | ||||
|     { | ||||
|       return NotFound(new { message = $"No se encontró el telegrama con ID {mesaId}" }); | ||||
|     } | ||||
|  | ||||
|     // Devolvemos todos los datos del telegrama | ||||
|     return Ok(new | ||||
|     { | ||||
|       telegrama.Id, | ||||
|       telegrama.AmbitoGeograficoId, | ||||
|       telegrama.ContenidoBase64, | ||||
|       telegrama.FechaEscaneo, | ||||
|       telegrama.FechaTotalizacion | ||||
|     }); | ||||
|   } | ||||
| } | ||||
| @@ -14,6 +14,8 @@ | ||||
|       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||||
|       <PrivateAssets>all</PrivateAssets> | ||||
|     </PackageReference> | ||||
|     <PackageReference Include="Serilog.AspNetCore" Version="9.0.0" /> | ||||
|     <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" /> | ||||
|     <PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   | ||||
| @@ -1,30 +1,26 @@ | ||||
| using Elecciones.Database; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Serilog; | ||||
|  | ||||
| // Esta es la estructura estándar y recomendada. | ||||
| var builder = WebApplication.CreateBuilder(args); | ||||
|  | ||||
| // --- 1. Configuración de Servicios --- | ||||
| // 1. Configurar Serilog. Esta es la forma correcta de integrarlo. | ||||
| builder.Host.UseSerilog((context, services, configuration) => configuration | ||||
|     .ReadFrom.Configuration(context.Configuration) | ||||
|     .ReadFrom.Services(services) | ||||
|     .Enrich.FromLogContext() | ||||
|     .WriteTo.Console() | ||||
|     .WriteTo.File("logs/api-.log", rollingInterval: RollingInterval.Day)); | ||||
|  | ||||
| // Añade la cadena de conexión y el DbContext para Entity Framework Core. | ||||
| // 2. Añadir servicios al contenedor. | ||||
| var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); | ||||
| builder.Services.AddDbContext<EleccionesDbContext>(options => | ||||
|     options.UseSqlServer(connectionString)); | ||||
|  | ||||
| // Añade los servicios para los controladores de la API. | ||||
| builder.Services.AddControllers(); | ||||
|  | ||||
| // Configura CORS para permitir que tu frontend (y www.eldia.com) consuman la API. | ||||
| // builder.Services.AddCors(options => | ||||
| // { | ||||
| //     options.AddDefaultPolicy(policy => | ||||
| //     { | ||||
| //         policy.WithOrigins("http://localhost:5173", "http://localhost:8600", "http://www.eldia.com", "http://elecciones2025.eldia.com") | ||||
| //               .AllowAnyHeader() | ||||
| //               .AllowAnyMethod(); | ||||
| //     }); | ||||
| // }); | ||||
|  | ||||
| var allowedOrigins = builder.Configuration["AllowedOrigins"]?.Split(',') ?? []; | ||||
| var allowedOrigins = builder.Configuration["AllowedOrigins"]?.Split(',') ?? Array.Empty<string>(); | ||||
| builder.Services.AddCors(options => | ||||
| { | ||||
|     options.AddDefaultPolicy(policy => | ||||
| @@ -38,34 +34,28 @@ builder.Services.AddCors(options => | ||||
|     }); | ||||
| }); | ||||
|  | ||||
|  | ||||
| // Añade la configuración de Swagger/OpenAPI para la documentación de la API. | ||||
| builder.Services.AddEndpointsApiExplorer(); | ||||
| builder.Services.AddSwaggerGen(); | ||||
|  | ||||
|  | ||||
| // 3. Construir la aplicación. | ||||
| var app = builder.Build(); | ||||
|  | ||||
| // --- 2. Configuración del Pipeline de Peticiones HTTP --- | ||||
| // 4. Configurar el pipeline de peticiones HTTP. | ||||
| // Añadimos el logging de peticiones de Serilog aquí. | ||||
| app.UseSerilogRequestLogging(); | ||||
|  | ||||
| // Habilita la UI de Swagger en el entorno de desarrollo. | ||||
| if (app.Environment.IsDevelopment()) | ||||
| { | ||||
|     app.UseSwagger(); | ||||
|     app.UseSwaggerUI(); | ||||
| } | ||||
|  | ||||
| // Redirige las peticiones HTTP a HTTPS. | ||||
| app.UseHttpsRedirection(); | ||||
|  | ||||
| // Usa la política de CORS que definimos arriba. | ||||
| app.UseCors(); | ||||
|  | ||||
| // Habilita la autorización (lo configuraremos si es necesario más adelante). | ||||
| app.UseAuthorization(); | ||||
|  | ||||
| // Mapea las rutas a los controladores de la API. | ||||
| app.MapControllers(); | ||||
|  | ||||
| // Inicia la aplicación. | ||||
| // 5. Ejecutar la aplicación. | ||||
| // El try/catch/finally se puede omitir; el logging de Serilog ya se encarga de los errores fatales. | ||||
| app.Run(); | ||||
| @@ -13,6 +13,8 @@ | ||||
|           "Microsoft.AspNetCore.OpenApi": "9.0.5", | ||||
|           "Microsoft.EntityFrameworkCore.SqlServer": "9.0.8", | ||||
|           "Microsoft.EntityFrameworkCore.Tools": "9.0.8", | ||||
|           "Serilog.AspNetCore": "9.0.0", | ||||
|           "Serilog.Sinks.File": "7.0.0", | ||||
|           "Swashbuckle.AspNetCore": "9.0.3" | ||||
|         }, | ||||
|         "runtime": { | ||||
| @@ -626,6 +628,20 @@ | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.FileProviders.Abstractions/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Primitives": "9.0.8" | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Hosting.Abstractions/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.FileProviders.Abstractions": "9.0.0", | ||||
|           "Microsoft.Extensions.Logging.Abstractions": "9.0.8" | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Http/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration.Abstractions": "9.0.8", | ||||
| @@ -840,6 +856,115 @@ | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog/4.2.0": { | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.dll": { | ||||
|             "assemblyVersion": "4.2.0.0", | ||||
|             "fileVersion": "4.2.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.AspNetCore/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0", | ||||
|           "Serilog.Extensions.Hosting": "9.0.0", | ||||
|           "Serilog.Formatting.Compact": "3.0.0", | ||||
|           "Serilog.Settings.Configuration": "9.0.0", | ||||
|           "Serilog.Sinks.Console": "6.0.0", | ||||
|           "Serilog.Sinks.Debug": "3.0.0", | ||||
|           "Serilog.Sinks.File": "7.0.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.AspNetCore.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Extensions.Hosting/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Hosting.Abstractions": "9.0.0", | ||||
|           "Microsoft.Extensions.Logging.Abstractions": "9.0.8", | ||||
|           "Serilog": "4.2.0", | ||||
|           "Serilog.Extensions.Logging": "9.0.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Extensions.Hosting.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Extensions.Logging/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Logging": "9.0.8", | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Extensions.Logging.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Formatting.Compact/3.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net8.0/Serilog.Formatting.Compact.dll": { | ||||
|             "assemblyVersion": "3.0.0.0", | ||||
|             "fileVersion": "3.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Settings.Configuration/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration.Binder": "9.0.8", | ||||
|           "Microsoft.Extensions.DependencyModel": "9.0.8", | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Settings.Configuration.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Sinks.Console/6.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net8.0/Serilog.Sinks.Console.dll": { | ||||
|             "assemblyVersion": "6.0.0.0", | ||||
|             "fileVersion": "6.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Sinks.Debug/3.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net8.0/Serilog.Sinks.Debug.dll": { | ||||
|             "assemblyVersion": "3.0.0.0", | ||||
|             "fileVersion": "3.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Sinks.File/7.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Sinks.File.dll": { | ||||
|             "assemblyVersion": "7.0.0.0", | ||||
|             "fileVersion": "7.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Swashbuckle.AspNetCore/9.0.3": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.ApiDescription.Server": "9.0.0", | ||||
| @@ -1426,6 +1551,20 @@ | ||||
|       "path": "microsoft.extensions.diagnostics.abstractions/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.diagnostics.abstractions.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.FileProviders.Abstractions/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-uK439QzYR0q2emLVtYzwyK3x+T5bTY4yWsd/k/ZUS9LR6Sflp8MIdhGXW8kQCd86dQD4tLqvcbLkku8qHY263Q==", | ||||
|       "path": "microsoft.extensions.fileproviders.abstractions/9.0.0", | ||||
|       "hashPath": "microsoft.extensions.fileproviders.abstractions.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Hosting.Abstractions/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-yUKJgu81ExjvqbNWqZKshBbLntZMbMVz/P7Way2SBx7bMqA08Mfdc9O7hWDKAiSp+zPUGT6LKcSCQIPeDK+CCw==", | ||||
|       "path": "microsoft.extensions.hosting.abstractions/9.0.0", | ||||
|       "hashPath": "microsoft.extensions.hosting.abstractions.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Http/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
| @@ -1566,6 +1705,69 @@ | ||||
|       "path": "mono.texttemplating/3.0.0", | ||||
|       "hashPath": "mono.texttemplating.3.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog/4.2.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-gmoWVOvKgbME8TYR+gwMf7osROiWAURterc6Rt2dQyX7wtjZYpqFiA/pY6ztjGQKKV62GGCyOcmtP1UKMHgSmA==", | ||||
|       "path": "serilog/4.2.0", | ||||
|       "hashPath": "serilog.4.2.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.AspNetCore/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-JslDajPlBsn3Pww1554flJFTqROvK9zz9jONNQgn0D8Lx2Trw8L0A8/n6zEQK1DAZWXrJwiVLw8cnTR3YFuYsg==", | ||||
|       "path": "serilog.aspnetcore/9.0.0", | ||||
|       "hashPath": "serilog.aspnetcore.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Extensions.Hosting/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-u2TRxuxbjvTAldQn7uaAwePkWxTHIqlgjelekBtilAGL5sYyF3+65NWctN4UrwwGLsDC7c3Vz3HnOlu+PcoxXg==", | ||||
|       "path": "serilog.extensions.hosting/9.0.0", | ||||
|       "hashPath": "serilog.extensions.hosting.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Extensions.Logging/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-NwSSYqPJeKNzl5AuXVHpGbr6PkZJFlNa14CdIebVjK3k/76kYj/mz5kiTRNVSsSaxM8kAIa1kpy/qyT9E4npRQ==", | ||||
|       "path": "serilog.extensions.logging/9.0.0", | ||||
|       "hashPath": "serilog.extensions.logging.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Formatting.Compact/3.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-wQsv14w9cqlfB5FX2MZpNsTawckN4a8dryuNGbebB/3Nh1pXnROHZov3swtu3Nj5oNG7Ba+xdu7Et/ulAUPanQ==", | ||||
|       "path": "serilog.formatting.compact/3.0.0", | ||||
|       "hashPath": "serilog.formatting.compact.3.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Settings.Configuration/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-4/Et4Cqwa+F88l5SeFeNZ4c4Z6dEAIKbu3MaQb2Zz9F/g27T5a3wvfMcmCOaAiACjfUb4A6wrlTVfyYUZk3RRQ==", | ||||
|       "path": "serilog.settings.configuration/9.0.0", | ||||
|       "hashPath": "serilog.settings.configuration.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Sinks.Console/6.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-fQGWqVMClCP2yEyTXPIinSr5c+CBGUvBybPxjAGcf7ctDhadFhrQw03Mv8rJ07/wR5PDfFjewf2LimvXCDzpbA==", | ||||
|       "path": "serilog.sinks.console/6.0.0", | ||||
|       "hashPath": "serilog.sinks.console.6.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Sinks.Debug/3.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-4BzXcdrgRX7wde9PmHuYd9U6YqycCC28hhpKonK7hx0wb19eiuRj16fPcPSVp0o/Y1ipJuNLYQ00R3q2Zs8FDA==", | ||||
|       "path": "serilog.sinks.debug/3.0.0", | ||||
|       "hashPath": "serilog.sinks.debug.3.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Sinks.File/7.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-fKL7mXv7qaiNBUC71ssvn/dU0k9t0o45+qm2XgKAlSt19xF+ijjxyA3R6HmCgfKEKwfcfkwWjayuQtRueZFkYw==", | ||||
|       "path": "serilog.sinks.file/7.0.0", | ||||
|       "hashPath": "serilog.sinks.file.7.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Swashbuckle.AspNetCore/9.0.3": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|   | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -14,7 +14,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1d580231134cc923bf8cbc524140ceb0ae88752f")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -173,3 +173,13 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft. | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Diagnostics.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Http.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\buenos-aires-municipios.geojson | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.AspNetCore.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Extensions.Hosting.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Extensions.Logging.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Formatting.Compact.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Settings.Configuration.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Sinks.Console.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Sinks.Debug.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Sinks.File.dll | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","AE1TAk4qas82IfXTyRHo\u002BfMlnTE4e7B1AJrEn9ZhBwo=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","r5wfLIFTEo2\u002Bd7Tsx44bFIb0SPNdPvg4KbBRNmbWVFA="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","/FHWuH7ftxc5u992j4YhVijd0fBiiQLWe\u002BV0ZlveX5c="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","AE1TAk4qas82IfXTyRHo\u002BfMlnTE4e7B1AJrEn9ZhBwo=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","r5wfLIFTEo2\u002Bd7Tsx44bFIb0SPNdPvg4KbBRNmbWVFA="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","/FHWuH7ftxc5u992j4YhVijd0fBiiQLWe\u002BV0ZlveX5c="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"O7YawHw32G/Fh2bs+snZgm9O7okI0WYgTQmXM931znY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","AE1TAk4qas82IfXTyRHo\u002BfMlnTE4e7B1AJrEn9ZhBwo="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"O7YawHw32G/Fh2bs+snZgm9O7okI0WYgTQmXM931znY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -71,6 +71,14 @@ | ||||
|               "target": "Package", | ||||
|               "version": "[9.0.8, )" | ||||
|             }, | ||||
|             "Serilog.AspNetCore": { | ||||
|               "target": "Package", | ||||
|               "version": "[9.0.0, )" | ||||
|             }, | ||||
|             "Serilog.Sinks.File": { | ||||
|               "target": "Package", | ||||
|               "version": "[7.0.0, )" | ||||
|             }, | ||||
|             "Swashbuckle.AspNetCore": { | ||||
|               "target": "Package", | ||||
|               "version": "[9.0.3, )" | ||||
|   | ||||
| @@ -3,10 +3,10 @@ | ||||
|   <ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> | ||||
|     <Import Project="$(NuGetPackageRoot)system.text.json\9.0.8\buildTransitive\net8.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\9.0.8\buildTransitive\net8.0\System.Text.Json.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.apidescription.server\9.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.apidescription.server\9.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)mono.texttemplating\3.0.0\buildTransitive\Mono.TextTemplating.targets" Condition="Exists('$(NuGetPackageRoot)mono.texttemplating\3.0.0\buildTransitive\Mono.TextTemplating.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)mono.texttemplating\3.0.0\buildTransitive\Mono.TextTemplating.targets" Condition="Exists('$(NuGetPackageRoot)mono.texttemplating\3.0.0\buildTransitive\Mono.TextTemplating.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets')" /> | ||||
|   </ImportGroup> | ||||
| </Project> | ||||
							
								
								
									
										20
									
								
								Elecciones-Web/src/Elecciones.Core/DTOs/BancaDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								Elecciones-Web/src/Elecciones.Core/DTOs/BancaDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| // src/Elecciones.Core/DTOs/BancaDto.cs | ||||
| using System.Text.Json.Serialization; | ||||
| namespace Elecciones.Core.DTOs; | ||||
|  | ||||
| public class BancaDto | ||||
| { | ||||
|   [JsonPropertyName("idAgrupacion")] | ||||
|   public string IdAgrupacion { get; set; } = null!; | ||||
|   [JsonPropertyName("nombreAgrupacion")] | ||||
|   public string NombreAgrupacion { get; set; } = null!; | ||||
|  | ||||
|   [JsonPropertyName("nroBancas")] | ||||
|   public int NroBancas { get; set; } | ||||
|  | ||||
|   public class RepartoBancasDto | ||||
|   { | ||||
|     [JsonPropertyName("repartoBancas")] | ||||
|     public List<BancaDto> RepartoBancas { get; set; } = []; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										15
									
								
								Elecciones-Web/src/Elecciones.Core/DTOs/CategoriaDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Elecciones-Web/src/Elecciones.Core/DTOs/CategoriaDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| using System.Text.Json.Serialization; | ||||
|  | ||||
| namespace Elecciones.Core.DTOs; | ||||
|  | ||||
| public class CategoriaDto | ||||
| { | ||||
|     [JsonPropertyName("orden")] | ||||
|     public int Orden { get; set; } | ||||
|  | ||||
|     [JsonPropertyName("categoriald")] | ||||
|     public int CategoriaId { get; set; } | ||||
|  | ||||
|     [JsonPropertyName("nombre")] | ||||
|     public string Nombre { get; set; } = null!; | ||||
| } | ||||
| @@ -1,4 +1,3 @@ | ||||
| // src/Elecciones.Core/DTOs/EstadoRecuentoDto.cs | ||||
| using System.Text.Json.Serialization; | ||||
|  | ||||
| namespace Elecciones.Core.DTOs; | ||||
| @@ -11,8 +10,14 @@ public class EstadoRecuentoDto | ||||
|     [JsonPropertyName("mesasTotalizadas")] | ||||
|     public int MesasTotalizadas { get; set; } | ||||
|      | ||||
|     [JsonPropertyName("mesasTotalizadasPorcentaje")] | ||||
|     public decimal MesasTotalizadasPorcentaje { get; set; } | ||||
|  | ||||
|     [JsonPropertyName("cantidadElectores")] | ||||
|     public int CantidadElectores { get; set; } | ||||
|      | ||||
|     [JsonPropertyName("cantidadVotantes")] | ||||
|     public int CantidadVotantes { get; set; } | ||||
|  | ||||
|     [JsonPropertyName("participacionPorcentaje")] | ||||
|     public decimal ParticipacionPorcentaje { get; set; } | ||||
|   | ||||
| @@ -0,0 +1,8 @@ | ||||
| using System.Text.Json.Serialization; | ||||
|  | ||||
| namespace Elecciones.Core.DTOs; | ||||
|  | ||||
| // Reutilizamos el DTO de estado de recuento que ya teníamos, | ||||
| // pero le damos un alias para claridad si es necesario. | ||||
| // A nivel de estructura son idénticos. | ||||
| public class EstadoRecuentoGeneralDto : EstadoRecuentoDto { } | ||||
							
								
								
									
										22
									
								
								Elecciones-Web/src/Elecciones.Core/DTOs/ResumenDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Elecciones-Web/src/Elecciones.Core/DTOs/ResumenDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| using System.Text.Json.Serialization; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Elecciones.Core.DTOs; | ||||
|  | ||||
| public class ResumenDto | ||||
| { | ||||
|     [JsonPropertyName("valoresTotalizadosPositivos")] | ||||
|     public List<ResumenPositivoDto> ValoresTotalizadosPositivos { get; set; } = []; | ||||
| } | ||||
|  | ||||
| public class ResumenPositivoDto | ||||
| { | ||||
|     [JsonPropertyName("idAgrupacion")] | ||||
|     public string IdAgrupacion { get; set; } = null!; | ||||
|      | ||||
|     [JsonPropertyName("votos")] | ||||
|     public long Votos { get; set; } | ||||
|  | ||||
|     [JsonPropertyName("votosPorcentaje")] | ||||
|     public decimal VotosPorcentaje { get; set; } | ||||
| } | ||||
							
								
								
									
										19
									
								
								Elecciones-Web/src/Elecciones.Core/DTOs/TelegramaFileDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Elecciones-Web/src/Elecciones.Core/DTOs/TelegramaFileDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| // src/Elecciones.Core/DTOs/TelegramaFileDto.cs | ||||
| using System.Text.Json.Serialization; | ||||
|  | ||||
| namespace Elecciones.Core.DTOs; | ||||
|  | ||||
| public class TelegramaFileDto | ||||
| { | ||||
|     [JsonPropertyName("nombreArchivo")] | ||||
|     public string NombreArchivo { get; set; } = null!; | ||||
|  | ||||
|     [JsonPropertyName("imagen")] | ||||
|     public string Imagen { get; set; } = null!; | ||||
|      | ||||
|     [JsonPropertyName("fechaEscaneo")] | ||||
|     public string FechaEscaneo { get; set; } = null!; | ||||
|      | ||||
|     [JsonPropertyName("fechaTotalizacion")] | ||||
|     public string FechaTotalizacion { get; set; } = null!; | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| { | ||||
|   "runtimeTarget": { | ||||
|     "name": ".NETCoreApp,Version=v9.0", | ||||
|     "signature": "" | ||||
|   }, | ||||
|   "compilationOptions": {}, | ||||
|   "targets": { | ||||
|     ".NETCoreApp,Version=v9.0": { | ||||
|       "Elecciones.Core/1.0.0": { | ||||
|         "runtime": { | ||||
|           "Elecciones.Core.dll": {} | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   "libraries": { | ||||
|     "Elecciones.Core/1.0.0": { | ||||
|       "type": "project", | ||||
|       "serviceable": false, | ||||
|       "sha512": "" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -13,7 +13,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b90baadeedb870b5b1c9eeeb7022a0d211b61bec")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -0,0 +1,4 @@ | ||||
| // <autogenerated /> | ||||
| using System; | ||||
| using System.Reflection; | ||||
| [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")] | ||||
| @@ -0,0 +1,22 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| // <auto-generated> | ||||
| //     This code was generated by a tool. | ||||
| // | ||||
| //     Changes to this file may cause incorrect behavior and will be lost if | ||||
| //     the code is regenerated. | ||||
| // </auto-generated> | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| using System; | ||||
| using System.Reflection; | ||||
|  | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|  | ||||
| // Generado por la clase WriteCodeFragment de MSBuild. | ||||
|  | ||||
| @@ -0,0 +1,15 @@ | ||||
| is_global = true | ||||
| build_property.TargetFramework = net9.0 | ||||
| build_property.TargetPlatformMinVersion =  | ||||
| build_property.UsingMicrosoftNETSdkWeb =  | ||||
| build_property.ProjectTypeGuids =  | ||||
| build_property.InvariantGlobalization =  | ||||
| build_property.PlatformNeutralAssembly =  | ||||
| build_property.EnforceExtendedAnalyzerRules =  | ||||
| build_property._SupportedPlatformList = Linux,macOS,Windows | ||||
| build_property.RootNamespace = Elecciones.Core | ||||
| build_property.ProjectDir = E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\ | ||||
| build_property.EnableComHosting =  | ||||
| build_property.EnableGeneratedComInterfaceComImportInterop =  | ||||
| build_property.EffectiveAnalysisLevelStyle = 9.0 | ||||
| build_property.EnableCodeStyleSeverity =  | ||||
| @@ -0,0 +1,8 @@ | ||||
| // <auto-generated/> | ||||
| global using global::System; | ||||
| global using global::System.Collections.Generic; | ||||
| global using global::System.IO; | ||||
| global using global::System.Linq; | ||||
| global using global::System.Net.Http; | ||||
| global using global::System.Threading; | ||||
| global using global::System.Threading.Tasks; | ||||
| @@ -0,0 +1,11 @@ | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\bin\Release\net9.0\Elecciones.Core.deps.json | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\bin\Release\net9.0\Elecciones.Core.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\bin\Release\net9.0\Elecciones.Core.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\obj\Release\net9.0\Elecciones.Core.GeneratedMSBuildEditorConfig.editorconfig | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\obj\Release\net9.0\Elecciones.Core.AssemblyInfoInputs.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\obj\Release\net9.0\Elecciones.Core.AssemblyInfo.cs | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\obj\Release\net9.0\Elecciones.Core.csproj.CoreCompileInputs.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\obj\Release\net9.0\Elecciones.Core.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\obj\Release\net9.0\refint\Elecciones.Core.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\obj\Release\net9.0\Elecciones.Core.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Core\obj\Release\net9.0\ref\Elecciones.Core.dll | ||||
| @@ -10,7 +10,11 @@ public class EleccionesDbContext(DbContextOptions<EleccionesDbContext> options) | ||||
|     public DbSet<AmbitoGeografico> AmbitosGeograficos { get; set; } | ||||
|     public DbSet<ResultadoVoto> ResultadosVotos { get; set; } | ||||
|     public DbSet<EstadoRecuento> EstadosRecuentos { get; set; } | ||||
|     // Podríamos añadir más tablas como CategoriaElectoral o ProyeccionBanca aquí | ||||
|     public DbSet<ProyeccionBanca> ProyeccionesBancas { get; set; } | ||||
|     public DbSet<Telegrama> Telegramas { get; set; } | ||||
|     public DbSet<ResumenVoto> ResumenesVotos { get; set; } | ||||
|     public DbSet<EstadoRecuentoGeneral> EstadosRecuentosGenerales { get; set; } | ||||
|     public DbSet<CategoriaElectoral> CategoriasElectorales { get; set; } | ||||
|  | ||||
|     protected override void OnModelCreating(ModelBuilder modelBuilder) | ||||
|     { | ||||
| @@ -27,5 +31,13 @@ public class EleccionesDbContext(DbContextOptions<EleccionesDbContext> options) | ||||
|             entity.Property(e => e.MesasTotalizadasPorcentaje).HasPrecision(5, 2); | ||||
|             entity.Property(e => e.ParticipacionPorcentaje).HasPrecision(5, 2); | ||||
|         }); | ||||
|         modelBuilder.Entity<ResumenVoto>() | ||||
|         .Property(e => e.VotosPorcentaje).HasPrecision(5, 2); | ||||
|  | ||||
|         modelBuilder.Entity<EstadoRecuentoGeneral>(entity => | ||||
|         { | ||||
|             entity.Property(e => e.MesasTotalizadasPorcentaje).HasPrecision(5, 2); | ||||
|             entity.Property(e => e.ParticipacionPorcentaje).HasPrecision(5, 2); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| namespace Elecciones.Database.Entities; | ||||
|  | ||||
| public class CategoriaElectoral | ||||
| { | ||||
|     [Key] | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.None)] // La API nos da el ID, no la BD. | ||||
|     public int Id { get; set; } // Corresponde a 'categoriald' | ||||
|  | ||||
|     [Required] | ||||
|     public string Nombre { get; set; } = null!; | ||||
|  | ||||
|     public int Orden { get; set; } | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| namespace Elecciones.Database.Entities; | ||||
|  | ||||
| public class EstadoRecuentoGeneral | ||||
| { | ||||
|     [Key] | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.None)] // Le dice a EF que no genere este valor. | ||||
|     public int AmbitoGeograficoId { get; set; } | ||||
|  | ||||
|     public int MesasEsperadas { get; set; } | ||||
|     public int MesasTotalizadas { get; set; } | ||||
|     public decimal MesasTotalizadasPorcentaje { get; set; } | ||||
|     public int CantidadElectores { get; set; } | ||||
|     public int CantidadVotantes { get; set; } | ||||
|     public decimal ParticipacionPorcentaje { get; set; } | ||||
| } | ||||
| @@ -0,0 +1,25 @@ | ||||
| // src/Elecciones.Database/Entities/ProyeccionBanca.cs | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| namespace Elecciones.Database.Entities; | ||||
|  | ||||
| public class ProyeccionBanca | ||||
| { | ||||
|     [Key] | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public int Id { get; set; } | ||||
|  | ||||
|     // El ámbito donde se proyecta (ej. Sección Electoral) | ||||
|     public int AmbitoGeograficoId { get; set; } | ||||
|     [ForeignKey("AmbitoGeograficoId")] | ||||
|     public AmbitoGeografico AmbitoGeografico { get; set; } = null!; | ||||
|  | ||||
|     // La agrupación que obtiene la banca | ||||
|     public string AgrupacionPoliticaId { get; set; } = null!; | ||||
|     [ForeignKey("AgrupacionPoliticaId")] | ||||
|     public AgrupacionPolitica AgrupacionPolitica { get; set; } = null!; | ||||
|  | ||||
|     // Cantidad de bancas obtenidas | ||||
|     public int NroBancas { get; set; } | ||||
| } | ||||
| @@ -0,0 +1,19 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| namespace Elecciones.Database.Entities; | ||||
|  | ||||
| public class ResumenVoto | ||||
| { | ||||
|     [Key] | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public int Id { get; set; } | ||||
|  | ||||
|     // El ámbito donde se resume (siempre provincial en este caso) | ||||
|     public int AmbitoGeograficoId { get; set; } | ||||
|  | ||||
|     public string AgrupacionPoliticaId { get; set; } = null!; | ||||
|  | ||||
|     public long Votos { get; set; } | ||||
|     public decimal VotosPorcentaje { get; set; } | ||||
| } | ||||
							
								
								
									
										21
									
								
								Elecciones-Web/src/Elecciones.Database/Entities/Telegrama.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								Elecciones-Web/src/Elecciones.Database/Entities/Telegrama.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
|  | ||||
| // src/Elecciones.Database/Entities/Telegrama.cs | ||||
| using System.ComponentModel.DataAnnotations; | ||||
|  | ||||
| namespace Elecciones.Database.Entities; | ||||
|  | ||||
| public class Telegrama | ||||
| { | ||||
|     // El ID único del telegrama (ej. "0202600060X") será nuestra Primary Key. | ||||
|     [Key] | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     // En qué ámbito fue escrutado | ||||
|     public int AmbitoGeograficoId { get; set; } | ||||
|      | ||||
|     // El contenido del telegrama en Base64 | ||||
|     public string ContenidoBase64 { get; set; } = null!; | ||||
|      | ||||
|     public DateTime FechaEscaneo { get; set; } | ||||
|     public DateTime FechaTotalizacion { get; set; } | ||||
| } | ||||
| @@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | ||||
| namespace Elecciones.Database.Migrations | ||||
| { | ||||
|     [DbContext(typeof(EleccionesDbContext))] | ||||
|     [Migration("20250814161142_InitialCreate")] | ||||
|     partial class InitialCreate | ||||
|     [Migration("20250815181913_InitialSchema")] | ||||
|     partial class InitialSchema | ||||
|     { | ||||
|         /// <inheritdoc /> | ||||
|         protected override void BuildTargetModel(ModelBuilder modelBuilder) | ||||
| @@ -126,6 +126,63 @@ namespace Elecciones.Database.Migrations | ||||
|                     b.ToTable("EstadosRecuentos"); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b => | ||||
|                 { | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     b.Property<int>("CantidadElectores") | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     b.Property<int>("CantidadVotantes") | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     b.Property<int>("MesasEsperadas") | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     b.Property<int>("MesasTotalizadas") | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     b.Property<decimal>("MesasTotalizadasPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
| 
 | ||||
|                     b.Property<decimal>("ParticipacionPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
| 
 | ||||
|                     b.HasKey("AmbitoGeograficoId"); | ||||
| 
 | ||||
|                     b.ToTable("EstadosRecuentosGenerales"); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); | ||||
| 
 | ||||
|                     b.Property<string>("AgrupacionPoliticaId") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(450)"); | ||||
| 
 | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     b.Property<int>("NroBancas") | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     b.HasKey("Id"); | ||||
| 
 | ||||
|                     b.HasIndex("AgrupacionPoliticaId"); | ||||
| 
 | ||||
|                     b.HasIndex("AmbitoGeograficoId"); | ||||
| 
 | ||||
|                     b.ToTable("ProyeccionesBancas"); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b => | ||||
|                 { | ||||
|                     b.Property<long>("Id") | ||||
| @@ -154,6 +211,56 @@ namespace Elecciones.Database.Migrations | ||||
|                     b.ToTable("ResultadosVotos"); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); | ||||
| 
 | ||||
|                     b.Property<string>("AgrupacionPoliticaId") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
| 
 | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     b.Property<long>("Votos") | ||||
|                         .HasColumnType("bigint"); | ||||
| 
 | ||||
|                     b.Property<decimal>("VotosPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
| 
 | ||||
|                     b.HasKey("Id"); | ||||
| 
 | ||||
|                     b.ToTable("ResumenesVotos"); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b => | ||||
|                 { | ||||
|                     b.Property<string>("Id") | ||||
|                         .HasColumnType("nvarchar(450)"); | ||||
| 
 | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
| 
 | ||||
|                     b.Property<string>("ContenidoBase64") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
| 
 | ||||
|                     b.Property<DateTime>("FechaEscaneo") | ||||
|                         .HasColumnType("datetime2"); | ||||
| 
 | ||||
|                     b.Property<DateTime>("FechaTotalizacion") | ||||
|                         .HasColumnType("datetime2"); | ||||
| 
 | ||||
|                     b.HasKey("Id"); | ||||
| 
 | ||||
|                     b.ToTable("Telegramas"); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b => | ||||
|                 { | ||||
|                     b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") | ||||
| @@ -165,6 +272,25 @@ namespace Elecciones.Database.Migrations | ||||
|                     b.Navigation("AmbitoGeografico"); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b => | ||||
|                 { | ||||
|                     b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") | ||||
|                         .WithMany() | ||||
|                         .HasForeignKey("AgrupacionPoliticaId") | ||||
|                         .OnDelete(DeleteBehavior.Cascade) | ||||
|                         .IsRequired(); | ||||
| 
 | ||||
|                     b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") | ||||
|                         .WithMany() | ||||
|                         .HasForeignKey("AmbitoGeograficoId") | ||||
|                         .OnDelete(DeleteBehavior.Cascade) | ||||
|                         .IsRequired(); | ||||
| 
 | ||||
|                     b.Navigation("AgrupacionPolitica"); | ||||
| 
 | ||||
|                     b.Navigation("AmbitoGeografico"); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b => | ||||
|                 { | ||||
|                     b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") | ||||
| @@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations; | ||||
| namespace Elecciones.Database.Migrations | ||||
| { | ||||
|     /// <inheritdoc /> | ||||
|     public partial class InitialCreate : Migration | ||||
|     public partial class InitialSchema : Migration | ||||
|     { | ||||
|         /// <inheritdoc /> | ||||
|         protected override void Up(MigrationBuilder migrationBuilder) | ||||
| @@ -45,6 +45,54 @@ namespace Elecciones.Database.Migrations | ||||
|                     table.PrimaryKey("PK_AmbitosGeograficos", x => x.Id); | ||||
|                 }); | ||||
| 
 | ||||
|             migrationBuilder.CreateTable( | ||||
|                 name: "EstadosRecuentosGenerales", | ||||
|                 columns: table => new | ||||
|                 { | ||||
|                     AmbitoGeograficoId = table.Column<int>(type: "int", nullable: false), | ||||
|                     MesasEsperadas = table.Column<int>(type: "int", nullable: false), | ||||
|                     MesasTotalizadas = table.Column<int>(type: "int", nullable: false), | ||||
|                     MesasTotalizadasPorcentaje = table.Column<decimal>(type: "decimal(5,2)", precision: 5, scale: 2, nullable: false), | ||||
|                     CantidadElectores = table.Column<int>(type: "int", nullable: false), | ||||
|                     CantidadVotantes = table.Column<int>(type: "int", nullable: false), | ||||
|                     ParticipacionPorcentaje = table.Column<decimal>(type: "decimal(5,2)", precision: 5, scale: 2, nullable: false) | ||||
|                 }, | ||||
|                 constraints: table => | ||||
|                 { | ||||
|                     table.PrimaryKey("PK_EstadosRecuentosGenerales", x => x.AmbitoGeograficoId); | ||||
|                 }); | ||||
| 
 | ||||
|             migrationBuilder.CreateTable( | ||||
|                 name: "ResumenesVotos", | ||||
|                 columns: table => new | ||||
|                 { | ||||
|                     Id = table.Column<int>(type: "int", nullable: false) | ||||
|                         .Annotation("SqlServer:Identity", "1, 1"), | ||||
|                     AmbitoGeograficoId = table.Column<int>(type: "int", nullable: false), | ||||
|                     AgrupacionPoliticaId = table.Column<string>(type: "nvarchar(max)", nullable: false), | ||||
|                     Votos = table.Column<long>(type: "bigint", nullable: false), | ||||
|                     VotosPorcentaje = table.Column<decimal>(type: "decimal(5,2)", precision: 5, scale: 2, nullable: false) | ||||
|                 }, | ||||
|                 constraints: table => | ||||
|                 { | ||||
|                     table.PrimaryKey("PK_ResumenesVotos", x => x.Id); | ||||
|                 }); | ||||
| 
 | ||||
|             migrationBuilder.CreateTable( | ||||
|                 name: "Telegramas", | ||||
|                 columns: table => new | ||||
|                 { | ||||
|                     Id = table.Column<string>(type: "nvarchar(450)", nullable: false), | ||||
|                     AmbitoGeograficoId = table.Column<int>(type: "int", nullable: false), | ||||
|                     ContenidoBase64 = table.Column<string>(type: "nvarchar(max)", nullable: false), | ||||
|                     FechaEscaneo = table.Column<DateTime>(type: "datetime2", nullable: false), | ||||
|                     FechaTotalizacion = table.Column<DateTime>(type: "datetime2", nullable: false) | ||||
|                 }, | ||||
|                 constraints: table => | ||||
|                 { | ||||
|                     table.PrimaryKey("PK_Telegramas", x => x.Id); | ||||
|                 }); | ||||
| 
 | ||||
|             migrationBuilder.CreateTable( | ||||
|                 name: "EstadosRecuentos", | ||||
|                 columns: table => new | ||||
| @@ -72,6 +120,33 @@ namespace Elecciones.Database.Migrations | ||||
|                         onDelete: ReferentialAction.Cascade); | ||||
|                 }); | ||||
| 
 | ||||
|             migrationBuilder.CreateTable( | ||||
|                 name: "ProyeccionesBancas", | ||||
|                 columns: table => new | ||||
|                 { | ||||
|                     Id = table.Column<int>(type: "int", nullable: false) | ||||
|                         .Annotation("SqlServer:Identity", "1, 1"), | ||||
|                     AmbitoGeograficoId = table.Column<int>(type: "int", nullable: false), | ||||
|                     AgrupacionPoliticaId = table.Column<string>(type: "nvarchar(450)", nullable: false), | ||||
|                     NroBancas = table.Column<int>(type: "int", nullable: false) | ||||
|                 }, | ||||
|                 constraints: table => | ||||
|                 { | ||||
|                     table.PrimaryKey("PK_ProyeccionesBancas", x => x.Id); | ||||
|                     table.ForeignKey( | ||||
|                         name: "FK_ProyeccionesBancas_AgrupacionesPoliticas_AgrupacionPoliticaId", | ||||
|                         column: x => x.AgrupacionPoliticaId, | ||||
|                         principalTable: "AgrupacionesPoliticas", | ||||
|                         principalColumn: "Id", | ||||
|                         onDelete: ReferentialAction.Cascade); | ||||
|                     table.ForeignKey( | ||||
|                         name: "FK_ProyeccionesBancas_AmbitosGeograficos_AmbitoGeograficoId", | ||||
|                         column: x => x.AmbitoGeograficoId, | ||||
|                         principalTable: "AmbitosGeograficos", | ||||
|                         principalColumn: "Id", | ||||
|                         onDelete: ReferentialAction.Cascade); | ||||
|                 }); | ||||
| 
 | ||||
|             migrationBuilder.CreateTable( | ||||
|                 name: "ResultadosVotos", | ||||
|                 columns: table => new | ||||
| @@ -99,6 +174,16 @@ namespace Elecciones.Database.Migrations | ||||
|                         onDelete: ReferentialAction.Cascade); | ||||
|                 }); | ||||
| 
 | ||||
|             migrationBuilder.CreateIndex( | ||||
|                 name: "IX_ProyeccionesBancas_AgrupacionPoliticaId", | ||||
|                 table: "ProyeccionesBancas", | ||||
|                 column: "AgrupacionPoliticaId"); | ||||
| 
 | ||||
|             migrationBuilder.CreateIndex( | ||||
|                 name: "IX_ProyeccionesBancas_AmbitoGeograficoId", | ||||
|                 table: "ProyeccionesBancas", | ||||
|                 column: "AmbitoGeograficoId"); | ||||
| 
 | ||||
|             migrationBuilder.CreateIndex( | ||||
|                 name: "IX_ResultadosVotos_AgrupacionPoliticaId", | ||||
|                 table: "ResultadosVotos", | ||||
| @@ -117,9 +202,21 @@ namespace Elecciones.Database.Migrations | ||||
|             migrationBuilder.DropTable( | ||||
|                 name: "EstadosRecuentos"); | ||||
| 
 | ||||
|             migrationBuilder.DropTable( | ||||
|                 name: "EstadosRecuentosGenerales"); | ||||
| 
 | ||||
|             migrationBuilder.DropTable( | ||||
|                 name: "ProyeccionesBancas"); | ||||
| 
 | ||||
|             migrationBuilder.DropTable( | ||||
|                 name: "ResultadosVotos"); | ||||
| 
 | ||||
|             migrationBuilder.DropTable( | ||||
|                 name: "ResumenesVotos"); | ||||
| 
 | ||||
|             migrationBuilder.DropTable( | ||||
|                 name: "Telegramas"); | ||||
| 
 | ||||
|             migrationBuilder.DropTable( | ||||
|                 name: "AgrupacionesPoliticas"); | ||||
| 
 | ||||
							
								
								
									
										332
									
								
								Elecciones-Web/src/Elecciones.Database/Migrations/20250815183610_AddCategoriasElectorales.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								Elecciones-Web/src/Elecciones.Database/Migrations/20250815183610_AddCategoriasElectorales.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,332 @@ | ||||
| // <auto-generated /> | ||||
| using System; | ||||
| using Elecciones.Database; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.EntityFrameworkCore.Infrastructure; | ||||
| using Microsoft.EntityFrameworkCore.Metadata; | ||||
| using Microsoft.EntityFrameworkCore.Migrations; | ||||
| using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | ||||
|  | ||||
| #nullable disable | ||||
|  | ||||
| namespace Elecciones.Database.Migrations | ||||
| { | ||||
|     [DbContext(typeof(EleccionesDbContext))] | ||||
|     [Migration("20250815183610_AddCategoriasElectorales")] | ||||
|     partial class AddCategoriasElectorales | ||||
|     { | ||||
|         /// <inheritdoc /> | ||||
|         protected override void BuildTargetModel(ModelBuilder modelBuilder) | ||||
|         { | ||||
| #pragma warning disable 612, 618 | ||||
|             modelBuilder | ||||
|                 .HasAnnotation("ProductVersion", "9.0.8") | ||||
|                 .HasAnnotation("Relational:MaxIdentifierLength", 128); | ||||
|  | ||||
|             SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b => | ||||
|                 { | ||||
|                     b.Property<string>("Id") | ||||
|                         .HasColumnType("nvarchar(450)"); | ||||
|  | ||||
|                     b.Property<string>("IdTelegrama") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<string>("Nombre") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.ToTable("AgrupacionesPoliticas"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.AmbitoGeografico", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); | ||||
|  | ||||
|                     b.Property<string>("CircuitoId") | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<string>("DistritoId") | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<string>("EstablecimientoId") | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<string>("MesaId") | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<string>("MunicipioId") | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<int>("NivelId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<string>("Nombre") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<string>("SeccionId") | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<string>("SeccionProvincialId") | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.ToTable("AmbitosGeograficos"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<string>("Nombre") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<int>("Orden") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.ToTable("CategoriasElectorales"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b => | ||||
|                 { | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("CantidadElectores") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("CantidadVotantes") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<DateTime>("FechaTotalizacion") | ||||
|                         .HasColumnType("datetime2"); | ||||
|  | ||||
|                     b.Property<int>("MesasEsperadas") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("MesasTotalizadas") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<decimal>("MesasTotalizadasPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
|  | ||||
|                     b.Property<decimal>("ParticipacionPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
|  | ||||
|                     b.Property<long>("VotosEnBlanco") | ||||
|                         .HasColumnType("bigint"); | ||||
|  | ||||
|                     b.Property<long>("VotosNulos") | ||||
|                         .HasColumnType("bigint"); | ||||
|  | ||||
|                     b.Property<long>("VotosRecurridos") | ||||
|                         .HasColumnType("bigint"); | ||||
|  | ||||
|                     b.HasKey("AmbitoGeograficoId"); | ||||
|  | ||||
|                     b.ToTable("EstadosRecuentos"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b => | ||||
|                 { | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("CantidadElectores") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("CantidadVotantes") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("MesasEsperadas") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("MesasTotalizadas") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<decimal>("MesasTotalizadasPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
|  | ||||
|                     b.Property<decimal>("ParticipacionPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
|  | ||||
|                     b.HasKey("AmbitoGeograficoId"); | ||||
|  | ||||
|                     b.ToTable("EstadosRecuentosGenerales"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); | ||||
|  | ||||
|                     b.Property<string>("AgrupacionPoliticaId") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(450)"); | ||||
|  | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("NroBancas") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.HasIndex("AgrupacionPoliticaId"); | ||||
|  | ||||
|                     b.HasIndex("AmbitoGeograficoId"); | ||||
|  | ||||
|                     b.ToTable("ProyeccionesBancas"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b => | ||||
|                 { | ||||
|                     b.Property<long>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("bigint"); | ||||
|  | ||||
|                     SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id")); | ||||
|  | ||||
|                     b.Property<string>("AgrupacionPoliticaId") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(450)"); | ||||
|  | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<long>("CantidadVotos") | ||||
|                         .HasColumnType("bigint"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.HasIndex("AgrupacionPoliticaId"); | ||||
|  | ||||
|                     b.HasIndex("AmbitoGeograficoId", "AgrupacionPoliticaId") | ||||
|                         .IsUnique(); | ||||
|  | ||||
|                     b.ToTable("ResultadosVotos"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); | ||||
|  | ||||
|                     b.Property<string>("AgrupacionPoliticaId") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<long>("Votos") | ||||
|                         .HasColumnType("bigint"); | ||||
|  | ||||
|                     b.Property<decimal>("VotosPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.ToTable("ResumenesVotos"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b => | ||||
|                 { | ||||
|                     b.Property<string>("Id") | ||||
|                         .HasColumnType("nvarchar(450)"); | ||||
|  | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<string>("ContenidoBase64") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<DateTime>("FechaEscaneo") | ||||
|                         .HasColumnType("datetime2"); | ||||
|  | ||||
|                     b.Property<DateTime>("FechaTotalizacion") | ||||
|                         .HasColumnType("datetime2"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.ToTable("Telegramas"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b => | ||||
|                 { | ||||
|                     b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") | ||||
|                         .WithMany() | ||||
|                         .HasForeignKey("AmbitoGeograficoId") | ||||
|                         .OnDelete(DeleteBehavior.Cascade) | ||||
|                         .IsRequired(); | ||||
|  | ||||
|                     b.Navigation("AmbitoGeografico"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b => | ||||
|                 { | ||||
|                     b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") | ||||
|                         .WithMany() | ||||
|                         .HasForeignKey("AgrupacionPoliticaId") | ||||
|                         .OnDelete(DeleteBehavior.Cascade) | ||||
|                         .IsRequired(); | ||||
|  | ||||
|                     b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") | ||||
|                         .WithMany() | ||||
|                         .HasForeignKey("AmbitoGeograficoId") | ||||
|                         .OnDelete(DeleteBehavior.Cascade) | ||||
|                         .IsRequired(); | ||||
|  | ||||
|                     b.Navigation("AgrupacionPolitica"); | ||||
|  | ||||
|                     b.Navigation("AmbitoGeografico"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b => | ||||
|                 { | ||||
|                     b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") | ||||
|                         .WithMany() | ||||
|                         .HasForeignKey("AgrupacionPoliticaId") | ||||
|                         .OnDelete(DeleteBehavior.Cascade) | ||||
|                         .IsRequired(); | ||||
|  | ||||
|                     b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") | ||||
|                         .WithMany() | ||||
|                         .HasForeignKey("AmbitoGeograficoId") | ||||
|                         .OnDelete(DeleteBehavior.Cascade) | ||||
|                         .IsRequired(); | ||||
|  | ||||
|                     b.Navigation("AgrupacionPolitica"); | ||||
|  | ||||
|                     b.Navigation("AmbitoGeografico"); | ||||
|                 }); | ||||
| #pragma warning restore 612, 618 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,34 @@ | ||||
| using Microsoft.EntityFrameworkCore.Migrations; | ||||
|  | ||||
| #nullable disable | ||||
|  | ||||
| namespace Elecciones.Database.Migrations | ||||
| { | ||||
|     /// <inheritdoc /> | ||||
|     public partial class AddCategoriasElectorales : Migration | ||||
|     { | ||||
|         /// <inheritdoc /> | ||||
|         protected override void Up(MigrationBuilder migrationBuilder) | ||||
|         { | ||||
|             migrationBuilder.CreateTable( | ||||
|                 name: "CategoriasElectorales", | ||||
|                 columns: table => new | ||||
|                 { | ||||
|                     Id = table.Column<int>(type: "int", nullable: false), | ||||
|                     Nombre = table.Column<string>(type: "nvarchar(max)", nullable: false), | ||||
|                     Orden = table.Column<int>(type: "int", nullable: false) | ||||
|                 }, | ||||
|                 constraints: table => | ||||
|                 { | ||||
|                     table.PrimaryKey("PK_CategoriasElectorales", x => x.Id); | ||||
|                 }); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         protected override void Down(MigrationBuilder migrationBuilder) | ||||
|         { | ||||
|             migrationBuilder.DropTable( | ||||
|                 name: "CategoriasElectorales"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -81,6 +81,23 @@ namespace Elecciones.Database.Migrations | ||||
|                     b.ToTable("AmbitosGeograficos"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<string>("Nombre") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<int>("Orden") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.ToTable("CategoriasElectorales"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b => | ||||
|                 { | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
| @@ -123,6 +140,63 @@ namespace Elecciones.Database.Migrations | ||||
|                     b.ToTable("EstadosRecuentos"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b => | ||||
|                 { | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("CantidadElectores") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("CantidadVotantes") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("MesasEsperadas") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("MesasTotalizadas") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<decimal>("MesasTotalizadasPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
|  | ||||
|                     b.Property<decimal>("ParticipacionPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
|  | ||||
|                     b.HasKey("AmbitoGeograficoId"); | ||||
|  | ||||
|                     b.ToTable("EstadosRecuentosGenerales"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); | ||||
|  | ||||
|                     b.Property<string>("AgrupacionPoliticaId") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(450)"); | ||||
|  | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<int>("NroBancas") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.HasIndex("AgrupacionPoliticaId"); | ||||
|  | ||||
|                     b.HasIndex("AmbitoGeograficoId"); | ||||
|  | ||||
|                     b.ToTable("ProyeccionesBancas"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b => | ||||
|                 { | ||||
|                     b.Property<long>("Id") | ||||
| @@ -151,6 +225,56 @@ namespace Elecciones.Database.Migrations | ||||
|                     b.ToTable("ResultadosVotos"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); | ||||
|  | ||||
|                     b.Property<string>("AgrupacionPoliticaId") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<long>("Votos") | ||||
|                         .HasColumnType("bigint"); | ||||
|  | ||||
|                     b.Property<decimal>("VotosPorcentaje") | ||||
|                         .HasPrecision(5, 2) | ||||
|                         .HasColumnType("decimal(5,2)"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.ToTable("ResumenesVotos"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b => | ||||
|                 { | ||||
|                     b.Property<string>("Id") | ||||
|                         .HasColumnType("nvarchar(450)"); | ||||
|  | ||||
|                     b.Property<int>("AmbitoGeograficoId") | ||||
|                         .HasColumnType("int"); | ||||
|  | ||||
|                     b.Property<string>("ContenidoBase64") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("nvarchar(max)"); | ||||
|  | ||||
|                     b.Property<DateTime>("FechaEscaneo") | ||||
|                         .HasColumnType("datetime2"); | ||||
|  | ||||
|                     b.Property<DateTime>("FechaTotalizacion") | ||||
|                         .HasColumnType("datetime2"); | ||||
|  | ||||
|                     b.HasKey("Id"); | ||||
|  | ||||
|                     b.ToTable("Telegramas"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b => | ||||
|                 { | ||||
|                     b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") | ||||
| @@ -162,6 +286,25 @@ namespace Elecciones.Database.Migrations | ||||
|                     b.Navigation("AmbitoGeografico"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b => | ||||
|                 { | ||||
|                     b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") | ||||
|                         .WithMany() | ||||
|                         .HasForeignKey("AgrupacionPoliticaId") | ||||
|                         .OnDelete(DeleteBehavior.Cascade) | ||||
|                         .IsRequired(); | ||||
|  | ||||
|                     b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") | ||||
|                         .WithMany() | ||||
|                         .HasForeignKey("AmbitoGeograficoId") | ||||
|                         .OnDelete(DeleteBehavior.Cascade) | ||||
|                         .IsRequired(); | ||||
|  | ||||
|                     b.Navigation("AgrupacionPolitica"); | ||||
|  | ||||
|                     b.Navigation("AmbitoGeografico"); | ||||
|                 }); | ||||
|  | ||||
|             modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b => | ||||
|                 { | ||||
|                     b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,14 @@ | ||||
| { | ||||
|   "runtimeOptions": { | ||||
|     "tfm": "net9.0", | ||||
|     "framework": { | ||||
|       "name": "Microsoft.NETCore.App", | ||||
|       "version": "9.0.0" | ||||
|     }, | ||||
|     "configProperties": { | ||||
|       "System.Reflection.Metadata.MetadataUpdater.IsSupported": false, | ||||
|       "System.Reflection.NullabilityInfoContext.IsSupported": true, | ||||
|       "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -13,7 +13,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b90baadeedb870b5b1c9eeeb7022a0d211b61bec")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -0,0 +1,4 @@ | ||||
| // <autogenerated /> | ||||
| using System; | ||||
| using System.Reflection; | ||||
| [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")] | ||||
| @@ -0,0 +1,22 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| // <auto-generated> | ||||
| //     This code was generated by a tool. | ||||
| // | ||||
| //     Changes to this file may cause incorrect behavior and will be lost if | ||||
| //     the code is regenerated. | ||||
| // </auto-generated> | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| using System; | ||||
| using System.Reflection; | ||||
|  | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|  | ||||
| // Generado por la clase WriteCodeFragment de MSBuild. | ||||
|  | ||||
| @@ -0,0 +1,23 @@ | ||||
| is_global = true | ||||
| build_property.TargetFramework = net9.0 | ||||
| build_property.TargetFramework = net9.0 | ||||
| build_property.TargetPlatformMinVersion =  | ||||
| build_property.TargetPlatformMinVersion =  | ||||
| build_property.UsingMicrosoftNETSdkWeb =  | ||||
| build_property.UsingMicrosoftNETSdkWeb =  | ||||
| build_property.ProjectTypeGuids =  | ||||
| build_property.ProjectTypeGuids =  | ||||
| build_property.InvariantGlobalization =  | ||||
| build_property.InvariantGlobalization =  | ||||
| build_property.PlatformNeutralAssembly =  | ||||
| build_property.PlatformNeutralAssembly =  | ||||
| build_property.EnforceExtendedAnalyzerRules =  | ||||
| build_property.EnforceExtendedAnalyzerRules =  | ||||
| build_property._SupportedPlatformList = Linux,macOS,Windows | ||||
| build_property._SupportedPlatformList = Linux,macOS,Windows | ||||
| build_property.RootNamespace = Elecciones.Database | ||||
| build_property.ProjectDir = E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\ | ||||
| build_property.EnableComHosting =  | ||||
| build_property.EnableGeneratedComInterfaceComImportInterop =  | ||||
| build_property.EffectiveAnalysisLevelStyle = 9.0 | ||||
| build_property.EnableCodeStyleSeverity =  | ||||
| @@ -0,0 +1,8 @@ | ||||
| // <auto-generated/> | ||||
| global using global::System; | ||||
| global using global::System.Collections.Generic; | ||||
| global using global::System.IO; | ||||
| global using global::System.Linq; | ||||
| global using global::System.Net.Http; | ||||
| global using global::System.Threading; | ||||
| global using global::System.Threading.Tasks; | ||||
| @@ -0,0 +1,14 @@ | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\bin\Release\net9.0\Elecciones.Database.deps.json | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\bin\Release\net9.0\Elecciones.Database.runtimeconfig.json | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\bin\Release\net9.0\Elecciones.Database.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\bin\Release\net9.0\Elecciones.Database.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\Elecciones.Database.csproj.AssemblyReference.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\Elecciones.Database.GeneratedMSBuildEditorConfig.editorconfig | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\Elecciones.Database.AssemblyInfoInputs.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\Elecciones.Database.AssemblyInfo.cs | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\Elecciones.Database.csproj.CoreCompileInputs.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\Elecciones.Database.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\refint\Elecciones.Database.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\Elecciones.Database.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\Elecciones.Database.genruntimeconfig.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Release\net9.0\ref\Elecciones.Database.dll | ||||
| @@ -9,6 +9,12 @@ | ||||
|     <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.8" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <None Update="buenos-aires-municipios.geojson"> | ||||
|       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||||
|     </None> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <PropertyGroup> | ||||
|     <TargetFramework>net9.0</TargetFramework> | ||||
|     <ImplicitUsings>enable</ImplicitUsings> | ||||
|   | ||||
| @@ -4,6 +4,7 @@ using System.Collections.Generic; | ||||
| using System.Net.Http; | ||||
| using System.Net.Http.Json; | ||||
| using System.Threading.Tasks; | ||||
| using static Elecciones.Core.DTOs.BancaDto; | ||||
|  | ||||
| namespace Elecciones.Infrastructure.Services; | ||||
|  | ||||
| @@ -18,6 +19,8 @@ public class ElectoralApiService : IElectoralApiService | ||||
|         _configuration = configuration; | ||||
|     } | ||||
|  | ||||
|     // --- MÉTODOS DE LA INTERFAZ --- | ||||
|  | ||||
|     public async Task<string?> GetAuthTokenAsync() | ||||
|     { | ||||
|         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | ||||
| @@ -67,20 +70,84 @@ public class ElectoralApiService : IElectoralApiService | ||||
|     public async Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId) | ||||
|     { | ||||
|         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | ||||
|  | ||||
|         // Construimos la URL con todos los parámetros requeridos. Usamos categoría 5 (Diputados) como ejemplo. | ||||
|         var requestUri = $"/api/resultados/getResultados?distritold={distritoId}&seccionld={seccionId}&municipiold={municipioId}&categoriald=5"; | ||||
|  | ||||
|         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | ||||
|         request.Headers.Add("Authorization", $"Bearer {authToken}"); | ||||
|  | ||||
|         var response = await client.SendAsync(request); | ||||
|         return response.IsSuccessStatusCode | ||||
|             ? await response.Content.ReadFromJsonAsync<ResultadosDto>() | ||||
|             : null; | ||||
|     } | ||||
|  | ||||
|         if (!response.IsSuccessStatusCode) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|     public async Task<RepartoBancasDto?> GetBancasAsync(string authToken, string distritoId, string seccionId) | ||||
|     { | ||||
|         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | ||||
|         var requestUri = $"/api/resultados/getBancas?distritold={distritoId}&seccionld={seccionId}&categoriald=5"; | ||||
|         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | ||||
|         request.Headers.Add("Authorization", $"Bearer {authToken}"); | ||||
|  | ||||
|         return await response.Content.ReadFromJsonAsync<ResultadosDto>(); | ||||
|         var response = await client.SendAsync(request); | ||||
|         return response.IsSuccessStatusCode | ||||
|             ? await response.Content.ReadFromJsonAsync<RepartoBancasDto>() | ||||
|             : null; | ||||
|     } | ||||
|  | ||||
|     public async Task<List<string[]>?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId) | ||||
|     { | ||||
|         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | ||||
|         var requestUri = $"/api/resultados/getTelegramasTotalizados?distritold={distritoId}&seccionld={seccionId}"; | ||||
|         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | ||||
|         request.Headers.Add("Authorization", $"Bearer {authToken}"); | ||||
|  | ||||
|         var response = await client.SendAsync(request); | ||||
|         return response.IsSuccessStatusCode | ||||
|             ? await response.Content.ReadFromJsonAsync<List<string[]>>() | ||||
|             : null; | ||||
|     } | ||||
|  | ||||
|     public async Task<TelegramaFileDto?> GetTelegramaFileAsync(string authToken, string mesaId) | ||||
|     { | ||||
|         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | ||||
|         var requestUri = $"/api/resultados/getFile?mesald={mesaId}"; | ||||
|         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | ||||
|         request.Headers.Add("Authorization", $"Bearer {authToken}"); | ||||
|  | ||||
|         var response = await client.SendAsync(request); | ||||
|         return response.IsSuccessStatusCode | ||||
|             ? await response.Content.ReadFromJsonAsync<TelegramaFileDto>() | ||||
|             : null; | ||||
|     } | ||||
|  | ||||
|     public async Task<ResumenDto?> GetResumenAsync(string authToken, string distritoId) | ||||
|     { | ||||
|         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | ||||
|         var requestUri = $"/api/resultados/getResumen?distritold={distritoId}"; | ||||
|         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | ||||
|         request.Headers.Add("Authorization", $"Bearer {authToken}"); | ||||
|         var response = await client.SendAsync(request); | ||||
|         return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<ResumenDto>() : null; | ||||
|     } | ||||
|  | ||||
|     public async Task<EstadoRecuentoGeneralDto?> GetEstadoRecuentoGeneralAsync(string authToken, string distritoId) | ||||
|     { | ||||
|         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | ||||
|         var requestUri = $"/api/estados/estadoRecuento?distritold={distritoId}"; | ||||
|         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | ||||
|         request.Headers.Add("Authorization", $"Bearer {authToken}"); | ||||
|         var response = await client.SendAsync(request); | ||||
|         return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<EstadoRecuentoGeneralDto>() : null; | ||||
|     } | ||||
|  | ||||
|     public async Task<List<CategoriaDto>?> GetCategoriasAsync(string authToken) | ||||
|     { | ||||
|         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | ||||
|         var request = new HttpRequestMessage(HttpMethod.Get, "/api/catalogo/getCategorias"); | ||||
|         request.Headers.Add("Authorization", $"Bearer {authToken}"); | ||||
|         var response = await client.SendAsync(request); | ||||
|         return response.IsSuccessStatusCode | ||||
|             ? await response.Content.ReadFromJsonAsync<List<CategoriaDto>>() | ||||
|             : null; | ||||
|     } | ||||
| } | ||||
| @@ -1,101 +1,145 @@ | ||||
| // src/Elecciones.Infrastructure/Services/FakeElectoralApiService.cs | ||||
| using Elecciones.Core.DTOs; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text.Json; | ||||
| using System.Threading.Tasks; | ||||
| using static Elecciones.Core.DTOs.BancaDto; | ||||
|  | ||||
| namespace Elecciones.Infrastructure.Services; | ||||
|  | ||||
| public class FakeElectoralApiService : IElectoralApiService | ||||
| { | ||||
|     private readonly ILogger<FakeElectoralApiService> _logger; | ||||
|     private List<AmbitoDto>? _fakeAmbitosCache = null; | ||||
|     private readonly Random _random = new Random(); | ||||
|  | ||||
|     public FakeElectoralApiService(ILogger<FakeElectoralApiService> logger) | ||||
|     { | ||||
|         _logger = logger; | ||||
|     } | ||||
|  | ||||
|     private void GenerateFakeAmbitosFromGeoJson() | ||||
|     { | ||||
|         if (_fakeAmbitosCache != null) return; | ||||
|         _logger.LogWarning("--- USANDO SERVICIO FALSO (FAKE) ---"); | ||||
|         _logger.LogInformation("Generando datos de prueba de ámbitos desde el archivo GeoJSON..."); | ||||
|  | ||||
|         var geoJsonPath = Path.Combine(AppContext.BaseDirectory, "buenos-aires-municipios.geojson"); | ||||
|         if (!File.Exists(geoJsonPath)) | ||||
|         { | ||||
|             _logger.LogError("No se encontró el archivo buenos-aires-municipios.geojson."); | ||||
|             _fakeAmbitosCache = new List<AmbitoDto>(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         var geoJsonString = File.ReadAllText(geoJsonPath); | ||||
|         using var document = JsonDocument.Parse(geoJsonString); | ||||
|         var features = document.RootElement.GetProperty("features").EnumerateArray().ToList(); | ||||
|  | ||||
|         var ambitos = new List<AmbitoDto>(); | ||||
|         ambitos.Add(new AmbitoDto { NivelId = 10, Nombre = "BUENOS AIRES", CodigoAmbitos = new CodigoAmbitoDto { DistritoId = "02" } }); | ||||
|         var secciones = new List<AmbitoDto> { | ||||
|             new() { NivelId = 4, Nombre = "PRIMERA SECCION ELECTORAL", CodigoAmbitos = new CodigoAmbitoDto { DistritoId = "02", SeccionId = "0001" } }, | ||||
|             new() { NivelId = 4, Nombre = "SEGUNDA SECCION ELECTORAL", CodigoAmbitos = new CodigoAmbitoDto { DistritoId = "02", SeccionId = "0002" } }, | ||||
|             new() { NivelId = 4, Nombre = "TERCERA SECCION ELECTORAL", CodigoAmbitos = new CodigoAmbitoDto { DistritoId = "02", SeccionId = "0003" } } | ||||
|         }; | ||||
|         ambitos.AddRange(secciones); | ||||
|  | ||||
|         for (int i = 0; i < features.Count; i++) | ||||
|         { | ||||
|             var feature = features[i]; | ||||
|             var properties = feature.GetProperty("properties"); | ||||
|             var seccionAsignada = secciones[i % secciones.Count]; | ||||
|             ambitos.Add(new AmbitoDto { NivelId = 5, Nombre = properties.GetProperty("nam").GetString() ?? "Sin Nombre", CodigoAmbitos = new CodigoAmbitoDto { MunicipioId = properties.GetProperty("cca").GetString(), DistritoId = "02", SeccionId = seccionAsignada.CodigoAmbitos.SeccionId } }); | ||||
|         } | ||||
|         _fakeAmbitosCache = ambitos; | ||||
|         _logger.LogInformation("Se generaron {count} ámbitos de prueba (Provincia, Secciones y Municipios).", _fakeAmbitosCache.Count); | ||||
|     } | ||||
|  | ||||
|     public Task<ResumenDto?> GetResumenAsync(string authToken, string distritoId) | ||||
|     { | ||||
|         _logger.LogInformation("Simulando obtención de Resumen para distrito {DistritoId}...", distritoId); | ||||
|         var resumen = new ResumenDto | ||||
|         { | ||||
|             ValoresTotalizadosPositivos = new List<ResumenPositivoDto> | ||||
|         { | ||||
|             new() { IdAgrupacion = "025", Votos = 2500000 + _random.Next(1000), VotosPorcentaje = 45.12m }, | ||||
|             new() { IdAgrupacion = "018", Votos = 2100000 + _random.Next(1000), VotosPorcentaje = 38.78m }, | ||||
|             new() { IdAgrupacion = "031", Votos = 800000 + _random.Next(1000), VotosPorcentaje = 14.10m } | ||||
|         } | ||||
|         }; | ||||
|         return Task.FromResult<ResumenDto?>(resumen); | ||||
|     } | ||||
|  | ||||
|     public Task<EstadoRecuentoGeneralDto?> GetEstadoRecuentoGeneralAsync(string authToken, string distritoId) | ||||
|     { | ||||
|         _logger.LogInformation("Simulando obtención de Estado de Recuento General para distrito {DistritoId}...", distritoId); | ||||
|         var estado = new EstadoRecuentoGeneralDto | ||||
|         { | ||||
|             MesasEsperadas = 38000, | ||||
|             MesasTotalizadas = _random.Next(28000, 37000), | ||||
|             MesasTotalizadasPorcentaje = 95.5m, | ||||
|             CantidadElectores = 12500000, | ||||
|             CantidadVotantes = 9375000, | ||||
|             ParticipacionPorcentaje = 75.0m | ||||
|         }; | ||||
|         return Task.FromResult<EstadoRecuentoGeneralDto?>(estado); | ||||
|     } | ||||
|  | ||||
|     public Task<string?> GetAuthTokenAsync() | ||||
|     { | ||||
|         _logger.LogWarning("--- USANDO SERVICIO FALSO (FAKE) ---"); | ||||
|         _logger.LogInformation("Simulando obtención de token..."); | ||||
|         string fakeToken = "FAKE_TOKEN_FOR_DEVELOPMENT"; | ||||
|         return Task.FromResult<string?>(fakeToken); | ||||
|         return Task.FromResult<string?>("FAKE_TOKEN_FOR_DEVELOPMENT"); | ||||
|     } | ||||
|  | ||||
|     public Task<List<CatalogoDto>?> GetCatalogoCompletoAsync(string authToken) | ||||
|     { | ||||
|         _logger.LogInformation("Simulando obtención de Catálogo Completo..."); | ||||
|  | ||||
|         var catalogo = new List<CatalogoDto> | ||||
|         { | ||||
|             new() // Simulamos el catálogo para la categoría de Diputados (ID 5) | ||||
|             { | ||||
|                 Version = 1, | ||||
|                 CategoriaId = 5, | ||||
|                 Ambitos = | ||||
|                 [ | ||||
|                     new() { NivelId = 10, Nombre = "BUENOS AIRES", CodigoAmbitos = new() { DistritoId = "02" } }, | ||||
|                     new() { NivelId = 5, Nombre = "LA PLATA", CodigoAmbitos = new() { DistritoId = "02", SeccionId = "0001", MunicipioId = "056" } }, | ||||
|                     new() { NivelId = 5, Nombre = "MAR DEL PLATA", CodigoAmbitos = new() { DistritoId = "02", SeccionId = "0005", MunicipioId = "035" } } | ||||
|                 ], | ||||
|                 Niveles = | ||||
|                 [ | ||||
|                     new() { NivelId = 10, Nombre = "Provincia" }, | ||||
|                     new() { NivelId = 5, Nombre = "Municipio" } | ||||
|                 ] | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         GenerateFakeAmbitosFromGeoJson(); | ||||
|         var catalogo = new List<CatalogoDto> { new() { Version = 1, CategoriaId = 5, Ambitos = _fakeAmbitosCache ?? new List<AmbitoDto>(), Niveles = new List<NivelDto> { new() { NivelId = 10, Nombre = "Provincia" }, new() { NivelId = 4, Nombre = "Seccion" }, new() { NivelId = 5, Nombre = "Municipio" } } } }; | ||||
|         return Task.FromResult<List<CatalogoDto>?>(catalogo); | ||||
|     } | ||||
|  | ||||
|     public Task<List<AgrupacionDto>?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId) | ||||
|     { | ||||
|         _logger.LogInformation("Simulando obtención de Agrupaciones Políticas para el distrito {Distrito} y categoría {Categoria}...", distritoId, categoriaId); | ||||
|  | ||||
|         var agrupaciones = new List<AgrupacionDto> | ||||
|     { | ||||
|         new() { IdAgrupacion = "018", IdAgrupacionTelegrama = "131", NombreAgrupacion = "FRENTE DE AVANZADA" }, | ||||
|         new() { IdAgrupacion = "025", IdAgrupacionTelegrama = "132", NombreAgrupacion = "ALIANZA POR EL FUTURO" }, | ||||
|         new() { IdAgrupacion = "031", IdAgrupacionTelegrama = "133", NombreAgrupacion = "UNION POPULAR" }, | ||||
|         new() { IdAgrupacion = "045", IdAgrupacionTelegrama = "134", NombreAgrupacion = "PARTIDO VECINALISTA" } | ||||
|     }; | ||||
|  | ||||
|         var agrupaciones = new List<AgrupacionDto> { new() { IdAgrupacion = "018", IdAgrupacionTelegrama = "131", NombreAgrupacion = "FRENTE DE AVANZADA" }, new() { IdAgrupacion = "025", IdAgrupacionTelegrama = "132", NombreAgrupacion = "ALIANZA POR EL FUTURO" }, new() { IdAgrupacion = "031", IdAgrupacionTelegrama = "133", NombreAgrupacion = "UNION POPULAR" }, new() { IdAgrupacion = "045", IdAgrupacionTelegrama = "134", NombreAgrupacion = "PARTIDO VECINALISTA" } }; | ||||
|         return Task.FromResult<List<AgrupacionDto>?>(agrupaciones); | ||||
|     } | ||||
|  | ||||
|     public Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId) | ||||
|     { | ||||
|         _logger.LogInformation("Simulando obtención de Resultados para el municipio {MunicipioId}...", municipioId); | ||||
|  | ||||
|         // YA NO FILTRAMOS POR ID. DEVOLVEMOS DATOS SIMULADOS PARA CUALQUIER MUNICIPIO. | ||||
|  | ||||
|         var random = new Random(); | ||||
|         var resultados = new ResultadosDto | ||||
|         { | ||||
|             FechaTotalizacion = DateTime.Now.ToString("o"), | ||||
|             EstadoRecuento = new EstadoRecuentoDto | ||||
|             { | ||||
|                 MesasEsperadas = random.Next(100, 2000), // Hacemos que varíe | ||||
|                 MesasTotalizadas = random.Next(50, 100), | ||||
|                 CantidadElectores = random.Next(50000, 600000), | ||||
|                 ParticipacionPorcentaje = random.Next(60, 85) + (decimal)random.NextDouble() | ||||
|             }, | ||||
|             ValoresTotalizadosPositivos = | ||||
|             [ | ||||
|                 // Usamos los IDs reales de nuestro catálogo de agrupaciones falsas | ||||
|                 new() { IdAgrupacion = "018", NombreAgrupacion = "FRENTE DE AVANZADA", Votos = random.Next(10000, 20000) }, | ||||
|             new() { IdAgrupacion = "025", NombreAgrupacion = "ALIANZA POR EL FUTURO", Votos = random.Next(15000, 25000) }, | ||||
|             new() { IdAgrupacion = "031", NombreAgrupacion = "UNION POPULAR", Votos = random.Next(5000, 10000) }, | ||||
|             new() { IdAgrupacion = "045", NombreAgrupacion = "PARTIDO VECINALISTA", Votos = random.Next(2000, 5000) } | ||||
|             ], | ||||
|             ValoresTotalizadosOtros = new VotosOtrosDto | ||||
|             { | ||||
|                 VotosEnBlanco = random.Next(1000, 2000), | ||||
|                 VotosNulos = random.Next(500, 1000), | ||||
|                 VotosRecurridos = random.Next(20, 50) | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         var resultados = new ResultadosDto { FechaTotalizacion = DateTime.Now.ToString("o"), EstadoRecuento = new EstadoRecuentoDto { MesasEsperadas = _random.Next(100, 2000), MesasTotalizadas = _random.Next(50, 100), CantidadElectores = _random.Next(50000, 600000), ParticipacionPorcentaje = _random.Next(60, 85) + (decimal)_random.NextDouble() }, ValoresTotalizadosPositivos = new List<VotosPositivosDto> { new() { IdAgrupacion = "018", Votos = _random.Next(10000, 20000) }, new() { IdAgrupacion = "025", Votos = _random.Next(15000, 25000) }, new() { IdAgrupacion = "031", Votos = _random.Next(5000, 10000) }, new() { IdAgrupacion = "045", Votos = _random.Next(2000, 5000) } }, ValoresTotalizadosOtros = new VotosOtrosDto { VotosEnBlanco = _random.Next(1000, 2000), VotosNulos = _random.Next(500, 1000), VotosRecurridos = _random.Next(20, 50) } }; | ||||
|         return Task.FromResult<ResultadosDto?>(resultados); | ||||
|     } | ||||
|  | ||||
|     public Task<RepartoBancasDto?> GetBancasAsync(string authToken, string distritoId, string seccionId) | ||||
|     { | ||||
|         var reparto = new RepartoBancasDto { RepartoBancas = new List<BancaDto> { new() { IdAgrupacion = "025", NroBancas = _random.Next(5, 9) }, new() { IdAgrupacion = "018", NroBancas = _random.Next(3, 7) } } }; | ||||
|         return Task.FromResult<RepartoBancasDto?>(reparto); | ||||
|     } | ||||
|  | ||||
|     public Task<List<string[]>?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId) | ||||
|     { | ||||
|         var lista = new List<string[]> { new[] { $"02{seccionId}0001M" }, new[] { $"02{seccionId}0002M" } }; | ||||
|         return Task.FromResult<List<string[]>?>(lista); | ||||
|     } | ||||
|  | ||||
|     public Task<TelegramaFileDto?> GetTelegramaFileAsync(string authToken, string mesaId) | ||||
|     { | ||||
|         var file = new TelegramaFileDto { NombreArchivo = mesaId, Imagen = "FAKE_BASE64_PDF_CONTENT", FechaEscaneo = DateTime.UtcNow.AddMinutes(-10).ToString("o"), FechaTotalizacion = DateTime.UtcNow.ToString("o") }; | ||||
|         return Task.FromResult<TelegramaFileDto?>(file); | ||||
|     } | ||||
|  | ||||
|     public Task<List<CategoriaDto>?> GetCategoriasAsync(string authToken) | ||||
|     { | ||||
|         _logger.LogInformation("Simulando obtención de Categorías Electorales..."); | ||||
|         var categorias = new List<CategoriaDto> | ||||
|     { | ||||
|         new() { CategoriaId = 5, Nombre = "DIPUTADOS NACIONALES", Orden = 1 }, | ||||
|         new() { CategoriaId = 6, Nombre = "SENADORES NACIONALES", Orden = 2 } | ||||
|     }; | ||||
|         return Task.FromResult<List<CategoriaDto>?>(categorias); | ||||
|     } | ||||
| } | ||||
| @@ -1,12 +1,24 @@ | ||||
| // src/Elecciones.Infrastructure/Services/IElectoralApiService.cs | ||||
| using Elecciones.Core.DTOs; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | ||||
| using static Elecciones.Core.DTOs.BancaDto; | ||||
|  | ||||
| namespace Elecciones.Infrastructure.Services; | ||||
|  | ||||
| public interface IElectoralApiService | ||||
| { | ||||
|     Task<string?> GetAuthTokenAsync(); | ||||
|  | ||||
|     // Métodos para catálogos | ||||
|     Task<List<CatalogoDto>?> GetCatalogoCompletoAsync(string authToken); | ||||
|     Task<List<AgrupacionDto>?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId); | ||||
|  | ||||
|     // Métodos para resultados y datos dinámicos | ||||
|     Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId); | ||||
|     Task<RepartoBancasDto?> GetBancasAsync(string authToken, string distritoId, string seccionId); | ||||
|     Task<List<string[]>?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId); | ||||
|     Task<TelegramaFileDto?> GetTelegramaFileAsync(string authToken, string mesaId); | ||||
|     Task<ResumenDto?> GetResumenAsync(string authToken, string distritoId); | ||||
|     Task<EstadoRecuentoGeneralDto?> GetEstadoRecuentoGeneralAsync(string authToken, string distritoId); | ||||
|     Task<List<CategoriaDto>?> GetCategoriasAsync(string authToken); | ||||
| } | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -0,0 +1,285 @@ | ||||
| { | ||||
|   "runtimeTarget": { | ||||
|     "name": ".NETCoreApp,Version=v9.0", | ||||
|     "signature": "" | ||||
|   }, | ||||
|   "compilationOptions": {}, | ||||
|   "targets": { | ||||
|     ".NETCoreApp,Version=v9.0": { | ||||
|       "Elecciones.Infrastructure/1.0.0": { | ||||
|         "dependencies": { | ||||
|           "Elecciones.Core": "1.0.0", | ||||
|           "Microsoft.Extensions.Configuration.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Http": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "Elecciones.Infrastructure.dll": {} | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Configuration/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Primitives": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Configuration.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Configuration.Abstractions/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Primitives": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Configuration.Abstractions.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Configuration.Binder/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration.Abstractions": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Configuration.Binder.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.DependencyInjection/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.DependencyInjection.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.8": { | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Diagnostics/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration": "9.0.8", | ||||
|           "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Diagnostics.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Diagnostics.Abstractions/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Options": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Http/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Diagnostics": "9.0.8", | ||||
|           "Microsoft.Extensions.Logging": "9.0.8", | ||||
|           "Microsoft.Extensions.Logging.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Options": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Http.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Logging/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.DependencyInjection": "9.0.8", | ||||
|           "Microsoft.Extensions.Logging.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Options": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Logging.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Logging.Abstractions/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Options/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Primitives": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Options.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Options.ConfigurationExtensions/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Configuration.Binder": "9.0.8", | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Options": "9.0.8", | ||||
|           "Microsoft.Extensions.Primitives": "9.0.8" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Primitives/9.0.8": { | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.Primitives.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.825.36511" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Elecciones.Core/1.0.0": { | ||||
|         "runtime": { | ||||
|           "Elecciones.Core.dll": { | ||||
|             "assemblyVersion": "1.0.0.0", | ||||
|             "fileVersion": "1.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   "libraries": { | ||||
|     "Elecciones.Infrastructure/1.0.0": { | ||||
|       "type": "project", | ||||
|       "serviceable": false, | ||||
|       "sha512": "" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Configuration/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-6m+8Xgmf8UWL0p/oGqBM+0KbHE5/ePXbV1hKXgC59zEv0aa0DW5oiiyxDbK5kH5j4gIvyD5uWL0+HadKBJngvQ==", | ||||
|       "path": "microsoft.extensions.configuration/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.configuration.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Configuration.Abstractions/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-yNou2KM35RvzOh4vUFtl2l33rWPvOCoba+nzEDJ+BgD8aOL/jew4WPCibQvntRfOJ2pJU8ARygSMD+pdjvDHuA==", | ||||
|       "path": "microsoft.extensions.configuration.abstractions/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.configuration.abstractions.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Configuration.Binder/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-0vK9DnYrYChdiH3yRZWkkp4x4LbrfkWEdBc5HOsQ8t/0CLOWKXKkkhOE8A1shlex0hGydbGrhObeypxz/QTm+w==", | ||||
|       "path": "microsoft.extensions.configuration.binder/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.configuration.binder.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.DependencyInjection/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-JJjI2Fa+QtZcUyuNjbKn04OjIUX5IgFGFu/Xc+qvzh1rXdZHLcnqqVXhR4093bGirTwacRlHiVg1XYI9xum6QQ==", | ||||
|       "path": "microsoft.extensions.dependencyinjection/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.dependencyinjection.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-xY3lTjj4+ZYmiKIkyWitddrp1uL5uYiweQjqo4BKBw01ZC4HhcfgLghDpPZcUlppgWAFqFy9SgkiYWOMx365pw==", | ||||
|       "path": "microsoft.extensions.dependencyinjection.abstractions/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.dependencyinjection.abstractions.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Diagnostics/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-BKkLCFXzJvNmdngeYBf72VXoZqTJSb1orvjdzDLaGobicoGFBPW8ug2ru1nnEewMEwJzMgnsjHQY8EaKWmVhKg==", | ||||
|       "path": "microsoft.extensions.diagnostics/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.diagnostics.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Diagnostics.Abstractions/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-UDY7blv4DCyIJ/8CkNrQKLaAZFypXQavRZ2DWf/2zi1mxYYKKw2t8AOCBWxNntyPZHPGhtEmL3snFM98ADZqTw==", | ||||
|       "path": "microsoft.extensions.diagnostics.abstractions/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.diagnostics.abstractions.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Http/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-jDj+4aDByk47oESlDDTtk6LWzlXlmoCsjCn6ihd+i9OntN885aPLszUII5+w0B/7wYSZcS3KdjqLAIhKLSiBXQ==", | ||||
|       "path": "microsoft.extensions.http/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.http.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Logging/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-Z/7ze+0iheT7FJeZPqJKARYvyC2bmwu3whbm/48BJjdlGVvgDguoCqJIkI/67NkroTYobd5geai1WheNQvWrgA==", | ||||
|       "path": "microsoft.extensions.logging/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.logging.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Logging.Abstractions/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-pYnAffJL7ARD/HCnnPvnFKSIHnTSmWz84WIlT9tPeQ4lHNiu0Az7N/8itihWvcF8sT+VVD5lq8V+ckMzu4SbOw==", | ||||
|       "path": "microsoft.extensions.logging.abstractions/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.logging.abstractions.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Options/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-OmTaQ0v4gxGQkehpwWIqPoEiwsPuG/u4HUsbOFoWGx4DKET2AXzopnFe/fE608FIhzc/kcg2p8JdyMRCCUzitQ==", | ||||
|       "path": "microsoft.extensions.options/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.options.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Options.ConfigurationExtensions/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-eW2s6n06x0w6w4nsX+SvpgsFYkl+Y0CttYAt6DKUXeqprX+hzNqjSfOh637fwNJBg7wRBrOIRHe49gKiTgJxzQ==", | ||||
|       "path": "microsoft.extensions.options.configurationextensions/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.options.configurationextensions.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Primitives/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-tizSIOEsIgSNSSh+hKeUVPK7xmTIjR8s+mJWOu1KXV3htvNQiPMFRMO17OdI1y/4ZApdBVk49u/08QGC9yvLug==", | ||||
|       "path": "microsoft.extensions.primitives/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.primitives.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Elecciones.Core/1.0.0": { | ||||
|       "type": "project", | ||||
|       "serviceable": false, | ||||
|       "sha512": "" | ||||
|     } | ||||
|   } | ||||
| } | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -13,7 +13,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b90baadeedb870b5b1c9eeeb7022a0d211b61bec")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -13,3 +13,4 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Debug\net9.0 | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Debug\net9.0\refint\Elecciones.Infrastructure.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Debug\net9.0\Elecciones.Infrastructure.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Debug\net9.0\ref\Elecciones.Infrastructure.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\bin\Debug\net9.0\buenos-aires-municipios.geojson | ||||
|   | ||||
| @@ -0,0 +1,4 @@ | ||||
| // <autogenerated /> | ||||
| using System; | ||||
| using System.Reflection; | ||||
| [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")] | ||||
| @@ -0,0 +1,22 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| // <auto-generated> | ||||
| //     This code was generated by a tool. | ||||
| // | ||||
| //     Changes to this file may cause incorrect behavior and will be lost if | ||||
| //     the code is regenerated. | ||||
| // </auto-generated> | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| using System; | ||||
| using System.Reflection; | ||||
|  | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|  | ||||
| // Generado por la clase WriteCodeFragment de MSBuild. | ||||
|  | ||||
| @@ -0,0 +1,15 @@ | ||||
| is_global = true | ||||
| build_property.TargetFramework = net9.0 | ||||
| build_property.TargetPlatformMinVersion =  | ||||
| build_property.UsingMicrosoftNETSdkWeb =  | ||||
| build_property.ProjectTypeGuids =  | ||||
| build_property.InvariantGlobalization =  | ||||
| build_property.PlatformNeutralAssembly =  | ||||
| build_property.EnforceExtendedAnalyzerRules =  | ||||
| build_property._SupportedPlatformList = Linux,macOS,Windows | ||||
| build_property.RootNamespace = Elecciones.Infrastructure | ||||
| build_property.ProjectDir = E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\ | ||||
| build_property.EnableComHosting =  | ||||
| build_property.EnableGeneratedComInterfaceComImportInterop =  | ||||
| build_property.EffectiveAnalysisLevelStyle = 9.0 | ||||
| build_property.EnableCodeStyleSeverity =  | ||||
| @@ -0,0 +1,8 @@ | ||||
| // <auto-generated/> | ||||
| global using global::System; | ||||
| global using global::System.Collections.Generic; | ||||
| global using global::System.IO; | ||||
| global using global::System.Linq; | ||||
| global using global::System.Net.Http; | ||||
| global using global::System.Threading; | ||||
| global using global::System.Threading.Tasks; | ||||
| @@ -0,0 +1,16 @@ | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\bin\Release\net9.0\buenos-aires-municipios.geojson | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\bin\Release\net9.0\Elecciones.Infrastructure.deps.json | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\bin\Release\net9.0\Elecciones.Infrastructure.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\bin\Release\net9.0\Elecciones.Infrastructure.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\bin\Release\net9.0\Elecciones.Core.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\bin\Release\net9.0\Elecciones.Core.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\Elecciones.Infrastructure.csproj.AssemblyReference.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\Elecciones.Infrastructure.GeneratedMSBuildEditorConfig.editorconfig | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\Elecciones.Infrastructure.AssemblyInfoInputs.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\Elecciones.Infrastructure.AssemblyInfo.cs | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\Elecciones.Infrastructure.csproj.CoreCompileInputs.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\Eleccion.B7F7B2EF.Up2Date | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\Elecciones.Infrastructure.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\refint\Elecciones.Infrastructure.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\Elecciones.Infrastructure.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Infrastructure\obj\Release\net9.0\ref\Elecciones.Infrastructure.dll | ||||
| @@ -11,6 +11,10 @@ | ||||
|     <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.8" /> | ||||
|     <PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" /> | ||||
|     <PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" /> | ||||
|     <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> | ||||
|     <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|   | ||||
| @@ -2,23 +2,37 @@ using Elecciones.Database; | ||||
| using Elecciones.Infrastructure.Services; | ||||
| using Elecciones.Worker; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Hosting; | ||||
| using Serilog; | ||||
| using System.Net.Http; | ||||
| using System.Net.Security; | ||||
| using System.Security.Authentication; | ||||
|  | ||||
| Log.Logger = new LoggerConfiguration() | ||||
|     .WriteTo.Console() | ||||
|     .CreateBootstrapLogger(); | ||||
|  | ||||
| Log.Information("Iniciando Elecciones.Worker Host..."); | ||||
|  | ||||
| var builder = Host.CreateApplicationBuilder(args); | ||||
|  | ||||
| // --- Configuración de Servicios --- | ||||
| builder.Services.AddSerilog(config =>  | ||||
|     config | ||||
|         .ReadFrom.Configuration(builder.Configuration) | ||||
|         .Enrich.FromLogContext() | ||||
|         .WriteTo.Console() | ||||
|         .WriteTo.File("logs/worker-.log", rollingInterval: RollingInterval.Day)); | ||||
|  | ||||
| // 1. Configuración de Base de Datos (¡Este bloque es esencial!) | ||||
| // --- Configuración de Servicios --- | ||||
| var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); | ||||
| builder.Services.AddDbContext<EleccionesDbContext>(options => | ||||
|     options.UseSqlServer(connectionString)); | ||||
|  | ||||
| // 2. Configuración del Servicio de API (elegirá el Real o el Falso según el modo de compilación) | ||||
| #if DEBUG | ||||
| // En modo DEBUG (desarrollo local), usamos el servicio FALSO. | ||||
| // No es necesario registrar el ILogger, .NET lo inyecta automáticamente. | ||||
| builder.Services.AddSingleton<IElectoralApiService, FakeElectoralApiService>(); | ||||
| #else | ||||
| // En modo RELEASE (producción), usamos el servicio REAL. | ||||
| // --- SECCIÓN MODIFICADA (FINAL) --- | ||||
| builder.Services.AddHttpClient("ElectoralApiClient", client => | ||||
| { | ||||
|     var baseUrl = builder.Configuration["ElectoralApi:BaseUrl"]; | ||||
| @@ -26,13 +40,44 @@ builder.Services.AddHttpClient("ElectoralApiClient", client => | ||||
|     { | ||||
|         client.BaseAddress = new Uri(baseUrl); | ||||
|     } | ||||
| }) | ||||
| .ConfigurePrimaryHttpMessageHandler(() => | ||||
| { | ||||
|     return new SocketsHttpHandler | ||||
|     { | ||||
|         SslOptions = new SslClientAuthenticationOptions | ||||
|         { | ||||
|             // Forzamos el protocolo TLS 1.3 | ||||
|             EnabledSslProtocols = SslProtocols.Tls13, | ||||
|  | ||||
|             // --- ¡¡¡LA LÍNEA CLAVE CORREGIDA!!! --- | ||||
|             // Forzamos explícitamente los únicos 3 cipher suites que el servidor acepta. | ||||
|             CipherSuitesPolicy = new CipherSuitesPolicy(new[] | ||||
|             { | ||||
|                 TlsCipherSuite.TLS_AES_128_GCM_SHA256, | ||||
|                 TlsCipherSuite.TLS_AES_256_GCM_SHA384, | ||||
|                 TlsCipherSuite.TLS_CHACHA20_POLY1305_SHA256 | ||||
|             }) | ||||
|         } | ||||
|     }; | ||||
| }); | ||||
|  | ||||
| builder.Services.AddSingleton<IElectoralApiService, ElectoralApiService>(); | ||||
| // --- FIN DE LA SECCIÓN MODIFICADA --- | ||||
| #endif | ||||
|  | ||||
| // 3. Registrar el Worker como un servicio que se ejecuta en segundo plano. | ||||
| builder.Services.AddHostedService<Worker>(); | ||||
|  | ||||
|  | ||||
| var host = builder.Build(); | ||||
| host.Run(); | ||||
|  | ||||
| try { | ||||
|     host.Run(); | ||||
| } | ||||
| catch (Exception ex) | ||||
| { | ||||
|     Log.Fatal(ex, "El Host de Elecciones.Worker terminó inesperadamente"); | ||||
| } | ||||
| finally | ||||
| { | ||||
|     Log.CloseAndFlush(); | ||||
| } | ||||
| @@ -28,33 +28,36 @@ public class Worker : BackgroundService | ||||
|     { | ||||
|         _logger.LogInformation("Elecciones Worker iniciado a las: {time}", DateTimeOffset.Now); | ||||
|  | ||||
|         // --- 1. SINCRONIZACIÓN INICIAL DE CATÁLOGOS --- | ||||
|         // Se ejecuta una sola vez al inicio para poblar las tablas maestras. | ||||
|         await SincronizarCatalogosAsync(stoppingToken); | ||||
|  | ||||
|         // --- 2. BUCLE DE SONDEO DE RESULTADOS --- | ||||
|         _logger.LogInformation("-------------------------------------------------"); | ||||
|         _logger.LogInformation("Iniciando sondeo periódico de resultados..."); | ||||
|         _logger.LogInformation("-------------------------------------------------"); | ||||
|  | ||||
|         while (!stoppingToken.IsCancellationRequested) | ||||
|         { | ||||
|             await SondearResultadosAsync(stoppingToken); | ||||
|             // Ejecutamos todos los sondeos en paralelo para mayor eficiencia | ||||
|             await Task.WhenAll( | ||||
|                 SondearResultadosAsync(stoppingToken), | ||||
|                 SondearBancasAsync(stoppingToken), | ||||
|                 SondearTelegramasAsync(stoppingToken), | ||||
|                 SondearResumenProvincialAsync(stoppingToken), | ||||
|                 SondearEstadoRecuentoGeneralAsync(stoppingToken) | ||||
|             ); | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 // Esperamos 10 segundos antes de la siguiente consulta. | ||||
|                 await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken); | ||||
|             } | ||||
|             catch (TaskCanceledException) | ||||
|             { | ||||
|                 // Es normal que esto ocurra cuando se detiene la aplicación. | ||||
|                 break; | ||||
|                 // Esperamos 1 minuto antes del siguiente ciclo completo de sondeos | ||||
|                 _logger.LogInformation("Ciclo de sondeo completado. Esperando 1 minuto para el siguiente..."); | ||||
|                 await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken); | ||||
|             } | ||||
|             catch (TaskCanceledException) { break; } | ||||
|         } | ||||
|  | ||||
|         _logger.LogInformation("Elecciones Worker se está deteniendo."); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     private async Task ObtenerTokenSiEsNecesario(CancellationToken stoppingToken) | ||||
|     { | ||||
|         // En un futuro, se podría añadir lógica para renovar el token solo cuando expire. | ||||
| @@ -114,7 +117,6 @@ public class Worker : BackgroundService | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // NUEVO MÉTODO AUXILIAR PARA GUARDAR LOS DATOS | ||||
|     private async Task GuardarResultadosDeAmbitoAsync(EleccionesDbContext dbContext, int ambitoId, Elecciones.Core.DTOs.ResultadosDto resultados, CancellationToken stoppingToken) | ||||
|     { | ||||
|         // --- ACTUALIZAR O INSERTAR ESTADO RECUENTO --- | ||||
| @@ -168,66 +170,359 @@ public class Worker : BackgroundService | ||||
|             using var scope = _serviceProvider.CreateScope(); | ||||
|             var dbContext = scope.ServiceProvider.GetRequiredService<EleccionesDbContext>(); | ||||
|  | ||||
|             _logger.LogInformation("Limpiando tablas maestras para la nueva ingesta..."); | ||||
|             await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM ResultadosVotos", stoppingToken); | ||||
|             await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM EstadosRecuentos", stoppingToken); | ||||
|             await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM AgrupacionesPoliticas", stoppingToken); | ||||
|             await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM AmbitosGeograficos", stoppingToken); | ||||
|  | ||||
|             // --- 1. INGESTA DE ÁMBITOS GEOGRÁFICOS --- | ||||
|             var catalogos = await _apiService.GetCatalogoCompletoAsync(_authToken); | ||||
|             if (catalogos is { Count: > 0 }) | ||||
|             // --- 1. SINCRONIZACIÓN DE CATEGORÍAS (NUEVO) --- | ||||
|             var categoriasApi = await _apiService.GetCategoriasAsync(_authToken); | ||||
|             if (categoriasApi is { Count: > 0 }) | ||||
|             { | ||||
|                 foreach (var ambitoDto in catalogos.SelectMany(c => c.Ambitos)) | ||||
|                 var categoriasEnDb = await dbContext.CategoriasElectorales.ToDictionaryAsync(c => c.Id, c => c, stoppingToken); | ||||
|                 foreach (var categoriaDto in categoriasApi) | ||||
|                 { | ||||
|                     var nuevoAmbito = new AmbitoGeografico | ||||
|                     if (categoriasEnDb.TryGetValue(categoriaDto.CategoriaId, out var categoriaExistente)) | ||||
|                     { | ||||
|                         Nombre = ambitoDto.Nombre, | ||||
|                         NivelId = ambitoDto.NivelId, | ||||
|                         DistritoId = ambitoDto.CodigoAmbitos.DistritoId, | ||||
|                         SeccionId = ambitoDto.CodigoAmbitos.SeccionId, | ||||
|                         MunicipioId = ambitoDto.CodigoAmbitos.MunicipioId, | ||||
|                         SeccionProvincialId = ambitoDto.CodigoAmbitos.SeccionProvincialId | ||||
|                     }; | ||||
|                     await dbContext.AmbitosGeograficos.AddAsync(nuevoAmbito, stoppingToken); | ||||
|                         categoriaExistente.Nombre = categoriaDto.Nombre; | ||||
|                         categoriaExistente.Orden = categoriaDto.Orden; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         await dbContext.CategoriasElectorales.AddAsync(new CategoriaElectoral | ||||
|                         { | ||||
|                             Id = categoriaDto.CategoriaId, | ||||
|                             Nombre = categoriaDto.Nombre, | ||||
|                             Orden = categoriaDto.Orden | ||||
|                         }, stoppingToken); | ||||
|                     } | ||||
|                 } | ||||
|                 _logger.LogInformation("Datos de Ámbitos Geográficos listos para ser guardados."); | ||||
|                 _logger.LogInformation("Sincronización de Categorías Electorales completada."); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.LogWarning("No se recibieron datos del catálogo de Ámbitos."); | ||||
|                 _logger.LogWarning("No se recibieron datos del catálogo de Categorías."); | ||||
|             } | ||||
|  | ||||
|             // --- 2. INGESTA DE AGRUPACIONES POLÍTICAS --- | ||||
|             var agrupaciones = await _apiService.GetAgrupacionesAsync(_authToken, "02", 5); | ||||
|             if (agrupaciones is { Count: > 0 }) | ||||
|             // --- 2. SINCRONIZACIÓN DE ÁMBITOS GEOGRÁFICOS --- | ||||
|             var catalogoAmbitosApi = await _apiService.GetCatalogoCompletoAsync(_authToken); | ||||
|             if (catalogoAmbitosApi is { Count: > 0 }) | ||||
|             { | ||||
|                 foreach (var agrupacionDto in agrupaciones) | ||||
|                 // Cargamos los ámbitos existentes de la BD en un diccionario para búsqueda rápida | ||||
|                 var ambitosEnDb = await dbContext.AmbitosGeograficos | ||||
|                     .ToDictionaryAsync(a => a.MunicipioId ?? a.SeccionId ?? a.DistritoId ?? a.Nombre, a => a, stoppingToken); | ||||
|  | ||||
|                 foreach (var ambitoDto in catalogoAmbitosApi.SelectMany(c => c.Ambitos)) | ||||
|                 { | ||||
|                     var nuevaAgrupacion = new AgrupacionPolitica | ||||
|                     // Usamos una clave única para identificar el ámbito (ej. ID de municipio) | ||||
|                     var claveUnica = ambitoDto.CodigoAmbitos.MunicipioId ?? ambitoDto.CodigoAmbitos.SeccionId ?? ambitoDto.CodigoAmbitos.DistritoId ?? ambitoDto.Nombre; | ||||
|  | ||||
|                     if (ambitosEnDb.TryGetValue(claveUnica, out var ambitoExistente)) | ||||
|                     { | ||||
|                         Id = agrupacionDto.IdAgrupacion, | ||||
|                         IdTelegrama = agrupacionDto.IdAgrupacionTelegrama, | ||||
|                         Nombre = agrupacionDto.NombreAgrupacion | ||||
|                     }; | ||||
|                     await dbContext.AgrupacionesPoliticas.AddAsync(nuevaAgrupacion, stoppingToken); | ||||
|                         // El ámbito ya existe, actualizamos sus datos descriptivos. | ||||
|                         // No actualizamos los IDs, ya que forman parte de la identidad del ámbito. | ||||
|                         ambitoExistente.Nombre = ambitoDto.Nombre; | ||||
|                         ambitoExistente.NivelId = ambitoDto.NivelId; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         // El ámbito es nuevo, lo añadimos (el código de inserción que ya tenemos es correcto) | ||||
|                         var nuevoAmbito = new AmbitoGeografico | ||||
|                         { | ||||
|                             Nombre = ambitoDto.Nombre, | ||||
|                             NivelId = ambitoDto.NivelId, | ||||
|                             DistritoId = ambitoDto.CodigoAmbitos.DistritoId, | ||||
|                             SeccionId = ambitoDto.CodigoAmbitos.SeccionId, | ||||
|                             MunicipioId = ambitoDto.CodigoAmbitos.MunicipioId, | ||||
|                             SeccionProvincialId = ambitoDto.CodigoAmbitos.SeccionProvincialId | ||||
|                         }; | ||||
|                         await dbContext.AmbitosGeograficos.AddAsync(nuevoAmbito, stoppingToken); | ||||
|                     } | ||||
|                 } | ||||
|                 _logger.LogInformation("Datos de Agrupaciones Políticas listos para ser guardados."); | ||||
|                 _logger.LogInformation("Sincronización de Ámbitos Geográficos completada."); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.LogWarning("No se recibieron datos del catálogo de Agrupaciones."); | ||||
|                 _logger.LogWarning("No se recibieron datos del catálogo de Ámbitos. Los datos existentes no serán modificados."); | ||||
|             } | ||||
|  | ||||
|             // --- 3. GUARDADO FINAL EN LA BASE DE DATOS --- | ||||
|             int registrosGuardados = await dbContext.SaveChangesAsync(stoppingToken); | ||||
|             _logger.LogInformation("{count} registros totales han sido guardados en la base de datos.", registrosGuardados); | ||||
|             // --- 3. SINCRONIZACIÓN DE AGRUPACIONES POLÍTICAS --- | ||||
|             var agrupacionesApi = await _apiService.GetAgrupacionesAsync(_authToken, "02", 5); | ||||
|             if (agrupacionesApi is { Count: > 0 }) | ||||
|             { | ||||
|                 var agrupacionesEnDb = await dbContext.AgrupacionesPoliticas | ||||
|                     .ToDictionaryAsync(a => a.Id, a => a, stoppingToken); | ||||
|  | ||||
|             _logger.LogInformation("Sincronización de catálogos completada exitosamente."); | ||||
|                 foreach (var agrupacionDto in agrupacionesApi) | ||||
|                 { | ||||
|                     if (agrupacionesEnDb.TryGetValue(agrupacionDto.IdAgrupacion, out var agrupacionExistente)) | ||||
|                     { | ||||
|                         // La agrupación ya existe, actualizamos el nombre por si cambia | ||||
|                         agrupacionExistente.Nombre = agrupacionDto.NombreAgrupacion; | ||||
|                         agrupacionExistente.IdTelegrama = agrupacionDto.IdAgrupacionTelegrama; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         // La agrupación es nueva, la añadimos | ||||
|                         var nuevaAgrupacion = new AgrupacionPolitica | ||||
|                         { | ||||
|                             Id = agrupacionDto.IdAgrupacion, | ||||
|                             IdTelegrama = agrupacionDto.IdAgrupacionTelegrama, | ||||
|                             Nombre = agrupacionDto.NombreAgrupacion | ||||
|                         }; | ||||
|                         await dbContext.AgrupacionesPoliticas.AddAsync(nuevaAgrupacion, stoppingToken); | ||||
|                     } | ||||
|                 } | ||||
|                 _logger.LogInformation("Sincronización de Agrupaciones Políticas completada."); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.LogWarning("No se recibieron datos del catálogo de Agrupaciones. Los datos existentes no serán modificados."); | ||||
|             } | ||||
|  | ||||
|             // --- 4. GUARDADO FINAL --- | ||||
|             int cambiosGuardados = await dbContext.SaveChangesAsync(stoppingToken); | ||||
|             _logger.LogInformation("{count} cambios en los catálogos han sido guardados en la base de datos.", cambiosGuardados); | ||||
|  | ||||
|             _logger.LogInformation("Sincronización de catálogos maestros finalizada."); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             _logger.LogError(ex, "Ocurrió un error CRÍTICO durante la sincronización de catálogos. El worker podría no funcionar correctamente."); | ||||
|             _logger.LogError(ex, "Ocurrió un error CRÍTICO durante la sincronización de catálogos."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task SondearBancasAsync(CancellationToken stoppingToken) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             await ObtenerTokenSiEsNecesario(stoppingToken); | ||||
|             if (string.IsNullOrEmpty(_authToken) || stoppingToken.IsCancellationRequested) return; | ||||
|  | ||||
|             using var scope = _serviceProvider.CreateScope(); | ||||
|             var dbContext = scope.ServiceProvider.GetRequiredService<EleccionesDbContext>(); | ||||
|  | ||||
|             // Obtenemos las secciones electorales (donde se reparten bancas de diputados) | ||||
|             var secciones = await dbContext.AmbitosGeograficos | ||||
|                 .AsNoTracking() | ||||
|                 .Where(a => a.NivelId == 4 && a.DistritoId != null && a.SeccionId != null) // Nivel 4 = Sección Electoral | ||||
|                 .ToListAsync(stoppingToken); | ||||
|  | ||||
|             if (!secciones.Any()) | ||||
|             { | ||||
|                 _logger.LogWarning("No se encontraron ámbitos de tipo 'Sección Electoral' en la BD para sondear bancas."); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             _logger.LogInformation("Iniciando sondeo de Bancas para {count} secciones...", secciones.Count); | ||||
|  | ||||
|             // Esta bandera nos asegura que solo borramos la tabla una vez y solo si hay datos nuevos. | ||||
|             bool hasReceivedNewData = false; | ||||
|  | ||||
|             foreach (var seccion in secciones) | ||||
|             { | ||||
|                 if (stoppingToken.IsCancellationRequested) break; | ||||
|  | ||||
|                 var repartoBancas = await _apiService.GetBancasAsync(_authToken, seccion.DistritoId!, seccion.SeccionId!); | ||||
|  | ||||
|                 // Verificamos que la respuesta no sea nula y que la lista de bancas contenga al menos un elemento. | ||||
|                 if (repartoBancas?.RepartoBancas is { Count: > 0 }) | ||||
|                 { | ||||
|                     // Si esta es la primera vez en este ciclo de sondeo que recibimos datos válidos, | ||||
|                     // borramos todos los datos viejos de la tabla. | ||||
|                     if (!hasReceivedNewData) | ||||
|                     { | ||||
|                         _logger.LogInformation("Se recibieron nuevos datos de bancas. Limpiando tabla de proyecciones..."); | ||||
|                         await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM ProyeccionesBancas", stoppingToken); | ||||
|                         hasReceivedNewData = true; // Marcamos que ya hemos limpiado la tabla. | ||||
|                     } | ||||
|  | ||||
|                     // Procedemos a añadir las nuevas proyecciones a la sesión de EF Core. | ||||
|                     foreach (var banca in repartoBancas.RepartoBancas) | ||||
|                     { | ||||
|                         var nuevaProyeccion = new ProyeccionBanca | ||||
|                         { | ||||
|                             AmbitoGeograficoId = seccion.Id, | ||||
|                             AgrupacionPoliticaId = banca.IdAgrupacion, | ||||
|                             NroBancas = banca.NroBancas | ||||
|                         }; | ||||
|                         await dbContext.ProyeccionesBancas.AddAsync(nuevaProyeccion, stoppingToken); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     _logger.LogWarning("No se recibieron datos de bancas para la sección {seccionId}.", seccion.SeccionId); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Si hemos añadido alguna entidad nueva (es decir, hasReceivedNewData es true), | ||||
|             // guardamos todos los cambios en la base de datos. | ||||
|             if (hasReceivedNewData) | ||||
|             { | ||||
|                 await dbContext.SaveChangesAsync(stoppingToken); | ||||
|                 _logger.LogInformation("Sondeo de Bancas completado. La tabla de proyecciones ha sido actualizada."); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.LogInformation("Sondeo de Bancas completado. No se encontraron datos nuevos, la tabla no fue modificada."); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             _logger.LogError(ex, "Ocurrió un error en el sondeo de Bancas."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task SondearTelegramasAsync(CancellationToken stoppingToken) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             await ObtenerTokenSiEsNecesario(stoppingToken); | ||||
|             if (string.IsNullOrEmpty(_authToken) || stoppingToken.IsCancellationRequested) return; | ||||
|  | ||||
|             // --- CADA SONDEO USA SU PROPIO DBCONTEXT FRESCO --- | ||||
|             using var scope = _serviceProvider.CreateScope(); | ||||
|             var dbContext = scope.ServiceProvider.GetRequiredService<EleccionesDbContext>(); | ||||
|  | ||||
|             var secciones = await dbContext.AmbitosGeograficos | ||||
|                 .AsNoTracking() | ||||
|                 .Where(a => a.NivelId == 4 && a.DistritoId != null && a.SeccionId != null) | ||||
|                 .ToListAsync(stoppingToken); | ||||
|  | ||||
|             if (!secciones.Any()) return; | ||||
|  | ||||
|             _logger.LogInformation("Iniciando sondeo de Telegramas nuevos..."); | ||||
|  | ||||
|             foreach (var seccion in secciones) | ||||
|             { | ||||
|                 if (stoppingToken.IsCancellationRequested) break; | ||||
|  | ||||
|                 var listaTelegramasApi = await _apiService.GetTelegramasTotalizadosAsync(_authToken, seccion.DistritoId!, seccion.SeccionId!); | ||||
|                 if (listaTelegramasApi is { Count: > 0 }) | ||||
|                 { | ||||
|                     var idsDeApi = listaTelegramasApi.Select(t => t[0]).Distinct().ToList(); | ||||
|  | ||||
|                     // --- LÓGICA DE DUPLICADOS --- | ||||
|                     // Consultamos a la base de datos por los IDs que la API nos acaba de dar | ||||
|                     var idsYaEnDb = await dbContext.Telegramas | ||||
|                         .Where(t => idsDeApi.Contains(t.Id)) | ||||
|                         .Select(t => t.Id) | ||||
|                         .ToListAsync(stoppingToken); | ||||
|  | ||||
|                     // Comparamos las dos listas para encontrar los que realmente son nuevos | ||||
|                     var nuevosTelegramasIds = idsDeApi.Except(idsYaEnDb).ToList(); | ||||
|  | ||||
|                     if (!nuevosTelegramasIds.Any()) | ||||
|                     { | ||||
|                         _logger.LogInformation("No hay telegramas nuevos para la sección {seccionId}.", seccion.SeccionId); | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     _logger.LogInformation("Se encontraron {count} telegramas nuevos en la sección {seccionId}. Descargando...", nuevosTelegramasIds.Count, seccion.SeccionId); | ||||
|  | ||||
|                     foreach (var mesaId in nuevosTelegramasIds) | ||||
|                     { | ||||
|                         if (stoppingToken.IsCancellationRequested) break; | ||||
|  | ||||
|                         var telegramaFile = await _apiService.GetTelegramaFileAsync(_authToken, mesaId); | ||||
|                         if (telegramaFile != null) | ||||
|                         { | ||||
|                             var nuevoTelegrama = new Telegrama | ||||
|                             { | ||||
|                                 Id = telegramaFile.NombreArchivo, | ||||
|                                 AmbitoGeograficoId = seccion.Id, // Lo asociamos a la sección por simplicidad | ||||
|                                 ContenidoBase64 = telegramaFile.Imagen, | ||||
|                                 FechaEscaneo = DateTime.Parse(telegramaFile.FechaEscaneo).ToUniversalTime(), | ||||
|                                 FechaTotalizacion = DateTime.Parse(telegramaFile.FechaTotalizacion).ToUniversalTime() | ||||
|                             }; | ||||
|                             // Como estamos en un DbContext fresco, AddAsync no dará conflicto | ||||
|                             await dbContext.Telegramas.AddAsync(nuevoTelegrama, stoppingToken); | ||||
|                         } | ||||
|                     } | ||||
|                     // Guardamos los cambios al final de cada sección procesada | ||||
|                     await dbContext.SaveChangesAsync(stoppingToken); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             _logger.LogInformation("Sondeo de Telegramas completado."); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             _logger.LogError(ex, "Ocurrió un error en el sondeo de Telegramas."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task SondearResumenProvincialAsync(CancellationToken stoppingToken) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             await ObtenerTokenSiEsNecesario(stoppingToken); | ||||
|             if (string.IsNullOrEmpty(_authToken)) return; | ||||
|  | ||||
|             using var scope = _serviceProvider.CreateScope(); | ||||
|             var dbContext = scope.ServiceProvider.GetRequiredService<EleccionesDbContext>(); | ||||
|  | ||||
|             var provincia = await dbContext.AmbitosGeograficos.AsNoTracking().FirstOrDefaultAsync(a => a.NivelId == 10, stoppingToken); | ||||
|             if (provincia == null) return; | ||||
|  | ||||
|             var resumen = await _apiService.GetResumenAsync(_authToken, provincia.DistritoId!); | ||||
|             if (resumen?.ValoresTotalizadosPositivos is { Count: > 0 }) | ||||
|             { | ||||
|                 // Estrategia: Reemplazo completo | ||||
|                 await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM ResumenesVotos", stoppingToken); | ||||
|                 foreach (var voto in resumen.ValoresTotalizadosPositivos) | ||||
|                 { | ||||
|                     await dbContext.ResumenesVotos.AddAsync(new ResumenVoto | ||||
|                     { | ||||
|                         AmbitoGeograficoId = provincia.Id, | ||||
|                         AgrupacionPoliticaId = voto.IdAgrupacion, | ||||
|                         Votos = voto.Votos, | ||||
|                         VotosPorcentaje = voto.VotosPorcentaje | ||||
|                     }, stoppingToken); | ||||
|                 } | ||||
|                 await dbContext.SaveChangesAsync(stoppingToken); | ||||
|                 _logger.LogInformation("Sondeo de Resumen Provincial completado."); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             _logger.LogError(ex, "Ocurrió un error en el sondeo de Resumen Provincial."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task SondearEstadoRecuentoGeneralAsync(CancellationToken stoppingToken) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             await ObtenerTokenSiEsNecesario(stoppingToken); | ||||
|             if (string.IsNullOrEmpty(_authToken)) return; | ||||
|  | ||||
|             using var scope = _serviceProvider.CreateScope(); | ||||
|             var dbContext = scope.ServiceProvider.GetRequiredService<EleccionesDbContext>(); | ||||
|  | ||||
|             var provincia = await dbContext.AmbitosGeograficos.AsNoTracking().FirstOrDefaultAsync(a => a.NivelId == 10, stoppingToken); | ||||
|             if (provincia == null) return; | ||||
|  | ||||
|             var estadoDto = await _apiService.GetEstadoRecuentoGeneralAsync(_authToken, provincia.DistritoId!); | ||||
|             if (estadoDto != null) | ||||
|             { | ||||
|                 // Estrategia: Upsert | ||||
|                 var registroDb = await dbContext.EstadosRecuentosGenerales.FindAsync(provincia.Id); | ||||
|                 if (registroDb == null) | ||||
|                 { | ||||
|                     registroDb = new EstadoRecuentoGeneral { AmbitoGeograficoId = provincia.Id }; | ||||
|                     dbContext.EstadosRecuentosGenerales.Add(registroDb); | ||||
|                 } | ||||
|  | ||||
|                 registroDb.MesasEsperadas = estadoDto.MesasEsperadas; | ||||
|                 registroDb.MesasTotalizadas = estadoDto.MesasTotalizadas; | ||||
|                 registroDb.MesasTotalizadasPorcentaje = estadoDto.MesasTotalizadasPorcentaje; | ||||
|                 registroDb.CantidadElectores = estadoDto.CantidadElectores; | ||||
|                 registroDb.CantidadVotantes = estadoDto.CantidadVotantes; | ||||
|                 registroDb.ParticipacionPorcentaje = estadoDto.ParticipacionPorcentaje; | ||||
|  | ||||
|                 await dbContext.SaveChangesAsync(stoppingToken); | ||||
|                 _logger.LogInformation("Sondeo de Estado Recuento General completado."); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             _logger.LogError(ex, "Ocurrió un error en el sondeo de Estado Recuento General."); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -12,7 +12,11 @@ | ||||
|           "Elecciones.Infrastructure": "1.0.0", | ||||
|           "Microsoft.EntityFrameworkCore.SqlServer": "9.0.8", | ||||
|           "Microsoft.Extensions.Hosting": "9.0.5", | ||||
|           "Microsoft.Extensions.Http": "9.0.8" | ||||
|           "Microsoft.Extensions.Http": "9.0.8", | ||||
|           "Serilog.Extensions.Hosting": "9.0.0", | ||||
|           "Serilog.Settings.Configuration": "9.0.0", | ||||
|           "Serilog.Sinks.Console": "6.0.0", | ||||
|           "Serilog.Sinks.File": "7.0.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "Elecciones.Worker.dll": {} | ||||
| @@ -323,6 +327,14 @@ | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.DependencyModel/9.0.0": { | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Microsoft.Extensions.DependencyModel.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.24.52809" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Microsoft.Extensions.Diagnostics/9.0.8": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration": "9.0.8", | ||||
| @@ -698,6 +710,76 @@ | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog/4.2.0": { | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.dll": { | ||||
|             "assemblyVersion": "4.2.0.0", | ||||
|             "fileVersion": "4.2.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Extensions.Hosting/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", | ||||
|           "Microsoft.Extensions.Hosting.Abstractions": "9.0.5", | ||||
|           "Microsoft.Extensions.Logging.Abstractions": "9.0.8", | ||||
|           "Serilog": "4.2.0", | ||||
|           "Serilog.Extensions.Logging": "9.0.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Extensions.Hosting.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Extensions.Logging/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Logging": "9.0.8", | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Extensions.Logging.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Settings.Configuration/9.0.0": { | ||||
|         "dependencies": { | ||||
|           "Microsoft.Extensions.Configuration.Binder": "9.0.8", | ||||
|           "Microsoft.Extensions.DependencyModel": "9.0.0", | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Settings.Configuration.dll": { | ||||
|             "assemblyVersion": "9.0.0.0", | ||||
|             "fileVersion": "9.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Sinks.Console/6.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net8.0/Serilog.Sinks.Console.dll": { | ||||
|             "assemblyVersion": "6.0.0.0", | ||||
|             "fileVersion": "6.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "Serilog.Sinks.File/7.0.0": { | ||||
|         "dependencies": { | ||||
|           "Serilog": "4.2.0" | ||||
|         }, | ||||
|         "runtime": { | ||||
|           "lib/net9.0/Serilog.Sinks.File.dll": { | ||||
|             "assemblyVersion": "7.0.0.0", | ||||
|             "fileVersion": "7.0.0.0" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "System.ClientModel/1.0.0": { | ||||
|         "dependencies": { | ||||
|           "System.Memory.Data": "1.0.2", | ||||
| @@ -1115,6 +1197,13 @@ | ||||
|       "path": "microsoft.extensions.dependencyinjection.abstractions/9.0.8", | ||||
|       "hashPath": "microsoft.extensions.dependencyinjection.abstractions.9.0.8.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.DependencyModel/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-saxr2XzwgDU77LaQfYFXmddEDRUKHF4DaGMZkNB3qjdVSZlax3//dGJagJkKrGMIPNZs2jVFXITyCCR6UHJNdA==", | ||||
|       "path": "microsoft.extensions.dependencymodel/9.0.0", | ||||
|       "hashPath": "microsoft.extensions.dependencymodel.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Microsoft.Extensions.Diagnostics/9.0.8": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
| @@ -1325,6 +1414,48 @@ | ||||
|       "path": "microsoft.win32.systemevents/6.0.0", | ||||
|       "hashPath": "microsoft.win32.systemevents.6.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog/4.2.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-gmoWVOvKgbME8TYR+gwMf7osROiWAURterc6Rt2dQyX7wtjZYpqFiA/pY6ztjGQKKV62GGCyOcmtP1UKMHgSmA==", | ||||
|       "path": "serilog/4.2.0", | ||||
|       "hashPath": "serilog.4.2.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Extensions.Hosting/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-u2TRxuxbjvTAldQn7uaAwePkWxTHIqlgjelekBtilAGL5sYyF3+65NWctN4UrwwGLsDC7c3Vz3HnOlu+PcoxXg==", | ||||
|       "path": "serilog.extensions.hosting/9.0.0", | ||||
|       "hashPath": "serilog.extensions.hosting.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Extensions.Logging/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-NwSSYqPJeKNzl5AuXVHpGbr6PkZJFlNa14CdIebVjK3k/76kYj/mz5kiTRNVSsSaxM8kAIa1kpy/qyT9E4npRQ==", | ||||
|       "path": "serilog.extensions.logging/9.0.0", | ||||
|       "hashPath": "serilog.extensions.logging.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Settings.Configuration/9.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-4/Et4Cqwa+F88l5SeFeNZ4c4Z6dEAIKbu3MaQb2Zz9F/g27T5a3wvfMcmCOaAiACjfUb4A6wrlTVfyYUZk3RRQ==", | ||||
|       "path": "serilog.settings.configuration/9.0.0", | ||||
|       "hashPath": "serilog.settings.configuration.9.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Sinks.Console/6.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-fQGWqVMClCP2yEyTXPIinSr5c+CBGUvBybPxjAGcf7ctDhadFhrQw03Mv8rJ07/wR5PDfFjewf2LimvXCDzpbA==", | ||||
|       "path": "serilog.sinks.console/6.0.0", | ||||
|       "hashPath": "serilog.sinks.console.6.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "Serilog.Sinks.File/7.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|       "sha512": "sha512-fKL7mXv7qaiNBUC71ssvn/dU0k9t0o45+qm2XgKAlSt19xF+ijjxyA3R6HmCgfKEKwfcfkwWjayuQtRueZFkYw==", | ||||
|       "path": "serilog.sinks.file/7.0.0", | ||||
|       "hashPath": "serilog.sinks.file.7.0.0.nupkg.sha512" | ||||
|     }, | ||||
|     "System.ClientModel/1.0.0": { | ||||
|       "type": "package", | ||||
|       "serviceable": true, | ||||
|   | ||||
| @@ -4,10 +4,5 @@ | ||||
|       "Default": "Information", | ||||
|       "Microsoft.Hosting.Lifetime": "Information" | ||||
|     } | ||||
|   }, | ||||
|   "ElectoralApi": { | ||||
|     "BaseUrl": "https://api.eleccionesbonaerenses.gba.gob.ar", | ||||
|     "Username": "30500094156@elecciones2025.onmicrosoft.com", | ||||
|     "Password": "PTP847elec" | ||||
|   } | ||||
| } | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,14 @@ | ||||
| { | ||||
|   "runtimeOptions": { | ||||
|     "tfm": "net9.0", | ||||
|     "framework": { | ||||
|       "name": "Microsoft.NETCore.App", | ||||
|       "version": "9.0.0" | ||||
|     }, | ||||
|     "configProperties": { | ||||
|       "System.Reflection.Metadata.MetadataUpdater.IsSupported": false, | ||||
|       "System.Reflection.NullabilityInfoContext.IsSupported": true, | ||||
|       "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| { | ||||
|   "Logging": { | ||||
|     "LogLevel": { | ||||
|       "Default": "Information", | ||||
|       "Microsoft.Hosting.Lifetime": "Information" | ||||
|     } | ||||
|     }, | ||||
|   "ElectoralApi": { | ||||
|     "BaseUrl": "https://api.eleccionesbonaerenses.gba.gob.ar", | ||||
|     "Username": "30500094156@elecciones2025.onmicrosoft.com", | ||||
|     "Password": "PTP847elec" | ||||
|   }, | ||||
|   "ConnectionStrings": { | ||||
|     "DefaultConnection": "Server=TECNICA3;Database=Elecciones2025;User Id=apielecciones2025;Password=PTP847Elecciones2025;Encrypt=False;MultipleActiveResultSets=True;TrustServerCertificate=True;" | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,8 @@ | ||||
| { | ||||
|   "Logging": { | ||||
|     "LogLevel": { | ||||
|       "Default": "Information", | ||||
|       "Microsoft.Hosting.Lifetime": "Information" | ||||
|     } | ||||
|   } | ||||
| } | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -14,7 +14,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Worker")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b90baadeedb870b5b1c9eeeb7022a0d211b61bec")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Worker")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Worker")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -96,3 +96,11 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\Eleccio | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\Elecciones.Worker.genruntimeconfig.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\ref\Elecciones.Worker.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\Microsoft.Extensions.Http.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\buenos-aires-municipios.geojson | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\Microsoft.Extensions.DependencyModel.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\Serilog.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\Serilog.Extensions.Hosting.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\Serilog.Extensions.Logging.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\Serilog.Settings.Configuration.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\Serilog.Sinks.Console.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\Serilog.Sinks.File.dll | ||||
|   | ||||
| @@ -289,6 +289,22 @@ | ||||
|             "Microsoft.Extensions.Http": { | ||||
|               "target": "Package", | ||||
|               "version": "[9.0.8, )" | ||||
|             }, | ||||
|             "Serilog.Extensions.Hosting": { | ||||
|               "target": "Package", | ||||
|               "version": "[9.0.0, )" | ||||
|             }, | ||||
|             "Serilog.Settings.Configuration": { | ||||
|               "target": "Package", | ||||
|               "version": "[9.0.0, )" | ||||
|             }, | ||||
|             "Serilog.Sinks.Console": { | ||||
|               "target": "Package", | ||||
|               "version": "[6.0.0, )" | ||||
|             }, | ||||
|             "Serilog.Sinks.File": { | ||||
|               "target": "Package", | ||||
|               "version": "[7.0.0, )" | ||||
|             } | ||||
|           }, | ||||
|           "imports": [ | ||||
|   | ||||
| @@ -2,8 +2,8 @@ | ||||
| <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> | ||||
|     <Import Project="$(NuGetPackageRoot)system.text.json\9.0.8\buildTransitive\net8.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\9.0.8\buildTransitive\net8.0\System.Text.Json.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" /> | ||||
|     <Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\9.0.5\buildTransitive\net8.0\Microsoft.Extensions.Configuration.UserSecrets.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\9.0.5\buildTransitive\net8.0\Microsoft.Extensions.Configuration.UserSecrets.targets')" /> | ||||
|   </ImportGroup> | ||||
|   | ||||
| @@ -0,0 +1,4 @@ | ||||
| // <autogenerated /> | ||||
| using System; | ||||
| using System.Reflection; | ||||
| [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")] | ||||
| @@ -0,0 +1,23 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| // <auto-generated> | ||||
| //     This code was generated by a tool. | ||||
| // | ||||
| //     Changes to this file may cause incorrect behavior and will be lost if | ||||
| //     the code is regenerated. | ||||
| // </auto-generated> | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| using System; | ||||
| using System.Reflection; | ||||
|  | ||||
| [assembly: Microsoft.Extensions.Configuration.UserSecrets.UserSecretsIdAttribute("dotnet-Elecciones.Worker-b1c6e5c0-7ebf-4eaf-af95-9386d6883c03")] | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Worker")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Worker")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Worker")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|  | ||||
| // Generado por la clase WriteCodeFragment de MSBuild. | ||||
|  | ||||
| @@ -0,0 +1,15 @@ | ||||
| is_global = true | ||||
| build_property.TargetFramework = net9.0 | ||||
| build_property.TargetPlatformMinVersion =  | ||||
| build_property.UsingMicrosoftNETSdkWeb =  | ||||
| build_property.ProjectTypeGuids =  | ||||
| build_property.InvariantGlobalization =  | ||||
| build_property.PlatformNeutralAssembly =  | ||||
| build_property.EnforceExtendedAnalyzerRules =  | ||||
| build_property._SupportedPlatformList = Linux,macOS,Windows | ||||
| build_property.RootNamespace = Elecciones.Worker | ||||
| build_property.ProjectDir = E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\ | ||||
| build_property.EnableComHosting =  | ||||
| build_property.EnableGeneratedComInterfaceComImportInterop =  | ||||
| build_property.EffectiveAnalysisLevelStyle = 9.0 | ||||
| build_property.EnableCodeStyleSeverity =  | ||||
| @@ -0,0 +1,12 @@ | ||||
| // <auto-generated/> | ||||
| global using global::Microsoft.Extensions.Configuration; | ||||
| global using global::Microsoft.Extensions.DependencyInjection; | ||||
| global using global::Microsoft.Extensions.Hosting; | ||||
| global using global::Microsoft.Extensions.Logging; | ||||
| global using global::System; | ||||
| global using global::System.Collections.Generic; | ||||
| global using global::System.IO; | ||||
| global using global::System.Linq; | ||||
| global using global::System.Net.Http; | ||||
| global using global::System.Threading; | ||||
| global using global::System.Threading.Tasks; | ||||
| @@ -0,0 +1,106 @@ | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\buenos-aires-municipios.geojson | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\appsettings.Development.json | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\appsettings.json | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Worker.exe | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Worker.deps.json | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Worker.runtimeconfig.json | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Worker.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Worker.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Azure.Core.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Azure.Identity.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Bcl.AsyncInterfaces.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Data.SqlClient.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.EntityFrameworkCore.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.EntityFrameworkCore.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.EntityFrameworkCore.Relational.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.EntityFrameworkCore.SqlServer.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Caching.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Caching.Memory.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Configuration.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Configuration.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Configuration.Binder.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Configuration.CommandLine.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Configuration.FileExtensions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Configuration.Json.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Configuration.UserSecrets.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.DependencyInjection.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.DependencyModel.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Diagnostics.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Diagnostics.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.FileProviders.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.FileProviders.Physical.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.FileSystemGlobbing.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Hosting.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Hosting.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Http.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Logging.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Logging.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Logging.Configuration.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Logging.Console.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Logging.Debug.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Logging.EventLog.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Logging.EventSource.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Options.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Extensions.Primitives.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Identity.Client.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Identity.Client.Extensions.Msal.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.IdentityModel.Abstractions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.IdentityModel.JsonWebTokens.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.IdentityModel.Logging.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.IdentityModel.Protocols.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.IdentityModel.Tokens.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.SqlServer.Server.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Microsoft.Win32.SystemEvents.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Serilog.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Serilog.Extensions.Hosting.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Serilog.Extensions.Logging.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Serilog.Settings.Configuration.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Serilog.Sinks.Console.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Serilog.Sinks.File.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.ClientModel.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Configuration.ConfigurationManager.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Diagnostics.EventLog.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Drawing.Common.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Formats.Asn1.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.IdentityModel.Tokens.Jwt.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Memory.Data.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Runtime.Caching.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Security.Cryptography.ProtectedData.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Security.Permissions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Text.Json.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\System.Windows.Extensions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\unix\lib\net6.0\Microsoft.Data.SqlClient.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win\lib\net6.0\Microsoft.Data.SqlClient.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win-arm\native\Microsoft.Data.SqlClient.SNI.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win-arm64\native\Microsoft.Data.SqlClient.SNI.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win-x64\native\Microsoft.Data.SqlClient.SNI.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win-x86\native\Microsoft.Data.SqlClient.SNI.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win\lib\net6.0\Microsoft.Win32.SystemEvents.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win\lib\net9.0\System.Diagnostics.EventLog.Messages.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win\lib\net9.0\System.Diagnostics.EventLog.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\unix\lib\net6.0\System.Drawing.Common.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win\lib\net6.0\System.Drawing.Common.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win\lib\net6.0\System.Runtime.Caching.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win\lib\net6.0\System.Security.Cryptography.ProtectedData.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\runtimes\win\lib\net6.0\System.Windows.Extensions.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Core.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Database.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Infrastructure.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Infrastructure.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Database.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Release\net9.0\Elecciones.Core.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\Elecciones.Worker.csproj.AssemblyReference.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\Elecciones.Worker.GeneratedMSBuildEditorConfig.editorconfig | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\Elecciones.Worker.AssemblyInfoInputs.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\Elecciones.Worker.AssemblyInfo.cs | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\Elecciones.Worker.csproj.CoreCompileInputs.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\Eleccion.0707F6F5.Up2Date | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\Elecciones.Worker.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\refint\Elecciones.Worker.dll | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\Elecciones.Worker.pdb | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\Elecciones.Worker.genruntimeconfig.cache | ||||
| E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Release\net9.0\ref\Elecciones.Worker.dll | ||||
| @@ -0,0 +1,28 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <Target Name="GetEFProjectMetadata"> | ||||
|     <MSBuild Condition=" '$(TargetFramework)' == '' " | ||||
|              Projects="$(MSBuildProjectFile)" | ||||
|              Targets="GetEFProjectMetadata" | ||||
|              Properties="TargetFramework=$(TargetFrameworks.Split(';')[0]);EFProjectMetadataFile=$(EFProjectMetadataFile)" /> | ||||
|     <ItemGroup Condition=" '$(TargetFramework)' != '' "> | ||||
|       <EFProjectMetadata Include="AssemblyName: $(AssemblyName)" /> | ||||
|       <EFProjectMetadata Include="Language: $(Language)" /> | ||||
|       <EFProjectMetadata Include="OutputPath: $(OutputPath)" /> | ||||
|       <EFProjectMetadata Include="Platform: $(Platform)" /> | ||||
|       <EFProjectMetadata Include="PlatformTarget: $(PlatformTarget)" /> | ||||
|       <EFProjectMetadata Include="ProjectAssetsFile: $(ProjectAssetsFile)" /> | ||||
|       <EFProjectMetadata Include="ProjectDir: $(ProjectDir)" /> | ||||
|       <EFProjectMetadata Include="RootNamespace: $(RootNamespace)" /> | ||||
|       <EFProjectMetadata Include="RuntimeFrameworkVersion: $(RuntimeFrameworkVersion)" /> | ||||
|       <EFProjectMetadata Include="TargetFileName: $(TargetFileName)" /> | ||||
|       <EFProjectMetadata Include="TargetFrameworkMoniker: $(TargetFrameworkMoniker)" /> | ||||
|       <EFProjectMetadata Include="Nullable: $(Nullable)" /> | ||||
|       <EFProjectMetadata Include="TargetFramework: $(TargetFramework)" /> | ||||
|       <EFProjectMetadata Include="TargetPlatformIdentifier: $(TargetPlatformIdentifier)" /> | ||||
|     </ItemGroup> | ||||
|     <WriteLinesToFile Condition=" '$(TargetFramework)' != '' " | ||||
|                       File="$(EFProjectMetadataFile)" | ||||
|                       Lines="@(EFProjectMetadata)" /> | ||||
|   </Target> | ||||
| </Project> | ||||
| @@ -0,0 +1,28 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <Target Name="GetEFProjectMetadata"> | ||||
|     <MSBuild Condition=" '$(TargetFramework)' == '' " | ||||
|              Projects="$(MSBuildProjectFile)" | ||||
|              Targets="GetEFProjectMetadata" | ||||
|              Properties="TargetFramework=$(TargetFrameworks.Split(';')[0]);EFProjectMetadataFile=$(EFProjectMetadataFile)" /> | ||||
|     <ItemGroup Condition=" '$(TargetFramework)' != '' "> | ||||
|       <EFProjectMetadata Include="AssemblyName: $(AssemblyName)" /> | ||||
|       <EFProjectMetadata Include="Language: $(Language)" /> | ||||
|       <EFProjectMetadata Include="OutputPath: $(OutputPath)" /> | ||||
|       <EFProjectMetadata Include="Platform: $(Platform)" /> | ||||
|       <EFProjectMetadata Include="PlatformTarget: $(PlatformTarget)" /> | ||||
|       <EFProjectMetadata Include="ProjectAssetsFile: $(ProjectAssetsFile)" /> | ||||
|       <EFProjectMetadata Include="ProjectDir: $(ProjectDir)" /> | ||||
|       <EFProjectMetadata Include="RootNamespace: $(RootNamespace)" /> | ||||
|       <EFProjectMetadata Include="RuntimeFrameworkVersion: $(RuntimeFrameworkVersion)" /> | ||||
|       <EFProjectMetadata Include="TargetFileName: $(TargetFileName)" /> | ||||
|       <EFProjectMetadata Include="TargetFrameworkMoniker: $(TargetFrameworkMoniker)" /> | ||||
|       <EFProjectMetadata Include="Nullable: $(Nullable)" /> | ||||
|       <EFProjectMetadata Include="TargetFramework: $(TargetFramework)" /> | ||||
|       <EFProjectMetadata Include="TargetPlatformIdentifier: $(TargetPlatformIdentifier)" /> | ||||
|     </ItemGroup> | ||||
|     <WriteLinesToFile Condition=" '$(TargetFramework)' != '' " | ||||
|                       File="$(EFProjectMetadataFile)" | ||||
|                       Lines="@(EFProjectMetadata)" /> | ||||
|   </Target> | ||||
| </Project> | ||||
		Reference in New Issue
	
	Block a user