Compare commits
108 Commits
801e21842a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5ae7fedef | ||
|
|
8d7cf86d4d | ||
|
|
81417b2a1c | ||
|
|
c0463a8f5b | ||
|
|
c4f1a1ca81 | ||
|
|
c523552d2f | ||
|
|
1e16dc5f18 | ||
|
|
313c4d6c60 | ||
|
|
0cbe46c93a | ||
|
|
55a118f8c9 | ||
|
|
056cac794b | ||
|
|
df2aaa38a3 | ||
|
|
d06dfed0e2 | ||
|
|
2161ebf1e8 | ||
|
|
42546af4f3 | ||
|
|
bd39a45dd2 | ||
|
|
cd2c2ac50d | ||
|
|
2bbd67e37d | ||
|
|
a2e14c73df | ||
|
|
c2161bdb91 | ||
|
|
49d32b0854 | ||
|
|
80b0e825b2 | ||
|
|
53b4a5e97d | ||
|
|
335112e044 | ||
|
|
9299e29ea6 | ||
|
|
5a17df917d | ||
|
|
8aed8d16b6 | ||
|
|
64aa9cf716 | ||
|
|
f63ccc2a38 | ||
|
|
a6fd3d720f | ||
|
|
77f6d2a475 | ||
|
|
85f559a607 | ||
|
|
0c2f131fff | ||
|
|
e96696f6be | ||
|
|
704e206476 | ||
|
|
6b19f08d6b | ||
|
|
146c557c25 | ||
|
|
fb24ffbf03 | ||
|
|
274f98baa4 | ||
|
|
80ffad6d86 | ||
|
|
5b0a8386ad | ||
|
|
4b8c54d38d | ||
|
|
cc96802637 | ||
|
|
95811ce3f8 | ||
|
|
4a7a2c30c9 | ||
|
|
8ebbb803e8 | ||
|
|
380978959b | ||
|
|
072369fa17 | ||
|
|
45994a9439 | ||
|
|
3ef872ac8c | ||
|
|
051ef625ba | ||
|
|
07f6451c5a | ||
|
|
979b05f2ca | ||
|
|
aefc653e22 | ||
|
|
4f14918b02 | ||
|
|
f8a33123d0 | ||
|
|
95bb989e07 | ||
|
|
004ac0c696 | ||
|
|
f0642e4587 | ||
|
|
2504fab3e7 | ||
|
|
a4229594bf | ||
|
|
55a254457b | ||
|
|
67670cc380 | ||
|
|
e26a809122 | ||
|
|
b1f20de393 | ||
|
|
c84699fd16 | ||
|
|
46299cb7f2 | ||
|
|
9f40b3f8a0 | ||
|
|
6cb2ebf3c8 | ||
|
|
871fe3a070 | ||
|
|
22ae26d488 | ||
|
|
b785051a89 | ||
|
|
0e58ffb735 | ||
|
|
76656bb6a8 | ||
|
|
113cce73ad | ||
|
|
fb62f076a0 | ||
|
|
6a43435950 | ||
|
|
f71be26ae4 | ||
|
|
d1e4901eee | ||
|
|
fc78ec0813 | ||
| 57bea7b54c | |||
|
|
465f9afc99 | ||
|
|
e3eb2dc7cb | ||
|
|
256ce76af1 | ||
|
|
b286fed88a | ||
|
|
bc77e39c72 | ||
|
|
eba00ffbf2 | ||
|
|
c44fbfdca9 | ||
|
|
84c6c45a0b | ||
|
|
83a71a6f1d | ||
|
|
fcd27943bf | ||
|
|
acbb72de3f | ||
|
|
c4efcc249b | ||
|
|
4da4a34443 | ||
|
|
77d3c741b1 | ||
|
|
e626daa7bc | ||
|
|
fe8e54b868 | ||
|
|
908bc469c6 | ||
|
|
3d6aa2d424 | ||
|
|
fd6759e3d0 | ||
|
|
4c60508d6d | ||
|
|
628f25a8be | ||
|
|
2e1e0f4670 | ||
|
|
a33ed400f1 | ||
|
|
5169889753 | ||
|
|
3b0ea79748 | ||
|
|
600df026d5 | ||
|
|
0cf9059195 |
52
.drone.yml
52
.drone.yml
@@ -2,45 +2,27 @@ kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
|
||||
volumes:
|
||||
- name: dockersock
|
||||
host:
|
||||
path: /var/run/docker.sock
|
||||
|
||||
steps:
|
||||
- name: build-dotnet
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0
|
||||
- name: docker-build
|
||||
image: docker:24
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run/docker.sock
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
LC_ALL: en_US.UTF-8
|
||||
DOTNET_CLI_UI_LANGUAGE: en-US
|
||||
commands:
|
||||
- dotnet publish Aberwyn/Aberwyn.csproj -c Release -o out
|
||||
|
||||
- name: build-docker
|
||||
image: plugins/docker
|
||||
settings:
|
||||
registry: 192.168.1.9:3000
|
||||
repo: 192.168.1.9:3000/tai/aberwyn/aberwyn
|
||||
username:
|
||||
GITEA_USERNAME:
|
||||
from_secret: gitea_username
|
||||
password:
|
||||
GITEA_TOKEN:
|
||||
from_secret: gitea_token
|
||||
dockerfile: Aberwyn/Dockerfile
|
||||
context: .
|
||||
tags:
|
||||
- latest
|
||||
insecure: true
|
||||
|
||||
- name: restart-unraid-container
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: 192.168.1.108
|
||||
port: 22
|
||||
username:
|
||||
from_secret: unraid_ssh_user
|
||||
key:
|
||||
from_secret: unraid_ssh_private_key
|
||||
script:
|
||||
- docker pull 192.168.1.9:3000/tai/aberwyn/aberwyn:latest
|
||||
- docker stop Aberwyn || true
|
||||
- docker rm Aberwyn || true
|
||||
- docker run -d --name='Aberwyn' --net='br0' -e TZ='Europe/Berlin' -p 80:80 192.168.1.9:3000/tai/aberwyn/aberwyn:latest
|
||||
commands:
|
||||
- export DOCKER_BUILDKIT=1
|
||||
- docker buildx create --use --driver docker-container || true
|
||||
- echo "$GITEA_TOKEN" | docker login 192.168.1.9:3000 -u "$GITEA_USERNAME" --password-stdin
|
||||
- docker buildx build --builder default --tag 192.168.1.9:3000/tai/aberwyn/aberwyn:latest --tag 192.168.1.9:3000/tai/aberwyn/aberwyn:${DRONE_COMMIT_SHA:0:7} --cache-from=type=registry,ref=192.168.1.9:3000/tai/aberwyn/aberwyn:buildcache --push -f Aberwyn/Dockerfile .
|
||||
|
||||
- name: notify-result
|
||||
image: alpine
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -361,3 +361,8 @@ MigrationBackup/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# Setupfil för Aberwyn
|
||||
infrastructure/setup.json
|
||||
Aberwyn/Infrastructure/setup.json
|
||||
/Aberwyn/Data/infrastructure/setup2.json
|
||||
|
||||
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"dotnet.defaultSolution": "Aberwyn.sln"
|
||||
}
|
||||
@@ -11,10 +11,6 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{423CD237-7404-4355-868F-CE5861835258}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{423CD237-7404-4355-868F-CE5861835258}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{423CD237-7404-4355-868F-CE5861835258}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{423CD237-7404-4355-868F-CE5861835258}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F5586986-B726-4E05-B31B-2E24CA5B2B89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F5586986-B726-4E05-B31B-2E24CA5B2B89}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F5586986-B726-4E05-B31B-2E24CA5B2B89}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
@@ -4,9 +4,9 @@ name: default
|
||||
|
||||
steps:
|
||||
- name: build-dotnet
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0
|
||||
image: alpine
|
||||
commands:
|
||||
- dotnet publish Aberwyn/Aberwyn.csproj -c Release -o out
|
||||
- echo "Docker build will handle dotnet publish"
|
||||
|
||||
- name: build-docker
|
||||
image: plugins/docker
|
||||
@@ -18,6 +18,26 @@ steps:
|
||||
password:
|
||||
from_secret: gitea_token
|
||||
dockerfile: Aberwyn/Dockerfile
|
||||
context: Aberwyn
|
||||
context: .
|
||||
tags:
|
||||
- latest
|
||||
insecure: true
|
||||
|
||||
- name: notify-result
|
||||
image: alpine
|
||||
when:
|
||||
status:
|
||||
- success
|
||||
- failure
|
||||
commands:
|
||||
- apk add --no-cache curl
|
||||
- |
|
||||
if [ "$DRONE_BUILD_STATUS" = "success" ]; then
|
||||
curl -X POST http://192.168.1.196:8123/api/webhook/aberwyn_update_success
|
||||
else
|
||||
curl -X POST http://192.168.1.196:8123/api/webhook/aberwyn_update_failed
|
||||
fi
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
|
||||
@@ -10,24 +10,15 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="NewFolder\**" />
|
||||
<Content Remove="NewFolder\**" />
|
||||
<EmbeddedResource Remove="NewFolder\**" />
|
||||
<None Remove="NewFolder\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Data\BudgetService.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Views\Home\Budget.cshtml" />
|
||||
<Content Remove="Views\Rss\_RssListPartial.cshtml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AngularJS.Core" Version="1.8.2" />
|
||||
<PackageReference Include="BencodeNET" Version="5.0.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.67" />
|
||||
<PackageReference Include="Lib.Net.Http.WebPush" Version="3.3.1" />
|
||||
<PackageReference Include="MessagePack" Version="3.1.4" />
|
||||
|
||||
<!-- Entity Framework Core 6 -->
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.36" />
|
||||
@@ -35,6 +26,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.36" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.36" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.36">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
@@ -52,12 +44,28 @@
|
||||
<!-- Övrigt -->
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.15.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.18" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageReference Include="System.Text.Json" Version="10.0.2" />
|
||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageReference Include="WebPush" Version="1.0.12" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Views\NewFolder\" />
|
||||
<Folder Include="Migrations\" />
|
||||
<Folder Include="wwwroot\images\meals\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.Development.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="appsettings.Production.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -14,70 +14,21 @@
|
||||
<hr />
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-floating">
|
||||
<input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" />
|
||||
<label asp-for="Input.Email" class="form-label"></label>
|
||||
<span asp-validation-for="Input.Email" class="text-danger"></span>
|
||||
<label asp-for="Input.UserName"></label>
|
||||
<input asp-for="Input.UserName" />
|
||||
<span asp-validation-for="Input.UserName" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating">
|
||||
<input asp-for="Input.Password" class="form-control" autocomplete="current-password" aria-required="true" />
|
||||
<label asp-for="Input.Password" class="form-label"></label>
|
||||
<input asp-for="Input.Password" class="form-control" autocomplete="current-password" aria-required="true" />
|
||||
<span asp-validation-for="Input.Password" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="checkbox">
|
||||
<label asp-for="Input.RememberMe" class="form-label">
|
||||
<input class="form-check-input" asp-for="Input.RememberMe" />
|
||||
@Html.DisplayNameFor(m => m.Input.RememberMe)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button id="login-submit" type="submit" class="w-100 btn btn-lg btn-primary">Log in</button>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<a id="forgot-password" asp-page="./ForgotPassword">Forgot your password?</a>
|
||||
</p>
|
||||
<p>
|
||||
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
|
||||
</p>
|
||||
<p>
|
||||
<a id="resend-confirmation" asp-page="./ResendEmailConfirmation">Resend email confirmation</a>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-md-6 col-md-offset-2">
|
||||
<section>
|
||||
<h3>Use another service to log in.</h3>
|
||||
<hr />
|
||||
@{
|
||||
if ((Model.ExternalLogins?.Count ?? 0) == 0)
|
||||
{
|
||||
<div>
|
||||
<p>
|
||||
There are no external authentication services configured. See this <a href="https://go.microsoft.com/fwlink/?LinkID=532715">article
|
||||
about setting up this ASP.NET application to support logging in via external services</a>.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
|
||||
<div>
|
||||
<p>
|
||||
@foreach (var provider in Model.ExternalLogins!)
|
||||
{
|
||||
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
|
||||
@@ -61,27 +61,14 @@ namespace Aberwyn.Areas.Identity.Pages.Account
|
||||
/// </summary>
|
||||
public class InputModel
|
||||
{
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
public string Email { get; set; }
|
||||
[Display(Name = "Username")]
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
[Display(Name = "Remember me?")]
|
||||
public bool RememberMe { get; set; }
|
||||
}
|
||||
|
||||
@@ -112,7 +99,7 @@ namespace Aberwyn.Areas.Identity.Pages.Account
|
||||
{
|
||||
// This doesn't count login failures towards account lockout
|
||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
||||
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
|
||||
var result = await _signInManager.PasswordSignInAsync(Input.UserName, Input.Password, isPersistent: true, lockoutOnFailure: false);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_logger.LogInformation("User logged in.");
|
||||
|
||||
@@ -53,6 +53,11 @@ namespace Aberwyn.Areas.Identity.Pages.Account.Manage
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
///
|
||||
[Required]
|
||||
[Display(Name = "Användarnamn")]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Current password")]
|
||||
|
||||
@@ -5,28 +5,35 @@ using Aberwyn.Models;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
|
||||
[Authorize(Roles = "Admin")]
|
||||
public class AdminController : Controller
|
||||
{
|
||||
private readonly MenuService _menuService;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly RoleManager<IdentityRole> _roleManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IHostEnvironment _env;
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
|
||||
public AdminController(
|
||||
MenuService menuService,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
RoleManager<IdentityRole> roleManager,
|
||||
IConfiguration configuration,
|
||||
IHostEnvironment env,
|
||||
ApplicationDbContext context)
|
||||
{
|
||||
_menuService = menuService;
|
||||
_userManager = userManager;
|
||||
_roleManager = roleManager;
|
||||
_configuration = configuration;
|
||||
_env = env;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var users = _userManager.Users.ToList();
|
||||
@@ -96,45 +103,287 @@ namespace Aberwyn.Controllers
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public IActionResult ImportMenusFromCustom(string dbHost, int dbPort, string dbName, string dbUser, string dbPassword)
|
||||
{
|
||||
var connStr = $"Server={dbHost};Port={dbPort};Database={dbName};Uid={dbUser};Pwd={dbPassword};";
|
||||
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
optionsBuilder.UseMySql(connStr, ServerVersion.AutoDetect(connStr));
|
||||
|
||||
using var customContext = new ApplicationDbContext(optionsBuilder.Options);
|
||||
var sourceService = new MenuService(customContext);
|
||||
var devService = new MenuService(_context);
|
||||
|
||||
var sourceMenus = sourceService.GetAllWeeklyMenus();
|
||||
var devMeals = devService.GetMeals();
|
||||
|
||||
foreach (var menu in sourceMenus)
|
||||
{
|
||||
var newMenu = new WeeklyMenu
|
||||
{
|
||||
DayOfWeek = menu.DayOfWeek,
|
||||
WeekNumber = menu.WeekNumber,
|
||||
Year = menu.Year,
|
||||
Cook = menu.Cook,
|
||||
BreakfastMealId = null,
|
||||
LunchMealId = null,
|
||||
DinnerMealId = null
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(menu.BreakfastMealName))
|
||||
newMenu.BreakfastMealId = devMeals.FirstOrDefault(m => m.Name == menu.BreakfastMealName)?.Id;
|
||||
|
||||
if (!string.IsNullOrEmpty(menu.LunchMealName))
|
||||
newMenu.LunchMealId = devMeals.FirstOrDefault(m => m.Name == menu.LunchMealName)?.Id;
|
||||
|
||||
if (!string.IsNullOrEmpty(menu.DinnerMealName))
|
||||
newMenu.DinnerMealId = devMeals.FirstOrDefault(m => m.Name == menu.DinnerMealName)?.Id;
|
||||
|
||||
_context.WeeklyMenus.Add(newMenu);
|
||||
}
|
||||
|
||||
_context.SaveChanges();
|
||||
TempData["Message"] = $"✅ Import av veckomenyer från extern databas klar ({sourceMenus.Count}).";
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public IActionResult GenerateThumbnails()
|
||||
{
|
||||
var count = _menuService.GenerateMissingThumbnails();
|
||||
return Ok($"{count} thumbnails skapades.");
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public IActionResult ImportMealsFromCustom(string dbHost, int dbPort, string dbName, string dbUser, string dbPassword)
|
||||
{
|
||||
var connStr = $"Server={dbHost};Port={dbPort};Database={dbName};Uid={dbUser};Pwd={dbPassword};";
|
||||
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
optionsBuilder.UseMySql(connStr, ServerVersion.AutoDetect(connStr), mySqlOptions => mySqlOptions.CommandTimeout(180));
|
||||
using var customContext = new ApplicationDbContext(optionsBuilder.Options);
|
||||
|
||||
var customService = new MenuService(customContext);
|
||||
var devService = new MenuService(_context);
|
||||
|
||||
try
|
||||
{
|
||||
var importedMeals = customService.GetMealsDetailed(); // Ska inkludera Ingredients
|
||||
foreach (var meal in importedMeals)
|
||||
{
|
||||
var newMeal = new Meal
|
||||
{
|
||||
Id = meal.Id, // 👈 Viktigt!
|
||||
Name = meal.Name,
|
||||
Description = meal.Description,
|
||||
ProteinType = meal.ProteinType,
|
||||
Category = meal.Category,
|
||||
CarbType = meal.CarbType,
|
||||
RecipeUrl = meal.RecipeUrl,
|
||||
ImageUrl = meal.ImageUrl,
|
||||
IsAvailable = meal.IsAvailable,
|
||||
CreatedAt = meal.CreatedAt,
|
||||
Instructions = meal.Instructions,
|
||||
ImageData = meal.ImageData,
|
||||
ImageMimeType = meal.ImageMimeType,
|
||||
Ingredients = meal.Ingredients.Select(i => new Ingredient
|
||||
{
|
||||
MealId = meal.Id, // 👈 Koppla till rätt måltid
|
||||
Quantity = i.Quantity,
|
||||
Item = i.Item
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
devService.SaveOrUpdateMealWithIngredients(newMeal);
|
||||
}
|
||||
|
||||
TempData["Message"] = $"✅ {importedMeals.Count} måltider importerade från extern databas.";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TempData["Message"] = $"❌ Fel vid import: {ex.Message}";
|
||||
}
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public IActionResult ImportBudgetFromCustom(string dbHost, int dbPort, string dbName, string dbUser, string dbPassword)
|
||||
{
|
||||
var connStr = $"Server={dbHost};Port={dbPort};Database={dbName};Uid={dbUser};Pwd={dbPassword};";
|
||||
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
optionsBuilder.UseMySql(connStr, ServerVersion.AutoDetect(connStr));
|
||||
|
||||
using var sourceContext = new ApplicationDbContext(optionsBuilder.Options);
|
||||
|
||||
var categoryDefs = sourceContext.BudgetCategoryDefinitions.ToList();
|
||||
var itemDefs = sourceContext.BudgetItemDefinitions.ToList();
|
||||
|
||||
foreach (var def in categoryDefs)
|
||||
{
|
||||
if (!_context.BudgetCategoryDefinitions.Any(d => d.Name == def.Name))
|
||||
{
|
||||
_context.BudgetCategoryDefinitions.Add(new BudgetCategoryDefinition
|
||||
{
|
||||
Name = def.Name,
|
||||
Color = def.Color ?? "#cccccc"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var def in itemDefs)
|
||||
{
|
||||
if (!_context.BudgetItemDefinitions.Any(d => d.Name == def.Name))
|
||||
{
|
||||
_context.BudgetItemDefinitions.Add(new BudgetItemDefinition { Name = def.Name });
|
||||
}
|
||||
}
|
||||
|
||||
_context.SaveChanges();
|
||||
|
||||
var devCategoryDefs = _context.BudgetCategoryDefinitions.ToList();
|
||||
var devItemDefs = _context.BudgetItemDefinitions.ToList();
|
||||
|
||||
var periods = sourceContext.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.ToList();
|
||||
|
||||
foreach (var period in periods)
|
||||
{
|
||||
var exists = _context.BudgetPeriods
|
||||
.Any(p => p.Year == period.Year && p.Month == period.Month);
|
||||
|
||||
if (exists)
|
||||
continue;
|
||||
|
||||
var newPeriod = new BudgetPeriod
|
||||
{
|
||||
Year = period.Year,
|
||||
Month = period.Month,
|
||||
Categories = period.Categories.Select(c => new BudgetCategory
|
||||
{
|
||||
Name = c.Name,
|
||||
Color = string.IsNullOrWhiteSpace(c.Color) ? "#cccccc" : c.Color,
|
||||
Order = c.Order,
|
||||
BudgetCategoryDefinitionId = devCategoryDefs
|
||||
.FirstOrDefault(d => d.Name == c.Definition?.Name)?.Id,
|
||||
Items = c.Items.Select(i => new BudgetItem
|
||||
{
|
||||
Name = i.Name,
|
||||
Amount = i.Amount,
|
||||
IsExpense = i.IsExpense,
|
||||
IncludeInSummary = i.IncludeInSummary,
|
||||
Order = i.Order,
|
||||
BudgetItemDefinitionId = devItemDefs
|
||||
.FirstOrDefault(d => d.Name == i.BudgetItemDefinition?.Name)?.Id
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
_context.BudgetPeriods.Add(newPeriod);
|
||||
}
|
||||
|
||||
_context.SaveChanges();
|
||||
TempData["Message"] = $"✅ Import av budgetdata från extern databas klar ({periods.Count} månader).";
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Todo
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Todo()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetTodoTasks()
|
||||
public IActionResult GetTodoTasks()
|
||||
{
|
||||
var tasks = await _context.TodoTasks.ToListAsync();
|
||||
var tasks = _context.TodoTasks
|
||||
.OrderByDescending(t => t.CreatedAt)
|
||||
.ToList();
|
||||
return Json(tasks);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddTodoTask([FromBody] TodoTask task)
|
||||
public IActionResult AddTodoTask([FromBody] TodoTask task)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(task?.Title))
|
||||
return BadRequest("Titel krävs");
|
||||
|
||||
task.CreatedAt = DateTime.UtcNow;
|
||||
task.Priority = task.Priority == 0 ? 1 : task.Priority; // default till låg om ej satt
|
||||
|
||||
task.Status ??= "ideas";
|
||||
task.Tags ??= "";
|
||||
task.AssignedTo ??= null;
|
||||
task.Description ??= "";
|
||||
|
||||
_context.TodoTasks.Add(task);
|
||||
await _context.SaveChangesAsync();
|
||||
return Ok(task);
|
||||
_context.SaveChanges();
|
||||
|
||||
return Json(task);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 👇 Returnera hela stacktracen som JSON för felsökning
|
||||
return StatusCode(500, ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> UpdateTodoTask([FromBody] TodoTask task)
|
||||
public IActionResult UpdateTodoTask([FromBody] TodoTask task)
|
||||
{
|
||||
var existing = await _context.TodoTasks.FindAsync(task.Id);
|
||||
if (existing == null) return NotFound();
|
||||
var existing = _context.TodoTasks.FirstOrDefault(t => t.Id == task.Id);
|
||||
if (existing == null)
|
||||
return NotFound();
|
||||
|
||||
existing.Title = task.Title;
|
||||
existing.Status = task.Status;
|
||||
existing.Priority = task.Priority;
|
||||
await _context.SaveChangesAsync();
|
||||
existing.Description = task.Description;
|
||||
existing.Tags = task.Tags;
|
||||
existing.AssignedTo = task.AssignedTo;
|
||||
existing.IsArchived = task.IsArchived;
|
||||
|
||||
_context.SaveChanges();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public IActionResult TestDbConnection(string dbHost, int dbPort, string dbName, string dbUser, string dbPassword)
|
||||
{
|
||||
var connStr = $"Server={dbHost};Port={dbPort};Database={dbName};Uid={dbUser};Pwd={dbPassword};";
|
||||
|
||||
try
|
||||
{
|
||||
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
builder.UseMySql(connStr, ServerVersion.AutoDetect(connStr));
|
||||
|
||||
using var context = new ApplicationDbContext(builder.Options);
|
||||
context.Database.OpenConnection();
|
||||
context.Database.CloseConnection();
|
||||
|
||||
return Json(new { success = true, message = "✅ Anslutning lyckades!" });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Json(new { success = false, message = $"❌ Anslutning misslyckades: {ex.Message}" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Aberwyn.Controllers
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var period = await _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
@@ -43,8 +44,8 @@ namespace Aberwyn.Controllers
|
||||
var dto = new BudgetDto
|
||||
{
|
||||
Id = period.Id,
|
||||
Year = period.Year,
|
||||
Month = period.Month,
|
||||
Year = period.Year ?? 0,
|
||||
Month = period.Month ?? 0,
|
||||
Categories = period.Categories
|
||||
.OrderBy(cat => cat.Order)
|
||||
.Select(cat => new BudgetCategoryDto
|
||||
@@ -61,7 +62,8 @@ namespace Aberwyn.Controllers
|
||||
Amount = i.Amount,
|
||||
IsExpense = i.IsExpense,
|
||||
IncludeInSummary = i.IncludeInSummary,
|
||||
BudgetItemDefinitionId = i.BudgetItemDefinitionId
|
||||
BudgetItemDefinitionId = i.BudgetItemDefinitionId,
|
||||
PaymentStatus = i.PaymentStatus
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
};
|
||||
@@ -74,6 +76,75 @@ namespace Aberwyn.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("byname/{name}")]
|
||||
public async Task<IActionResult> GetBudgetByName(string name)
|
||||
{
|
||||
var period = _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.AsEnumerable() // hämta från db och gör resten i minnet
|
||||
.FirstOrDefault(p => p.Name != null &&
|
||||
p.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
|
||||
if (period == null)
|
||||
{
|
||||
return Ok(new BudgetDto
|
||||
{
|
||||
Name = name,
|
||||
Categories = new List<BudgetCategoryDto>()
|
||||
});
|
||||
}
|
||||
|
||||
var dto = new BudgetDto
|
||||
{
|
||||
Id = period.Id,
|
||||
Name = period.Name,
|
||||
Year = period.Year ?? 0,
|
||||
Month = period.Month ?? 0,
|
||||
Categories = period.Categories
|
||||
.OrderBy(cat => cat.Order)
|
||||
.Select(cat => new BudgetCategoryDto
|
||||
{
|
||||
Id = cat.Id,
|
||||
Name = cat.Name,
|
||||
Color = cat.Color,
|
||||
Items = cat.Items
|
||||
.OrderBy(i => i.Order)
|
||||
.Select(i => new BudgetItemDto
|
||||
{
|
||||
Id = i.Id,
|
||||
Name = i.Name,
|
||||
Amount = i.Amount,
|
||||
IsExpense = i.IsExpense,
|
||||
IncludeInSummary = i.IncludeInSummary,
|
||||
BudgetItemDefinitionId = i.BudgetItemDefinitionId,
|
||||
PaymentStatus = i.PaymentStatus
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
return Ok(dto);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPut("updatePaymentStatus")]
|
||||
public IActionResult UpdatePaymentStatus([FromBody] PaymentStatusUpdateDto dto)
|
||||
{
|
||||
if (dto == null)
|
||||
return BadRequest("dto is null");
|
||||
|
||||
var item = _context.BudgetItems.Find(dto.ItemId);
|
||||
if (item == null) return NotFound();
|
||||
|
||||
item.PaymentStatus = (PaymentStatus)dto.Status;
|
||||
_context.SaveChanges();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
[HttpPut("category/{id}")]
|
||||
public async Task<IActionResult> UpdateCategory(int id, [FromBody] BudgetCategoryDto updatedCategory)
|
||||
{
|
||||
@@ -183,11 +254,37 @@ namespace Aberwyn.Controllers
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreatePeriod([FromBody] BudgetPeriod newPeriod)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(newPeriod.Name))
|
||||
{
|
||||
var existingNamed = await _context.BudgetPeriods
|
||||
.FirstOrDefaultAsync(p => p.Name != null && p.Name.ToLower() == newPeriod.Name.ToLower());
|
||||
|
||||
if (existingNamed != null)
|
||||
return Conflict("En budget med detta namn finns redan.");
|
||||
|
||||
_context.BudgetPeriods.Add(newPeriod);
|
||||
await _context.SaveChangesAsync();
|
||||
return CreatedAtAction(nameof(GetBudget), new { year = newPeriod.Year, month = newPeriod.Month }, newPeriod);
|
||||
return Ok(new { id = newPeriod.Id });
|
||||
}
|
||||
|
||||
if (newPeriod.Year.HasValue && newPeriod.Month.HasValue)
|
||||
{
|
||||
var existing = await _context.BudgetPeriods
|
||||
.FirstOrDefaultAsync(p => p.Year == newPeriod.Year && p.Month == newPeriod.Month);
|
||||
|
||||
if (existing != null)
|
||||
return Conflict("En budget för denna månad finns redan.");
|
||||
|
||||
_context.BudgetPeriods.Add(newPeriod);
|
||||
await _context.SaveChangesAsync();
|
||||
return Ok(new { id = newPeriod.Id });
|
||||
}
|
||||
|
||||
return BadRequest("Varken namn eller år/månad angivet.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPut("item/{id}")]
|
||||
public async Task<IActionResult> UpdateItem(int id, [FromBody] BudgetItem updatedItem)
|
||||
{
|
||||
@@ -270,6 +367,73 @@ namespace Aberwyn.Controllers
|
||||
return Ok(new { id = newItem.Id });
|
||||
}
|
||||
|
||||
[HttpGet("list")]
|
||||
public async Task<IActionResult> GetAllBudgets()
|
||||
{
|
||||
var periods = await _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.OrderByDescending(p => p.Year)
|
||||
.ThenByDescending(p => p.Month)
|
||||
.ToListAsync();
|
||||
|
||||
var result = periods.Select(p => new
|
||||
{
|
||||
id = p.Id,
|
||||
name = p.Name,
|
||||
year = p.Year,
|
||||
month = p.Month,
|
||||
categories = p.Categories
|
||||
.OrderBy(c => c.Order)
|
||||
.Select(c => new
|
||||
{
|
||||
id = c.Id,
|
||||
name = c.Name,
|
||||
color = c.Color,
|
||||
total = c.Items.Sum(i => i.Amount),
|
||||
items = c.Items
|
||||
.OrderBy(i => i.Order)
|
||||
.Select(i => new
|
||||
{
|
||||
id = i.Id,
|
||||
name = i.Name,
|
||||
amount = i.Amount,
|
||||
isExpense = i.IsExpense,
|
||||
includeInSummary = i.IncludeInSummary
|
||||
}).ToList()
|
||||
}).ToList(),
|
||||
total = p.Categories.Sum(c => c.Items.Sum(i => i.Amount))
|
||||
});
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
|
||||
// DELETE: api/budget/byname/{name}
|
||||
[HttpDelete("byname/{name}")]
|
||||
public async Task<IActionResult> DeleteByName(string name)
|
||||
{
|
||||
var period = await _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.FirstOrDefaultAsync(p => p.Name != null && p.Name.ToLower() == name.ToLower());
|
||||
|
||||
if (period == null)
|
||||
return NotFound();
|
||||
|
||||
foreach (var category in period.Categories)
|
||||
{
|
||||
_context.BudgetItems.RemoveRange(category.Items);
|
||||
}
|
||||
|
||||
_context.BudgetCategories.RemoveRange(period.Categories);
|
||||
_context.BudgetPeriods.Remove(period);
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[HttpDelete("item/{id}")]
|
||||
@@ -314,19 +478,12 @@ namespace Aberwyn.Controllers
|
||||
return BadRequest("Ogiltig data.");
|
||||
|
||||
var period = await _context.BudgetPeriods
|
||||
.FirstOrDefaultAsync(p => p.Year == newCategoryDto.Year && p.Month == newCategoryDto.Month);
|
||||
.FirstOrDefaultAsync(p => p.Id == newCategoryDto.BudgetPeriodId);
|
||||
|
||||
if (period == null)
|
||||
{
|
||||
period = new BudgetPeriod
|
||||
{
|
||||
Year = newCategoryDto.Year,
|
||||
Month = newCategoryDto.Month
|
||||
};
|
||||
_context.BudgetPeriods.Add(period);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
return NotFound("Kunde inte hitta angiven budgetperiod.");
|
||||
|
||||
// 🔁 fortsätt som tidigare…
|
||||
var definition = await _context.BudgetCategoryDefinitions
|
||||
.FirstOrDefaultAsync(d => d.Name.ToLower() == newCategoryDto.Name.ToLower());
|
||||
|
||||
@@ -356,6 +513,8 @@ namespace Aberwyn.Controllers
|
||||
return Ok(new { id = category.Id });
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpDelete("category/{id}")]
|
||||
public async Task<IActionResult> DeleteCategory(int id)
|
||||
{
|
||||
@@ -374,7 +533,7 @@ namespace Aberwyn.Controllers
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost("copy/{year:int}/{month:int}")]
|
||||
/*[HttpPost("copy/{year:int}/{month:int}")]
|
||||
public async Task<IActionResult> CopyFromPreviousMonth(int year, int month)
|
||||
{
|
||||
var targetPeriod = await _context.BudgetPeriods
|
||||
@@ -420,9 +579,333 @@ namespace Aberwyn.Controllers
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return Ok();
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
// Gemensam intern metod
|
||||
private async Task<BudgetPeriod?> CopyBudgetAsync(
|
||||
BudgetPeriod targetPeriod,
|
||||
BudgetPeriod sourcePeriod)
|
||||
{
|
||||
if (sourcePeriod == null) return null;
|
||||
|
||||
targetPeriod.Categories = sourcePeriod.Categories.Select(cat => new BudgetCategory
|
||||
{
|
||||
Name = cat.Name,
|
||||
Color = cat.Color,
|
||||
Order = cat.Order,
|
||||
BudgetCategoryDefinitionId = cat.BudgetCategoryDefinitionId,
|
||||
Items = cat.Items.Select(item => new BudgetItem
|
||||
{
|
||||
Name = item.Name,
|
||||
Amount = item.Amount,
|
||||
IsExpense = item.IsExpense,
|
||||
IncludeInSummary = item.IncludeInSummary,
|
||||
Order = item.Order,
|
||||
BudgetItemDefinitionId = item.BudgetItemDefinitionId
|
||||
}).ToList()
|
||||
}).ToList();
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
return targetPeriod;
|
||||
}
|
||||
[HttpPost("copy/byname/{targetName}")]
|
||||
public async Task<IActionResult> CopyToNamedBudget(
|
||||
string targetName,
|
||||
[FromQuery] string? from,
|
||||
[FromQuery] int? fromYear,
|
||||
[FromQuery] int? fromMonth)
|
||||
{
|
||||
var targetPeriod = await _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.FirstOrDefaultAsync(p => p.Name != null && p.Name.ToLower() == targetName.ToLower());
|
||||
|
||||
if (targetPeriod == null)
|
||||
{
|
||||
targetPeriod = new BudgetPeriod { Name = targetName };
|
||||
_context.BudgetPeriods.Add(targetPeriod);
|
||||
}
|
||||
else if (targetPeriod.Categories.Any())
|
||||
{
|
||||
return BadRequest("Det finns redan data för denna budget.");
|
||||
}
|
||||
|
||||
// Hämta källperiod
|
||||
var sourcePeriod = await FindSourcePeriod(from, fromYear, fromMonth);
|
||||
if (sourcePeriod == null)
|
||||
return NotFound("Ingen budget hittades att kopiera från.");
|
||||
|
||||
await CopyBudgetAsync(targetPeriod, sourcePeriod);
|
||||
return Ok(new { id = targetPeriod.Id });
|
||||
}
|
||||
[HttpPost("copy/{year:int}/{month:int}")]
|
||||
public async Task<IActionResult> CopyToYearMonth(
|
||||
int year,
|
||||
int month,
|
||||
[FromQuery] string? from,
|
||||
[FromQuery] int? fromYear,
|
||||
[FromQuery] int? fromMonth)
|
||||
{
|
||||
var targetPeriod = await _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.FirstOrDefaultAsync(p => p.Year == year && p.Month == month);
|
||||
|
||||
if (targetPeriod == null)
|
||||
{
|
||||
targetPeriod = new BudgetPeriod { Year = year, Month = month };
|
||||
_context.BudgetPeriods.Add(targetPeriod);
|
||||
}
|
||||
else if (targetPeriod.Categories.Any())
|
||||
{
|
||||
return BadRequest("Det finns redan data för denna månad.");
|
||||
}
|
||||
|
||||
// Hämta källperiod
|
||||
var sourcePeriod = await FindSourcePeriod(from, fromYear, fromMonth, year, month);
|
||||
if (sourcePeriod == null)
|
||||
return NotFound("Ingen data att kopiera från.");
|
||||
|
||||
await CopyBudgetAsync(targetPeriod, sourcePeriod);
|
||||
return Ok(new { id = targetPeriod.Id });
|
||||
}
|
||||
private async Task<BudgetPeriod?> FindSourcePeriod(
|
||||
string? from,
|
||||
int? fromYear,
|
||||
int? fromMonth,
|
||||
int? defaultYear = null,
|
||||
int? defaultMonth = null)
|
||||
{
|
||||
BudgetPeriod? sourcePeriod = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(from))
|
||||
{
|
||||
sourcePeriod = await _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.FirstOrDefaultAsync(p => p.Name != null && p.Name.ToLower() == from.ToLower());
|
||||
}
|
||||
else if (fromYear.HasValue && fromMonth.HasValue)
|
||||
{
|
||||
sourcePeriod = await _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.FirstOrDefaultAsync(p => p.Year == fromYear && p.Month == fromMonth);
|
||||
}
|
||||
else if (defaultYear.HasValue && defaultMonth.HasValue)
|
||||
{
|
||||
var previous = new DateTime(defaultYear.Value, defaultMonth.Value, 1).AddMonths(-1);
|
||||
sourcePeriod = await _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.FirstOrDefaultAsync(p => p.Year == previous.Year && p.Month == previous.Month);
|
||||
}
|
||||
|
||||
return sourcePeriod;
|
||||
}
|
||||
|
||||
[HttpGet("metadata")]
|
||||
public async Task<IActionResult> GetMetadata([FromQuery] int? year, [FromQuery] int? month)
|
||||
{
|
||||
var categoriesQuery = _context.BudgetCategories
|
||||
.Include(c => c.BudgetPeriod)
|
||||
.Include(c => c.Items)
|
||||
.ThenInclude(i => i.BudgetItemDefinition)
|
||||
.AsQueryable();
|
||||
|
||||
if (year.HasValue)
|
||||
categoriesQuery = categoriesQuery.Where(c => c.BudgetPeriod.Year == year.Value);
|
||||
if (month.HasValue)
|
||||
categoriesQuery = categoriesQuery.Where(c => c.BudgetPeriod.Month == month.Value);
|
||||
|
||||
var categories = await categoriesQuery.ToListAsync();
|
||||
|
||||
var categoryDefs = categories
|
||||
.Where(c => c.BudgetCategoryDefinitionId.HasValue)
|
||||
.GroupBy(c => c.Definition?.Name ?? c.Name)
|
||||
.Select(g => new {
|
||||
Name = g.Key,
|
||||
Color = g.First().Color ?? "#cccccc" // direkt från kategorin
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var categoryLabels = categories
|
||||
.GroupBy(c => c.Name)
|
||||
.Select(g => new {
|
||||
Name = g.Key,
|
||||
Color = g.First().Color ?? "#cccccc"
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
var itemDefs = categories
|
||||
.SelectMany(c => c.Items)
|
||||
.Select(i => i.BudgetItemDefinition?.Name ?? i.Name)
|
||||
.Distinct()
|
||||
.OrderBy(n => n)
|
||||
.ToList();
|
||||
|
||||
var itemLabels = categories
|
||||
.SelectMany(c => c.Items)
|
||||
.Select(i => i.Name)
|
||||
.Distinct()
|
||||
.OrderBy(n => n)
|
||||
.ToList();
|
||||
|
||||
Console.WriteLine($"Metadata: {categories.Count} categories, {itemLabels.Count} items");
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
CategoryDefinitions = categoryDefs,
|
||||
CategoryLabels = categoryLabels,
|
||||
ItemDefinitions = itemDefs,
|
||||
ItemLabels = itemLabels
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("report/spreadsheet")]
|
||||
public async Task<IActionResult> GetBudgetReport(
|
||||
[FromQuery] int? year = null,
|
||||
[FromQuery] List<int>? itemDefinitionIds = null,
|
||||
[FromQuery] List<int>? categoryDefinitionIds = null,
|
||||
[FromQuery] string? itemLabel = null,
|
||||
[FromQuery] string? categoryLabel = null,
|
||||
[FromQuery] bool includeCategoryDefinitions = false,
|
||||
[FromQuery] bool includeCategoryLabels = false,
|
||||
[FromQuery] bool includeItemDefinitions = true,
|
||||
[FromQuery] bool includeItemLabels = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
// ✅ Ladda navigationsproperties för definitions
|
||||
var query = _context.BudgetPeriods
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Definition) // CategoryDefinition
|
||||
.Include(p => p.Categories)
|
||||
.ThenInclude(c => c.Items)
|
||||
.ThenInclude(i => i.BudgetItemDefinition) // ItemDefinition
|
||||
.Where(p => p.Year.HasValue && p.Month.HasValue)
|
||||
.AsQueryable();
|
||||
|
||||
if (year.HasValue)
|
||||
query = query.Where(p => p.Year == year);
|
||||
|
||||
var periods = await query
|
||||
.OrderByDescending(p => p.Year)
|
||||
.ThenByDescending(p => p.Month)
|
||||
.ToListAsync();
|
||||
|
||||
var reportData = periods.Select(p =>
|
||||
{
|
||||
var filteredCategories = p.Categories
|
||||
.Where(c =>
|
||||
(categoryDefinitionIds == null || categoryDefinitionIds.Count == 0 ||
|
||||
(c.BudgetCategoryDefinitionId.HasValue &&
|
||||
categoryDefinitionIds.Contains(c.BudgetCategoryDefinitionId.Value))) &&
|
||||
(string.IsNullOrEmpty(categoryLabel) ||
|
||||
(c.Name ?? string.Empty).Contains(categoryLabel, StringComparison.OrdinalIgnoreCase))
|
||||
)
|
||||
.ToList(); // Viktigt: gå över till LINQ to Objects
|
||||
|
||||
var filteredItems = filteredCategories
|
||||
.SelectMany(c => c.Items)
|
||||
.Where(i =>
|
||||
i.IncludeInSummary &&
|
||||
(itemDefinitionIds == null || itemDefinitionIds.Count == 0 ||
|
||||
(i.BudgetItemDefinitionId.HasValue &&
|
||||
itemDefinitionIds.Contains(i.BudgetItemDefinitionId.Value))) &&
|
||||
(string.IsNullOrEmpty(itemLabel) ||
|
||||
(i.Name ?? string.Empty).Contains(itemLabel, StringComparison.OrdinalIgnoreCase))
|
||||
)
|
||||
.ToList();
|
||||
|
||||
// 🔹 Skapa kolumner
|
||||
var itemDefColumns = new Dictionary<string, decimal>();
|
||||
var itemLabelColumns = new Dictionary<string, decimal>();
|
||||
var catDefColumns = new Dictionary<string, decimal>();
|
||||
var catLabelColumns = new Dictionary<string, decimal>();
|
||||
|
||||
if (includeItemDefinitions)
|
||||
{
|
||||
foreach (var g in filteredItems
|
||||
.Where(i => i.BudgetItemDefinition != null)
|
||||
.GroupBy(i => i.BudgetItemDefinition!.Name))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(g.Key))
|
||||
itemDefColumns[g.Key] = g.Sum(i => i.IsExpense ? -i.Amount : i.Amount);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeItemLabels)
|
||||
{
|
||||
foreach (var g in filteredItems
|
||||
.Where(i => !string.IsNullOrEmpty(i.Name))
|
||||
.GroupBy(i => i.Name))
|
||||
{
|
||||
itemLabelColumns[g.Key] = g.Sum(i => i.IsExpense ? -i.Amount : i.Amount);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeCategoryDefinitions)
|
||||
{
|
||||
foreach (var g in filteredCategories
|
||||
.Where(c => c.Definition != null)
|
||||
.GroupBy(c => c.Definition!.Name))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(g.Key))
|
||||
{
|
||||
var total = g.SelectMany(c => c.Items)
|
||||
.Where(i => i.IncludeInSummary)
|
||||
.Sum(i => i.IsExpense ? -i.Amount : i.Amount);
|
||||
catDefColumns[g.Key] = total;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (includeCategoryLabels)
|
||||
{
|
||||
foreach (var g in filteredCategories
|
||||
.Where(c => !string.IsNullOrEmpty(c.Name))
|
||||
.GroupBy(c => c.Name))
|
||||
{
|
||||
var total = g.SelectMany(c => c.Items)
|
||||
.Where(i => i.IncludeInSummary)
|
||||
.Sum(i => i.IsExpense ? -i.Amount : i.Amount);
|
||||
catLabelColumns[g.Key] = total;
|
||||
}
|
||||
}
|
||||
|
||||
return new
|
||||
{
|
||||
id = p.Id,
|
||||
year = p.Year ?? 0,
|
||||
month = p.Month ?? 0,
|
||||
income = filteredItems.Where(i => !i.IsExpense).Sum(i => i.Amount),
|
||||
expense = filteredItems.Where(i => i.IsExpense).Sum(i => i.Amount),
|
||||
net = filteredItems.Sum(i => i.IsExpense ? -i.Amount : i.Amount),
|
||||
itemDefinitions = itemDefColumns,
|
||||
itemLabels = itemLabelColumns,
|
||||
categoryDefinitions = catDefColumns,
|
||||
categoryLabels = catLabelColumns
|
||||
};
|
||||
});
|
||||
|
||||
return Ok(reportData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine($"[GetBudgetReport] {ex}");
|
||||
return StatusCode(500, $"Ett fel uppstod i rapportgenereringen: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,47 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Aberwyn.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
[Authorize(Roles = "Budget")]
|
||||
public class BudgetController : Controller
|
||||
{
|
||||
[Authorize(Roles = "Budget")]
|
||||
public IActionResult Index()
|
||||
[Route("budget/{year:int}/{month:int}")]
|
||||
public IActionResult Index(int year, int month)
|
||||
{
|
||||
ViewData["HideSidebar"] = true;
|
||||
ViewBag.Year = year;
|
||||
ViewBag.Month = month;
|
||||
return View();
|
||||
}
|
||||
[Route("budget/list")]
|
||||
public IActionResult List()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[Route("budget/{name}")]
|
||||
public IActionResult Index(string name)
|
||||
{
|
||||
ViewBag.BudgetName = name;
|
||||
return View();
|
||||
}
|
||||
|
||||
[Route("budget/elkostnad")]
|
||||
public IActionResult Elkostnad()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
|
||||
// För fallback när ingen månad/år anges
|
||||
[Route("budget")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
return RedirectToAction("Index", new { year = now.Year, month = now.Month });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
23
Aberwyn/Controllers/ErrorController.cs
Normal file
23
Aberwyn/Controllers/ErrorController.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Microsoft.AspNetCore.Diagnostics;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
public class ErrorController : Controller
|
||||
{
|
||||
[Route("Error/{statusCode}")]
|
||||
public IActionResult HttpStatusCodeHandler(int statusCode)
|
||||
{
|
||||
ViewData["ErrorCode"] = statusCode;
|
||||
return View("Error");
|
||||
}
|
||||
|
||||
[Route("Error")]
|
||||
public IActionResult Error()
|
||||
{
|
||||
var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
|
||||
ViewData["Exception"] = exceptionFeature?.Error;
|
||||
return View("Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Aberwyn.Services;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
@@ -19,23 +21,28 @@ namespace Aberwyn.Controllers
|
||||
private readonly IHostEnvironment _env;
|
||||
private readonly MenuService _menuService;
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly PushNotificationService _notificationService;
|
||||
private readonly PizzaNotificationService _pizzaNotifier;
|
||||
|
||||
public FoodMenuController(MenuService menuService, IConfiguration configuration, IHostEnvironment env, ApplicationDbContext context)
|
||||
public FoodMenuController(MenuService menuService, IConfiguration configuration, IHostEnvironment env, ApplicationDbContext context, PushNotificationService notificationService, PizzaNotificationService pizzaNotificationService)
|
||||
{
|
||||
_menuService = menuService;
|
||||
|
||||
_configuration = configuration;
|
||||
_env = env;
|
||||
_context = context;
|
||||
_notificationService = notificationService;
|
||||
_pizzaNotifier = pizzaNotificationService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult PizzaOrder()
|
||||
{
|
||||
var pizzas = _menuService.GetMealsByCategory("Pizza")
|
||||
.Where(p => p.IsAvailable)
|
||||
.ToList();
|
||||
var meals = _menuService.GetMealsByCategoryName("Pizza", onlyAvailable: true);
|
||||
Console.WriteLine("Pizzas: ", meals);
|
||||
var dtoList = meals.Select(m => MealListDto.FromMeal(m)).ToList();
|
||||
ViewBag.Pizzas = dtoList;
|
||||
|
||||
ViewBag.Pizzas = pizzas;
|
||||
ViewBag.RestaurantIsOpen = GetRestaurantStatus();
|
||||
|
||||
int? lastId = HttpContext.Session.GetInt32("LastPizzaOrderId");
|
||||
@@ -52,6 +59,7 @@ namespace Aberwyn.Controllers
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult EditPizzaOrder(int id)
|
||||
{
|
||||
@@ -61,10 +69,10 @@ namespace Aberwyn.Controllers
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
|
||||
// Sätt session så vi vet att det är en uppdatering
|
||||
// S<EFBFBD>tt session s<EFBFBD> vi vet att det <EFBFBD>r en uppdatering
|
||||
HttpContext.Session.SetInt32("LastPizzaOrderId", order.Id);
|
||||
|
||||
// Visa formuläret
|
||||
// Visa formul<EFBFBD>ret
|
||||
TempData["ForceShowForm"] = "true";
|
||||
|
||||
return RedirectToAction("PizzaOrder");
|
||||
@@ -81,11 +89,11 @@ namespace Aberwyn.Controllers
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult PizzaOrder(string customerName, string pizzaName, string ingredients, int? orderId)
|
||||
public async Task<IActionResult> PizzaOrder(string customerName, string pizzaName, string ingredients, int? orderId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(customerName) || string.IsNullOrWhiteSpace(pizzaName))
|
||||
{
|
||||
TempData["Error"] = "Fyll i både namn och pizza!";
|
||||
TempData["Error"] = "Fyll i både namn och pizza!";
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
|
||||
@@ -101,10 +109,10 @@ namespace Aberwyn.Controllers
|
||||
order.CustomerName = customerName.Trim();
|
||||
order.PizzaName = pizzaName.Trim();
|
||||
order.IngredientsJson = ingredients;
|
||||
order.Status = "Unconfirmed";// återställ status om du vill
|
||||
order.Status = "Unconfirmed";
|
||||
_context.SaveChanges();
|
||||
|
||||
TempData["Success"] = $"Din beställning har uppdaterats!";
|
||||
TempData["Success"] = $"Din beställning har uppdaterats!";
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
}
|
||||
@@ -122,11 +130,11 @@ namespace Aberwyn.Controllers
|
||||
_context.PizzaOrders.Add(order);
|
||||
_context.SaveChanges();
|
||||
TempData["ForceShowForm"] = "true";
|
||||
|
||||
await _pizzaNotifier.NotifyPizzaSubscribersAsync(order.PizzaName, order.CustomerName);
|
||||
|
||||
HttpContext.Session.SetInt32("LastPizzaOrderId", order.Id);
|
||||
|
||||
TempData["Success"] = $"Tack {order.CustomerName}! Din pizza är beställd!";
|
||||
TempData["Success"] = $"Tack {order.CustomerName}! Din pizza är beställd!";
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
|
||||
@@ -151,11 +159,15 @@ namespace Aberwyn.Controllers
|
||||
|
||||
var allMeals = _menuService.GetMeals();
|
||||
|
||||
var categories = _menuService.GetMealCategories();
|
||||
var pizzaCategory = categories.FirstOrDefault(c => c.Name.Equals("Pizza", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
viewModel.AvailablePizzas = allMeals
|
||||
.Where(m => m.Category == "Pizza")
|
||||
.Where(m => m.MealCategoryId == pizzaCategory?.Id)
|
||||
.OrderBy(m => m.Name)
|
||||
.ToList();
|
||||
|
||||
|
||||
ViewBag.RestaurantIsOpen = GetRestaurantStatus();
|
||||
|
||||
return View(viewModel);
|
||||
@@ -166,27 +178,70 @@ namespace Aberwyn.Controllers
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Chef")]
|
||||
public IActionResult UpdatePizzaOrder(int id, string status, string ingredientsJson)
|
||||
{
|
||||
var order = _context.PizzaOrders.FirstOrDefault(p => p.Id == id);
|
||||
if (order != null)
|
||||
public async Task<IActionResult> UpdatePizzaOrder(int id, string status, string ingredientsJson)
|
||||
{
|
||||
var order = await _context.PizzaOrders.FirstOrDefaultAsync(p => p.Id == id);
|
||||
if (order == null)
|
||||
return RedirectToAction("PizzaAdmin");
|
||||
|
||||
order.Status = status;
|
||||
order.IngredientsJson = ingredientsJson;
|
||||
_context.SaveChanges();
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Skicka pushnotiser till kopplade prenumeranter
|
||||
var subscribers = await _context.PushSubscribers
|
||||
.Where(s => s.PizzaOrderId == id)
|
||||
.ToListAsync();
|
||||
|
||||
var payload = $@"{{
|
||||
""title"": ""Din pizza! 🍕"",
|
||||
""body"": ""Statusuppdatering: {status}""
|
||||
}}";
|
||||
|
||||
foreach (var sub in subscribers)
|
||||
{
|
||||
try
|
||||
{
|
||||
_notificationService.SendNotification(sub.Endpoint, sub.P256DH, sub.Auth, payload);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Kunde inte skicka notis till {sub.Endpoint}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
return RedirectToAction("PizzaAdmin");
|
||||
}
|
||||
|
||||
|
||||
[Authorize(Roles = "Chef")]
|
||||
public IActionResult Veckomeny(int? week, int? year)
|
||||
{
|
||||
var menuService = new MenuService(_configuration, _env);
|
||||
var menuService = _menuService;
|
||||
|
||||
var today = DateTime.Today;
|
||||
int resolvedWeek = week ?? ISOWeek.GetWeekOfYear(today);
|
||||
int resolvedYear = year ?? today.Year;
|
||||
|
||||
// Starta alltid från ett GILTIGT datum
|
||||
DateTime referenceDate;
|
||||
|
||||
if (week.HasValue && year.HasValue)
|
||||
{
|
||||
// Om week < 1 eller > 53 – tolka det som navigering
|
||||
// från närliggande vecka i stället för att krascha
|
||||
int safeWeek = Math.Clamp(week.Value, 1, 53);
|
||||
referenceDate = ISOWeek.ToDateTime(year.Value, safeWeek, DayOfWeek.Monday);
|
||||
|
||||
// Justera datumet med differensen (ex: week=0 → -1 vecka)
|
||||
referenceDate = referenceDate.AddDays((week.Value - safeWeek) * 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
referenceDate = today;
|
||||
}
|
||||
|
||||
// Normalisera alltid via datum
|
||||
int resolvedWeek = ISOWeek.GetWeekOfYear(referenceDate);
|
||||
int resolvedYear = ISOWeek.GetYear(referenceDate);
|
||||
|
||||
var menus = menuService.GetWeeklyMenu(resolvedWeek, resolvedYear);
|
||||
|
||||
@@ -195,14 +250,18 @@ namespace Aberwyn.Controllers
|
||||
WeekNumber = resolvedWeek,
|
||||
Year = resolvedYear,
|
||||
WeeklyMenus = menus,
|
||||
AvailableCooks = menuService.GetUsers()
|
||||
WishList = _context.MealWishes
|
||||
.Include(w => w.RequestedByUser)
|
||||
.Where(w => !w.IsArchived)
|
||||
.OrderByDescending(w => w.CreatedAt)
|
||||
.ToList()
|
||||
};
|
||||
|
||||
var recent = menuService
|
||||
.GetMenuEntriesByDateRange(DateTime.Now.AddDays(-28), DateTime.Now)
|
||||
.Select(x => new WeeklyMenuViewModel.RecentMenuEntry
|
||||
{
|
||||
Date = x.Date,
|
||||
Date = x.CreatedAt,
|
||||
BreakfastMealName = x.BreakfastMealName,
|
||||
LunchMealName = x.LunchMealName,
|
||||
DinnerMealName = x.DinnerMealName
|
||||
@@ -219,24 +278,24 @@ namespace Aberwyn.Controllers
|
||||
public IActionResult AddMealAjax([FromBody] Meal meal)
|
||||
{
|
||||
if (meal == null || string.IsNullOrWhiteSpace(meal.Name))
|
||||
return BadRequest("Ogiltigt måltidsobjekt.");
|
||||
return BadRequest("Ogiltigt m<EFBFBD>ltidsobjekt.");
|
||||
|
||||
var service = new MenuService(_configuration, _env);
|
||||
var service = _menuService;
|
||||
|
||||
// Kontrollera om en måltid med samma namn redan finns
|
||||
// Kontrollera om en m<EFBFBD>ltid med samma namn redan finns
|
||||
var existing = service.GetMeals()
|
||||
.FirstOrDefault(m => m.Name.Equals(meal.Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
// Fyll i CreatedAt om det inte sätts automatiskt i databasen
|
||||
// Fyll i CreatedAt om det inte s<EFBFBD>tts automatiskt i databasen
|
||||
meal.CreatedAt = DateTime.Now;
|
||||
service.SaveOrUpdateMeal(meal);
|
||||
existing = meal;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Om måltiden finns men saknar data (t.ex. är bara ett namn) kan vi uppdatera den
|
||||
// Om m<EFBFBD>ltiden finns men saknar data (t.ex. <EFBFBD>r bara ett namn) kan vi uppdatera den
|
||||
existing.Description = meal.Description;
|
||||
existing.ProteinType = meal.ProteinType;
|
||||
existing.CarbType = meal.CarbType;
|
||||
@@ -258,7 +317,7 @@ namespace Aberwyn.Controllers
|
||||
|
||||
public IActionResult MealAdmin()
|
||||
{
|
||||
var service = new MenuService(_configuration, _env);
|
||||
var service = _menuService;
|
||||
var meals = service.GetMealsDetailed();
|
||||
return View("MealAdmin", meals);
|
||||
}
|
||||
@@ -269,7 +328,7 @@ namespace Aberwyn.Controllers
|
||||
if (string.IsNullOrWhiteSpace(term))
|
||||
return Json(new List<string>());
|
||||
|
||||
var menuService = new MenuService(_configuration, _env);
|
||||
var menuService = _menuService;
|
||||
var meals = menuService.GetMeals();
|
||||
|
||||
var result = meals
|
||||
@@ -285,7 +344,7 @@ namespace Aberwyn.Controllers
|
||||
[HttpPost]
|
||||
public IActionResult SaveVeckomeny(IFormCollection form, int week, int year)
|
||||
{
|
||||
var menuService = new MenuService(_configuration, _env);
|
||||
var menuService = _menuService;
|
||||
var allMeals = menuService.GetMeals();
|
||||
|
||||
var model = new MenuViewModel
|
||||
@@ -319,7 +378,7 @@ namespace Aberwyn.Controllers
|
||||
}
|
||||
|
||||
entry.Cook = cook;
|
||||
|
||||
entry.Date = FirstDateOfISOWeek(year, week).AddDays(day);
|
||||
if (string.IsNullOrWhiteSpace(mealName))
|
||||
{
|
||||
switch (mealType.ToLower())
|
||||
@@ -368,6 +427,7 @@ namespace Aberwyn.Controllers
|
||||
|
||||
return RedirectToAction("Veckomeny", new { week, year });
|
||||
}
|
||||
|
||||
private bool GetRestaurantStatus()
|
||||
{
|
||||
var value = _context.AppSettings.FirstOrDefault(s => s.Key == "RestaurantIsOpen")?.Value;
|
||||
@@ -436,7 +496,7 @@ namespace Aberwyn.Controllers
|
||||
[Authorize(Roles = "Chef")]
|
||||
public IActionResult UpdatePizzaAvailability(List<int> availableIds)
|
||||
{
|
||||
availableIds ??= new List<int>(); // Om null, ersätt med tom lista
|
||||
availableIds ??= new List<int>(); // Om null, ers<EFBFBD>tt med tom lista
|
||||
|
||||
var allPizzas = _menuService.GetMealsByCategory("Pizza");
|
||||
|
||||
@@ -453,6 +513,108 @@ namespace Aberwyn.Controllers
|
||||
return RedirectToAction("PizzaAdmin");
|
||||
}
|
||||
|
||||
[Authorize(Roles = "Chef")]
|
||||
[HttpGet]
|
||||
public IActionResult Calculator()
|
||||
{
|
||||
var plans = _context.DoughPlans
|
||||
.OrderByDescending(p => p.Datum)
|
||||
.ThenByDescending(p => p.Id)
|
||||
.ToList();
|
||||
|
||||
ViewBag.Plans = plans;
|
||||
|
||||
return View(new DoughPlan { AntalPizzor = 8, ViktPerPizza = 220 });
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetRecentMenuEntries(int weeksBack = 4)
|
||||
{
|
||||
var today = DateTime.Today;
|
||||
|
||||
// Datum för måndag i nuvarande vecka
|
||||
int deltaToMonday = ((int)today.DayOfWeek + 6) % 7; // måndag=0, söndag=6
|
||||
var thisWeekMonday = today.AddDays(-deltaToMonday);
|
||||
|
||||
// Startdatum: måndag X veckor bak
|
||||
var startMonday = thisWeekMonday.AddDays(-7 * weeksBack);
|
||||
|
||||
// Slutdatum: söndag för förra veckan
|
||||
var endSunday = thisWeekMonday.AddDays(-1);
|
||||
|
||||
// Hämta alla veckomenyer inom intervallet
|
||||
var allMenus = _context.WeeklyMenus
|
||||
.Where(w => w.Date >= startMonday && w.Date <= endSunday)
|
||||
.OrderBy(w => w.Date)
|
||||
.ToList();
|
||||
|
||||
// Hämta alla relevanta meal IDs
|
||||
var mealIds = allMenus
|
||||
.SelectMany(w => new[] { w.BreakfastMealId, w.LunchMealId, w.DinnerMealId })
|
||||
.Where(id => id.HasValue)
|
||||
.Select(id => id!.Value)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
var meals = _context.Meals
|
||||
.Where(m => mealIds.Contains(m.Id))
|
||||
.ToDictionary(m => m.Id, m => m.Name);
|
||||
|
||||
// Skapa entries
|
||||
var entries = allMenus
|
||||
.Select(w => new RecentMenuEntry
|
||||
{
|
||||
Date = w.Date,
|
||||
WeekNumber = ISOWeek.GetWeekOfYear(w.Date),
|
||||
Year = w.Date.Year,
|
||||
BreakfastMealName = w.BreakfastMealId.HasValue && meals.ContainsKey(w.BreakfastMealId.Value)
|
||||
? meals[w.BreakfastMealId.Value]
|
||||
: "—",
|
||||
LunchMealName = w.LunchMealId.HasValue && meals.ContainsKey(w.LunchMealId.Value)
|
||||
? meals[w.LunchMealId.Value]
|
||||
: "—",
|
||||
DinnerMealName = w.DinnerMealId.HasValue && meals.ContainsKey(w.DinnerMealId.Value)
|
||||
? meals[w.DinnerMealId.Value]
|
||||
: "—"
|
||||
})
|
||||
.OrderBy(e => e.Date)
|
||||
.ToList();
|
||||
|
||||
return Json(entries);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static DateTime FirstDateOfISOWeek(int year, int weekOfYear)
|
||||
{
|
||||
DateTime jan4 = new DateTime(year, 1, 4);
|
||||
int daysOffset = DayOfWeek.Thursday - jan4.DayOfWeek;
|
||||
|
||||
DateTime firstThursday = jan4.AddDays(daysOffset);
|
||||
var cal = System.Globalization.CultureInfo.CurrentCulture.Calendar;
|
||||
int firstWeek = cal.GetWeekOfYear(firstThursday, System.Globalization.CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
|
||||
|
||||
if (firstWeek <= 1)
|
||||
weekOfYear -= 1;
|
||||
|
||||
DateTime result = firstThursday.AddDays(weekOfYear * 7);
|
||||
return result.AddDays(-3); // tillbaka till måndag
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[Authorize(Roles = "Chef")]
|
||||
[HttpPost]
|
||||
public IActionResult SaveDoughPlan([FromBody] DoughPlan model)
|
||||
{
|
||||
if (model == null) return BadRequest();
|
||||
|
||||
_context.DoughPlans.Add(model);
|
||||
_context.SaveChanges();
|
||||
|
||||
return Json(new { success = true, id = model.Id });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,23 +13,38 @@ namespace Aberwyn.Controllers
|
||||
//private readonly BudgetService _budgetService;
|
||||
private readonly MenuService _menuService;
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly TorrentService _torrentService;
|
||||
|
||||
|
||||
// Constructor to inject dependencies
|
||||
public HomeController(ApplicationDbContext applicationDbContext, ILogger<HomeController> logger, MenuService menuService)
|
||||
public HomeController(ApplicationDbContext applicationDbContext, ILogger<HomeController> logger, MenuService menuService, TorrentService torrentService)
|
||||
{
|
||||
_logger = logger;
|
||||
_menuService = menuService;
|
||||
_context = applicationDbContext;
|
||||
_torrentService = torrentService;
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var isOpen = _context.AppSettings.FirstOrDefault(x => x.Key == "RestaurantIsOpen")?.Value == "True";
|
||||
ViewBag.RestaurantIsOpen = isOpen;
|
||||
return View();
|
||||
|
||||
var now = DateTime.Now;
|
||||
var showDate = now.Hour >= 20 ? now.Date.AddDays(1) : now.Date;
|
||||
|
||||
var todaysMenu = _menuService.GetMenuForDate(showDate);
|
||||
var userId = User.Identity?.Name ?? "guest";
|
||||
|
||||
// Awaita async-metoden
|
||||
var newCount = await _torrentService.GetUnseenTorrentCountAsync(userId);
|
||||
|
||||
ViewBag.NewTorrentCount = newCount;
|
||||
ViewBag.ShowDate = showDate;
|
||||
return View(todaysMenu);
|
||||
}
|
||||
|
||||
|
||||
public IActionResult Privacy()
|
||||
{
|
||||
return View();
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using Aberwyn.Models;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using SixLabors.ImageSharp;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
@@ -9,35 +11,56 @@ namespace Aberwyn.Controllers
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IHostEnvironment _env;
|
||||
|
||||
public MealController(IConfiguration configuration, IHostEnvironment env)
|
||||
private readonly MenuService _menuService;
|
||||
public MealController(MenuService menuService, IConfiguration configuration, IHostEnvironment env)
|
||||
{
|
||||
_menuService = menuService;
|
||||
_configuration = configuration;
|
||||
_env = env;
|
||||
}
|
||||
[HttpGet("/meal")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View("Index");
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult View(int id, bool edit = false)
|
||||
public IActionResult View(int? id, bool edit = false)
|
||||
{
|
||||
var service = new MenuService(_configuration, _env);
|
||||
var meal = service.GetMealById(id);
|
||||
|
||||
ViewData["IsEditing"] = edit; // → här
|
||||
Meal meal;
|
||||
|
||||
if (id.HasValue)
|
||||
{
|
||||
meal = _menuService.GetMealById(id.Value);
|
||||
if (meal == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
meal = new Meal
|
||||
{
|
||||
Name = "",
|
||||
Description = "",
|
||||
Ingredients = new List<Ingredient>(),
|
||||
IsAvailable = true,
|
||||
CreatedAt = DateTime.Now
|
||||
};
|
||||
}
|
||||
ViewBag.Categories = _menuService.GetMealCategories()
|
||||
.Where(c => c.IsActive)
|
||||
.OrderBy(c => c.Name)
|
||||
.ToList();
|
||||
ViewData["IsEditing"] = edit;
|
||||
return View("View", meal);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet]
|
||||
[Route("Meal/Tooltip/{id}")]
|
||||
public IActionResult Tooltip(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new MenuService(_configuration, _env);
|
||||
var service = _menuService;
|
||||
var meal = service.GetMealById(id);
|
||||
|
||||
if (meal == null)
|
||||
@@ -68,6 +91,15 @@ namespace Aberwyn.Controllers
|
||||
return StatusCode(500, $"<pre>{ex.Message}</pre>");
|
||||
}
|
||||
}
|
||||
[HttpGet("Meal/Thumbnail/{id}")]
|
||||
public IActionResult Thumbnail(int id)
|
||||
{
|
||||
var meal = _menuService.GetMealById(id);
|
||||
if (meal == null || meal.ThumbnailData == null)
|
||||
return NotFound();
|
||||
|
||||
return File(meal.ThumbnailData, "image/webp"); // eller image/jpeg om du använder det
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -75,7 +107,7 @@ namespace Aberwyn.Controllers
|
||||
[HttpGet]
|
||||
public IActionResult Edit(int? id)
|
||||
{
|
||||
var service = new MenuService(_configuration, _env);
|
||||
var service = _menuService;
|
||||
var meal = id.HasValue ? service.GetMealById(id.Value) : new Meal();
|
||||
return View("Meal", meal);
|
||||
}
|
||||
@@ -83,7 +115,7 @@ namespace Aberwyn.Controllers
|
||||
[HttpPost]
|
||||
public IActionResult SaveMeal(Meal meal, IFormFile ImageFile, string ExistingImageUrl)
|
||||
{
|
||||
var service = new MenuService(_configuration, _env);
|
||||
var service = _menuService;
|
||||
|
||||
if (ImageFile != null && ImageFile.Length > 0)
|
||||
{
|
||||
@@ -91,6 +123,8 @@ namespace Aberwyn.Controllers
|
||||
ImageFile.CopyTo(ms);
|
||||
meal.ImageData = ms.ToArray();
|
||||
meal.ImageMimeType = ImageFile.ContentType;
|
||||
meal.ThumbnailData = GenerateThumbnail(ImageFile);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -109,6 +143,19 @@ namespace Aberwyn.Controllers
|
||||
}
|
||||
|
||||
|
||||
private byte[] GenerateThumbnail(IFormFile file)
|
||||
{
|
||||
using var image = SixLabors.ImageSharp.Image.Load(file.OpenReadStream());
|
||||
image.Mutate(x => x.Resize(new ResizeOptions
|
||||
{
|
||||
Mode = ResizeMode.Max,
|
||||
Size = new Size(300, 300) // eller vad du vill för korten
|
||||
}));
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
image.SaveAsWebp(ms); // kräver ImageSharp.Webp-paketet
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -116,9 +163,127 @@ namespace Aberwyn.Controllers
|
||||
[HttpPost]
|
||||
public IActionResult DeleteMeal(int id)
|
||||
{
|
||||
var service = new MenuService(_configuration, _env);
|
||||
var service = _menuService;
|
||||
//service.DeleteMeal(id);
|
||||
return RedirectToAction("Edit"); // eller tillbaka till lista
|
||||
}
|
||||
|
||||
[Authorize(Roles = "Admin,Chef")]
|
||||
[HttpGet("/meal/categories")]
|
||||
public IActionResult Categories()
|
||||
{
|
||||
var categories = _menuService.GetMealCategories()
|
||||
.Select(cat => {
|
||||
cat.MealCount = _menuService.GetMealCountForCategory(cat.Id);
|
||||
return cat;
|
||||
}).ToList();
|
||||
|
||||
return View("MealCategories", categories);
|
||||
}
|
||||
|
||||
[Authorize(Roles = "Admin,Chef")]
|
||||
[HttpPost("/meal/categories/save")]
|
||||
public IActionResult SaveCategory(MealCategory category)
|
||||
{
|
||||
_menuService.SaveOrUpdateCategory(category);
|
||||
return RedirectToAction("Categories");
|
||||
}
|
||||
|
||||
[Authorize(Roles = "Admin,Chef")]
|
||||
[HttpPost("/meal/categories/delete")]
|
||||
public IActionResult DeleteCategory(int id)
|
||||
{
|
||||
_menuService.DeleteCategory(id);
|
||||
return RedirectToAction("Categories");
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("/meal/lab")]
|
||||
public IActionResult Lab(int? id)
|
||||
{
|
||||
if (id.HasValue)
|
||||
{
|
||||
var entry = _menuService.GetRecipeLabEntryById(id.Value);
|
||||
if (entry == null) return NotFound();
|
||||
|
||||
// Hämta versioner först när vi vet att entry finns
|
||||
entry.Versions = _menuService.GetLabVersionsForEntry(id.Value);
|
||||
return View("Lab", entry);
|
||||
}
|
||||
|
||||
// Skapa ett tomt labb-entry för formulär
|
||||
var newEntry = new RecipeLabEntry
|
||||
{
|
||||
Title = "",
|
||||
Inspiration = "",
|
||||
Notes = "",
|
||||
Tags = ""
|
||||
};
|
||||
|
||||
return View("Lab", newEntry);
|
||||
}
|
||||
// Lägg till dessa actions i din MealController
|
||||
|
||||
[HttpPost("/meal/lab/save")]
|
||||
public IActionResult SaveLabEntry(RecipeLabEntry entry)
|
||||
{
|
||||
if (entry.Id == 0)
|
||||
{
|
||||
// Ny entry
|
||||
entry.CreatedAt = DateTime.Now;
|
||||
_menuService.AddLabEntry(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Uppdatera befintlig
|
||||
_menuService.UpdateLabEntry(entry);
|
||||
}
|
||||
|
||||
return RedirectToAction("Lab", new { id = entry.Id });
|
||||
}
|
||||
[HttpPost("/meal/lab/create")]
|
||||
public IActionResult CreateLabEntry(RecipeLabEntry entry)
|
||||
{
|
||||
entry.CreatedAt = DateTime.Now;
|
||||
_menuService.AddLabEntry(entry);
|
||||
|
||||
return RedirectToAction("Lab", new { id = entry.Id });
|
||||
}
|
||||
|
||||
[HttpPost("/meal/lab/save-ingredients")]
|
||||
public IActionResult SaveLabIngredients(int RecipeLabEntryId, List<LabIngredient> Ingredients)
|
||||
{
|
||||
_menuService.SaveIngredientsForLabEntry(RecipeLabEntryId, Ingredients);
|
||||
return RedirectToAction("Lab", new { id = RecipeLabEntryId });
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("/meal/lab/addversion")]
|
||||
public IActionResult AddLabVersion(RecipeLabVersion version)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
return RedirectToAction("Lab", new { id = version.RecipeLabEntryId });
|
||||
|
||||
var entry = _menuService.GetRecipeLabEntryById(version.RecipeLabEntryId);
|
||||
if (entry == null) return NotFound();
|
||||
|
||||
version.CreatedAt = DateTime.Now;
|
||||
|
||||
// Kopiera nuvarande ingredienser
|
||||
var copiedIngredients = entry.Ingredients
|
||||
.Select(i => new LabVersionIngredient
|
||||
{
|
||||
Quantity = i.Quantity,
|
||||
Item = i.Item
|
||||
})
|
||||
.ToList();
|
||||
|
||||
_menuService.SaveLabVersionWithIngredients(version, copiedIngredients);
|
||||
|
||||
return RedirectToAction("Lab", new { id = version.RecipeLabEntryId });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
// MealMenuApiController.cs
|
||||
using Aberwyn.Models;
|
||||
using Aberwyn.Data;
|
||||
using Aberwyn.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
@@ -13,9 +16,9 @@ namespace Aberwyn.Controllers
|
||||
{
|
||||
private readonly MenuService _menuService;
|
||||
|
||||
public MealMenuApiController(IConfiguration configuration, IHostEnvironment env)
|
||||
public MealMenuApiController(MenuService menuService, IConfiguration configuration, IHostEnvironment env)
|
||||
{
|
||||
_menuService = new MenuService(configuration, env);
|
||||
_menuService = menuService;
|
||||
}
|
||||
|
||||
[HttpGet("menu")]
|
||||
@@ -25,15 +28,61 @@ namespace Aberwyn.Controllers
|
||||
return Ok(menu ?? new List<WeeklyMenu>());
|
||||
}
|
||||
|
||||
[HttpGet("getPublishedMeals")]
|
||||
public IActionResult GetPublishedMeals([FromQuery] bool includeUnpublished = false)
|
||||
{
|
||||
var meals = _menuService.GetMeals()
|
||||
.Where(m => includeUnpublished || m.IsPublished)
|
||||
.Select(m => new {
|
||||
m.Id,
|
||||
m.Name,
|
||||
m.Description,
|
||||
ThumbnailData = m.ThumbnailData != null ? Convert.ToBase64String(m.ThumbnailData) : null
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return Ok(meals);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet("getMeals")]
|
||||
public IActionResult GetMeals()
|
||||
{
|
||||
var meals = _menuService.GetMealsDetailed(); // Hämtar med ImageData
|
||||
var mealDtos = meals.Select(MealDto.FromMeal).ToList();
|
||||
var meals = _menuService.GetMealsSlim(true);
|
||||
var mealDtos = meals.Select(m => MealDto.FromMeal(m, includeThumbnail: true)).ToList(); // 👈 fix
|
||||
return Ok(mealDtos);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("getWeeklyMenu")]
|
||||
public IActionResult GetWeeklyMenu(int weekNumber, int year)
|
||||
{
|
||||
var menuDtos = _menuService.GetWeeklyMenuDto(weekNumber, year);
|
||||
Console.WriteLine("Hämtar meals: " + menuDtos);
|
||||
return Ok(menuDtos);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("today")]
|
||||
public IActionResult GetTodayMenu()
|
||||
{
|
||||
var today = DateTime.Today;
|
||||
var menu = _menuService.GetMenuForDate(today);
|
||||
|
||||
if (menu == null)
|
||||
return NotFound(new { message = "Ingen meny hittades för idag." });
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
date = today.ToString("yyyy-MM-dd"),
|
||||
lunch = menu.LunchMealName ?? "",
|
||||
dinner = menu.DinnerMealName ?? "",
|
||||
breakfast = menu.BreakfastMealName ?? ""
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
[HttpPut("menu")]
|
||||
public IActionResult SaveMenu([FromBody] MenuViewModel weeklyMenu)
|
||||
{
|
||||
@@ -55,5 +104,48 @@ namespace Aberwyn.Controllers
|
||||
|
||||
return StatusCode(500, "Failed to add meal.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#region Skolmat
|
||||
[HttpGet("skolmat")]
|
||||
public async Task<IActionResult> GetSkolmat(int week, [FromQuery] string sensor = "sensor.engelbrektsskolan")
|
||||
{
|
||||
var token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3M2Q5ODIyYzU4ZWI0MjM4OWEyMGQ2MWQ2MWVhOWYzYyIsImlhdCI6MTc0OTE1MzY1MCwiZXhwIjoyMDY0NTEzNjUwfQ.8C_dKm7P1BbFVJKc_wT76YnQqiZxkP9EzrsLbfD0Ml8";
|
||||
var client = new HttpClient();
|
||||
client.BaseAddress = new Uri("http://192.168.1.196:8123/");
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
|
||||
var res = await client.GetAsync($"/api/states/{sensor}");
|
||||
|
||||
if (!res.IsSuccessStatusCode)
|
||||
return StatusCode((int)res.StatusCode, $"Kunde inte hämta data för {sensor}");
|
||||
|
||||
var json = await res.Content.ReadAsStringAsync();
|
||||
var doc = JsonDocument.Parse(json);
|
||||
|
||||
var attr = doc.RootElement.GetProperty("attributes");
|
||||
|
||||
if (!attr.TryGetProperty("calendar", out var calendar))
|
||||
return NotFound("Ingen kalender hittades i attributen");
|
||||
|
||||
if (!calendar.TryGetProperty(week.ToString(), out var weekData))
|
||||
return NotFound("Ingen skolmat för vecka " + week);
|
||||
|
||||
var result = new List<object>();
|
||||
foreach (var day in weekData.EnumerateArray())
|
||||
{
|
||||
var weekday = day.GetProperty("weekday").GetString();
|
||||
var date = day.GetProperty("date").GetString();
|
||||
var courses = day.GetProperty("courses").EnumerateArray().Select(c => c.GetString()).ToList();
|
||||
|
||||
result.Add(new { weekday, date, courses });
|
||||
}
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
79
Aberwyn/Controllers/MealRatingApiController.cs
Normal file
79
Aberwyn/Controllers/MealRatingApiController.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using Aberwyn.Data;
|
||||
using Aberwyn.Models;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class MealRatingApiController : ControllerBase
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
|
||||
public MealRatingApiController(ApplicationDbContext context, UserManager<ApplicationUser> userManager)
|
||||
{
|
||||
_context = context;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
[HttpGet("{mealId}")]
|
||||
public async Task<IActionResult> GetRating(int mealId)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null) return Unauthorized();
|
||||
|
||||
var rating = await _context.MealRatings
|
||||
.FirstOrDefaultAsync(r => r.MealId == mealId && r.UserId == user.Id);
|
||||
|
||||
return Ok(rating?.Rating ?? 0);
|
||||
}
|
||||
[HttpGet("average/{mealId}")]
|
||||
public async Task<IActionResult> GetAverageRating(int mealId)
|
||||
{
|
||||
var ratings = await _context.MealRatings
|
||||
.Where(r => r.MealId == mealId)
|
||||
.ToListAsync();
|
||||
|
||||
if (ratings.Count == 0)
|
||||
return Ok(0);
|
||||
|
||||
var avg = ratings.Average(r => r.Rating);
|
||||
return Ok(avg);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> SetRating([FromBody] MealRatingDto model)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null) return Unauthorized();
|
||||
|
||||
var existing = await _context.MealRatings
|
||||
.FirstOrDefaultAsync(r => r.MealId == model.MealId && r.UserId == user.Id);
|
||||
|
||||
if (existing != null)
|
||||
{
|
||||
existing.Rating = model.Rating;
|
||||
existing.CreatedAt = DateTime.UtcNow;
|
||||
}
|
||||
else
|
||||
{
|
||||
_context.MealRatings.Add(new MealRating
|
||||
{
|
||||
MealId = model.MealId,
|
||||
UserId = user.Id,
|
||||
Rating = model.Rating,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
124
Aberwyn/Controllers/MealWishController.cs
Normal file
124
Aberwyn/Controllers/MealWishController.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using Aberwyn.Data;
|
||||
using Aberwyn.Models; // Byt till din namespace
|
||||
using Humanizer;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class MealWishController : ControllerBase
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public MealWishController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// 1. Skapa en ny önskan
|
||||
[HttpPost("create")]
|
||||
public async Task<ActionResult<MealWishDto>> Create([FromBody] CreateMealWishDto dto)
|
||||
{
|
||||
var wish = new MealWish
|
||||
{
|
||||
Name = dto.Name,
|
||||
Recipe = dto.Recipe
|
||||
};
|
||||
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? "anonymous";
|
||||
wish.RequestedByUserId = userId;
|
||||
wish.CreatedAt = DateTime.UtcNow;
|
||||
wish.IsArchived = false;
|
||||
wish.IsImported = false;
|
||||
|
||||
_context.MealWishes.Add(wish);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return Ok(MealWishDto.FromEntity(wish)); // ✅ returnera DTO
|
||||
}
|
||||
|
||||
// 2. Hämta alla önskningar (admin)
|
||||
[HttpGet("all")]
|
||||
public async Task<IActionResult> GetAll(bool includeArchived = false)
|
||||
{
|
||||
var wishes = await _context.MealWishes
|
||||
.Include(w => w.RequestedByUser) // hämta användaren
|
||||
.Where(w => includeArchived || !w.IsArchived)
|
||||
.OrderByDescending(w => w.CreatedAt)
|
||||
.Select(w => new {
|
||||
w.Id,
|
||||
w.Name,
|
||||
w.Recipe,
|
||||
RequestedByUserName = w.RequestedByUser != null ? w.RequestedByUser.UserName : "Okänd",
|
||||
CreatedAt = w.CreatedAt.ToLocalTime().ToString("yyyy-MM-dd HH:mm"),
|
||||
w.IsArchived,
|
||||
w.IsImported
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
return Ok(wishes);
|
||||
}
|
||||
|
||||
|
||||
// 3. Avfärda / arkivera
|
||||
[HttpPost("{id}/archive")]
|
||||
public async Task<IActionResult> Archive(int id)
|
||||
{
|
||||
var wish = await _context.MealWishes.FindAsync(id);
|
||||
if (wish == null) return NotFound();
|
||||
|
||||
wish.IsArchived = true;
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return Ok(wish);
|
||||
}
|
||||
|
||||
// 4. Importera till Meals
|
||||
[HttpPost("{id}/import")]
|
||||
public async Task<IActionResult> Import(int id)
|
||||
{
|
||||
var wish = await _context.MealWishes.FindAsync(id);
|
||||
if (wish == null) return NotFound();
|
||||
|
||||
if (wish.IsImported)
|
||||
return BadRequest("Denna rätt har redan importerats.");
|
||||
|
||||
// Skapa en ny Meal
|
||||
var meal = new Meal
|
||||
{
|
||||
Name = wish.Name,
|
||||
Instructions = wish.Recipe,
|
||||
IsAvailable = true,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
IsPublished = false
|
||||
};
|
||||
|
||||
_context.Meals.Add(meal);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
wish.LinkedMealId = meal.Id;
|
||||
wish.IsImported = true;
|
||||
wish.IsArchived = true;
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return Ok(wish);
|
||||
}
|
||||
|
||||
[HttpGet("search")]
|
||||
public async Task<IActionResult> Search([FromQuery] string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name)) return BadRequest();
|
||||
|
||||
var meals = await _context.Meals
|
||||
.Where(m => m.Name.Contains(name))
|
||||
.OrderBy(m => m.Name)
|
||||
.Take(10)
|
||||
.Select(m => new { m.Id, m.Name })
|
||||
.ToListAsync();
|
||||
|
||||
return Ok(meals);
|
||||
}
|
||||
}
|
||||
13
Aberwyn/Controllers/MovieController.cs
Normal file
13
Aberwyn/Controllers/MovieController.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
public class MovieController : Controller
|
||||
{
|
||||
[HttpGet("/movie/search")]
|
||||
public IActionResult Search()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using Aberwyn.Data;
|
||||
using Aberwyn.Models;
|
||||
using System.Linq;
|
||||
using Aberwyn.Services;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
@@ -9,11 +10,14 @@ namespace Aberwyn.Controllers
|
||||
{
|
||||
private readonly MenuService _menuService;
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly PizzaNotificationService _pizzaNotifier;
|
||||
|
||||
public PizzaController(MenuService menuService, ApplicationDbContext context)
|
||||
public PizzaController(PizzaNotificationService pizzaNotifier,MenuService menuService, ApplicationDbContext context)
|
||||
{
|
||||
_menuService = menuService;
|
||||
_context = context;
|
||||
_pizzaNotifier = pizzaNotifier;
|
||||
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
@@ -50,9 +54,13 @@ namespace Aberwyn.Controllers
|
||||
|
||||
_context.PizzaOrders.Add(order);
|
||||
_context.SaveChanges();
|
||||
_pizzaNotifier.NotifyPizzaSubscribersAsync(pizzaName, customerName);
|
||||
|
||||
TempData["Success"] = "Beställningen har lagts!";
|
||||
return RedirectToAction("Order");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ using Aberwyn.Models;
|
||||
using Lib.Net.Http.WebPush;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Aberwyn.Services;
|
||||
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
@@ -12,41 +15,95 @@ namespace Aberwyn.Controllers
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly PushNotificationService _notificationService;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly PizzaNotificationService _pizzaNotifier;
|
||||
|
||||
public PushController(ApplicationDbContext context, PushNotificationService notificationService)
|
||||
|
||||
public PushController(ApplicationDbContext context,
|
||||
PushNotificationService notificationService,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
PizzaNotificationService pizzaNotifier)
|
||||
{
|
||||
_context = context;
|
||||
_notificationService = notificationService;
|
||||
_userManager = userManager;
|
||||
_pizzaNotifier = pizzaNotifier;
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("subscribe")]
|
||||
public async Task<IActionResult> Subscribe([FromBody] PushSubscription subscription)
|
||||
[HttpPost("notify-pizza")]
|
||||
public async Task<IActionResult> NotifyPizza()
|
||||
{
|
||||
var count = await _pizzaNotifier.NotifyPizzaSubscribersAsync("Capricciosa", User.Identity.Name);
|
||||
|
||||
return Ok(new { message = $"Skickade pizzanotiser till {count} användare." });
|
||||
}
|
||||
|
||||
[HttpPost("subscribe-user")]
|
||||
public async Task<IActionResult> SubscribeUser([FromBody] PushSubscription subscription)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null) return Unauthorized();
|
||||
|
||||
var existing = await _context.PushSubscribers
|
||||
.FirstOrDefaultAsync(s => s.Endpoint == subscription.Endpoint);
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
var newSubscriber = new PushSubscriber
|
||||
var newSub = new PushSubscriber
|
||||
{
|
||||
Endpoint = subscription.Endpoint,
|
||||
P256DH = subscription.Keys["p256dh"],
|
||||
Auth = subscription.Keys["auth"]
|
||||
Auth = subscription.Keys["auth"],
|
||||
UserId = user.Id
|
||||
};
|
||||
|
||||
_context.PushSubscribers.Add(newSubscriber);
|
||||
_context.PushSubscribers.Add(newSub);
|
||||
}
|
||||
else
|
||||
{
|
||||
existing.P256DH = subscription.Keys["p256dh"];
|
||||
existing.Auth = subscription.Keys["auth"];
|
||||
existing.UserId = user.Id;
|
||||
}
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPost("subscribe")]
|
||||
public async Task<IActionResult> Subscribe([FromBody] PushSubscriptionWithOrder dto)
|
||||
{
|
||||
var existing = await _context.PushSubscribers
|
||||
.FirstOrDefaultAsync(s => s.Endpoint == dto.Subscription.Endpoint);
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
var newSub = new PushSubscriber
|
||||
{
|
||||
Endpoint = dto.Subscription.Endpoint,
|
||||
P256DH = dto.Subscription.Keys["p256dh"],
|
||||
Auth = dto.Subscription.Keys["auth"],
|
||||
PizzaOrderId = dto.PizzaOrderId
|
||||
};
|
||||
_context.PushSubscribers.Add(newSub);
|
||||
}
|
||||
else
|
||||
{
|
||||
existing.P256DH = dto.Subscription.Keys["p256dh"];
|
||||
existing.Auth = dto.Subscription.Keys["auth"];
|
||||
existing.PizzaOrderId = dto.PizzaOrderId; // uppdatera kopplingen
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
public class PushSubscriptionWithOrder
|
||||
{
|
||||
public PushSubscription Subscription { get; set; }
|
||||
public int PizzaOrderId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("vapid-public-key")]
|
||||
public IActionResult GetVapidKey([FromServices] IConfiguration config)
|
||||
{
|
||||
@@ -62,7 +119,12 @@ namespace Aberwyn.Controllers
|
||||
return BadRequest("Titel och meddelande krävs.");
|
||||
}
|
||||
|
||||
var subscribers = await _context.PushSubscribers.ToListAsync();
|
||||
var subscribers = await _context.PushSubscribers
|
||||
.Include(s => s.User)
|
||||
.ThenInclude(u => u.Preferences)
|
||||
.Where(s => s.User != null && s.User.Preferences.NotifyPizza)
|
||||
.ToListAsync();
|
||||
|
||||
var payload = $"{{\"title\":\"{message.Title}\",\"body\":\"{message.Body}\"}}";
|
||||
|
||||
int successCount = 0;
|
||||
@@ -82,6 +144,24 @@ namespace Aberwyn.Controllers
|
||||
return Ok($"Skickade notiser till {successCount} användare.");
|
||||
}
|
||||
|
||||
[HttpPost("unsubscribe")]
|
||||
public async Task<IActionResult> Unsubscribe([FromBody] PushUnsubscribeDto dto)
|
||||
{
|
||||
var sub = await _context.PushSubscribers.FirstOrDefaultAsync(s => s.Endpoint == dto.Endpoint);
|
||||
if (sub != null)
|
||||
{
|
||||
_context.PushSubscribers.Remove(sub);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
public class PushUnsubscribeDto
|
||||
{
|
||||
public string Endpoint { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,43 +22,5 @@ namespace Aberwyn.Controllers
|
||||
_context = context;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> GetReport([FromBody] BudgetReportRequestDto request)
|
||||
{
|
||||
var start = new DateTime(request.StartYear, request.StartMonth, 1);
|
||||
var end = new DateTime(request.EndYear, request.EndMonth, 1);
|
||||
|
||||
var items = await _context.BudgetItems
|
||||
.Include(i => i.BudgetItemDefinition)
|
||||
.Include(i => i.BudgetCategory)
|
||||
.ThenInclude(c => c.BudgetPeriod)
|
||||
.Where(i =>
|
||||
i.BudgetCategory.BudgetPeriod.Year * 12 + i.BudgetCategory.BudgetPeriod.Month >= start.Year * 12 + start.Month &&
|
||||
i.BudgetCategory.BudgetPeriod.Year * 12 + i.BudgetCategory.BudgetPeriod.Month <= end.Year * 12 + end.Month &&
|
||||
request.DefinitionIds.Contains(i.BudgetItemDefinitionId ?? -1))
|
||||
.ToListAsync();
|
||||
|
||||
var grouped = items
|
||||
.GroupBy(i => new { i.BudgetCategory.BudgetPeriod.Year, i.BudgetCategory.BudgetPeriod.Month })
|
||||
.Select(g => new BudgetReportResultDto
|
||||
{
|
||||
Year = g.Key.Year,
|
||||
Month = g.Key.Month,
|
||||
Definitions = g
|
||||
.GroupBy(i => new { i.BudgetItemDefinitionId, i.BudgetItemDefinition.Name })
|
||||
.Select(dg => new DefinitionSumDto
|
||||
{
|
||||
DefinitionId = dg.Key.BudgetItemDefinitionId ?? 0,
|
||||
DefinitionName = dg.Key.Name,
|
||||
TotalAmount = dg.Sum(x => x.Amount)
|
||||
}).ToList()
|
||||
})
|
||||
.OrderBy(r => r.Year).ThenBy(r => r.Month)
|
||||
.ToList();
|
||||
|
||||
return Ok(grouped);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Aberwyn.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
@@ -6,9 +7,9 @@ namespace Aberwyn.Controllers
|
||||
[Authorize(Roles = "Budget")]
|
||||
public class ReportController : Controller
|
||||
{
|
||||
public IActionResult BudgetReport()
|
||||
public IActionResult Budget()
|
||||
{
|
||||
return View("BudgetReport");
|
||||
return View(new BudgetReportViewModel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
245
Aberwyn/Controllers/RssController.cs
Normal file
245
Aberwyn/Controllers/RssController.cs
Normal file
@@ -0,0 +1,245 @@
|
||||
using Aberwyn.Data;
|
||||
using BencodeNET.Torrents;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
public class RssController : Controller
|
||||
{
|
||||
private readonly ITorrentService _torrentService;
|
||||
private readonly ILogger<RssController> _logger;
|
||||
private readonly DelugeClient _deluge;
|
||||
private readonly MovieMetadataService _movieMetadataService;
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public RssController(
|
||||
ITorrentService torrentService,
|
||||
ILogger<RssController> logger,
|
||||
DelugeClient delugeClient,
|
||||
MovieMetadataService movieMetadataService,
|
||||
ApplicationDbContext context)
|
||||
{
|
||||
_torrentService = torrentService;
|
||||
_logger = logger;
|
||||
_deluge = delugeClient;
|
||||
_movieMetadataService = movieMetadataService;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Index(int page = 1, string sort = "date", string range = "all")
|
||||
{
|
||||
var pageSize = 20;
|
||||
var userId = User.Identity?.Name ?? "guest";
|
||||
|
||||
var torrents = await _torrentService.GetRecentTorrentsAsync(500);
|
||||
|
||||
// Filtrera på tidsintervall
|
||||
torrents = range switch
|
||||
{
|
||||
"day" => torrents.Where(t => t.PublishDate > DateTime.UtcNow.AddDays(-1)).ToList(),
|
||||
"week" => torrents.Where(t => t.PublishDate > DateTime.UtcNow.AddDays(-7)).ToList(),
|
||||
"month" => torrents.Where(t => t.PublishDate > DateTime.UtcNow.AddMonths(-1)).ToList(),
|
||||
_ => torrents
|
||||
};
|
||||
|
||||
// Sortera
|
||||
torrents = sort switch
|
||||
{
|
||||
"seeders" => torrents.OrderByDescending(t => t.Seeders).ToList(),
|
||||
"leechers" => torrents.OrderByDescending(t => t.Leechers).ToList(),
|
||||
"title" => torrents.OrderBy(t => t.MovieName).ToList(),
|
||||
_ => torrents.OrderByDescending(t => t.PublishDate).ToList(),
|
||||
};
|
||||
|
||||
// Hämta sedda torrents för användaren
|
||||
var seenHashes = await _context.UserTorrentSeen
|
||||
.Where(x => x.UserId == userId)
|
||||
.Select(x => x.InfoHash)
|
||||
.ToListAsync();
|
||||
|
||||
// Bygg viewmodels med IsNew
|
||||
var pagedItems = torrents
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(t => new TorrentListItemViewModel
|
||||
{
|
||||
InfoHash = t.InfoHash ?? "",
|
||||
Title = t.Title,
|
||||
MovieName = t.MovieName ?? "",
|
||||
PublishDate = t.PublishDate,
|
||||
Seeders = t.Seeders,
|
||||
Leechers = t.Leechers,
|
||||
TorrentUrl = t.TorrentUrl,
|
||||
Metadata = t.Metadata,
|
||||
IsDownloaded = t.IsDownloaded,
|
||||
IsNew = t.InfoHash != null && !seenHashes.Contains(t.InfoHash),
|
||||
AvailableOn = !string.IsNullOrEmpty(t.Metadata?.Providers)
|
||||
? t.Metadata.Providers.Split(',').ToList()
|
||||
: new List<string>()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// Markera som sedda
|
||||
var newSeen = pagedItems
|
||||
.Where(i => i.IsNew && !string.IsNullOrEmpty(i.InfoHash))
|
||||
.Select(i => new UserTorrentSeen
|
||||
{
|
||||
UserId = userId,
|
||||
InfoHash = i.InfoHash,
|
||||
SeenDate = DateTime.UtcNow
|
||||
});
|
||||
|
||||
_context.UserTorrentSeen.AddRange(newSeen);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var vm = new TorrentListViewModel
|
||||
{
|
||||
Items = pagedItems,
|
||||
CurrentPage = page,
|
||||
TotalPages = (int)Math.Ceiling(torrents.Count / (double)pageSize),
|
||||
CurrentSort = sort,
|
||||
CurrentRange = range
|
||||
};
|
||||
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Add(string torrentUrl)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await _deluge.LoginAsync("deluge1"))
|
||||
{
|
||||
var success = await _deluge.AddTorrentUrlAsync(torrentUrl);
|
||||
|
||||
if (success)
|
||||
{
|
||||
// Hämta torrenten baserat på TorrentUrl
|
||||
var torrent = await _context.Set<TorrentItem>()
|
||||
.FirstOrDefaultAsync(t => t.TorrentUrl == torrentUrl);
|
||||
|
||||
if (torrent != null)
|
||||
{
|
||||
// Markera som nerladdad
|
||||
torrent.IsDownloaded = true;
|
||||
torrent.Status = TorrentStatus.Downloaded;
|
||||
_context.Update(torrent);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skapa ny post om den inte finns
|
||||
var newTorrent = new TorrentItem
|
||||
{
|
||||
Title = torrentUrl, // byt till korrekt namnkälla om du har
|
||||
TorrentUrl = torrentUrl,
|
||||
PublishDate = DateTime.UtcNow,
|
||||
Status = TorrentStatus.Downloaded,
|
||||
IsDownloaded = true,
|
||||
RssSource = "Manuell", // eller sätt rätt källa
|
||||
};
|
||||
|
||||
_context.Add(newTorrent);
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
_logger.LogInformation("SavedChanges to torrents");
|
||||
return Json(new
|
||||
{
|
||||
success = true,
|
||||
message = "Torrent tillagd i Deluge och markerad som nerladdad."
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return Json(new { success = false, message = "Misslyckades att lägga till torrent i Deluge." });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Fel vid tillägg av torrent");
|
||||
return Json(new { success = false, message = "Ett fel uppstod vid tillägg av torrent." });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Upload(TorrentUploadViewModel model)
|
||||
{
|
||||
if (model.TorrentFile == null || model.TorrentFile.Length == 0)
|
||||
{
|
||||
ModelState.AddModelError("TorrentFile", "Vänligen välj en torrent-fil");
|
||||
return View("Index", model);
|
||||
}
|
||||
|
||||
if (!model.TorrentFile.FileName.EndsWith(".torrent", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ModelState.AddModelError("TorrentFile", "Endast .torrent filer är tillåtna");
|
||||
return View("Index", model);
|
||||
}
|
||||
|
||||
if (model.TorrentFile.Length > 10 * 1024 * 1024) // 10MB limit
|
||||
{
|
||||
ModelState.AddModelError("TorrentFile", "Filen är för stor (max 10MB)");
|
||||
return View("Index", model);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var torrentInfo = await _torrentService.ParseTorrentAsync(model.TorrentFile);
|
||||
|
||||
if (!string.IsNullOrEmpty(torrentInfo.ErrorMessage))
|
||||
{
|
||||
ModelState.AddModelError("", torrentInfo.ErrorMessage);
|
||||
return View("Index", model);
|
||||
}
|
||||
|
||||
torrentInfo = await _torrentService.FetchTrackerStatsAsync(torrentInfo);
|
||||
|
||||
model.TorrentInfo = torrentInfo;
|
||||
model.ShowResults = true;
|
||||
|
||||
return View("Index", model);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Fel vid uppladdning av torrent");
|
||||
ModelState.AddModelError("", "Ett oväntat fel inträffade");
|
||||
return View("Index", model);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> RefreshStats(string infoHash, string scrapeUrl)
|
||||
{
|
||||
try
|
||||
{
|
||||
var torrentInfo = new TorrentInfo
|
||||
{
|
||||
InfoHash = infoHash,
|
||||
ScrapeUrl = scrapeUrl,
|
||||
InfoHashBytes = Convert.FromHexString(infoHash.Replace("%", ""))
|
||||
};
|
||||
|
||||
var updatedInfo = await _torrentService.FetchTrackerStatsAsync(torrentInfo);
|
||||
|
||||
return Json(new
|
||||
{
|
||||
success = updatedInfo.HasTrackerData,
|
||||
seeders = updatedInfo.Seeders,
|
||||
leechers = updatedInfo.Leechers,
|
||||
completed = updatedInfo.Completed,
|
||||
error = updatedInfo.ErrorMessage
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Fel vid uppdatering av tracker-stats");
|
||||
return Json(new { success = false, error = "Fel vid uppdatering" });
|
||||
}
|
||||
}
|
||||
}
|
||||
78
Aberwyn/Controllers/SetupApiController.cs
Normal file
78
Aberwyn/Controllers/SetupApiController.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/setup")]
|
||||
public class SetupApiController : ControllerBase
|
||||
{
|
||||
[HttpPost("testdb")]
|
||||
public IActionResult TestDbConnection([FromBody] DbTestRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var builder = new MySqlConnectionStringBuilder
|
||||
{
|
||||
Server = request.Host,
|
||||
Port = uint.Parse(request.Port),
|
||||
UserID = request.User,
|
||||
Password = request.Pass,
|
||||
Database = "information_schema"
|
||||
};
|
||||
|
||||
using (var conn = new MySqlConnection(builder.ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
// Kontrollera om databasen redan finns
|
||||
var checkCmd = new MySqlCommand("SELECT SCHEMA_NAME FROM SCHEMATA WHERE SCHEMA_NAME = @dbName", conn);
|
||||
checkCmd.Parameters.AddWithValue("@dbName", request.Db);
|
||||
var exists = checkCmd.ExecuteScalar();
|
||||
|
||||
if (exists != null)
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
success = true,
|
||||
message = "Anslutning OK och databasen finns redan."
|
||||
});
|
||||
}
|
||||
|
||||
// Testa skapa en temporär databas
|
||||
var testDbName = $"testcheck_{Guid.NewGuid():N}".Substring(0, 12);
|
||||
var createCmd = new MySqlCommand($"CREATE DATABASE `{testDbName}`", conn);
|
||||
createCmd.ExecuteNonQuery();
|
||||
|
||||
var dropCmd = new MySqlCommand($"DROP DATABASE `{testDbName}`", conn);
|
||||
dropCmd.ExecuteNonQuery();
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
success = true,
|
||||
message = "Anslutning OK. Databasen finns inte, men CREATE DATABASE är tillåten."
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
success = false,
|
||||
message = ex.Message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class DbTestRequest
|
||||
{
|
||||
public string Host { get; set; }
|
||||
public string Port { get; set; }
|
||||
public string Db { get; set; }
|
||||
public string User { get; set; }
|
||||
public string Pass { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
173
Aberwyn/Controllers/SetupController.cs
Normal file
173
Aberwyn/Controllers/SetupController.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data.MySqlClient;
|
||||
using System.Text.Json;
|
||||
using Aberwyn.Data;
|
||||
using Aberwyn.Models;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
[Route("setup")]
|
||||
public class SetupController : Controller
|
||||
{
|
||||
private readonly IWebHostEnvironment _env;
|
||||
private readonly ILogger<SetupController> _logger;
|
||||
private readonly string _filePath;
|
||||
|
||||
public SetupController(IWebHostEnvironment env, ILogger<SetupController> logger)
|
||||
{
|
||||
_env = env;
|
||||
_logger = logger;
|
||||
var dataRoot = Path.Combine(Directory.GetCurrentDirectory(), "data"); // /app/data i containern
|
||||
_filePath = Path.Combine(dataRoot, "infrastructure", "setup.json");
|
||||
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
ViewBag.IsSetupMode = true;
|
||||
base.OnActionExecuting(context);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Index() => View(new SetupSettings());
|
||||
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPost("reset")]
|
||||
public IActionResult Reset()
|
||||
{
|
||||
var path = _filePath;
|
||||
|
||||
var resetSettings = new SetupSettings
|
||||
{
|
||||
IsConfigured = false,
|
||||
DbHost = "",
|
||||
DbPort = 3306,
|
||||
DbName = "",
|
||||
DbUser = "",
|
||||
DbPassword = "",
|
||||
AdminUsername = "admin",
|
||||
AdminEmail = "admin@localhost",
|
||||
AdminPassword = "Admin123!"
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(resetSettings, new JsonSerializerOptions { WriteIndented = true });
|
||||
System.IO.File.WriteAllText(path, json);
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[HttpPost("")]
|
||||
public async Task<IActionResult> Setup([FromBody] SetupSettings model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
var allErrors = ModelState
|
||||
.Where(e => e.Value.Errors.Count > 0)
|
||||
.Select(e => new { Field = e.Key, Errors = e.Value.Errors.Select(x => x.ErrorMessage) });
|
||||
|
||||
return BadRequest(new { error = "Modellen är ogiltig", details = allErrors });
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Start setup write");
|
||||
// Bygg connection string säkert
|
||||
var baseConnBuilder = new MySqlConnectionStringBuilder
|
||||
{
|
||||
Server = model.DbHost,
|
||||
Port = (uint)model.DbPort,
|
||||
UserID = model.DbUser,
|
||||
Password = model.DbPassword,
|
||||
Database = "information_schema"
|
||||
};
|
||||
|
||||
// Kontrollera om databasen redan finns
|
||||
using (var conn = new MySqlConnection(baseConnBuilder.ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
var cmd = new MySqlCommand("SELECT SCHEMA_NAME FROM SCHEMATA WHERE SCHEMA_NAME = @dbName", conn);
|
||||
cmd.Parameters.AddWithValue("@dbName", model.DbName);
|
||||
var exists = cmd.ExecuteScalar();
|
||||
|
||||
if (exists == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var createCmd = new MySqlCommand($"CREATE DATABASE `{model.DbName}`", conn);
|
||||
createCmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Kunde inte skapa databasen.");
|
||||
return BadRequest(new { error = "Databasen finns inte och kunde inte skapas.", details = ex.Message });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bygg EF-connection
|
||||
var efConnBuilder = new MySqlConnectionStringBuilder
|
||||
{
|
||||
Server = model.DbHost,
|
||||
Port = (uint)model.DbPort,
|
||||
UserID = model.DbUser,
|
||||
Password = model.DbPassword,
|
||||
Database = model.DbName
|
||||
};
|
||||
|
||||
var tempProvider = SetupService.BuildTemporaryServices(efConnBuilder.ConnectionString);
|
||||
using var scope = tempProvider.CreateScope();
|
||||
|
||||
// Skapa databastabeller
|
||||
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
||||
await db.Database.MigrateAsync();
|
||||
|
||||
// Sätt konfig-flagga tidigt
|
||||
model.IsConfigured = true;
|
||||
_logger.LogDebug("Filepath" + _filePath);
|
||||
// Spara setup.json
|
||||
var json = JsonSerializer.Serialize(model, new JsonSerializerOptions { WriteIndented = true });
|
||||
System.IO.File.WriteAllText(_filePath, json);
|
||||
// Roller och admin
|
||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
|
||||
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
|
||||
|
||||
string[] roles = { "Admin", "Chef", "Budget" };
|
||||
foreach (var role in roles)
|
||||
{
|
||||
if (!await roleManager.RoleExistsAsync(role))
|
||||
await roleManager.CreateAsync(new IdentityRole(role));
|
||||
}
|
||||
|
||||
var existingUser = await userManager.FindByNameAsync(model.AdminUsername);
|
||||
if (existingUser == null)
|
||||
{
|
||||
var adminUser = new ApplicationUser
|
||||
{
|
||||
UserName = model.AdminUsername,
|
||||
Email = model.AdminEmail,
|
||||
EmailConfirmed = true
|
||||
};
|
||||
|
||||
var result = await userManager.CreateAsync(adminUser, model.AdminPassword);
|
||||
if (!result.Succeeded)
|
||||
return BadRequest(new { error = "Kunde inte skapa administratör", details = result.Errors });
|
||||
|
||||
await userManager.AddToRoleAsync(adminUser, "Admin");
|
||||
}
|
||||
|
||||
return Ok(new { message = "Installation slutförd!" });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Fel vid installation.");
|
||||
return BadRequest(new { error = "Fel vid installation", details = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
public IActionResult SetupComplete() => View();
|
||||
}
|
||||
}
|
||||
61
Aberwyn/Controllers/UserController.cs
Normal file
61
Aberwyn/Controllers/UserController.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Aberwyn.Models;
|
||||
using System.Threading.Tasks;
|
||||
using Aberwyn.Data;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class UserController : Controller
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public UserController(UserManager<ApplicationUser> userManager, ApplicationDbContext context)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Profile()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
var prefs = await _context.UserPreferences.FindAsync(user.Id) ?? new UserPreferences();
|
||||
|
||||
var model = new UserProfileViewModel
|
||||
{
|
||||
Name = user.UserName,
|
||||
Email = user.Email,
|
||||
NotifyPizza = prefs.NotifyPizza,
|
||||
NotifyMenu = prefs.NotifyMenu,
|
||||
NotifyBudget = prefs.NotifyBudget
|
||||
};
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> SaveProfile(UserProfileViewModel model)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
var prefs = await _context.UserPreferences.FindAsync(user.Id);
|
||||
|
||||
if (prefs == null)
|
||||
{
|
||||
prefs = new UserPreferences { UserId = user.Id };
|
||||
_context.UserPreferences.Add(prefs);
|
||||
}
|
||||
|
||||
prefs.NotifyPizza = model.NotifyPizza;
|
||||
prefs.NotifyMenu = model.NotifyMenu;
|
||||
prefs.NotifyBudget = model.NotifyBudget;
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return RedirectToAction("Profile");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using Aberwyn.Models;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Aberwyn.Data
|
||||
{
|
||||
@@ -11,15 +12,62 @@ namespace Aberwyn.Data
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
builder.Entity<TorrentItem>()
|
||||
.HasIndex(t => t.InfoHash)
|
||||
.IsUnique();
|
||||
|
||||
builder.Entity<TorrentItem>()
|
||||
.Property(t => t.Status)
|
||||
.HasConversion<string>();
|
||||
builder.Entity<WeeklyMenu>().ToTable("WeeklyMenu");
|
||||
builder.Entity<MealCategory>().HasData(
|
||||
new MealCategory
|
||||
{
|
||||
Id = 1,
|
||||
Name = "Pizza",
|
||||
Slug = "pizza",
|
||||
Icon = "🍕",
|
||||
Color = "#f97316",
|
||||
IsActive = true,
|
||||
DisplayOrder = 1
|
||||
}
|
||||
);
|
||||
builder.Entity<TorrentItem>()
|
||||
.OwnsOne(t => t.Metadata);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public DbSet<DoughPlan> DoughPlans { get; set; }
|
||||
|
||||
public DbSet<BudgetPeriod> BudgetPeriods { get; set; }
|
||||
public DbSet<BudgetCategory> BudgetCategories { get; set; }
|
||||
public DbSet<BudgetItem> BudgetItems { get; set; }
|
||||
public DbSet<PushSubscriber> PushSubscribers { get; set; }
|
||||
public DbSet<PizzaOrder> PizzaOrders { get; set; }
|
||||
public DbSet<AppSetting> AppSettings { get; set; }
|
||||
public DbSet<TodoTask> TodoTasks { get; set; }
|
||||
public DbSet<BudgetItemDefinition> BudgetItemDefinitions { get; set; }
|
||||
public DbSet<BudgetCategoryDefinition> BudgetCategoryDefinitions { get; set; }
|
||||
public DbSet<TodoTask> TodoTasks { get; set; }
|
||||
public DbSet<Meal> Meals { get; set; }
|
||||
public DbSet<WeeklyMenu> WeeklyMenus { get; set; }
|
||||
public DbSet<Ingredient> Ingredients { get; set; }
|
||||
public DbSet<UserPreferences> UserPreferences { get; set; }
|
||||
public DbSet<StoredPushSubscription> PushSubscriptions { get; set; }
|
||||
public DbSet<MealCategory> MealCategories { get; set; }
|
||||
public DbSet<RecipeLabEntry> RecipeLabEntries { get; set; }
|
||||
public DbSet<RecipeLabVersion> RecipeLabVersions { get; set; }
|
||||
public DbSet<LabIngredient> LabIngredients { get; set; }
|
||||
public DbSet<LabVersionIngredient> LabVersionIngredients { get; set; }
|
||||
public DbSet<MealRating> MealRatings { get; set; }
|
||||
public DbSet<TorrentItem> TorrentItems { get; set; }
|
||||
public DbSet<RssFeed> RssFeeds { get; set; }
|
||||
public DbSet<DownloadRule> DownloadRules { get; set; }
|
||||
public DbSet<UserTorrentSeen> UserTorrentSeen { get; set; }
|
||||
public DbSet<MealWish> MealWishes { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Aberwyn.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using static Aberwyn.Data.SetupService;
|
||||
|
||||
namespace Aberwyn.Data
|
||||
{
|
||||
@@ -10,29 +13,51 @@ namespace Aberwyn.Data
|
||||
{
|
||||
public ApplicationDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
var basePath = Directory.GetCurrentDirectory();
|
||||
var config = new ConfigurationBuilder()
|
||||
.SetBasePath(basePath)
|
||||
.AddJsonFile("appsettings.json")
|
||||
.Build();
|
||||
var setup = LoadSetup();
|
||||
|
||||
|
||||
var connectionString = config.GetConnectionString("DefaultConnection");
|
||||
File.WriteAllText("connection-log.txt", $"Connection string: {connectionString}");
|
||||
|
||||
Console.WriteLine($"Anslutningssträng: {connectionString}");
|
||||
|
||||
if (string.IsNullOrEmpty(connectionString))
|
||||
var csBuilder = new MySqlConnector.MySqlConnectionStringBuilder
|
||||
{
|
||||
throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
|
||||
}
|
||||
Server = setup.DbHost,
|
||||
Port = (uint)setup.DbPort,
|
||||
Database = setup.DbName,
|
||||
UserID = setup.DbUser,
|
||||
Password = setup.DbPassword,
|
||||
AllowUserVariables = true
|
||||
};
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
optionsBuilder.UseMySql(
|
||||
connectionString,
|
||||
new MySqlServerVersion(new Version(8, 0, 36)));
|
||||
optionsBuilder.UseMySql(csBuilder.ConnectionString, new MySqlServerVersion(new Version(8, 0, 36)));
|
||||
|
||||
return new ApplicationDbContext(optionsBuilder.Options);
|
||||
}
|
||||
|
||||
public static ApplicationDbContext CreateWithConfig(IHostEnvironment env, bool useProdDb = false)
|
||||
{
|
||||
var setup = SetupLoader.Load(env);
|
||||
var connStr = SetupLoader.GetConnectionString(setup);
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
optionsBuilder.UseMySql(connStr, new MySqlServerVersion(new Version(8, 0, 36)));
|
||||
|
||||
return new ApplicationDbContext(optionsBuilder.Options);
|
||||
}
|
||||
|
||||
|
||||
private static SetupSettings LoadSetup()
|
||||
{
|
||||
var basePath = Directory.GetCurrentDirectory();
|
||||
var setupPath = Path.Combine(basePath, "infrastructure", "setup.json");
|
||||
|
||||
if (!File.Exists(setupPath))
|
||||
throw new FileNotFoundException("setup.json saknas i infrastructure-mappen.");
|
||||
|
||||
var json = File.ReadAllText(setupPath);
|
||||
var setup = JsonSerializer.Deserialize<SetupSettings>(json);
|
||||
|
||||
if (setup == null || !setup.IsConfigured)
|
||||
throw new InvalidOperationException("setup.json är inte korrekt konfigurerad.");
|
||||
|
||||
return setup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
using MySql.Data.MySqlClient;
|
||||
using System.Collections.Generic;
|
||||
using Aberwyn.Models;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting; // Add this namespace
|
||||
|
||||
namespace Aberwyn.Data
|
||||
{
|
||||
public class BudgetService
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IHostEnvironment _env; // Add this field
|
||||
|
||||
public BudgetService(IConfiguration configuration, IHostEnvironment env) // Update constructor
|
||||
{
|
||||
_configuration = configuration;
|
||||
_env = env; // Initialize the environment field
|
||||
}
|
||||
|
||||
public MySqlConnection GetConnection()
|
||||
{
|
||||
var connectionString = _env.IsDevelopment() // Use the injected environment variable
|
||||
? _configuration.GetConnectionString("DefaultConnection")
|
||||
: _configuration.GetConnectionString("ProductionConnection");
|
||||
|
||||
return new MySqlConnection(connectionString);
|
||||
}
|
||||
|
||||
public bool UpdateBudgetItem(BudgetItem item)
|
||||
{
|
||||
using (var connection = GetConnection())
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
string query = @"
|
||||
UPDATE tblBudgetItems
|
||||
SET Name = @name, Amount = @amount
|
||||
WHERE idtblBudgetItems = @id";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, connection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@name", item.Name);
|
||||
cmd.Parameters.AddWithValue("@amount", item.Amount);
|
||||
cmd.Parameters.AddWithValue("@id", item.ID);
|
||||
return cmd.ExecuteNonQuery() > 0; // Returns true if one or more rows are updated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<BudgetItem> GetBudgetItems(int month, int year)
|
||||
{
|
||||
var budgetItems = new List<BudgetItem>();
|
||||
|
||||
using (var connection = GetConnection())
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
string query = @"
|
||||
SELECT
|
||||
b.idtblBudgetItems AS id,
|
||||
b.Name AS item_name,
|
||||
b.Amount AS amount,
|
||||
c1.Name AS category,
|
||||
b.Month,
|
||||
b.Year,
|
||||
b.Description AS description
|
||||
FROM tblBudgetItems b
|
||||
LEFT JOIN tblCategories c1 ON b.Category = c1.idtblCategories
|
||||
WHERE b.Month = @month AND b.Year = @year";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, connection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@month", month);
|
||||
cmd.Parameters.AddWithValue("@year", year);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
budgetItems.Add(new BudgetItem
|
||||
{
|
||||
ID = reader.GetInt32("id"),
|
||||
Name = reader.GetString("item_name"), // Updated alias
|
||||
Amount = reader.GetDecimal("amount"),
|
||||
Category = reader.GetString("category"),
|
||||
Month = reader.GetInt32("Month"),
|
||||
Year = reader.GetInt32("Year"),
|
||||
Description = reader.IsDBNull(reader.GetOrdinal("description"))
|
||||
? null
|
||||
: reader.GetString("description")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return budgetItems;
|
||||
}
|
||||
|
||||
public bool AddBudgetItem(BudgetItem item)
|
||||
{
|
||||
using (var connection = GetConnection())
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
string query = @"
|
||||
INSERT INTO tblBudgetItems (Name, Amount, Category, Month, Year)
|
||||
VALUES (@name, @amount, @category, @month, @year)";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, connection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@name", item.Name);
|
||||
cmd.Parameters.AddWithValue("@amount", item.Amount);
|
||||
cmd.Parameters.AddWithValue("@category", item.Category);
|
||||
cmd.Parameters.AddWithValue("@month", item.Month);
|
||||
cmd.Parameters.AddWithValue("@year", item.Year);
|
||||
return cmd.ExecuteNonQuery() > 0; // Returns true if a row was inserted
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// New method to fetch all categories
|
||||
public List<string> GetCategories()
|
||||
{
|
||||
var categories = new List<string>();
|
||||
|
||||
using (var connection = GetConnection())
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
string query = "SELECT Name FROM tblCategories"; // Adjust based on your table structure
|
||||
|
||||
using (var cmd = new MySqlCommand(query, connection))
|
||||
{
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
categories.Add(reader.GetString("Name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return categories;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
Aberwyn/Data/DelugeClient.cs
Normal file
79
Aberwyn/Data/DelugeClient.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using MySqlX.XDevAPI;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Aberwyn.Data
|
||||
{
|
||||
public class DelugeClient
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly string _url;
|
||||
private string _sessionId;
|
||||
|
||||
public DelugeClient(HttpClient httpClient, string baseUrl = "http://192.168.1.3:8112/json")
|
||||
{
|
||||
_http = httpClient;
|
||||
_url = baseUrl;
|
||||
}
|
||||
|
||||
public async Task<bool> LoginAsync(string password)
|
||||
{
|
||||
var payload = new
|
||||
{
|
||||
method = "auth.login",
|
||||
@params = new object[] { password },
|
||||
id = 1
|
||||
};
|
||||
|
||||
var response = await _http.PostAsJsonAsync(_url, payload);
|
||||
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
|
||||
|
||||
// spara sessioncookie för framtida requests
|
||||
if (response.Headers.TryGetValues("Set-Cookie", out var cookies))
|
||||
{
|
||||
_sessionId = cookies.FirstOrDefault()?.Split(';')[0];
|
||||
if (!_http.DefaultRequestHeaders.Contains("Cookie"))
|
||||
_http.DefaultRequestHeaders.Add("Cookie", _sessionId);
|
||||
}
|
||||
|
||||
return json.GetProperty("result").GetBoolean();
|
||||
}
|
||||
|
||||
public async Task<bool> AddMagnetAsync(string magnetLink)
|
||||
{
|
||||
var payload = new
|
||||
{
|
||||
method = "core.add_torrent_url",
|
||||
@params = new object[] { magnetLink, new { } },
|
||||
id = 2
|
||||
};
|
||||
|
||||
var response = await _http.PostAsJsonAsync(_url, payload);
|
||||
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
|
||||
return json.GetProperty("result").ValueKind != JsonValueKind.Null;
|
||||
}
|
||||
public async Task<bool> AddTorrentUrlAsync(string torrentUrl)
|
||||
{
|
||||
var payload = new
|
||||
{
|
||||
method = "core.add_torrent_url",
|
||||
@params = new object[]
|
||||
{
|
||||
torrentUrl,
|
||||
new
|
||||
{
|
||||
download_location = "/download/incomplete",
|
||||
move_completed = true,
|
||||
move_completed_path = "/media/Movies",
|
||||
}
|
||||
},
|
||||
id = 3
|
||||
};
|
||||
|
||||
var response = await _http.PostAsJsonAsync(_url, payload);
|
||||
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
|
||||
|
||||
return json.GetProperty("result").ValueKind != JsonValueKind.Null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
103
Aberwyn/Data/HDTorrentsTrackerScraper.cs
Normal file
103
Aberwyn/Data/HDTorrentsTrackerScraper.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Aberwyn.Data
|
||||
{
|
||||
public class HdTorrentsTrackerScraper
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ILogger<HdTorrentsTrackerScraper> _logger;
|
||||
|
||||
public HdTorrentsTrackerScraper(HttpClient httpClient, ILogger<HdTorrentsTrackerScraper> logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<(int seeders, int leechers, int completed)> ScrapeHdTorrents(string infoHash, string downloadKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(infoHash) || string.IsNullOrEmpty(downloadKey))
|
||||
return (0, 0, 0);
|
||||
|
||||
// Konvertera hex InfoHash till URL-encoded bytes
|
||||
var infoHashBytes = HexStringToBytes(infoHash);
|
||||
|
||||
//%67%2e%d6%f9%30%e9%33%88%e3%1b%c6%f0%85%f5%f7%78%44%05%10%e7
|
||||
var encodedInfoHash = Uri.EscapeDataString(Encoding.GetEncoding("ISO-8859-1").GetString(infoHashBytes));
|
||||
var encodedInfoHashv2 = EncodeInfoHash(infoHash);
|
||||
|
||||
// Bygga scrape URL baserat på HD-Torrents format
|
||||
var scrapeUrl = $"https://hdts-announce.ru/scrape.php?pid=98d498dedff78ba0334f662d151eb19b7?info_hash={encodedInfoHashv2}";
|
||||
|
||||
_logger.LogInformation("Scraping HD-Torrents: {Url}", scrapeUrl);
|
||||
|
||||
var response = await _httpClient.GetAsync(scrapeUrl);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var content = await response.Content.ReadAsByteArrayAsync(); // Fix: Content.ReadAsByteArrayAsync()
|
||||
return ParseBencodeResponse(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("Scrape failed with status: {StatusCode}", response.StatusCode);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to scrape HD-Torrents for InfoHash: {InfoHash}", infoHash);
|
||||
}
|
||||
|
||||
return (0, 0, 0);
|
||||
}
|
||||
private static string EncodeInfoHash(string hex)
|
||||
{
|
||||
var bytes = HexStringToBytes(hex);
|
||||
return string.Concat(bytes.Select(b => $"%{b:X2}")).ToLower();
|
||||
}
|
||||
private static byte[] HexStringToBytes(string hex)
|
||||
{
|
||||
if (hex.Length % 2 != 0)
|
||||
throw new ArgumentException("Invalid hex string length.");
|
||||
|
||||
var bytes = new byte[hex.Length / 2];
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
{
|
||||
bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private (int seeders, int leechers, int completed) ParseBencodeResponse(byte[] data)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Enkel bencode parsing för tracker response
|
||||
var response = System.Text.Encoding.UTF8.GetString(data);
|
||||
|
||||
// Tracker response är vanligtvis i format:
|
||||
// d5:filesd20:[info_hash]d8:completei[antal]e9:downloadedi[antal]e10:incompletei[antal]eee
|
||||
|
||||
// Hitta complete (seeders)
|
||||
var completeMatch = System.Text.RegularExpressions.Regex.Match(response, @"8:completei(\d+)e");
|
||||
var seeders = completeMatch.Success ? int.Parse(completeMatch.Groups[1].Value) : 0;
|
||||
|
||||
// Hitta incomplete (leechers)
|
||||
var incompleteMatch = System.Text.RegularExpressions.Regex.Match(response, @"10:incompletei(\d+)e");
|
||||
var leechers = incompleteMatch.Success ? int.Parse(incompleteMatch.Groups[1].Value) : 0;
|
||||
|
||||
// Hitta downloaded (completed)
|
||||
var downloadedMatch = System.Text.RegularExpressions.Regex.Match(response, @"9:downloadedi(\d+)e");
|
||||
var completed = downloadedMatch.Success ? int.Parse(downloadedMatch.Groups[1].Value) : 0;
|
||||
|
||||
return (seeders, leechers, completed);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to parse bencode response");
|
||||
return (0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Aberwyn/Data/IRssProcessor.cs
Normal file
7
Aberwyn/Data/IRssProcessor.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Aberwyn.Data
|
||||
{
|
||||
public interface IRssProcessor
|
||||
{
|
||||
Task ProcessRssFeeds();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Aberwyn.Models;
|
||||
|
||||
@@ -6,12 +7,18 @@ namespace Aberwyn.Data
|
||||
{
|
||||
public static class IdentityDataInitializer
|
||||
{
|
||||
public static async Task SeedData(IServiceProvider serviceProvider)
|
||||
public static async Task<IdentityResult> SeedData(IServiceProvider serviceProvider, SetupSettings? setup = null)
|
||||
{
|
||||
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
|
||||
var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
|
||||
var config = serviceProvider.GetService<IConfiguration>();
|
||||
|
||||
string[] roles = { "Admin" };
|
||||
if (setup == null && config != null)
|
||||
{
|
||||
setup = config.GetSection("SetupSettings").Get<SetupSettings>() ?? new SetupSettings();
|
||||
}
|
||||
|
||||
string[] roles = { "Admin", "Chef", "Budget" };
|
||||
|
||||
foreach (var role in roles)
|
||||
{
|
||||
@@ -19,25 +26,38 @@ namespace Aberwyn.Data
|
||||
await roleManager.CreateAsync(new IdentityRole(role));
|
||||
}
|
||||
|
||||
string adminEmail = "tai@zcz.se";
|
||||
string password = "Admin123!";
|
||||
|
||||
if (await userManager.FindByEmailAsync(adminEmail) == null)
|
||||
var existingUser = await userManager.FindByEmailAsync(setup.AdminEmail);
|
||||
if (existingUser == null)
|
||||
{
|
||||
var user = new ApplicationUser
|
||||
{
|
||||
UserName = adminEmail,
|
||||
Email = adminEmail,
|
||||
UserName = setup.AdminUsername,
|
||||
Email = setup.AdminEmail,
|
||||
EmailConfirmed = true
|
||||
};
|
||||
|
||||
var result = await userManager.CreateAsync(user, password);
|
||||
var result = await userManager.CreateAsync(user, setup.AdminPassword);
|
||||
|
||||
if (result.Succeeded)
|
||||
await userManager.AddToRoleAsync(user, "Admin");
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var token = await userManager.GeneratePasswordResetTokenAsync(existingUser);
|
||||
var result = await userManager.ResetPasswordAsync(existingUser, token, setup.AdminPassword);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await userManager.AddToRoleAsync(user, "Admin");
|
||||
}
|
||||
var rolesForUser = await userManager.GetRolesAsync(existingUser);
|
||||
if (!rolesForUser.Contains("Admin"))
|
||||
await userManager.AddToRoleAsync(existingUser, "Admin");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
104
Aberwyn/Data/MovieMetadataService.cs
Normal file
104
Aberwyn/Data/MovieMetadataService.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Aberwyn.Data
|
||||
{
|
||||
public class MovieMetadataService
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly string _apiKey = "6a666b45";
|
||||
private readonly string _tpiKey = "6a666b45";
|
||||
|
||||
|
||||
public MovieMetadataService(HttpClient httpClient)
|
||||
{
|
||||
_http = httpClient;
|
||||
}
|
||||
|
||||
public async Task<MovieMetadata?> GetMovieAsync(string title, int? year = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(title))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
MovieMetadata? metadata = null;
|
||||
|
||||
// Först försök med titel + år
|
||||
if (year.HasValue)
|
||||
{
|
||||
var urlWithYear = $"https://www.omdbapi.com/?t={Uri.EscapeDataString(title)}&y={year.Value}&apikey={_apiKey}";
|
||||
metadata = await _http.GetFromJsonAsync<MovieMetadata>(urlWithYear);
|
||||
}
|
||||
|
||||
// Om inget hittas, försök bara med titel
|
||||
if (metadata == null || string.IsNullOrEmpty(metadata.Title))
|
||||
{
|
||||
var urlTitleOnly = $"https://www.omdbapi.com/?t={Uri.EscapeDataString(title)}&apikey={_apiKey}";
|
||||
metadata = await _http.GetFromJsonAsync<MovieMetadata>(urlTitleOnly);
|
||||
}
|
||||
|
||||
// Returnera metadata om något hittades
|
||||
return (metadata != null && !string.IsNullOrEmpty(metadata.Title)) ? metadata : null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TmdbService
|
||||
{
|
||||
private readonly HttpClient _http = new();
|
||||
private readonly string _apiKey = "aef2f49296b77b9b9c269678d04bdbc6";
|
||||
private readonly string _country = "SE";
|
||||
|
||||
public async Task<string> GetWatchProvidersByTitleAsync(string title, int? year = null)
|
||||
{
|
||||
var query = Uri.EscapeDataString(title);
|
||||
var url = $"https://api.themoviedb.org/3/search/movie?api_key={_apiKey}&query={query}";
|
||||
if (year.HasValue)
|
||||
url += $"&year={year.Value}";
|
||||
|
||||
var searchResult = await _http.GetFromJsonAsync<TmdbSearchResponse>(url);
|
||||
var movie = searchResult?.Results?.FirstOrDefault();
|
||||
if (movie == null) return "";
|
||||
|
||||
var providersUrl = $"https://api.themoviedb.org/3/movie/{movie.Id}/watch/providers?api_key={_apiKey}";
|
||||
var providersResult = await _http.GetFromJsonAsync<WatchProvidersResponse>(providersUrl);
|
||||
|
||||
if (providersResult?.Results?.ContainsKey(_country) == true)
|
||||
{
|
||||
var seProviders = providersResult.Results[_country];
|
||||
var names = new List<string>();
|
||||
if (seProviders.Flatrate != null) names.AddRange(seProviders.Flatrate.Select(p => p.ProviderName));
|
||||
//if (seProviders.Rent != null) names.AddRange(seProviders.Rent.Select(p => p.ProviderName));
|
||||
//if (seProviders.Buy != null) names.AddRange(seProviders.Buy.Select(p => p.ProviderName));
|
||||
return string.Join(", ", names.Distinct());
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// JSON-klasser för TMDb
|
||||
public class TmdbSearchResponse { public List<TmdbMovie> Results { get; set; } = new(); }
|
||||
public class TmdbMovie { public int Id { get; set; } }
|
||||
public class WatchProvidersResponse { public Dictionary<string, CountryProviders> Results { get; set; } = new(); }
|
||||
public class CountryProviders
|
||||
{
|
||||
public List<Provider>? Flatrate { get; set; }
|
||||
public List<Provider>? Rent { get; set; }
|
||||
public List<Provider>? Buy { get; set; }
|
||||
}
|
||||
public class Provider
|
||||
{
|
||||
[JsonPropertyName("provider_name")]
|
||||
public string ProviderName { get; set; } = "";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
76
Aberwyn/Data/PizzaNotificationService.cs
Normal file
76
Aberwyn/Data/PizzaNotificationService.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using WebPush;
|
||||
|
||||
namespace Aberwyn.Services
|
||||
{
|
||||
public class PizzaNotificationService
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly PushNotificationService _push;
|
||||
|
||||
public PizzaNotificationService(ApplicationDbContext context, PushNotificationService push)
|
||||
{
|
||||
Console.WriteLine("🍕 PizzaNotificationService constructor körs!");
|
||||
|
||||
_context = context;
|
||||
_push = push;
|
||||
}
|
||||
|
||||
public async Task<int> NotifyPizzaSubscribersAsync(string pizzaName = null, string userName = null)
|
||||
{
|
||||
var title = "Ny pizzabeställning 🍕";
|
||||
var body = "En pizza har precis beställts!";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(pizzaName))
|
||||
body = $"Pizzan '{pizzaName}' har precis beställts!";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(userName))
|
||||
body += $" (av {userName})";
|
||||
|
||||
var payload = $@"{{""title"":""{title}"",""body"":""{body}""}}";
|
||||
|
||||
var subscribers = await _context.PushSubscribers
|
||||
.Include(s => s.User)
|
||||
.ThenInclude(u => u.Preferences)
|
||||
.Where(s => s.User != null &&
|
||||
s.User.Preferences != null &&
|
||||
s.User.Preferences.NotifyPizza &&
|
||||
!string.IsNullOrEmpty(s.Endpoint) &&
|
||||
s.Endpoint.StartsWith("https://"))
|
||||
.ToListAsync();
|
||||
|
||||
var allSubscribers = await _context.PushSubscribers
|
||||
.Include(s => s.User)
|
||||
.ThenInclude(u => u.Preferences)
|
||||
.ToListAsync();
|
||||
foreach (var s in allSubscribers)
|
||||
{
|
||||
Console.WriteLine($"🔍 Sub: {s.Endpoint}, User: {s.User?.UserName}, NotifyPizza: {s.User?.Preferences?.NotifyPizza}");
|
||||
}
|
||||
int successCount = 0;
|
||||
foreach (var sub in subscribers)
|
||||
{
|
||||
try
|
||||
{
|
||||
_push.SendNotification(sub.Endpoint, sub.P256DH, sub.Auth, payload);
|
||||
successCount++;
|
||||
}
|
||||
catch (WebPushException ex) when (ex.StatusCode == System.Net.HttpStatusCode.Gone || ex.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
Console.WriteLine($"🗑️ Ogiltig prenumeration tas bort: {sub.Endpoint}");
|
||||
_context.PushSubscribers.Remove(sub);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Misslyckades att skicka till {sub.Endpoint}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return successCount;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
304
Aberwyn/Data/RssProcessor.cs
Normal file
304
Aberwyn/Data/RssProcessor.cs
Normal file
@@ -0,0 +1,304 @@
|
||||
using Aberwyn.Data;
|
||||
using Aberwyn.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Aberwyn.Data
|
||||
{
|
||||
public class RssProcessor : IRssProcessor
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly ILogger<RssProcessor> _logger;
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly HdTorrentsTrackerScraper _trackerScraper;
|
||||
private readonly MovieMetadataService _movieMetadataService;
|
||||
|
||||
public RssProcessor(ApplicationDbContext context, ILogger<RssProcessor> logger,
|
||||
HttpClient httpClient, HdTorrentsTrackerScraper trackerScraper, MovieMetadataService movieMetadataService)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
_httpClient = httpClient;
|
||||
_trackerScraper = trackerScraper;
|
||||
_movieMetadataService = movieMetadataService;
|
||||
}
|
||||
|
||||
public async Task ProcessRssFeeds()
|
||||
{
|
||||
|
||||
var debug = false;
|
||||
|
||||
var oneHourAgo = DateTime.UtcNow.AddHours(-1);
|
||||
if (debug)
|
||||
oneHourAgo = DateTime.UtcNow.AddHours(1);
|
||||
|
||||
var activeFeeds = await _context.RssFeeds
|
||||
.Where(f => f.IsActive && f.LastChecked <= oneHourAgo)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var feed in activeFeeds)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ProcessSingleFeed(feed);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error processing RSS feed {FeedName}", feed.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessSingleFeed(RssFeed feed)
|
||||
{
|
||||
var rssContent = await _httpClient.GetStringAsync(feed.Url);
|
||||
var rssDoc = XDocument.Parse(rssContent);
|
||||
var items = rssDoc.Descendants("item");
|
||||
try
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
try
|
||||
{
|
||||
var torrentItem = ParseRssItem(item, feed);
|
||||
Console.WriteLine($"Trying to save: Title='{torrentItem.Title}', InfoHash='{torrentItem.InfoHash}', MovieName='{torrentItem.MovieName}'");
|
||||
|
||||
// Kolla om den redan finns
|
||||
var exists = await _context.TorrentItems
|
||||
.AnyAsync(t => t.InfoHash == torrentItem.InfoHash ||
|
||||
(t.Title == torrentItem.Title && t.RssSource == feed.Name));
|
||||
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(torrentItem.InfoHash) && !string.IsNullOrEmpty(torrentItem.DownloadKey))
|
||||
{
|
||||
var (seeders, leechers, completed) = await _trackerScraper.ScrapeHdTorrents(
|
||||
torrentItem.InfoHash,
|
||||
torrentItem.DownloadKey);
|
||||
|
||||
torrentItem.Seeders = seeders;
|
||||
torrentItem.Leechers = leechers;
|
||||
torrentItem.Completed = completed;
|
||||
|
||||
Console.WriteLine($"Scraped stats for {torrentItem.Title}: S:{seeders} L:{leechers} C:{completed}");
|
||||
}
|
||||
|
||||
var metadata = await _movieMetadataService.GetMovieAsync(torrentItem.MovieName, torrentItem.Year);
|
||||
if (metadata != null)
|
||||
{
|
||||
torrentItem.Metadata = metadata;
|
||||
var tmdbService = new TmdbService();
|
||||
torrentItem.Metadata.Providers = await tmdbService.GetWatchProvidersByTitleAsync(torrentItem.MovieName, torrentItem.Year);
|
||||
|
||||
}
|
||||
|
||||
_context.TorrentItems.Add(torrentItem);
|
||||
var savedChanges = await _context.SaveChangesAsync();
|
||||
Console.WriteLine($"SaveChanges returned: {savedChanges}");
|
||||
// Kolla auto-download regler
|
||||
if (await ShouldAutoDownload(torrentItem))
|
||||
{
|
||||
await ProcessTorrentDownload(torrentItem);
|
||||
}
|
||||
} else
|
||||
{
|
||||
|
||||
var howLongAgo = DateTime.UtcNow.AddHours(-6);
|
||||
if (torrentItem.PublishDate >= howLongAgo)
|
||||
{
|
||||
|
||||
var existing = await _context.TorrentItems
|
||||
.FirstOrDefaultAsync(t => t.InfoHash == torrentItem.InfoHash
|
||||
|| (t.Title == torrentItem.Title && t.RssSource == feed.Name));
|
||||
|
||||
if (existing != null)
|
||||
{
|
||||
var (seeders, leechers, completed) = await _trackerScraper.ScrapeHdTorrents(
|
||||
existing.InfoHash,
|
||||
existing.DownloadKey);
|
||||
|
||||
existing.Seeders = seeders;
|
||||
existing.Leechers = leechers;
|
||||
existing.Completed = completed;
|
||||
|
||||
_context.TorrentItems.Update(existing);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine($"Updated stats for {existing.Title}: S:{seeders} L:{leechers} C:{completed}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception itemEx)
|
||||
{
|
||||
Console.WriteLine($"Error processing individual item: {itemEx.Message}");
|
||||
Console.WriteLine($"Stack trace: {itemEx.StackTrace}");
|
||||
}
|
||||
}
|
||||
|
||||
feed.LastChecked = DateTime.UtcNow;
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error in ProcessSingleFeed: {ex.Message}");
|
||||
Console.WriteLine($"Stack trace: {ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
|
||||
private TorrentItem ParseRssItem(XElement item, RssFeed feed)
|
||||
{
|
||||
var title = item.Element("title")?.Value ?? "Unknown Title";
|
||||
var description = item.Element("description")?.Value ?? ""; // Fix: Default till tom sträng
|
||||
var pubDate = DateTime.TryParse(item.Element("pubDate")?.Value, out var date) ? date : DateTime.UtcNow;
|
||||
var link = item.Element("link")?.Value ?? "";
|
||||
|
||||
var infoHash = ExtractInfoHashFromUrl(link);
|
||||
var downloadKey = ExtractParameterFromUrl(link, "key");
|
||||
var token = ExtractParameterFromUrl(link, "token");
|
||||
var (movieName, year) = ParseMovieNameAndYear(title);
|
||||
|
||||
var magnetLink = "";
|
||||
if (!string.IsNullOrEmpty(infoHash))
|
||||
{
|
||||
magnetLink = $"magnet:?xt=urn:btih:{infoHash}&dn={Uri.EscapeDataString(title)}";
|
||||
}
|
||||
|
||||
return new TorrentItem
|
||||
{
|
||||
Title = title ?? "Unknown Title", // Garanterat inte null
|
||||
Description = description ?? string.Empty, // Garanterat inte null
|
||||
TorrentUrl = string.IsNullOrEmpty(link) ? null : link,
|
||||
MagnetLink = string.IsNullOrEmpty(magnetLink) ? null : magnetLink,
|
||||
InfoHash = string.IsNullOrEmpty(infoHash) ? null : infoHash,
|
||||
PublishDate = pubDate,
|
||||
RssSource = feed.Name ?? "Unknown", // Garanterat inte null
|
||||
Status = TorrentStatus.New,
|
||||
DownloadKey = string.IsNullOrEmpty(downloadKey) ? null : downloadKey,
|
||||
Token = string.IsNullOrEmpty(token) ? null : token,
|
||||
MovieName = string.IsNullOrEmpty(movieName) ? null : movieName,
|
||||
Year = year,
|
||||
Category = DetermineCategory(title),
|
||||
CreatedAt = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
private (string movieName, int? year) ParseMovieNameAndYear(string title)
|
||||
{
|
||||
// Exempel titlar:
|
||||
// "Bring It on Fight to the Finish 2009 BluRay 1080p DDP 5.1 x264-hallowed"
|
||||
// "Deadpool & Wolverine 2024 Hybrid 1080p UHD BluRay DD+5.1 Atmos DV HDR10+ x265-HiDt"
|
||||
|
||||
var movieName = "";
|
||||
int? year = null;
|
||||
|
||||
// Leta efter år (4 siffror mellan 1900-2099)
|
||||
var yearMatch = System.Text.RegularExpressions.Regex.Match(title, @"\b(19\d{2}|20\d{2})\b");
|
||||
if (yearMatch.Success && int.TryParse(yearMatch.Groups[1].Value, out var parsedYear))
|
||||
{
|
||||
year = parsedYear;
|
||||
|
||||
// Ta allt före året som filmnamn
|
||||
var yearIndex = yearMatch.Index;
|
||||
movieName = title.Substring(0, yearIndex).Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Om inget år hittas, ta första delen före vanliga release-keywords
|
||||
var keywordMatch = System.Text.RegularExpressions.Regex.Match(title,
|
||||
@"\b(BluRay|WEB-DL|WEBRip|HDTV|DVDRIP|REMUX|UHD|1080p|720p|480p|2160p)\b",
|
||||
RegexOptions.IgnoreCase);
|
||||
|
||||
if (keywordMatch.Success)
|
||||
{
|
||||
movieName = title.Substring(0, keywordMatch.Index).Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: ta första delen innan sista bindestreck
|
||||
var lastDashIndex = title.LastIndexOf('-');
|
||||
if (lastDashIndex > 0)
|
||||
{
|
||||
movieName = title.Substring(0, lastDashIndex).Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
movieName = title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rensa bort vanliga suffix från filmnamnet
|
||||
movieName = System.Text.RegularExpressions.Regex.Replace(movieName,
|
||||
@"\b(REMASTERED|REPACK|PROPER|REAL|EXTENDED|DIRECTORS?\.?CUT|UNRATED)\b",
|
||||
"", RegexOptions.IgnoreCase).Trim();
|
||||
|
||||
return (movieName, year);
|
||||
}
|
||||
|
||||
private string ExtractInfoHashFromUrl(string url)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url)) return "";
|
||||
|
||||
var match = System.Text.RegularExpressions.Regex.Match(url, @"hash=([a-fA-F0-9]{40})");
|
||||
return match.Success ? match.Groups[1].Value.ToUpper() : "";
|
||||
}
|
||||
|
||||
private string ExtractParameterFromUrl(string url, string paramName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url)) return "";
|
||||
|
||||
var match = System.Text.RegularExpressions.Regex.Match(url, $@"{paramName}=([^&]+)");
|
||||
return match.Success ? Uri.UnescapeDataString(match.Groups[1].Value) : "";
|
||||
}
|
||||
|
||||
private string DetermineCategory(string title)
|
||||
{
|
||||
if (System.Text.RegularExpressions.Regex.IsMatch(title, @"\b(S\d{2}E\d{2}|Season|Episode)\b", RegexOptions.IgnoreCase))
|
||||
return "TV";
|
||||
else
|
||||
return "Movies";
|
||||
}
|
||||
|
||||
private async Task<bool> ShouldAutoDownload(TorrentItem item)
|
||||
{
|
||||
var rules = await _context.DownloadRules.Where(r => r.AutoDownload).ToListAsync();
|
||||
|
||||
return rules.Any(rule =>
|
||||
(string.IsNullOrEmpty(rule.KeywordFilter) ||
|
||||
item.Title.Contains(rule.KeywordFilter, StringComparison.OrdinalIgnoreCase)) &&
|
||||
(string.IsNullOrEmpty(rule.CategoryFilter) ||
|
||||
item.Category == rule.CategoryFilter) &&
|
||||
item.Seeders >= rule.MinSeeders &&
|
||||
(rule.MaxSize == 0 || item.Size <= rule.MaxSize));
|
||||
}
|
||||
|
||||
private async Task ProcessTorrentDownload(TorrentItem item)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.MagnetLink))
|
||||
{
|
||||
_logger.LogInformation("Starting magnet download for {Title}", item.Title);
|
||||
item.Status = TorrentStatus.Downloaded;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(item.TorrentUrl))
|
||||
{
|
||||
var torrentData = await _httpClient.GetByteArrayAsync(item.TorrentUrl);
|
||||
item.Status = TorrentStatus.Downloaded;
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error downloading torrent {Title}", item.Title);
|
||||
item.Status = TorrentStatus.Failed;
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
76
Aberwyn/Data/SetupService.cs
Normal file
76
Aberwyn/Data/SetupService.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Aberwyn.Models;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Aberwyn.Data
|
||||
{
|
||||
// SetupService.cs
|
||||
public class SetupService
|
||||
{
|
||||
private readonly IWebHostEnvironment _env;
|
||||
private readonly string _filePath;
|
||||
|
||||
public SetupService(IWebHostEnvironment env)
|
||||
{
|
||||
_env = env;
|
||||
var dataRoot = Path.Combine(Directory.GetCurrentDirectory(), "data"); // /app/data i containern
|
||||
_filePath = Path.Combine(dataRoot, "infrastructure", "setup.json");
|
||||
}
|
||||
|
||||
|
||||
public SetupSettings GetSetup()
|
||||
{
|
||||
if (!File.Exists(_filePath))
|
||||
return new SetupSettings { IsConfigured = false };
|
||||
|
||||
var json = File.ReadAllText(_filePath);
|
||||
return JsonSerializer.Deserialize<SetupSettings>(json) ?? new SetupSettings { IsConfigured = false };
|
||||
}
|
||||
|
||||
|
||||
internal static IServiceProvider BuildTemporaryServices(string connectionString)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
// Konfigurera EF + Identity
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));
|
||||
|
||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
.AddDefaultTokenProviders();
|
||||
|
||||
// Lägg till en tom konfiguration för att undvika null
|
||||
services.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build());
|
||||
|
||||
// Valfritt: Lägg till loggning om något kräver det
|
||||
services.AddLogging();
|
||||
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
public static class SetupLoader
|
||||
{
|
||||
public static SetupSettings Load(IHostEnvironment env)
|
||||
{
|
||||
var dataRoot = Path.Combine(Directory.GetCurrentDirectory(), "data"); // /app/data i containern
|
||||
var filePath = Path.Combine(dataRoot, "infrastructure", "setup.json");
|
||||
|
||||
var json = File.ReadAllText(filePath);
|
||||
return JsonSerializer.Deserialize<SetupSettings>(json)!;
|
||||
}
|
||||
|
||||
public static string GetConnectionString(SetupSettings setup)
|
||||
{
|
||||
return $"server={setup.DbHost};port={setup.DbPort};database={setup.DbName};user={setup.DbUser};password={setup.DbPassword}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
41
Aberwyn/Data/TorrentRssService.cs
Normal file
41
Aberwyn/Data/TorrentRssService.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Aberwyn.Data;
|
||||
|
||||
namespace Aberwyn.Services
|
||||
{
|
||||
public class TorrentRssService : BackgroundService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ILogger<TorrentRssService> _logger;
|
||||
|
||||
public TorrentRssService(IServiceProvider serviceProvider, ILogger<TorrentRssService> logger)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
// Vänta lite innan första körningen
|
||||
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
|
||||
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var rssProcessor = scope.ServiceProvider.GetRequiredService<IRssProcessor>();
|
||||
await rssProcessor.ProcessRssFeeds();
|
||||
|
||||
_logger.LogInformation("RSS feeds processed successfully at {Time}", DateTime.UtcNow);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error processing RSS feeds");
|
||||
}
|
||||
|
||||
// Vänta 10 minuter innan nästa körning
|
||||
await Task.Delay(TimeSpan.FromMinutes(10), stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
213
Aberwyn/Data/TorrentService.cs
Normal file
213
Aberwyn/Data/TorrentService.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
using Aberwyn.Data;
|
||||
using BencodeNET.Objects;
|
||||
using BencodeNET.Parsing;
|
||||
using BencodeNET.Torrents;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Text;
|
||||
|
||||
public interface ITorrentService
|
||||
{
|
||||
Task<TorrentInfo> ParseTorrentAsync(IFormFile file);
|
||||
Task<TorrentInfo> FetchTrackerStatsAsync(TorrentInfo info);
|
||||
Task<List<TorrentItem>> GetRecentTorrentsAsync(int count);
|
||||
}
|
||||
|
||||
public class TorrentService : ITorrentService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ILogger<TorrentService> _logger;
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
// Kända trackers och deras egenskaper
|
||||
private readonly Dictionary<string, TrackerInfo> _knownTrackers = new()
|
||||
{
|
||||
["hdts-announce.ru"] = new TrackerInfo
|
||||
{
|
||||
Name = "HD-Torrents",
|
||||
SupportsScraping = true, // Ändrat till true
|
||||
RequiresAuth = false, // Kan fungera utan auth för scraping
|
||||
IsPrivate = true,
|
||||
Notes = "Privat tracker, scraping kan fungera utan inloggning"
|
||||
}
|
||||
};
|
||||
|
||||
public TorrentService(HttpClient httpClient, ILogger<TorrentService> logger, ApplicationDbContext context)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_logger = logger;
|
||||
_context = context;
|
||||
_httpClient.Timeout = TimeSpan.FromSeconds(10);
|
||||
}
|
||||
|
||||
public async Task<List<TorrentItem>> GetRecentTorrentsAsync(int count)
|
||||
{
|
||||
return await _context.TorrentItems
|
||||
.OrderByDescending(t => t.PublishDate)
|
||||
.Take(count)
|
||||
.ToListAsync();
|
||||
}
|
||||
public async Task<TorrentInfo> ParseTorrentAsync(IFormFile file)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var stream = new MemoryStream();
|
||||
await file.CopyToAsync(stream);
|
||||
stream.Position = 0;
|
||||
|
||||
var parser = new TorrentParser();
|
||||
var torrent = parser.Parse(stream);
|
||||
var infoHash = torrent.GetInfoHashBytes();
|
||||
var announceUrl = torrent.Trackers?.FirstOrDefault()?.FirstOrDefault()?.ToString();
|
||||
|
||||
return new TorrentInfo
|
||||
{
|
||||
FileName = torrent.DisplayName ?? file.FileName,
|
||||
AnnounceUrl = announceUrl,
|
||||
ScrapeUrl = ConvertAnnounceToScrape(announceUrl),
|
||||
InfoHash = UrlEncodeInfoHash(infoHash),
|
||||
InfoHashBytes = infoHash,
|
||||
Size = torrent.TotalSize
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Fel vid parsing av torrent-fil");
|
||||
return new TorrentInfo
|
||||
{
|
||||
FileName = file.FileName,
|
||||
ErrorMessage = $"Kunde inte parsa torrent-filen: {ex.Message}"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<TorrentInfo> FetchTrackerStatsAsync(TorrentInfo info)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(info.ScrapeUrl))
|
||||
{
|
||||
info.ErrorMessage = "Ingen scrape URL tillgänglig";
|
||||
return info;
|
||||
}
|
||||
|
||||
var url = $"{info.ScrapeUrl}?info_hash={info.InfoHash}";
|
||||
_logger.LogInformation("Scraping tracker: {Url}", url);
|
||||
|
||||
try
|
||||
{
|
||||
var data = await _httpClient.GetByteArrayAsync(url);
|
||||
var parser = new BencodeParser();
|
||||
var bdict = parser.Parse<BDictionary>(data);
|
||||
|
||||
if (bdict.TryGetValue("files", out var filesValue) && filesValue is BDictionary files)
|
||||
{
|
||||
// Använd direkt byte array istället för att konvertera till sträng
|
||||
if (TryGetStatsFromFiles(files, info.InfoHashBytes, info))
|
||||
{
|
||||
info.HasTrackerData = true;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Om det inte fungerar, prova att URL-decode först
|
||||
if (!string.IsNullOrEmpty(info.InfoHash))
|
||||
{
|
||||
try
|
||||
{
|
||||
string decoded = Uri.UnescapeDataString(info.InfoHash);
|
||||
byte[] decodedBytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(decoded);
|
||||
|
||||
if (TryGetStatsFromFiles(files, decodedBytes, info))
|
||||
{
|
||||
info.HasTrackerData = true;
|
||||
return info;
|
||||
}
|
||||
}
|
||||
catch { /* Ignore decode errors */ }
|
||||
}
|
||||
|
||||
info.ErrorMessage = "Info hash hittades inte i tracker-svaret";
|
||||
}
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
info.ErrorMessage = $"HTTP fel: {ex.Message}";
|
||||
_logger.LogWarning(ex, "HTTP fel vid tracker scraping");
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
info.ErrorMessage = "Timeout vid anslutning till tracker";
|
||||
_logger.LogWarning("Timeout vid tracker scraping");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.ErrorMessage = $"Fel vid parsing: {ex.Message}";
|
||||
_logger.LogError(ex, "Fel vid tracker scraping");
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
private bool ByteArraysEqual(byte[] a, byte[] b)
|
||||
{
|
||||
if (a.Length != b.Length) return false;
|
||||
for (int i = 0; i < a.Length; i++)
|
||||
{
|
||||
if (a[i] != b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private bool TryGetStatsFromFiles(BDictionary files, byte[] hashBytes, TorrentInfo info)
|
||||
{
|
||||
// Skapa en BString från byte array
|
||||
var bStringKey = new BString(hashBytes);
|
||||
|
||||
if (files.TryGetValue(bStringKey, out var hashEntry) && hashEntry is BDictionary stats)
|
||||
{
|
||||
info.Seeders = stats.TryGetInt("complete") ?? 0;
|
||||
info.Leechers = stats.TryGetInt("incomplete") ?? 0;
|
||||
info.Completed = stats.TryGetInt("downloaded") ?? 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public async Task<int> GetUnseenTorrentCountAsync(string userId)
|
||||
{
|
||||
// Hämta alla infohashes som användaren redan sett
|
||||
var seenHashes = await _context.UserTorrentSeen
|
||||
.Where(x => x.UserId == userId)
|
||||
.Select(x => x.InfoHash)
|
||||
.ToListAsync();
|
||||
|
||||
// Räkna alla torrents som inte finns i seenHashes och som har > 40 seeders
|
||||
var count = await _context.TorrentItems
|
||||
.Where(t => t.InfoHash != null
|
||||
&& !seenHashes.Contains(t.InfoHash)
|
||||
&& t.Seeders > 40)
|
||||
.CountAsync();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private string ConvertAnnounceToScrape(string announceUrl)
|
||||
{
|
||||
if (string.IsNullOrEmpty(announceUrl))
|
||||
return null;
|
||||
|
||||
return announceUrl.Replace("/announce", "/scrape");
|
||||
}
|
||||
|
||||
private string UrlEncodeInfoHash(byte[] infoHash)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (byte b in infoHash)
|
||||
{
|
||||
sb.AppendFormat("%{0:x2}", b);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class BDictionaryExtensions
|
||||
{
|
||||
public static int? TryGetInt(this BDictionary dict, string key)
|
||||
{
|
||||
return dict.TryGetValue(key, out var value) && value is BNumber num ? (int?)num.Value : null;
|
||||
}
|
||||
}
|
||||
11
Aberwyn/Data/infrastructure/setup.json
Normal file
11
Aberwyn/Data/infrastructure/setup.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"AdminUsername": "admin",
|
||||
"AdminEmail": "admin@localhost",
|
||||
"AdminPassword": "Admin123!",
|
||||
"IsConfigured": true,
|
||||
"DbHost": "192.168.1.108",
|
||||
"DbPort": 3306,
|
||||
"DbName": "lewel_prod",
|
||||
"DbUser": "lewel",
|
||||
"DbPassword": "W542.Hl;)%ta"
|
||||
}
|
||||
@@ -1,22 +1,47 @@
|
||||
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
# Basimage för runtime
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
|
||||
|
||||
# Installera svenska språkinställningar
|
||||
RUN apt-get update && \
|
||||
apt-get install -y locales && \
|
||||
locale-gen sv_SE.UTF-8
|
||||
|
||||
# Ställ in svenska som standard
|
||||
ENV LANG=sv_SE.UTF-8
|
||||
ENV LANGUAGE=sv_SE:sv
|
||||
ENV LC_ALL=sv_SE.UTF-8
|
||||
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
|
||||
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
VOLUME /app/data
|
||||
|
||||
# Byggimage med SDK
|
||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||
WORKDIR /src
|
||||
|
||||
# Kopiera endast .csproj först för att kunna cacha restore
|
||||
COPY ["Aberwyn/Aberwyn.csproj", "Aberwyn/"]
|
||||
RUN dotnet restore "Aberwyn/Aberwyn.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/Aberwyn"
|
||||
RUN dotnet build "Aberwyn.csproj" -c Release -o /app/build
|
||||
WORKDIR /src/Aberwyn
|
||||
|
||||
# Restore beroenden
|
||||
RUN dotnet restore "Aberwyn.csproj"
|
||||
|
||||
# Kopiera övrig kod
|
||||
COPY Aberwyn/. .
|
||||
|
||||
# Bygg utan att köra restore igen
|
||||
RUN dotnet build "Aberwyn.csproj" -c Release -o /app/build --no-restore
|
||||
|
||||
# Publicera utan att köra restore eller build igen
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "Aberwyn.csproj" -c Release -o /app/publish
|
||||
RUN dotnet publish "Aberwyn.csproj" -c Release -o /app/publish --no-restore
|
||||
|
||||
# Slutgiltig image baserad på runtime
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
|
||||
ENTRYPOINT ["dotnet", "Aberwyn.dll"]
|
||||
38
Aberwyn/Infrastructure/docker-compose.dev.yml
Normal file
38
Aberwyn/Infrastructure/docker-compose.dev.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
aberwyn-app:
|
||||
image: aberwyn:latest
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "5000:80"
|
||||
environment:
|
||||
ASPNETCORE_ENVIRONMENT: Development
|
||||
DB_NAME: aberwyn_dev
|
||||
|
||||
depends_on:
|
||||
- mysql
|
||||
networks:
|
||||
- aberwyn-net
|
||||
|
||||
mysql:
|
||||
image: mysql:8
|
||||
container_name: aberwyn-mysql-dev
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: rootpass
|
||||
MYSQL_DATABASE: aberwyn_dev
|
||||
MYSQL_USER: aberwyn
|
||||
MYSQL_PASSWORD: 3edc4RFV
|
||||
volumes:
|
||||
- mysql-dev-data:/var/lib/mysql
|
||||
networks:
|
||||
- aberwyn-net
|
||||
|
||||
volumes:
|
||||
mysql-dev-data:
|
||||
|
||||
networks:
|
||||
aberwyn-net:
|
||||
38
Aberwyn/Infrastructure/docker-compose.prod.yml
Normal file
38
Aberwyn/Infrastructure/docker-compose.prod.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
aberwyn-app:
|
||||
image: 192.168.1.9:3000/tai/aberwyn/aberwyn:latest
|
||||
container_name: aberwyn-app-prod
|
||||
ports:
|
||||
- "8080:80"
|
||||
environment:
|
||||
ASPNETCORE_ENVIRONMENT: Production
|
||||
DB_HOST: aberwyn-mysql-prod
|
||||
DB_NAME: aberwyn_prod
|
||||
DB_USER: aberwyn
|
||||
DB_PASSWORD: 3edc4RFV
|
||||
depends_on:
|
||||
- aberwyn-mysql-prod
|
||||
networks:
|
||||
- aberwyn-net
|
||||
|
||||
aberwyn-mysql-prod:
|
||||
image: mysql:8
|
||||
container_name: aberwyn-mysql-prod
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: rootpass
|
||||
MYSQL_DATABASE: aberwyn_prod
|
||||
MYSQL_USER: aberwyn
|
||||
MYSQL_PASSWORD: 3edc4RFV
|
||||
volumes:
|
||||
- mysql-prod-data:/var/lib/mysql
|
||||
networks:
|
||||
- aberwyn-net
|
||||
|
||||
volumes:
|
||||
mysql-prod-data:
|
||||
|
||||
networks:
|
||||
aberwyn-net:
|
||||
11
Aberwyn/Infrastructure/setup.json
Normal file
11
Aberwyn/Infrastructure/setup.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"AdminUsername": "admin",
|
||||
"AdminEmail": "admin@localhost",
|
||||
"AdminPassword": "Admin123!",
|
||||
"IsConfigured": true,
|
||||
"DbHost": "192.168.1.108",
|
||||
"DbPort": 3306,
|
||||
"DbName": "lewel_prod",
|
||||
"DbUser": "lewel",
|
||||
"DbPassword": "W542.Hl;)%ta"
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250506132522_CreateIdentitySchema")]
|
||||
partial class CreateIdentitySchema
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class CreateIdentitySchema : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterDatabase()
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoles",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Name = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
NormalizedName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUsers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
UserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
NormalizedUserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
NormalizedEmail = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
EmailConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
PasswordHash = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
SecurityStamp = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PhoneNumber = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PhoneNumberConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
TwoFactorEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
LockoutEnd = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true),
|
||||
LockoutEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoleClaims",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
RoleId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ClaimType = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
|
||||
column: x => x.RoleId,
|
||||
principalTable: "AspNetRoles",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserClaims",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ClaimType = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserLogins",
|
||||
columns: table => new
|
||||
{
|
||||
LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ProviderKey = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ProviderDisplayName = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserRoles",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
RoleId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
|
||||
column: x => x.RoleId,
|
||||
principalTable: "AspNetRoles",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserTokens",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Name = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Value = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetRoleClaims_RoleId",
|
||||
table: "AspNetRoleClaims",
|
||||
column: "RoleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "RoleNameIndex",
|
||||
table: "AspNetRoles",
|
||||
column: "NormalizedName",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserClaims_UserId",
|
||||
table: "AspNetUserClaims",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserLogins_UserId",
|
||||
table: "AspNetUserLogins",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserRoles_RoleId",
|
||||
table: "AspNetUserRoles",
|
||||
column: "RoleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "EmailIndex",
|
||||
table: "AspNetUsers",
|
||||
column: "NormalizedEmail");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "UserNameIndex",
|
||||
table: "AspNetUsers",
|
||||
column: "NormalizedUserName",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetRoleClaims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserClaims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserLogins");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserRoles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserTokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetRoles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUsers");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,375 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250515202922_CreateBudgetSchema")]
|
||||
partial class CreateBudgetSchema
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Person")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class CreateBudgetSchema : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetPeriods",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Year = table.Column<int>(type: "int", nullable: false),
|
||||
Month = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetPeriods", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetCategories",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Color = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
BudgetPeriodId = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetCategories", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_BudgetCategories_BudgetPeriods_BudgetPeriodId",
|
||||
column: x => x.BudgetPeriodId,
|
||||
principalTable: "BudgetPeriods",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetItems",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Person = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Amount = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
|
||||
IsExpense = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
IncludeInSummary = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
BudgetCategoryId = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetItems", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_BudgetItems_BudgetCategories_BudgetCategoryId",
|
||||
column: x => x.BudgetCategoryId,
|
||||
principalTable: "BudgetCategories",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetCategories_BudgetPeriodId",
|
||||
table: "BudgetCategories",
|
||||
column: "BudgetPeriodId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetItems_BudgetCategoryId",
|
||||
table: "BudgetItems",
|
||||
column: "BudgetCategoryId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetItems");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetCategories");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetPeriods");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,374 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250515204407_MakePersonNullable")]
|
||||
partial class MakePersonNullable
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Person")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class MakePersonNullable : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Person",
|
||||
table: "BudgetItems",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext")
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.UpdateData(
|
||||
table: "BudgetItems",
|
||||
keyColumn: "Person",
|
||||
keyValue: null,
|
||||
column: "Person",
|
||||
value: "");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Person",
|
||||
table: "BudgetItems",
|
||||
type: "longtext",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext",
|
||||
oldNullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,380 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250519213736_AddOrderToBudgetCategory")]
|
||||
partial class AddOrderToBudgetCategory
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddOrderToBudgetCategory : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Person",
|
||||
table: "BudgetItems");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Order",
|
||||
table: "BudgetPeriods",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Order",
|
||||
table: "BudgetItems",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Order",
|
||||
table: "BudgetCategories",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Order",
|
||||
table: "BudgetPeriods");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Order",
|
||||
table: "BudgetItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Order",
|
||||
table: "BudgetCategories");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Person",
|
||||
table: "BudgetItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,380 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250522074358_AddMealImageData")]
|
||||
partial class AddMealImageData
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,403 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250523075931_AddPushSubscribers")]
|
||||
partial class AddPushSubscribers
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddPushSubscribers : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PushSubscribers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Endpoint = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
P256DH = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Auth = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PushSubscribers", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PushSubscribers");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,403 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250524103706_AddPizzaOrder")]
|
||||
partial class AddPizzaOrder
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddPizzaOrder : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,432 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250524121511_AddPizzaOrderTable")]
|
||||
partial class AddPizzaOrderTable
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CustomerName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("IngredientsJson")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("OrderedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("PizzaName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PizzaOrders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,451 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250524173316_AddAppSettings")]
|
||||
partial class AddAppSettings
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.AppSetting", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("AppSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CustomerName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("IngredientsJson")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("OrderedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("PizzaName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PizzaOrders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddAppSettings : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AppSettings",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Key = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Value = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AppSettings", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AppSettings");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddBudgetDefinitions : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "BudgetItemDefinitionId",
|
||||
table: "BudgetItems",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "BudgetCategoryDefinitionId",
|
||||
table: "BudgetCategories",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetCategoryDefinition",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Color = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetCategoryDefinition", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetItemDefinition",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
DefaultCategory = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IsExpense = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
IncludeInSummary = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetItemDefinition", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetItems_BudgetItemDefinitionId",
|
||||
table: "BudgetItems",
|
||||
column: "BudgetItemDefinitionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetCategories_BudgetCategoryDefinitionId",
|
||||
table: "BudgetCategories",
|
||||
column: "BudgetCategoryDefinitionId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_BudgetCategories_BudgetCategoryDefinition_BudgetCategoryDefi~",
|
||||
table: "BudgetCategories",
|
||||
column: "BudgetCategoryDefinitionId",
|
||||
principalTable: "BudgetCategoryDefinition",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_BudgetItems_BudgetItemDefinition_BudgetItemDefinitionId",
|
||||
table: "BudgetItems",
|
||||
column: "BudgetItemDefinitionId",
|
||||
principalTable: "BudgetItemDefinition",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_BudgetCategories_BudgetCategoryDefinition_BudgetCategoryDefi~",
|
||||
table: "BudgetCategories");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_BudgetItems_BudgetItemDefinition_BudgetItemDefinitionId",
|
||||
table: "BudgetItems");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetCategoryDefinition");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetItemDefinition");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_BudgetItems_BudgetItemDefinitionId",
|
||||
table: "BudgetItems");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_BudgetCategories_BudgetCategoryDefinitionId",
|
||||
table: "BudgetCategories");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BudgetItemDefinitionId",
|
||||
table: "BudgetItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BudgetCategoryDefinitionId",
|
||||
table: "BudgetCategories");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddBudgetItemDefinitions : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_BudgetCategories_BudgetCategoryDefinition_BudgetCategoryDefi~",
|
||||
table: "BudgetCategories");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_BudgetItems_BudgetItemDefinition_BudgetItemDefinitionId",
|
||||
table: "BudgetItems");
|
||||
|
||||
migrationBuilder.DropPrimaryKey(
|
||||
name: "PK_BudgetItemDefinition",
|
||||
table: "BudgetItemDefinition");
|
||||
|
||||
migrationBuilder.DropPrimaryKey(
|
||||
name: "PK_BudgetCategoryDefinition",
|
||||
table: "BudgetCategoryDefinition");
|
||||
|
||||
migrationBuilder.RenameTable(
|
||||
name: "BudgetItemDefinition",
|
||||
newName: "BudgetItemDefinitions");
|
||||
|
||||
migrationBuilder.RenameTable(
|
||||
name: "BudgetCategoryDefinition",
|
||||
newName: "BudgetCategoryDefinitions");
|
||||
|
||||
migrationBuilder.AddPrimaryKey(
|
||||
name: "PK_BudgetItemDefinitions",
|
||||
table: "BudgetItemDefinitions",
|
||||
column: "Id");
|
||||
|
||||
migrationBuilder.AddPrimaryKey(
|
||||
name: "PK_BudgetCategoryDefinitions",
|
||||
table: "BudgetCategoryDefinitions",
|
||||
column: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_BudgetCategories_BudgetCategoryDefinitions_BudgetCategoryDef~",
|
||||
table: "BudgetCategories",
|
||||
column: "BudgetCategoryDefinitionId",
|
||||
principalTable: "BudgetCategoryDefinitions",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_BudgetItems_BudgetItemDefinitions_BudgetItemDefinitionId",
|
||||
table: "BudgetItems",
|
||||
column: "BudgetItemDefinitionId",
|
||||
principalTable: "BudgetItemDefinitions",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_BudgetCategories_BudgetCategoryDefinitions_BudgetCategoryDef~",
|
||||
table: "BudgetCategories");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_BudgetItems_BudgetItemDefinitions_BudgetItemDefinitionId",
|
||||
table: "BudgetItems");
|
||||
|
||||
migrationBuilder.DropPrimaryKey(
|
||||
name: "PK_BudgetItemDefinitions",
|
||||
table: "BudgetItemDefinitions");
|
||||
|
||||
migrationBuilder.DropPrimaryKey(
|
||||
name: "PK_BudgetCategoryDefinitions",
|
||||
table: "BudgetCategoryDefinitions");
|
||||
|
||||
migrationBuilder.RenameTable(
|
||||
name: "BudgetItemDefinitions",
|
||||
newName: "BudgetItemDefinition");
|
||||
|
||||
migrationBuilder.RenameTable(
|
||||
name: "BudgetCategoryDefinitions",
|
||||
newName: "BudgetCategoryDefinition");
|
||||
|
||||
migrationBuilder.AddPrimaryKey(
|
||||
name: "PK_BudgetItemDefinition",
|
||||
table: "BudgetItemDefinition",
|
||||
column: "Id");
|
||||
|
||||
migrationBuilder.AddPrimaryKey(
|
||||
name: "PK_BudgetCategoryDefinition",
|
||||
table: "BudgetCategoryDefinition",
|
||||
column: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_BudgetCategories_BudgetCategoryDefinition_BudgetCategoryDefi~",
|
||||
table: "BudgetCategories",
|
||||
column: "BudgetCategoryDefinitionId",
|
||||
principalTable: "BudgetCategoryDefinition",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_BudgetItems_BudgetItemDefinition_BudgetItemDefinitionId",
|
||||
table: "BudgetItems",
|
||||
column: "BudgetItemDefinitionId",
|
||||
principalTable: "BudgetItemDefinition",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250529183339_CreateTodoTaskTable")]
|
||||
partial class CreateTodoTaskTable
|
||||
[Migration("20250602131723_InitCleanSlate")]
|
||||
partial class InitCleanSlate
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -236,6 +236,78 @@ namespace Aberwyn.Migrations
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Ingredient", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Item")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("MealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Quantity")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MealId");
|
||||
|
||||
b.ToTable("Ingredients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CarbType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Category")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<byte[]>("ImageData")
|
||||
.HasColumnType("longblob");
|
||||
|
||||
b.Property<string>("ImageMimeType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Instructions")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsAvailable")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ProteinType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RecipeUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Meals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -294,9 +366,20 @@ namespace Aberwyn.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("AssignedTo")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsArchived")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("int");
|
||||
|
||||
@@ -304,6 +387,10 @@ namespace Aberwyn.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
@@ -313,6 +400,41 @@ namespace Aberwyn.Migrations
|
||||
b.ToTable("TodoTasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("BreakfastMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Cook")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("DayOfWeek")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("DinnerMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("LunchMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("WeekNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("WeeklyMenu", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
@@ -475,6 +597,15 @@ namespace Aberwyn.Migrations
|
||||
b.Navigation("BudgetItemDefinition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Ingredient", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.Meal", null)
|
||||
.WithMany("Ingredients")
|
||||
.HasForeignKey("MealId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
@@ -535,6 +666,11 @@ namespace Aberwyn.Migrations
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.Navigation("Ingredients");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
599
Aberwyn/Migrations/20250602131723_InitCleanSlate.cs
Normal file
599
Aberwyn/Migrations/20250602131723_InitCleanSlate.cs
Normal file
@@ -0,0 +1,599 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class InitCleanSlate : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterDatabase()
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AppSettings",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Key = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Value = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AppSettings", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoles",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Name = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
NormalizedName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUsers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
UserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
NormalizedUserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
NormalizedEmail = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
EmailConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
PasswordHash = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
SecurityStamp = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PhoneNumber = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PhoneNumberConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
TwoFactorEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
LockoutEnd = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true),
|
||||
LockoutEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetCategoryDefinitions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Color = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetCategoryDefinitions", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetItemDefinitions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
DefaultCategory = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IsExpense = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
IncludeInSummary = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetItemDefinitions", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetPeriods",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Year = table.Column<int>(type: "int", nullable: false),
|
||||
Month = table.Column<int>(type: "int", nullable: false),
|
||||
Order = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetPeriods", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Meals",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Description = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ProteinType = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Category = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CarbType = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
RecipeUrl = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ImageUrl = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IsAvailable = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
ImageData = table.Column<byte[]>(type: "longblob", nullable: true),
|
||||
ImageMimeType = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Instructions = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Meals", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PizzaOrders",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
CustomerName = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PizzaName = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IngredientsJson = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Status = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
OrderedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PizzaOrders", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PushSubscribers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Endpoint = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
P256DH = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Auth = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PushSubscribers", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TodoTasks",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Title = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Description = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Priority = table.Column<int>(type: "int", nullable: false),
|
||||
Status = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
AssignedTo = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IsArchived = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
Tags = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_TodoTasks", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "WeeklyMenu",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
DayOfWeek = table.Column<int>(type: "int", nullable: false),
|
||||
BreakfastMealId = table.Column<int>(type: "int", nullable: true),
|
||||
LunchMealId = table.Column<int>(type: "int", nullable: true),
|
||||
DinnerMealId = table.Column<int>(type: "int", nullable: true),
|
||||
Cook = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
WeekNumber = table.Column<int>(type: "int", nullable: false),
|
||||
Year = table.Column<int>(type: "int", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_WeeklyMenu", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoleClaims",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
RoleId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ClaimType = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
|
||||
column: x => x.RoleId,
|
||||
principalTable: "AspNetRoles",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserClaims",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ClaimType = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserLogins",
|
||||
columns: table => new
|
||||
{
|
||||
LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ProviderKey = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ProviderDisplayName = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserRoles",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
RoleId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
|
||||
column: x => x.RoleId,
|
||||
principalTable: "AspNetRoles",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserTokens",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Name = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Value = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetCategories",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Color = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
BudgetPeriodId = table.Column<int>(type: "int", nullable: false),
|
||||
Order = table.Column<int>(type: "int", nullable: false),
|
||||
BudgetCategoryDefinitionId = table.Column<int>(type: "int", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetCategories", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_BudgetCategories_BudgetCategoryDefinitions_BudgetCategoryDef~",
|
||||
column: x => x.BudgetCategoryDefinitionId,
|
||||
principalTable: "BudgetCategoryDefinitions",
|
||||
principalColumn: "Id");
|
||||
table.ForeignKey(
|
||||
name: "FK_BudgetCategories_BudgetPeriods_BudgetPeriodId",
|
||||
column: x => x.BudgetPeriodId,
|
||||
principalTable: "BudgetPeriods",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Ingredients",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
MealId = table.Column<int>(type: "int", nullable: false),
|
||||
Quantity = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Item = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Ingredients", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Ingredients_Meals_MealId",
|
||||
column: x => x.MealId,
|
||||
principalTable: "Meals",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetItems",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Amount = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
|
||||
IsExpense = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
IncludeInSummary = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
Order = table.Column<int>(type: "int", nullable: false),
|
||||
BudgetItemDefinitionId = table.Column<int>(type: "int", nullable: true),
|
||||
BudgetCategoryId = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetItems", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_BudgetItems_BudgetCategories_BudgetCategoryId",
|
||||
column: x => x.BudgetCategoryId,
|
||||
principalTable: "BudgetCategories",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_BudgetItems_BudgetItemDefinitions_BudgetItemDefinitionId",
|
||||
column: x => x.BudgetItemDefinitionId,
|
||||
principalTable: "BudgetItemDefinitions",
|
||||
principalColumn: "Id");
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetRoleClaims_RoleId",
|
||||
table: "AspNetRoleClaims",
|
||||
column: "RoleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "RoleNameIndex",
|
||||
table: "AspNetRoles",
|
||||
column: "NormalizedName",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserClaims_UserId",
|
||||
table: "AspNetUserClaims",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserLogins_UserId",
|
||||
table: "AspNetUserLogins",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserRoles_RoleId",
|
||||
table: "AspNetUserRoles",
|
||||
column: "RoleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "EmailIndex",
|
||||
table: "AspNetUsers",
|
||||
column: "NormalizedEmail");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "UserNameIndex",
|
||||
table: "AspNetUsers",
|
||||
column: "NormalizedUserName",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetCategories_BudgetCategoryDefinitionId",
|
||||
table: "BudgetCategories",
|
||||
column: "BudgetCategoryDefinitionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetCategories_BudgetPeriodId",
|
||||
table: "BudgetCategories",
|
||||
column: "BudgetPeriodId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetItems_BudgetCategoryId",
|
||||
table: "BudgetItems",
|
||||
column: "BudgetCategoryId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetItems_BudgetItemDefinitionId",
|
||||
table: "BudgetItems",
|
||||
column: "BudgetItemDefinitionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Ingredients_MealId",
|
||||
table: "Ingredients",
|
||||
column: "MealId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AppSettings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetRoleClaims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserClaims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserLogins");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserRoles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserTokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetItems");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Ingredients");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PizzaOrders");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PushSubscribers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "TodoTasks");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "WeeklyMenu");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetRoles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetCategories");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetItemDefinitions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Meals");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetCategoryDefinitions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetPeriods");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250526133558_AddBudgetItemDefinitions")]
|
||||
partial class AddBudgetItemDefinitions
|
||||
[Migration("20250618203117_AddPaymentStatusToBudgetItem")]
|
||||
partial class AddPaymentStatusToBudgetItem
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -183,6 +183,9 @@ namespace Aberwyn.Migrations
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("PaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
@@ -201,6 +204,9 @@ namespace Aberwyn.Migrations
|
||||
b.Property<string>("DefaultCategory")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("DefaultPaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
@@ -236,6 +242,128 @@ namespace Aberwyn.Migrations
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Ingredient", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Item")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("MealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Quantity")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MealId");
|
||||
|
||||
b.ToTable("Ingredients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CarbType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<byte[]>("ImageData")
|
||||
.HasColumnType("longblob");
|
||||
|
||||
b.Property<string>("ImageMimeType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Instructions")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsAvailable")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int?>("MealCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ProteinType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RecipeUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<byte[]>("ThumbnailData")
|
||||
.HasColumnType("longblob");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MealCategoryId");
|
||||
|
||||
b.ToTable("Meals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.MealCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("DisplayOrder")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Icon")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("MealCategories");
|
||||
|
||||
b.HasData(
|
||||
new
|
||||
{
|
||||
Id = 1,
|
||||
Color = "#f97316",
|
||||
DisplayOrder = 1,
|
||||
Icon = "🍕",
|
||||
IsActive = true,
|
||||
Name = "Pizza",
|
||||
Slug = "pizza"
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -283,11 +411,144 @@ namespace Aberwyn.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("PizzaOrderId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PizzaOrderId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.StoredPushSubscription", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PushSubscriptions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.TodoTask", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("AssignedTo")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsArchived")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("TodoTasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.UserPreferences", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<bool>("NotifyBudget")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("NotifyMenu")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("NotifyPizza")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.ToTable("UserPreferences");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("BreakfastMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Cook")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("DayOfWeek")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("DinnerMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("LunchMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("WeekNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("WeeklyMenu", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
@@ -418,7 +679,7 @@ namespace Aberwyn.Migrations
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "BudgetItemDefinition")
|
||||
b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition")
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetCategoryDefinitionId");
|
||||
|
||||
@@ -430,12 +691,12 @@ namespace Aberwyn.Migrations
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
|
||||
b.Navigation("BudgetItemDefinition");
|
||||
b.Navigation("Definition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", null)
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
@@ -445,11 +706,66 @@ namespace Aberwyn.Migrations
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetItemDefinitionId");
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
|
||||
b.Navigation("BudgetItemDefinition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Ingredient", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.Meal", null)
|
||||
.WithMany("Ingredients")
|
||||
.HasForeignKey("MealId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.MealCategory", "Category")
|
||||
.WithMany("Meals")
|
||||
.HasForeignKey("MealCategoryId");
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.PizzaOrder", "PizzaOrder")
|
||||
.WithMany()
|
||||
.HasForeignKey("PizzaOrderId");
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("PizzaOrder");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.StoredPushSubscription", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.UserPreferences", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", "User")
|
||||
.WithOne("Preferences")
|
||||
.HasForeignKey("Aberwyn.Models.UserPreferences", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
@@ -501,6 +817,12 @@ namespace Aberwyn.Migrations
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Navigation("Preferences")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
@@ -510,6 +832,16 @@ namespace Aberwyn.Migrations
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.Navigation("Ingredients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.MealCategory", b =>
|
||||
{
|
||||
b.Navigation("Meals");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddPaymentStatusToBudgetItem : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "PaymentStatus",
|
||||
table: "BudgetItems",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DefaultPaymentStatus",
|
||||
table: "BudgetItemDefinitions",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PaymentStatus",
|
||||
table: "BudgetItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DefaultPaymentStatus",
|
||||
table: "BudgetItemDefinitions");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250526121643_AddBudgetDefinitions")]
|
||||
partial class AddBudgetDefinitions
|
||||
[Migration("20250624150426_AddIsPublishedToMeals")]
|
||||
partial class AddIsPublishedToMeals
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -152,7 +152,7 @@ namespace Aberwyn.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetCategoryDefinition");
|
||||
b.ToTable("BudgetCategoryDefinitions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
@@ -183,6 +183,9 @@ namespace Aberwyn.Migrations
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("PaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
@@ -201,6 +204,9 @@ namespace Aberwyn.Migrations
|
||||
b.Property<string>("DefaultCategory")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("DefaultPaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
@@ -213,7 +219,7 @@ namespace Aberwyn.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetItemDefinition");
|
||||
b.ToTable("BudgetItemDefinitions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
@@ -236,6 +242,131 @@ namespace Aberwyn.Migrations
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Ingredient", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Item")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("MealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Quantity")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MealId");
|
||||
|
||||
b.ToTable("Ingredients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CarbType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<byte[]>("ImageData")
|
||||
.HasColumnType("longblob");
|
||||
|
||||
b.Property<string>("ImageMimeType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Instructions")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsAvailable")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsPublished")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int?>("MealCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ProteinType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RecipeUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<byte[]>("ThumbnailData")
|
||||
.HasColumnType("longblob");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MealCategoryId");
|
||||
|
||||
b.ToTable("Meals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.MealCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("DisplayOrder")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Icon")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("MealCategories");
|
||||
|
||||
b.HasData(
|
||||
new
|
||||
{
|
||||
Id = 1,
|
||||
Color = "#f97316",
|
||||
DisplayOrder = 1,
|
||||
Icon = "🍕",
|
||||
IsActive = true,
|
||||
Name = "Pizza",
|
||||
Slug = "pizza"
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -283,11 +414,144 @@ namespace Aberwyn.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("PizzaOrderId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PizzaOrderId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.StoredPushSubscription", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PushSubscriptions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.TodoTask", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("AssignedTo")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsArchived")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("TodoTasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.UserPreferences", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<bool>("NotifyBudget")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("NotifyMenu")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("NotifyPizza")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.ToTable("UserPreferences");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("BreakfastMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Cook")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("DayOfWeek")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("DinnerMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("LunchMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("WeekNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("WeeklyMenu", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
@@ -418,7 +682,7 @@ namespace Aberwyn.Migrations
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "BudgetItemDefinition")
|
||||
b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition")
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetCategoryDefinitionId");
|
||||
|
||||
@@ -430,12 +694,12 @@ namespace Aberwyn.Migrations
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
|
||||
b.Navigation("BudgetItemDefinition");
|
||||
b.Navigation("Definition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", null)
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
@@ -445,11 +709,66 @@ namespace Aberwyn.Migrations
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetItemDefinitionId");
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
|
||||
b.Navigation("BudgetItemDefinition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Ingredient", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.Meal", null)
|
||||
.WithMany("Ingredients")
|
||||
.HasForeignKey("MealId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.MealCategory", "Category")
|
||||
.WithMany("Meals")
|
||||
.HasForeignKey("MealCategoryId");
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.PizzaOrder", "PizzaOrder")
|
||||
.WithMany()
|
||||
.HasForeignKey("PizzaOrderId");
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("PizzaOrder");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.StoredPushSubscription", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.UserPreferences", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", "User")
|
||||
.WithOne("Preferences")
|
||||
.HasForeignKey("Aberwyn.Models.UserPreferences", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
@@ -501,6 +820,12 @@ namespace Aberwyn.Migrations
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Navigation("Preferences")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
@@ -510,6 +835,16 @@ namespace Aberwyn.Migrations
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.Navigation("Ingredients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.MealCategory", b =>
|
||||
{
|
||||
b.Navigation("Meals");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
26
Aberwyn/Migrations/20250624150426_AddIsPublishedToMeals.cs
Normal file
26
Aberwyn/Migrations/20250624150426_AddIsPublishedToMeals.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddIsPublishedToMeals : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsPublished",
|
||||
table: "Meals",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsPublished",
|
||||
table: "Meals");
|
||||
}
|
||||
}
|
||||
}
|
||||
949
Aberwyn/Migrations/20250630123620_AddRecipeLab.Designer.cs
generated
Normal file
949
Aberwyn/Migrations/20250630123620_AddRecipeLab.Designer.cs
generated
Normal file
@@ -0,0 +1,949 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250630123620_AddRecipeLab")]
|
||||
partial class AddRecipeLab
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.AppSetting", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("AppSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("BudgetCategoryDefinitionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryDefinitionId");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategoryDefinition", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetCategoryDefinitions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("BudgetItemDefinitionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("PaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.HasIndex("BudgetItemDefinitionId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItemDefinition", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("DefaultCategory")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("DefaultPaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetItemDefinitions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Ingredient", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Item")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("MealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Quantity")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MealId");
|
||||
|
||||
b.ToTable("Ingredients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CarbType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<byte[]>("ImageData")
|
||||
.HasColumnType("longblob");
|
||||
|
||||
b.Property<string>("ImageMimeType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Instructions")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsAvailable")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsPublished")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int?>("MealCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ProteinType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RecipeUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<byte[]>("ThumbnailData")
|
||||
.HasColumnType("longblob");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MealCategoryId");
|
||||
|
||||
b.ToTable("Meals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.MealCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("DisplayOrder")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Icon")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("MealCategories");
|
||||
|
||||
b.HasData(
|
||||
new
|
||||
{
|
||||
Id = 1,
|
||||
Color = "#f97316",
|
||||
DisplayOrder = 1,
|
||||
Icon = "🍕",
|
||||
IsActive = true,
|
||||
Name = "Pizza",
|
||||
Slug = "pizza"
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CustomerName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("IngredientsJson")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("OrderedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("PizzaName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PizzaOrders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("PizzaOrderId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PizzaOrderId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.RecipeLabEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("BaseMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Category")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Inspiration")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("Rating")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TestedBy")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BaseMealId");
|
||||
|
||||
b.ToTable("RecipeLabEntries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.RecipeLabVersion", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Ingredients")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Instructions")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("RecipeLabEntryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ResultNotes")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("VersionLabel")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RecipeLabEntryId");
|
||||
|
||||
b.ToTable("RecipeLabVersions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.StoredPushSubscription", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PushSubscriptions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.TodoTask", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("AssignedTo")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsArchived")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("TodoTasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.UserPreferences", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<bool>("NotifyBudget")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("NotifyMenu")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("NotifyPizza")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.ToTable("UserPreferences");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("BreakfastMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Cook")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("DayOfWeek")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("DinnerMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("LunchMealId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("WeekNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("WeeklyMenu", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition")
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetCategoryDefinitionId");
|
||||
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
|
||||
b.Navigation("Definition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", null)
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.BudgetItemDefinition", "BudgetItemDefinition")
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetItemDefinitionId");
|
||||
|
||||
b.Navigation("BudgetItemDefinition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Ingredient", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.Meal", null)
|
||||
.WithMany("Ingredients")
|
||||
.HasForeignKey("MealId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.MealCategory", "Category")
|
||||
.WithMany("Meals")
|
||||
.HasForeignKey("MealCategoryId");
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.PizzaOrder", "PizzaOrder")
|
||||
.WithMany()
|
||||
.HasForeignKey("PizzaOrderId");
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("PizzaOrder");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.RecipeLabEntry", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.Meal", "BaseMeal")
|
||||
.WithMany()
|
||||
.HasForeignKey("BaseMealId");
|
||||
|
||||
b.Navigation("BaseMeal");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.RecipeLabVersion", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.RecipeLabEntry", "Entry")
|
||||
.WithMany("Versions")
|
||||
.HasForeignKey("RecipeLabEntryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Entry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.StoredPushSubscription", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.UserPreferences", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", "User")
|
||||
.WithOne("Preferences")
|
||||
.HasForeignKey("Aberwyn.Models.UserPreferences", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Navigation("Preferences")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.Meal", b =>
|
||||
{
|
||||
b.Navigation("Ingredients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.MealCategory", b =>
|
||||
{
|
||||
b.Navigation("Meals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.RecipeLabEntry", b =>
|
||||
{
|
||||
b.Navigation("Versions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
95
Aberwyn/Migrations/20250630123620_AddRecipeLab.cs
Normal file
95
Aberwyn/Migrations/20250630123620_AddRecipeLab.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddRecipeLab : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "RecipeLabEntries",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Title = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Category = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Inspiration = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
BaseMealId = table.Column<int>(type: "int", nullable: true),
|
||||
Notes = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Rating = table.Column<int>(type: "int", nullable: true),
|
||||
TestedBy = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Tags = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_RecipeLabEntries", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_RecipeLabEntries_Meals_BaseMealId",
|
||||
column: x => x.BaseMealId,
|
||||
principalTable: "Meals",
|
||||
principalColumn: "Id");
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "RecipeLabVersions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
RecipeLabEntryId = table.Column<int>(type: "int", nullable: false),
|
||||
VersionLabel = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Ingredients = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Instructions = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ResultNotes = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_RecipeLabVersions", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_RecipeLabVersions_RecipeLabEntries_RecipeLabEntryId",
|
||||
column: x => x.RecipeLabEntryId,
|
||||
principalTable: "RecipeLabEntries",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_RecipeLabEntries_BaseMealId",
|
||||
table: "RecipeLabEntries",
|
||||
column: "BaseMealId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_RecipeLabVersions_RecipeLabEntryId",
|
||||
table: "RecipeLabVersions",
|
||||
column: "RecipeLabEntryId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "RecipeLabVersions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "RecipeLabEntries");
|
||||
}
|
||||
}
|
||||
}
|
||||
1026
Aberwyn/Migrations/20250630133813_AddLabIngredientModel.Designer.cs
generated
Normal file
1026
Aberwyn/Migrations/20250630133813_AddLabIngredientModel.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
80
Aberwyn/Migrations/20250630133813_AddLabIngredientModel.cs
Normal file
80
Aberwyn/Migrations/20250630133813_AddLabIngredientModel.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddLabIngredientModel : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LabIngredients",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
RecipeLabEntryId = table.Column<int>(type: "int", nullable: false),
|
||||
Quantity = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Item = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LabIngredients", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_LabIngredients_RecipeLabEntries_RecipeLabEntryId",
|
||||
column: x => x.RecipeLabEntryId,
|
||||
principalTable: "RecipeLabEntries",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LabVersionIngredients",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
RecipeLabVersionId = table.Column<int>(type: "int", nullable: false),
|
||||
Quantity = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Item = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LabVersionIngredients", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_LabVersionIngredients_RecipeLabVersions_RecipeLabVersionId",
|
||||
column: x => x.RecipeLabVersionId,
|
||||
principalTable: "RecipeLabVersions",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LabIngredients_RecipeLabEntryId",
|
||||
table: "LabIngredients",
|
||||
column: "RecipeLabEntryId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LabVersionIngredients_RecipeLabVersionId",
|
||||
table: "LabVersionIngredients",
|
||||
column: "RecipeLabVersionId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "LabIngredients");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LabVersionIngredients");
|
||||
}
|
||||
}
|
||||
}
|
||||
1023
Aberwyn/Migrations/20250630141059_AddRecipeLabModels.Designer.cs
generated
Normal file
1023
Aberwyn/Migrations/20250630141059_AddRecipeLabModels.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
Aberwyn/Migrations/20250630141059_AddRecipeLabModels.cs
Normal file
26
Aberwyn/Migrations/20250630141059_AddRecipeLabModels.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddRecipeLabModels : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Ingredients",
|
||||
table: "RecipeLabVersions");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Ingredients",
|
||||
table: "RecipeLabVersions",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
}
|
||||
}
|
||||
1060
Aberwyn/Migrations/20250707125951_AddMealRating.Designer.cs
generated
Normal file
1060
Aberwyn/Migrations/20250707125951_AddMealRating.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,37 +6,44 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddPizzaOrderTable : Migration
|
||||
public partial class AddMealRating : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PizzaOrders",
|
||||
name: "MealRatings",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
CustomerName = table.Column<string>(type: "longtext", nullable: false)
|
||||
MealId = table.Column<int>(type: "int", nullable: false),
|
||||
UserId = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PizzaName = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IngredientsJson = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Status = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
OrderedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
Rating = table.Column<int>(type: "int", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PizzaOrders", x => x.Id);
|
||||
table.PrimaryKey("PK_MealRatings", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_MealRatings_Meals_MealId",
|
||||
column: x => x.MealId,
|
||||
principalTable: "Meals",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_MealRatings_MealId",
|
||||
table: "MealRatings",
|
||||
column: "MealId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PizzaOrders");
|
||||
name: "MealRatings");
|
||||
}
|
||||
}
|
||||
}
|
||||
1060
Aberwyn/Migrations/20250708102137_AddNameToBudgetPeriod.Designer.cs
generated
Normal file
1060
Aberwyn/Migrations/20250708102137_AddNameToBudgetPeriod.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddMealImageData : Migration
|
||||
public partial class AddNameToBudgetPeriod : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
1063
Aberwyn/Migrations/20250708102224_AddNameToBudgetPeriod2.Designer.cs
generated
Normal file
1063
Aberwyn/Migrations/20250708102224_AddNameToBudgetPeriod2.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
Aberwyn/Migrations/20250708102224_AddNameToBudgetPeriod2.cs
Normal file
26
Aberwyn/Migrations/20250708102224_AddNameToBudgetPeriod2.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddNameToBudgetPeriod2 : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Name",
|
||||
table: "BudgetPeriods",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Name",
|
||||
table: "BudgetPeriods");
|
||||
}
|
||||
}
|
||||
}
|
||||
1063
Aberwyn/Migrations/20250708104331_MakeYearMonthNullable.Designer.cs
generated
Normal file
1063
Aberwyn/Migrations/20250708104331_MakeYearMonthNullable.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
51
Aberwyn/Migrations/20250708104331_MakeYearMonthNullable.cs
Normal file
51
Aberwyn/Migrations/20250708104331_MakeYearMonthNullable.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class MakeYearMonthNullable : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "Year",
|
||||
table: "BudgetPeriods",
|
||||
type: "int",
|
||||
nullable: true,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "Month",
|
||||
table: "BudgetPeriods",
|
||||
type: "int",
|
||||
nullable: true,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "Year",
|
||||
table: "BudgetPeriods",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "Month",
|
||||
table: "BudgetPeriods",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldNullable: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
1177
Aberwyn/Migrations/20250805202224_AddTorrentTables.Designer.cs
generated
Normal file
1177
Aberwyn/Migrations/20250805202224_AddTorrentTables.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
105
Aberwyn/Migrations/20250805202224_AddTorrentTables.cs
Normal file
105
Aberwyn/Migrations/20250805202224_AddTorrentTables.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddTorrentTables : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "DownloadRules",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
KeywordFilter = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CategoryFilter = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
MinSeeders = table.Column<int>(type: "int", nullable: false),
|
||||
MaxSize = table.Column<long>(type: "bigint", nullable: false),
|
||||
AutoDownload = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_DownloadRules", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "RssFeeds",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Url = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
LastChecked = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_RssFeeds", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TorrentItems",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Title = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
MagnetLink = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
InfoHash = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PublishDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
Size = table.Column<long>(type: "bigint", nullable: false),
|
||||
Seeders = table.Column<int>(type: "int", nullable: false),
|
||||
Leechers = table.Column<int>(type: "int", nullable: false),
|
||||
Status = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Category = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
RssSource = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Description = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
TorrentUrl = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_TorrentItems", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TorrentItems_InfoHash",
|
||||
table: "TorrentItems",
|
||||
column: "InfoHash",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "DownloadRules");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "RssFeeds");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "TorrentItems");
|
||||
}
|
||||
}
|
||||
}
|
||||
1195
Aberwyn/Migrations/20250806065232_AddTorrentTablesv2.Designer.cs
generated
Normal file
1195
Aberwyn/Migrations/20250806065232_AddTorrentTablesv2.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
69
Aberwyn/Migrations/20250806065232_AddTorrentTablesv2.cs
Normal file
69
Aberwyn/Migrations/20250806065232_AddTorrentTablesv2.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddTorrentTablesv2 : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Completed",
|
||||
table: "TorrentItems",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "DownloadKey",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "MovieName",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Token",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Year",
|
||||
table: "TorrentItems",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Completed",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DownloadKey",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "MovieName",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Token",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Year",
|
||||
table: "TorrentItems");
|
||||
}
|
||||
}
|
||||
}
|
||||
1188
Aberwyn/Migrations/20250806072233_MakeTorrentFieldsNullable.Designer.cs
generated
Normal file
1188
Aberwyn/Migrations/20250806072233_MakeTorrentFieldsNullable.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
211
Aberwyn/Migrations/20250806072233_MakeTorrentFieldsNullable.cs
Normal file
211
Aberwyn/Migrations/20250806072233_MakeTorrentFieldsNullable.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class MakeTorrentFieldsNullable : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "TorrentUrl",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext")
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Token",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext")
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "MovieName",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext")
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "MagnetLink",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext")
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "InfoHash",
|
||||
table: "TorrentItems",
|
||||
type: "varchar(255)",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "varchar(255)")
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "DownloadKey",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext")
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Category",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext")
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.UpdateData(
|
||||
table: "TorrentItems",
|
||||
keyColumn: "TorrentUrl",
|
||||
keyValue: null,
|
||||
column: "TorrentUrl",
|
||||
value: "");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "TorrentUrl",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext",
|
||||
oldNullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "TorrentItems",
|
||||
keyColumn: "Token",
|
||||
keyValue: null,
|
||||
column: "Token",
|
||||
value: "");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Token",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext",
|
||||
oldNullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "TorrentItems",
|
||||
keyColumn: "MovieName",
|
||||
keyValue: null,
|
||||
column: "MovieName",
|
||||
value: "");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "MovieName",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext",
|
||||
oldNullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "TorrentItems",
|
||||
keyColumn: "MagnetLink",
|
||||
keyValue: null,
|
||||
column: "MagnetLink",
|
||||
value: "");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "MagnetLink",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext",
|
||||
oldNullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "TorrentItems",
|
||||
keyColumn: "InfoHash",
|
||||
keyValue: null,
|
||||
column: "InfoHash",
|
||||
value: "");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "InfoHash",
|
||||
table: "TorrentItems",
|
||||
type: "varchar(255)",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "varchar(255)",
|
||||
oldNullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "TorrentItems",
|
||||
keyColumn: "DownloadKey",
|
||||
keyValue: null,
|
||||
column: "DownloadKey",
|
||||
value: "");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "DownloadKey",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext",
|
||||
oldNullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "TorrentItems",
|
||||
keyColumn: "Category",
|
||||
keyValue: null,
|
||||
column: "Category",
|
||||
value: "");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Category",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext",
|
||||
oldNullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
}
|
||||
}
|
||||
1237
Aberwyn/Migrations/20250819221425_AddMovieMetadataToTorrentItem.Designer.cs
generated
Normal file
1237
Aberwyn/Migrations/20250819221425_AddMovieMetadataToTorrentItem.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,125 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddMovieMetadataToTorrentItem : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_Actors",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_Director",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_Genre",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_ImdbID",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_ImdbRating",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_Plot",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_Poster",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_Runtime",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_Title",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_Year",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_Actors",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_Director",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_Genre",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_ImdbID",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_ImdbRating",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_Plot",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_Poster",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_Runtime",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_Title",
|
||||
table: "TorrentItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_Year",
|
||||
table: "TorrentItems");
|
||||
}
|
||||
}
|
||||
}
|
||||
1240
Aberwyn/Migrations/20250820133435_AddProvidersToMovieMetadata.Designer.cs
generated
Normal file
1240
Aberwyn/Migrations/20250820133435_AddProvidersToMovieMetadata.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddProvidersToMovieMetadata : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata_Providers",
|
||||
table: "TorrentItems",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata_Providers",
|
||||
table: "TorrentItems");
|
||||
}
|
||||
}
|
||||
}
|
||||
1261
Aberwyn/Migrations/20250824172213_AddUserTorrentSeen.Designer.cs
generated
Normal file
1261
Aberwyn/Migrations/20250824172213_AddUserTorrentSeen.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,26 +6,24 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class CreateTodoTaskTable : Migration
|
||||
public partial class AddUserTorrentSeen : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TodoTasks",
|
||||
name: "UserTorrentSeen",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Title = table.Column<string>(type: "longtext", nullable: false)
|
||||
UserId = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Status = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
Priority = table.Column<int>(type: "int", nullable: false)
|
||||
TorrentId = table.Column<int>(type: "int", nullable: false),
|
||||
SeenDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_TodoTasks", x => x.Id);
|
||||
table.PrimaryKey("PK_UserTorrentSeen", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
@@ -33,7 +31,7 @@ namespace Aberwyn.Migrations
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "TodoTasks");
|
||||
name: "UserTorrentSeen");
|
||||
}
|
||||
}
|
||||
}
|
||||
1262
Aberwyn/Migrations/20250824172938_AddUserTorrentSeenv2.Designer.cs
generated
Normal file
1262
Aberwyn/Migrations/20250824172938_AddUserTorrentSeenv2.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
37
Aberwyn/Migrations/20250824172938_AddUserTorrentSeenv2.cs
Normal file
37
Aberwyn/Migrations/20250824172938_AddUserTorrentSeenv2.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddUserTorrentSeenv2 : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TorrentId",
|
||||
table: "UserTorrentSeen");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "InfoHash",
|
||||
table: "UserTorrentSeen",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "InfoHash",
|
||||
table: "UserTorrentSeen");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "TorrentId",
|
||||
table: "UserTorrentSeen",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
1304
Aberwyn/Migrations/20250903130637_AddDoughPlans.Designer.cs
generated
Normal file
1304
Aberwyn/Migrations/20250903130637_AddDoughPlans.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user