Fase 2 - T2
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
Actúa como un Ingeniero de Software Principal y Agente Autónomo de Desarrollo. Tu objetivo es cumplir el plan de desarrollo del repositorio de forma iterativa y segura.
|
||||
|
||||
### Contexto del Proyecto
|
||||
- El proyecto utiliza Git para el control de versiones.
|
||||
- El estado actual y la descripción general están en `Readme.md`.
|
||||
- La hoja de ruta y los objetivos están detallados en el archivo del plan de desarrollo.
|
||||
|
||||
### Instrucciones de Operación (Ciclo de Ejecución)
|
||||
1. ANALIZAR: Lee el plan de desarrollo y compáralo con el código actual para identificar la próxima tarea pendiente.
|
||||
2. PLANIFICAR: Divide esa tarea en subpasos técnicos sumamente específicos antes de escribir código.
|
||||
3. EJECUTAR: Modifica o crea los archivos necesarios para completar el subpaso actual.
|
||||
4. VALIDAR: Asegúrate de que los cambios compilen, no rompan la arquitectura y cumplan con el objetivo.
|
||||
5. AVANZAR: Una vez completada una tarea, actualiza el archivo del plan de desarrollo marcándola como completada y pasa a la siguiente.
|
||||
|
||||
### Reglas Estrictas
|
||||
- No intentes resolver todo el plan de desarrollo de un solo golpe; trabaja en tareas atómicas y secuenciales.
|
||||
- Mantén el código limpio, documentado y modular.
|
||||
- Si encuentras un bloqueo o ambigüedad en el plan, detén la ejecución y pregunta al usuario.
|
||||
@@ -0,0 +1,25 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Tecnología
|
||||
- ASP.NET Core 8 + MVC con Razor Views.
|
||||
- MySQL via Pomelo.EntityFrameworkCore.MySql para acceso a datos.
|
||||
- Identity para gestión de usuarios y roles (Admin, Usuario).
|
||||
|
||||
## Commands
|
||||
- `dotnet build` - compilar sin restaurar packages.
|
||||
- `dotnet restore` - restore packages desde nuget.org.
|
||||
- `dotnet run --urls https://*:5001;http://*:5000` - launch dev server con HTTPS y HTTP.
|
||||
|
||||
## Estructura clave
|
||||
- Módulos por controller: UsuariosController, AccountController, RolesController.
|
||||
- Models: ApplicationUser (extiende IdentityUser), ErrorViewModel.
|
||||
- Data: ApplicationDbContext (EF Core DbContext) en `Data/ApplicationDbContext.cs`.
|
||||
- Views: Razor views bajo `Views/` folder.
|
||||
|
||||
## Seeds
|
||||
- Program.cs incluye seeds para roles y usuario admin (`admin@example.com` / "Admin123!").
|
||||
- Roles creados: Admin, Usuario.
|
||||
|
||||
## Migraciones
|
||||
- Usa `dotnet ef migrations add <name> -c ApplicationDbContext`.
|
||||
- Aplica con `dotnet ef database update`.
|
||||
@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using vita_asistente.Models;
|
||||
|
||||
namespace vita_asistente.Controllers
|
||||
{
|
||||
@@ -61,13 +61,82 @@ namespace vita_asistente.Controllers
|
||||
return View();
|
||||
}
|
||||
|
||||
// GET: Roles/Edit/5
|
||||
public async Task<IActionResult> Edit(string id)
|
||||
{
|
||||
if (id == null) return NotFound();
|
||||
var role = await _roleManager.FindByIdAsync(id);
|
||||
if (role == null) return NotFound();
|
||||
ViewBag.RoleName = role.Name;
|
||||
return View(role);
|
||||
}
|
||||
|
||||
// POST: Roles/Edit/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(string id, IdentityRole roleActualizado)
|
||||
{
|
||||
if (id != roleActualizado.Id) return NotFound();
|
||||
|
||||
var roleExistente = await _roleManager.FindByIdAsync(id);
|
||||
if (roleExistente == null) return NotFound();
|
||||
|
||||
// Actualizar solo el nombre
|
||||
roleExistente.Name = roleActualizado.Name;
|
||||
var result = await _roleManager.UpdateAsync(roleExistente);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError("", error.Description);
|
||||
}
|
||||
return View(roleActualizado);
|
||||
}
|
||||
|
||||
// GET: Roles/Disable/5
|
||||
public async Task<IActionResult> Disable(string id)
|
||||
{
|
||||
if (id == null) return NotFound();
|
||||
var role = await _roleManager.FindByIdAsync(id);
|
||||
if (role == null) return NotFound();
|
||||
return View(role);
|
||||
}
|
||||
|
||||
// POST: Roles/Disable/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DisableConfirmed(string id)
|
||||
{
|
||||
var role = await _roleManager.FindByIdAsync(id);
|
||||
if (role != null)
|
||||
{
|
||||
// En Identity, "deshabilitar" un rol implica eliminarlo
|
||||
// Pero primero verificamos si tiene usuarios asignados
|
||||
using var scope = HttpContext.RequestServices.CreateScope();
|
||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
|
||||
var usersInRole = await userManager.GetUsersInRoleAsync(role.Name);
|
||||
|
||||
if (usersInRole.Any())
|
||||
{
|
||||
ModelState.AddModelError("", "No se puede deshabilitar un rol que tiene usuarios asignados.");
|
||||
return View("Disable", role);
|
||||
}
|
||||
|
||||
await _roleManager.DeleteAsync(role);
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
// GET: Roles/Delete/5
|
||||
public async Task<IActionResult> Delete(string id)
|
||||
{
|
||||
if (id == null) return NotFound();
|
||||
var rol = await _roleManager.FindByIdAsync(id);
|
||||
if (rol == null) return NotFound();
|
||||
return View(rol);
|
||||
var role = await _roleManager.FindByIdAsync(id);
|
||||
if (role == null) return NotFound();
|
||||
return View(role);
|
||||
}
|
||||
|
||||
// POST: Roles/Delete/5
|
||||
@@ -75,10 +144,28 @@ namespace vita_asistente.Controllers
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DeleteConfirmed(string id)
|
||||
{
|
||||
var rol = await _roleManager.FindByIdAsync(id);
|
||||
if (rol != null)
|
||||
var role = await _roleManager.FindByIdAsync(id);
|
||||
if (role != null)
|
||||
{
|
||||
await _roleManager.DeleteAsync(rol);
|
||||
// Verificar que no sea el rol "Admin" (o cualquier otro rol esencial)
|
||||
if (role.Name == "Admin" || role.Name == "Administrador")
|
||||
{
|
||||
ModelState.AddModelError("", "No se puede eliminar el rol Admin/Administrador.");
|
||||
return View(role);
|
||||
}
|
||||
|
||||
// Verificar que no tenga usuarios asignados
|
||||
using var scope = HttpContext.RequestServices.CreateScope();
|
||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
|
||||
var usersInRole = await userManager.GetUsersInRoleAsync(role.Name);
|
||||
|
||||
if (usersInRole.Any())
|
||||
{
|
||||
ModelState.AddModelError("", "No se puede eliminar un rol que tiene usuarios asignados.");
|
||||
return View(role);
|
||||
}
|
||||
|
||||
await _roleManager.DeleteAsync(role);
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
@model IdentityRole
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Deshabilitar rol";
|
||||
}
|
||||
|
||||
<h1>Deshabilitar rol: @Model.Name</h1>
|
||||
|
||||
<p>¿Está seguro que desea deshabilitar este rol? Esto afectará a los usuarios con este rol.</p>
|
||||
|
||||
<form asp-action="DisableConfirmed" method="post">
|
||||
<input type="hidden" name="id" value="@Model.Id" />
|
||||
@Html.AntiForgeryToken()
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-warning">Deshabilitar rol</button>
|
||||
<a asp-action="Index" class="btn btn-secondary">Cancelar</a>
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,24 @@
|
||||
@model IdentityRole
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Editar rol";
|
||||
}
|
||||
|
||||
<h1>Editar rol: @Model.Name</h1>
|
||||
|
||||
<form asp-action="Edit">
|
||||
<input type="hidden" asp-for="Id" />
|
||||
<div class="form-group">
|
||||
<label asp-for="Name" class="control-label"></label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Guardar cambios" class="btn btn-primary" />
|
||||
<a asp-action="Index" class="btn btn-secondary">Cancelar</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
section scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
@@ -11,7 +11,75 @@
|
||||
<tr>
|
||||
<td>@role.Name</td>
|
||||
<td>
|
||||
<a asp-action="Delete" asp-route-id="@role.Id" class="btn btn-danger btn-sm">Eliminar</a>
|
||||
<a href="#" class="btn btn-info btn-sm" data-bs-toggle="modal" data-bs-target="#editModal-@role.Id">Editar</a>
|
||||
|
||||
<!-- Modal de edición -->
|
||||
<div class="modal fade" id="editModal-@role.Id" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form asp-action="Edit" method="post">
|
||||
<input type="hidden" name="id" value="@role.Id" />
|
||||
@HttpContext.RequestServices.GetService typeof(Antiforgery.IAntiforgery)
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="editModalLabel">Editar rol: @role.Name</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input asp-for="Name" class="form-control" placeholder="Nuevo nombre del rol" />
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
||||
<button type="submit" class="btn btn-primary">Guardar cambios</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="#" class="btn btn-warning btn-sm" data-bs-toggle="modal" data-bs-target="#disableModal-@role.Id">Deshabilitar</a>
|
||||
|
||||
<!-- Modal de deshabilitar -->
|
||||
<div class="modal fade" id="disableModal-@role.Id" tabindex="-1" aria-labelledby="disableModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form asp-action="Disable" method="post">
|
||||
<input type="hidden" name="id" value="@role.Id" />
|
||||
@Html.AntiForgeryToken()
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="disableModalLabel">Deshabilitar rol: @role.Name</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
¿Está seguro que desea deshabilitar este rol? Esto afectará a los usuarios con este rol.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-warning">Deshabilitar</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal de confirmación de eliminar (solo para Admin) -->
|
||||
<div class="modal fade" id="deleteModal-@role.Id" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form asp-action="DeleteConfirmed" method="post">
|
||||
<input type="hidden" name="id" value="@role.Id" />
|
||||
@Html.AntiForgeryToken()
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="deleteModalLabel">Confirmar eliminación</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
¿Está seguro que desea eliminar definitivamente este rol(@role.Name)?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-danger">Eliminar</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"dTHwDiTQ4hJYdmKO9xqu9ZCVKoaec0XI9AxL+YTrrxc=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BpImrEMo52w6bqrejlV7vSb82az\u002BZyHdvkc5K26Y7eE=","a5UsKPhkI9FkpAiNA1ymkUo7ug72D30zrmd5jJuyLb4=","VXCSduCoRGoZ5eOSfAj51GsGnNVvq7A5qKF5D/N7Vx0=","lYOz00m47sCm26fa1A/DFVKnjqVzxu9nwMLP8IuW7xo=","6bA4Xmr8qmrZ2r4ukqX9rM6kVzUrIeI94cM9zBObY3M=","l099lCYtMtQryAqb9VTCRIBp0Jcbpf4BalfsulUoFzQ=","V6/Mi3mlMBego46prUANQbdZ1JC0JZHHdYiXWq2\u002Bl0Y=","tl0jSwp2oIQnMenRmm6Mbm313bzgl9pBwBPGlB4uOPo=","tbh14xDAb77jsCKNNZjBojrK8V\u002BuRrCt8pXuAbtqkIo=","GxKlsEe\u002BPorb4Q9gASZJViO4cZfx6jUCEBQjth\u002BbKyQ=","BujRH2INcYzLBulIqjiKKoWj4\u002BbBT0vuhWVB9V7qy9Q=","EepEENuPyTp00hVBGTVzBoVinVly6PiqjQii1osa6kM=","5HcjLmCBtQj/w6XbXf8\u002BCvPC21ftmG5huW5hAakQj2I=","pREL0QA5WROOeeZwRBgJ9om8ccir8XjyYPvQGVlEOqw=","uTfRVeFsnFdQrds7/R5pdtDmoRt4CgIt0nZfMajU8Ok=","kOjALiJp3ssJnC9/\u002BufurmbWP5mGTftoFnUlCEDvu1Y=","OVuwBaCI8R1LKgQ7MpbBQW1MLJdJ5YTckKjK0e\u002BBB/0=","iJvX3JMtNzW09/txMzwAkKxEZoDub7KMH169RwIXBPs=","Jx7VvNisirl41n21YXz5RZ7YC3p\u002BduhgL9Fl4hAQXnU=","uQn60G4s3oNGwLqstU1/neNzshVCswoyOWLl1Fj05Tg=","XHFdkx1NMsJcQH4i0fivlz4h7J3Cn7en7webWTH/bmo=","U67CgipeJ7PfwasvH\u002Bfqt7SBewDnpnt99z8DKoXQzNA=","mseMwc\u002BhG\u002BU8usO5dRA2P\u002BpOMd5PWhffhlwmduKXCJk=","Gq2CAmOPKxxarQPAX2MqPfSN6pt/LIZWFWEa8tBng0I=","HYsHOl/AYyjvk1kiJz18194UGfuAbW0SnMf4TCopcw4=","rwehZlDMvo1sryVYAsPJaHmrJ2rPhqvgKQD6Z1O\u002B3Uc=","XeKKeCm2D4KUJaU5sqmJQdUk7\u002B8A\u002BLzMpqzubv2aoOM=","/zzWV7B7mzbQrZfS96I5FnN7LBmNW5EbLXpSn\u002B9WW/M=","z5U4weixRLkjNozy8VE0T7duu5LEz2RPAmLbFfytYGY=","/N/rp0KUV9X4nDd0kU44g9GSMRdkLmQ9YbtXm/pS5dA=","Ohkm3vqgAWGBAAI4WLyDTwmqAP/wOdKFE42zO9dfl0Q=","eNSJVvFwOiBiNSPF24v6tmv/8/FN9UzPYVoi8Qn8bEo=","0UQKTStUtl3P2puWo1DKykq\u002BjjwDwKRon3olDS6tvHU=","6Q3AeoSqI7vpqdDDUNOSnQ4FYwL5EUR6rTOt9Sf1Rz0=","1rt5\u002B0050W7zo/TZnQe\u002BZec8SBN47eRtlHMUPbm9BU8=","8SGo\u002BxEjiy6wtpY2qoLQAVpU2SnQo7iN34B5T4AlURg=","x79AODv3QZ5w9i3xqovT9BbAXxxd6JZxhVAy6o4ajzs=","cKjDw3B8lc9k/tvqcaER\u002B3ndMwrGQHrDYWSdOY4faV8=","p8dvjfGnu7pGuvblA3vxKLKx29xYbQIUIWysdq2dmUo=","BG1wzq2\u002BUnva6Gj660f/4QSvh7Y\u002B4BkZ/wY9RL4Gw1E=","EMBCFam7ihuahYKSXkchvO5Oq1G6WATBlbGZb/1Wvgw=","qmvGIjcCX8r6TSFwIn5\u002BLEqxe0r6TyWX6Dh7IZuXPyc=","lN17WNch1WB21wDcx8isw\u002B9LESsxbL5ZLcwkcguFwDw=","xFTE\u002BmS9ms48MwKeAOZlAcjQcW2SFEb1HqUl40vv6\u002BA=","I7cNmUMe4LNDvkoc59Tb/PSRJVZAmfnrfaLGIkazUE8=","mVV74WiMoMIt7VWKgRMp3Ffhsn6zMwDlhI11UroeBuY=","1be6J4hFUF43o4ugBHafnfNfQTkZ3vWGedt\u002BdP8sPo4=","vuftYVY\u002Bo7U2Nxhh6XMNpilZIm3ZsptViz7\u002BanqA3Hc=","imfvoQHzb8LfDXM7qRYlx7axOpksQyHig/s\u002BmIcfxpk=","nJpGXEZYduduKpUXiNd6keeqmPvaEgvDoDFQWsGCzcw=","STogQT7rnxvTzdXO1jKjFvHAJyiRDy1pcjGg\u002Bz2lLbU=","y0yeF4H9Zqn1\u002BRsgkxQlXguGWbRQmGSTY1Z1BC0FCuQ=","K/Thn9wvK/PAKEKSQqsu\u002BKF/gsoXvfT2yWOkYV9irEY=","vhLVcon4oX9c1uw5NqDO\u002Bbmp7U8Wut5qBvibR3av0rA=","QKHrAtLbmxUoOsZrHwyNH/IyH86zNvOqxWSlN3FyucA=","6wCEa/kwBVkKvxfkUIFAxzHXWu4/p/R5/WtLkSHmLHc=","G07nmbZoVpM0XTP8Lz65k3KltLdOeLXLxcbihltgpGQ=","1hKIH5KS3ipyc1\u002BCQ\u002BxwaZMNvI1OZnLX8eArQaOVzAE=","J\u002BTkoAeMyxDzquSGJ3s6/xjqRpSmQj3hnQ/nQ3ZMT2w=","6RMMCAIDMT6w6ebgi/Bdd1UPJ1TWHh5v/RLyuInLByM=","XdM7cHaWP0hnWT6hjmmAQZrH5muzSfxofZZMReavdhE=","Y6FuXJmG4asZZywv8eq2Ki3M3DHBabgHxixPNEPtsg0=","ocP7tLQvAC3JoF1EP3jOXtv3\u002Bd0qM3kdE0/8cY\u002BVC18=","CH9QcGeTGE6F7iss5IMJIdGAfaixRCv52kGorH\u002Br7UQ=","T1FmR6BuWj8NdQOpYSYpkD9zKCBLg9Fq2Txyqzbv0ow=","7pE8sSLDf7aqo6DjV5RYq1M\u002BISPAIo7BW6XwwSh6O1w=","yALO4iHkRJn2NKox\u002B\u002B4OZBqzhGPkvrA2bOX0emXGiac=","9JrQ3zBPaGik8svNVNuioqNGKWNvShwz32tj7Oyf9wM=","j0EJHazrwSEUHAPSEiUUhdwXrZ4ben27F7iH5Hnje/M=","JiuGUyztERDBSvF/6GDip3jqDWJzkWH6IdRYkvi5bw0=","bfM6e\u002BYucNXsBEQIq6EkXf6mNT\u002BPp63/xGN1rdjLZiQ=","7rNiQh7D0WAW\u002BBIalpkA6TbN/zPYEJsqZgWhr/HPCVs=","5CJDU5WOqZlcGfMhyrjY8yklCO49EP8N2oJgZCPtCvA=","PwMpWOwh/ebKXLFaIW93w/Nmg9sgkp21\u002BkJjs5VxJFY=","JPhvOaP4s5GzcXST3QvJD8qP\u002B/4XR1TCfIiP4loGLb8=","NVCP0V7YVnf5urwl2ofENh5w6TJfZ2MUUgzQ389SA1w=","VfTAU/4gffsId\u002B7V4v5FnVYVwig5FKCwrdNkRzRwGU0=","Y7eqVxFX7a20bQsQuQshHeV5QtkyeSYASzhM4PXTo30=","Ic9h4\u002ByTmAHzupqRA6FL9\u002Bd/N6fmL1U2i85d6qZ8KgM=","Yixqc1XRFIJzTzMVIDHsDQ6xJExHcrnledpmuK51aKg=","iVaBsCbDJK\u002BCXBwkZfuSrXjnlGIjKrqCgVJI6FVlWn0="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"dTHwDiTQ4hJYdmKO9xqu9ZCVKoaec0XI9AxL+YTrrxc=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BpImrEMo52w6bqrejlV7vSb82az\u002BZyHdvkc5K26Y7eE=","a5UsKPhkI9FkpAiNA1ymkUo7ug72D30zrmd5jJuyLb4=","VXCSduCoRGoZ5eOSfAj51GsGnNVvq7A5qKF5D/N7Vx0=","lYOz00m47sCm26fa1A/DFVKnjqVzxu9nwMLP8IuW7xo=","6bA4Xmr8qmrZ2r4ukqX9rM6kVzUrIeI94cM9zBObY3M=","l099lCYtMtQryAqb9VTCRIBp0Jcbpf4BalfsulUoFzQ=","V6/Mi3mlMBego46prUANQbdZ1JC0JZHHdYiXWq2\u002Bl0Y=","tl0jSwp2oIQnMenRmm6Mbm313bzgl9pBwBPGlB4uOPo=","tbh14xDAb77jsCKNNZjBojrK8V\u002BuRrCt8pXuAbtqkIo=","GxKlsEe\u002BPorb4Q9gASZJViO4cZfx6jUCEBQjth\u002BbKyQ=","BujRH2INcYzLBulIqjiKKoWj4\u002BbBT0vuhWVB9V7qy9Q=","EepEENuPyTp00hVBGTVzBoVinVly6PiqjQii1osa6kM=","5HcjLmCBtQj/w6XbXf8\u002BCvPC21ftmG5huW5hAakQj2I=","pREL0QA5WROOeeZwRBgJ9om8ccir8XjyYPvQGVlEOqw=","uTfRVeFsnFdQrds7/R5pdtDmoRt4CgIt0nZfMajU8Ok=","kOjALiJp3ssJnC9/\u002BufurmbWP5mGTftoFnUlCEDvu1Y=","OVuwBaCI8R1LKgQ7MpbBQW1MLJdJ5YTckKjK0e\u002BBB/0=","iJvX3JMtNzW09/txMzwAkKxEZoDub7KMH169RwIXBPs=","Jx7VvNisirl41n21YXz5RZ7YC3p\u002BduhgL9Fl4hAQXnU=","uQn60G4s3oNGwLqstU1/neNzshVCswoyOWLl1Fj05Tg=","XHFdkx1NMsJcQH4i0fivlz4h7J3Cn7en7webWTH/bmo=","U67CgipeJ7PfwasvH\u002Bfqt7SBewDnpnt99z8DKoXQzNA=","mseMwc\u002BhG\u002BU8usO5dRA2P\u002BpOMd5PWhffhlwmduKXCJk=","Gq2CAmOPKxxarQPAX2MqPfSN6pt/LIZWFWEa8tBng0I=","HYsHOl/AYyjvk1kiJz18194UGfuAbW0SnMf4TCopcw4=","rwehZlDMvo1sryVYAsPJaHmrJ2rPhqvgKQD6Z1O\u002B3Uc=","XeKKeCm2D4KUJaU5sqmJQdUk7\u002B8A\u002BLzMpqzubv2aoOM=","/zzWV7B7mzbQrZfS96I5FnN7LBmNW5EbLXpSn\u002B9WW/M=","z5U4weixRLkjNozy8VE0T7duu5LEz2RPAmLbFfytYGY=","/N/rp0KUV9X4nDd0kU44g9GSMRdkLmQ9YbtXm/pS5dA=","Ohkm3vqgAWGBAAI4WLyDTwmqAP/wOdKFE42zO9dfl0Q=","eNSJVvFwOiBiNSPF24v6tmv/8/FN9UzPYVoi8Qn8bEo=","0UQKTStUtl3P2puWo1DKykq\u002BjjwDwKRon3olDS6tvHU=","6Q3AeoSqI7vpqdDDUNOSnQ4FYwL5EUR6rTOt9Sf1Rz0=","1rt5\u002B0050W7zo/TZnQe\u002BZec8SBN47eRtlHMUPbm9BU8=","8SGo\u002BxEjiy6wtpY2qoLQAVpU2SnQo7iN34B5T4AlURg=","x79AODv3QZ5w9i3xqovT9BbAXxxd6JZxhVAy6o4ajzs=","cKjDw3B8lc9k/tvqcaER\u002B3ndMwrGQHrDYWSdOY4faV8=","p8dvjfGnu7pGuvblA3vxKLKx29xYbQIUIWysdq2dmUo=","BG1wzq2\u002BUnva6Gj660f/4QSvh7Y\u002B4BkZ/wY9RL4Gw1E=","EMBCFam7ihuahYKSXkchvO5Oq1G6WATBlbGZb/1Wvgw=","qmvGIjcCX8r6TSFwIn5\u002BLEqxe0r6TyWX6Dh7IZuXPyc=","lN17WNch1WB21wDcx8isw\u002B9LESsxbL5ZLcwkcguFwDw=","xFTE\u002BmS9ms48MwKeAOZlAcjQcW2SFEb1HqUl40vv6\u002BA=","I7cNmUMe4LNDvkoc59Tb/PSRJVZAmfnrfaLGIkazUE8=","mVV74WiMoMIt7VWKgRMp3Ffhsn6zMwDlhI11UroeBuY=","1be6J4hFUF43o4ugBHafnfNfQTkZ3vWGedt\u002BdP8sPo4=","vuftYVY\u002Bo7U2Nxhh6XMNpilZIm3ZsptViz7\u002BanqA3Hc=","imfvoQHzb8LfDXM7qRYlx7axOpksQyHig/s\u002BmIcfxpk=","nJpGXEZYduduKpUXiNd6keeqmPvaEgvDoDFQWsGCzcw=","STogQT7rnxvTzdXO1jKjFvHAJyiRDy1pcjGg\u002Bz2lLbU=","y0yeF4H9Zqn1\u002BRsgkxQlXguGWbRQmGSTY1Z1BC0FCuQ=","K/Thn9wvK/PAKEKSQqsu\u002BKF/gsoXvfT2yWOkYV9irEY=","vhLVcon4oX9c1uw5NqDO\u002Bbmp7U8Wut5qBvibR3av0rA=","QKHrAtLbmxUoOsZrHwyNH/IyH86zNvOqxWSlN3FyucA=","6wCEa/kwBVkKvxfkUIFAxzHXWu4/p/R5/WtLkSHmLHc=","G07nmbZoVpM0XTP8Lz65k3KltLdOeLXLxcbihltgpGQ=","1hKIH5KS3ipyc1\u002BCQ\u002BxwaZMNvI1OZnLX8eArQaOVzAE=","J\u002BTkoAeMyxDzquSGJ3s6/xjqRpSmQj3hnQ/nQ3ZMT2w=","6RMMCAIDMT6w6ebgi/Bdd1UPJ1TWHh5v/RLyuInLByM=","XdM7cHaWP0hnWT6hjmmAQZrH5muzSfxofZZMReavdhE=","Y6FuXJmG4asZZywv8eq2Ki3M3DHBabgHxixPNEPtsg0=","ocP7tLQvAC3JoF1EP3jOXtv3\u002Bd0qM3kdE0/8cY\u002BVC18=","CH9QcGeTGE6F7iss5IMJIdGAfaixRCv52kGorH\u002Br7UQ=","T1FmR6BuWj8NdQOpYSYpkD9zKCBLg9Fq2Txyqzbv0ow=","7pE8sSLDf7aqo6DjV5RYq1M\u002BISPAIo7BW6XwwSh6O1w=","yALO4iHkRJn2NKox\u002B\u002B4OZBqzhGPkvrA2bOX0emXGiac=","9JrQ3zBPaGik8svNVNuioqNGKWNvShwz32tj7Oyf9wM=","j0EJHazrwSEUHAPSEiUUhdwXrZ4ben27F7iH5Hnje/M=","JiuGUyztERDBSvF/6GDip3jqDWJzkWH6IdRYkvi5bw0=","bfM6e\u002BYucNXsBEQIq6EkXf6mNT\u002BPp63/xGN1rdjLZiQ=","7rNiQh7D0WAW\u002BBIalpkA6TbN/zPYEJsqZgWhr/HPCVs=","5CJDU5WOqZlcGfMhyrjY8yklCO49EP8N2oJgZCPtCvA=","PwMpWOwh/ebKXLFaIW93w/Nmg9sgkp21\u002BkJjs5VxJFY=","JPhvOaP4s5GzcXST3QvJD8qP\u002B/4XR1TCfIiP4loGLb8=","NVCP0V7YVnf5urwl2ofENh5w6TJfZ2MUUgzQ389SA1w=","VfTAU/4gffsId\u002B7V4v5FnVYVwig5FKCwrdNkRzRwGU0=","Y7eqVxFX7a20bQsQuQshHeV5QtkyeSYASzhM4PXTo30=","yOVmWadteUwj\u002BNmQpObPtaDAt52hoJ\u002Bl\u002BNzJVK7MBAU=","9cTrEyIQdmDa25ocL8Eyud7FcyZQ0KIMjdK17iVzX2k=","LpesthIqevfUpWNrijFwa6P4yw9y1fjCvhDIJi1HNSY=","7KbCVRYfzTj0uAmCgvUKF\u002B90LeMurRZZC0\u002BbZdNLQgg=","Yixqc1XRFIJzTzMVIDHsDQ6xJExHcrnledpmuK51aKg=","829a\u002BDQvI6dHkKDNA93VIjPgJhUHsPn\u002BBTPY8rp9WgM="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"b3AVK0PfgHEjkHEQ+ecR24BVpHFQ4S+w6p/xGRP0mXU=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BpImrEMo52w6bqrejlV7vSb82az\u002BZyHdvkc5K26Y7eE=","a5UsKPhkI9FkpAiNA1ymkUo7ug72D30zrmd5jJuyLb4=","VXCSduCoRGoZ5eOSfAj51GsGnNVvq7A5qKF5D/N7Vx0=","lYOz00m47sCm26fa1A/DFVKnjqVzxu9nwMLP8IuW7xo=","6bA4Xmr8qmrZ2r4ukqX9rM6kVzUrIeI94cM9zBObY3M=","l099lCYtMtQryAqb9VTCRIBp0Jcbpf4BalfsulUoFzQ=","V6/Mi3mlMBego46prUANQbdZ1JC0JZHHdYiXWq2\u002Bl0Y=","tl0jSwp2oIQnMenRmm6Mbm313bzgl9pBwBPGlB4uOPo=","tbh14xDAb77jsCKNNZjBojrK8V\u002BuRrCt8pXuAbtqkIo=","GxKlsEe\u002BPorb4Q9gASZJViO4cZfx6jUCEBQjth\u002BbKyQ=","BujRH2INcYzLBulIqjiKKoWj4\u002BbBT0vuhWVB9V7qy9Q=","EepEENuPyTp00hVBGTVzBoVinVly6PiqjQii1osa6kM=","5HcjLmCBtQj/w6XbXf8\u002BCvPC21ftmG5huW5hAakQj2I=","pREL0QA5WROOeeZwRBgJ9om8ccir8XjyYPvQGVlEOqw=","uTfRVeFsnFdQrds7/R5pdtDmoRt4CgIt0nZfMajU8Ok=","kOjALiJp3ssJnC9/\u002BufurmbWP5mGTftoFnUlCEDvu1Y=","OVuwBaCI8R1LKgQ7MpbBQW1MLJdJ5YTckKjK0e\u002BBB/0=","iJvX3JMtNzW09/txMzwAkKxEZoDub7KMH169RwIXBPs=","Jx7VvNisirl41n21YXz5RZ7YC3p\u002BduhgL9Fl4hAQXnU=","uQn60G4s3oNGwLqstU1/neNzshVCswoyOWLl1Fj05Tg=","XHFdkx1NMsJcQH4i0fivlz4h7J3Cn7en7webWTH/bmo=","U67CgipeJ7PfwasvH\u002Bfqt7SBewDnpnt99z8DKoXQzNA=","mseMwc\u002BhG\u002BU8usO5dRA2P\u002BpOMd5PWhffhlwmduKXCJk=","Gq2CAmOPKxxarQPAX2MqPfSN6pt/LIZWFWEa8tBng0I=","HYsHOl/AYyjvk1kiJz18194UGfuAbW0SnMf4TCopcw4=","rwehZlDMvo1sryVYAsPJaHmrJ2rPhqvgKQD6Z1O\u002B3Uc=","XeKKeCm2D4KUJaU5sqmJQdUk7\u002B8A\u002BLzMpqzubv2aoOM=","/zzWV7B7mzbQrZfS96I5FnN7LBmNW5EbLXpSn\u002B9WW/M=","z5U4weixRLkjNozy8VE0T7duu5LEz2RPAmLbFfytYGY=","/N/rp0KUV9X4nDd0kU44g9GSMRdkLmQ9YbtXm/pS5dA=","Ohkm3vqgAWGBAAI4WLyDTwmqAP/wOdKFE42zO9dfl0Q=","eNSJVvFwOiBiNSPF24v6tmv/8/FN9UzPYVoi8Qn8bEo=","0UQKTStUtl3P2puWo1DKykq\u002BjjwDwKRon3olDS6tvHU=","6Q3AeoSqI7vpqdDDUNOSnQ4FYwL5EUR6rTOt9Sf1Rz0=","1rt5\u002B0050W7zo/TZnQe\u002BZec8SBN47eRtlHMUPbm9BU8=","8SGo\u002BxEjiy6wtpY2qoLQAVpU2SnQo7iN34B5T4AlURg=","x79AODv3QZ5w9i3xqovT9BbAXxxd6JZxhVAy6o4ajzs=","cKjDw3B8lc9k/tvqcaER\u002B3ndMwrGQHrDYWSdOY4faV8=","p8dvjfGnu7pGuvblA3vxKLKx29xYbQIUIWysdq2dmUo=","BG1wzq2\u002BUnva6Gj660f/4QSvh7Y\u002B4BkZ/wY9RL4Gw1E=","EMBCFam7ihuahYKSXkchvO5Oq1G6WATBlbGZb/1Wvgw=","qmvGIjcCX8r6TSFwIn5\u002BLEqxe0r6TyWX6Dh7IZuXPyc=","lN17WNch1WB21wDcx8isw\u002B9LESsxbL5ZLcwkcguFwDw=","xFTE\u002BmS9ms48MwKeAOZlAcjQcW2SFEb1HqUl40vv6\u002BA=","I7cNmUMe4LNDvkoc59Tb/PSRJVZAmfnrfaLGIkazUE8=","mVV74WiMoMIt7VWKgRMp3Ffhsn6zMwDlhI11UroeBuY=","1be6J4hFUF43o4ugBHafnfNfQTkZ3vWGedt\u002BdP8sPo4=","vuftYVY\u002Bo7U2Nxhh6XMNpilZIm3ZsptViz7\u002BanqA3Hc=","imfvoQHzb8LfDXM7qRYlx7axOpksQyHig/s\u002BmIcfxpk=","nJpGXEZYduduKpUXiNd6keeqmPvaEgvDoDFQWsGCzcw=","STogQT7rnxvTzdXO1jKjFvHAJyiRDy1pcjGg\u002Bz2lLbU=","y0yeF4H9Zqn1\u002BRsgkxQlXguGWbRQmGSTY1Z1BC0FCuQ=","K/Thn9wvK/PAKEKSQqsu\u002BKF/gsoXvfT2yWOkYV9irEY=","vhLVcon4oX9c1uw5NqDO\u002Bbmp7U8Wut5qBvibR3av0rA=","QKHrAtLbmxUoOsZrHwyNH/IyH86zNvOqxWSlN3FyucA=","6wCEa/kwBVkKvxfkUIFAxzHXWu4/p/R5/WtLkSHmLHc=","G07nmbZoVpM0XTP8Lz65k3KltLdOeLXLxcbihltgpGQ=","1hKIH5KS3ipyc1\u002BCQ\u002BxwaZMNvI1OZnLX8eArQaOVzAE=","J\u002BTkoAeMyxDzquSGJ3s6/xjqRpSmQj3hnQ/nQ3ZMT2w=","6RMMCAIDMT6w6ebgi/Bdd1UPJ1TWHh5v/RLyuInLByM=","XdM7cHaWP0hnWT6hjmmAQZrH5muzSfxofZZMReavdhE=","Y6FuXJmG4asZZywv8eq2Ki3M3DHBabgHxixPNEPtsg0=","ocP7tLQvAC3JoF1EP3jOXtv3\u002Bd0qM3kdE0/8cY\u002BVC18=","CH9QcGeTGE6F7iss5IMJIdGAfaixRCv52kGorH\u002Br7UQ=","T1FmR6BuWj8NdQOpYSYpkD9zKCBLg9Fq2Txyqzbv0ow=","7pE8sSLDf7aqo6DjV5RYq1M\u002BISPAIo7BW6XwwSh6O1w=","yALO4iHkRJn2NKox\u002B\u002B4OZBqzhGPkvrA2bOX0emXGiac=","9JrQ3zBPaGik8svNVNuioqNGKWNvShwz32tj7Oyf9wM=","j0EJHazrwSEUHAPSEiUUhdwXrZ4ben27F7iH5Hnje/M=","JiuGUyztERDBSvF/6GDip3jqDWJzkWH6IdRYkvi5bw0=","bfM6e\u002BYucNXsBEQIq6EkXf6mNT\u002BPp63/xGN1rdjLZiQ=","7rNiQh7D0WAW\u002BBIalpkA6TbN/zPYEJsqZgWhr/HPCVs=","5CJDU5WOqZlcGfMhyrjY8yklCO49EP8N2oJgZCPtCvA=","PwMpWOwh/ebKXLFaIW93w/Nmg9sgkp21\u002BkJjs5VxJFY=","JPhvOaP4s5GzcXST3QvJD8qP\u002B/4XR1TCfIiP4loGLb8=","NVCP0V7YVnf5urwl2ofENh5w6TJfZ2MUUgzQ389SA1w=","VfTAU/4gffsId\u002B7V4v5FnVYVwig5FKCwrdNkRzRwGU0=","Y7eqVxFX7a20bQsQuQshHeV5QtkyeSYASzhM4PXTo30=","Ic9h4\u002ByTmAHzupqRA6FL9\u002Bd/N6fmL1U2i85d6qZ8KgM=","Yixqc1XRFIJzTzMVIDHsDQ6xJExHcrnledpmuK51aKg=","iVaBsCbDJK\u002BCXBwkZfuSrXjnlGIjKrqCgVJI6FVlWn0="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"b3AVK0PfgHEjkHEQ+ecR24BVpHFQ4S+w6p/xGRP0mXU=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BpImrEMo52w6bqrejlV7vSb82az\u002BZyHdvkc5K26Y7eE=","a5UsKPhkI9FkpAiNA1ymkUo7ug72D30zrmd5jJuyLb4=","VXCSduCoRGoZ5eOSfAj51GsGnNVvq7A5qKF5D/N7Vx0=","lYOz00m47sCm26fa1A/DFVKnjqVzxu9nwMLP8IuW7xo=","6bA4Xmr8qmrZ2r4ukqX9rM6kVzUrIeI94cM9zBObY3M=","l099lCYtMtQryAqb9VTCRIBp0Jcbpf4BalfsulUoFzQ=","V6/Mi3mlMBego46prUANQbdZ1JC0JZHHdYiXWq2\u002Bl0Y=","tl0jSwp2oIQnMenRmm6Mbm313bzgl9pBwBPGlB4uOPo=","tbh14xDAb77jsCKNNZjBojrK8V\u002BuRrCt8pXuAbtqkIo=","GxKlsEe\u002BPorb4Q9gASZJViO4cZfx6jUCEBQjth\u002BbKyQ=","BujRH2INcYzLBulIqjiKKoWj4\u002BbBT0vuhWVB9V7qy9Q=","EepEENuPyTp00hVBGTVzBoVinVly6PiqjQii1osa6kM=","5HcjLmCBtQj/w6XbXf8\u002BCvPC21ftmG5huW5hAakQj2I=","pREL0QA5WROOeeZwRBgJ9om8ccir8XjyYPvQGVlEOqw=","uTfRVeFsnFdQrds7/R5pdtDmoRt4CgIt0nZfMajU8Ok=","kOjALiJp3ssJnC9/\u002BufurmbWP5mGTftoFnUlCEDvu1Y=","OVuwBaCI8R1LKgQ7MpbBQW1MLJdJ5YTckKjK0e\u002BBB/0=","iJvX3JMtNzW09/txMzwAkKxEZoDub7KMH169RwIXBPs=","Jx7VvNisirl41n21YXz5RZ7YC3p\u002BduhgL9Fl4hAQXnU=","uQn60G4s3oNGwLqstU1/neNzshVCswoyOWLl1Fj05Tg=","XHFdkx1NMsJcQH4i0fivlz4h7J3Cn7en7webWTH/bmo=","U67CgipeJ7PfwasvH\u002Bfqt7SBewDnpnt99z8DKoXQzNA=","mseMwc\u002BhG\u002BU8usO5dRA2P\u002BpOMd5PWhffhlwmduKXCJk=","Gq2CAmOPKxxarQPAX2MqPfSN6pt/LIZWFWEa8tBng0I=","HYsHOl/AYyjvk1kiJz18194UGfuAbW0SnMf4TCopcw4=","rwehZlDMvo1sryVYAsPJaHmrJ2rPhqvgKQD6Z1O\u002B3Uc=","XeKKeCm2D4KUJaU5sqmJQdUk7\u002B8A\u002BLzMpqzubv2aoOM=","/zzWV7B7mzbQrZfS96I5FnN7LBmNW5EbLXpSn\u002B9WW/M=","z5U4weixRLkjNozy8VE0T7duu5LEz2RPAmLbFfytYGY=","/N/rp0KUV9X4nDd0kU44g9GSMRdkLmQ9YbtXm/pS5dA=","Ohkm3vqgAWGBAAI4WLyDTwmqAP/wOdKFE42zO9dfl0Q=","eNSJVvFwOiBiNSPF24v6tmv/8/FN9UzPYVoi8Qn8bEo=","0UQKTStUtl3P2puWo1DKykq\u002BjjwDwKRon3olDS6tvHU=","6Q3AeoSqI7vpqdDDUNOSnQ4FYwL5EUR6rTOt9Sf1Rz0=","1rt5\u002B0050W7zo/TZnQe\u002BZec8SBN47eRtlHMUPbm9BU8=","8SGo\u002BxEjiy6wtpY2qoLQAVpU2SnQo7iN34B5T4AlURg=","x79AODv3QZ5w9i3xqovT9BbAXxxd6JZxhVAy6o4ajzs=","cKjDw3B8lc9k/tvqcaER\u002B3ndMwrGQHrDYWSdOY4faV8=","p8dvjfGnu7pGuvblA3vxKLKx29xYbQIUIWysdq2dmUo=","BG1wzq2\u002BUnva6Gj660f/4QSvh7Y\u002B4BkZ/wY9RL4Gw1E=","EMBCFam7ihuahYKSXkchvO5Oq1G6WATBlbGZb/1Wvgw=","qmvGIjcCX8r6TSFwIn5\u002BLEqxe0r6TyWX6Dh7IZuXPyc=","lN17WNch1WB21wDcx8isw\u002B9LESsxbL5ZLcwkcguFwDw=","xFTE\u002BmS9ms48MwKeAOZlAcjQcW2SFEb1HqUl40vv6\u002BA=","I7cNmUMe4LNDvkoc59Tb/PSRJVZAmfnrfaLGIkazUE8=","mVV74WiMoMIt7VWKgRMp3Ffhsn6zMwDlhI11UroeBuY=","1be6J4hFUF43o4ugBHafnfNfQTkZ3vWGedt\u002BdP8sPo4=","vuftYVY\u002Bo7U2Nxhh6XMNpilZIm3ZsptViz7\u002BanqA3Hc=","imfvoQHzb8LfDXM7qRYlx7axOpksQyHig/s\u002BmIcfxpk=","nJpGXEZYduduKpUXiNd6keeqmPvaEgvDoDFQWsGCzcw=","STogQT7rnxvTzdXO1jKjFvHAJyiRDy1pcjGg\u002Bz2lLbU=","y0yeF4H9Zqn1\u002BRsgkxQlXguGWbRQmGSTY1Z1BC0FCuQ=","K/Thn9wvK/PAKEKSQqsu\u002BKF/gsoXvfT2yWOkYV9irEY=","vhLVcon4oX9c1uw5NqDO\u002Bbmp7U8Wut5qBvibR3av0rA=","QKHrAtLbmxUoOsZrHwyNH/IyH86zNvOqxWSlN3FyucA=","6wCEa/kwBVkKvxfkUIFAxzHXWu4/p/R5/WtLkSHmLHc=","G07nmbZoVpM0XTP8Lz65k3KltLdOeLXLxcbihltgpGQ=","1hKIH5KS3ipyc1\u002BCQ\u002BxwaZMNvI1OZnLX8eArQaOVzAE=","J\u002BTkoAeMyxDzquSGJ3s6/xjqRpSmQj3hnQ/nQ3ZMT2w=","6RMMCAIDMT6w6ebgi/Bdd1UPJ1TWHh5v/RLyuInLByM=","XdM7cHaWP0hnWT6hjmmAQZrH5muzSfxofZZMReavdhE=","Y6FuXJmG4asZZywv8eq2Ki3M3DHBabgHxixPNEPtsg0=","ocP7tLQvAC3JoF1EP3jOXtv3\u002Bd0qM3kdE0/8cY\u002BVC18=","CH9QcGeTGE6F7iss5IMJIdGAfaixRCv52kGorH\u002Br7UQ=","T1FmR6BuWj8NdQOpYSYpkD9zKCBLg9Fq2Txyqzbv0ow=","7pE8sSLDf7aqo6DjV5RYq1M\u002BISPAIo7BW6XwwSh6O1w=","yALO4iHkRJn2NKox\u002B\u002B4OZBqzhGPkvrA2bOX0emXGiac=","9JrQ3zBPaGik8svNVNuioqNGKWNvShwz32tj7Oyf9wM=","j0EJHazrwSEUHAPSEiUUhdwXrZ4ben27F7iH5Hnje/M=","JiuGUyztERDBSvF/6GDip3jqDWJzkWH6IdRYkvi5bw0=","bfM6e\u002BYucNXsBEQIq6EkXf6mNT\u002BPp63/xGN1rdjLZiQ=","7rNiQh7D0WAW\u002BBIalpkA6TbN/zPYEJsqZgWhr/HPCVs=","5CJDU5WOqZlcGfMhyrjY8yklCO49EP8N2oJgZCPtCvA=","PwMpWOwh/ebKXLFaIW93w/Nmg9sgkp21\u002BkJjs5VxJFY=","JPhvOaP4s5GzcXST3QvJD8qP\u002B/4XR1TCfIiP4loGLb8=","NVCP0V7YVnf5urwl2ofENh5w6TJfZ2MUUgzQ389SA1w=","VfTAU/4gffsId\u002B7V4v5FnVYVwig5FKCwrdNkRzRwGU0=","Y7eqVxFX7a20bQsQuQshHeV5QtkyeSYASzhM4PXTo30=","yOVmWadteUwj\u002BNmQpObPtaDAt52hoJ\u002Bl\u002BNzJVK7MBAU=","9cTrEyIQdmDa25ocL8Eyud7FcyZQ0KIMjdK17iVzX2k=","LpesthIqevfUpWNrijFwa6P4yw9y1fjCvhDIJi1HNSY=","7KbCVRYfzTj0uAmCgvUKF\u002B90LeMurRZZC0\u002BbZdNLQgg=","Yixqc1XRFIJzTzMVIDHsDQ6xJExHcrnledpmuK51aKg=","829a\u002BDQvI6dHkKDNA93VIjPgJhUHsPn\u002BBTPY8rp9WgM="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("vita-asistente")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3b7e629f7516b043e50080d4fda3dec4625b1db8")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+5c0cce7c1f3fa01b1f4930c2e7fdf7a92b7f700d")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("vita-asistente")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("vita-asistente")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
68ac8d6c1716eb6f2e80ee2727addb3d6bf2d33e35f9f985b924becf3c1df660
|
||||
438fa0af1f685fa87f855a8f86df0fd884cc1bbd4af8bf4bcd2f11fa5373f7c7
|
||||
|
||||
@@ -39,6 +39,14 @@ build_metadata.AdditionalFiles.CssScope =
|
||||
build_metadata.AdditionalFiles.TargetPath = Vmlld3NcSG9tZVxQcml2YWN5LmNzaHRtbA==
|
||||
build_metadata.AdditionalFiles.CssScope =
|
||||
|
||||
[C:/Users/franc/source/repos/Vita-Asistente/Views/Roles/Disable.cshtml]
|
||||
build_metadata.AdditionalFiles.TargetPath = Vmlld3NcUm9sZXNcRGlzYWJsZS5jc2h0bWw=
|
||||
build_metadata.AdditionalFiles.CssScope =
|
||||
|
||||
[C:/Users/franc/source/repos/Vita-Asistente/Views/Roles/Edit.cshtml]
|
||||
build_metadata.AdditionalFiles.TargetPath = Vmlld3NcUm9sZXNcRWRpdC5jc2h0bWw=
|
||||
build_metadata.AdditionalFiles.CssScope =
|
||||
|
||||
[C:/Users/franc/source/repos/Vita-Asistente/Views/Roles/Index.cshtml]
|
||||
build_metadata.AdditionalFiles.TargetPath = Vmlld3NcUm9sZXNcSW5kZXguY3NodG1s
|
||||
build_metadata.AdditionalFiles.CssScope =
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
# Plan de Desarrollo — Sistema de Gestión Médica
|
||||
|
||||
> **Stack:** ASP.NET Core 6+ MVC · MySQL (Pomelo EF Core) · Google Calendar API · Chatwoot
|
||||
> **Stack:** ASP.NET Core 8 + MVC · MySQL (Pomelo EF Core) · Google Calendar API · Chatwoot
|
||||
> **Duración estimada total:** 12–15 semanas
|
||||
|
||||
---
|
||||
@@ -22,23 +22,23 @@
|
||||
|
||||
**Objetivo:** Scaffolding del proyecto, modelos de datos, roles e Identity.
|
||||
|
||||
- [ ] Crear solución ASP.NET Core 6+ con MVC
|
||||
- [x] Crear solución ASP.NET Core 8+ con MVC
|
||||
- Configurar `Program.cs`, inyección de dependencias, Pomelo MySQL y Migrations base
|
||||
|
||||
- [ ] Implementar `ApplicationUser` con ASP.NET Identity
|
||||
- [x] Implementar `ApplicationUser` con ASP.NET Identity
|
||||
- Campos: `Nombre`, `Apellido`, `Documento`, `Dirección`, `Teléfono`, `RolPrincipal`
|
||||
|
||||
- [ ] Definir roles y políticas de autorización
|
||||
- [x] Definir roles y políticas de autorización
|
||||
- Roles: `Administrador`, `Médico`, `Secretaria`, `Recepcionista`
|
||||
- Implementar `RoleSeeder.cs`
|
||||
|
||||
- [ ] Construir `AccountController` (login / logout / registro)
|
||||
- [x] Construir `AccountController` (login / logout / registro)
|
||||
- Views con Bootstrap, validación del lado cliente y servidor
|
||||
|
||||
- [ ] Layout compartido y navbar condicional por rol
|
||||
- [x] Layout compartido y navbar condicional por rol
|
||||
- `_Layout.cshtml` con menú adaptado según claims del usuario autenticado
|
||||
|
||||
- [ ] Migraciones iniciales y seeder de roles
|
||||
- [x] Migraciones iniciales y seeder de roles
|
||||
- Verificar creación de tablas Identity en MySQL y usuario administrador inicial
|
||||
|
||||
---
|
||||
@@ -47,11 +47,14 @@
|
||||
|
||||
**Objetivo:** CRUD completo de personal médico y pacientes.
|
||||
|
||||
- [ ] Módulo de usuarios (`UsuariosController`)
|
||||
- [x] Módulo de usuarios (`UsuariosController`)
|
||||
- Listar, crear, editar, deshabilitar
|
||||
- Asignación de roles
|
||||
- Perfil de médico: `Especialidad`, `MatriculaProfesional`, `HorarioAtencion`
|
||||
|
||||
- [x] CRUD de roles (`RolesController`)
|
||||
- En el mismo index generar modales para poder editar los roles, y ademas poder habilitarlos o deshabilitarlos.
|
||||
|
||||
- [ ] Modelo y migración de `Paciente`
|
||||
- Campos: `Nombres`, `Apellidos`, `FechaNacimiento`, `Genero`, `DocumentoIdentidad` (único), `Direccion`, `Telefono`, `Email`, `ObraSocial`, `FechaRegistro`, FK a `UsuarioAlta`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user