This commit is contained in:
@@ -61,7 +61,8 @@ namespace Aberwyn.Controllers
|
||||
Amount = i.Amount,
|
||||
IsExpense = i.IsExpense,
|
||||
IncludeInSummary = i.IncludeInSummary,
|
||||
BudgetItemDefinitionId = i.BudgetItemDefinitionId
|
||||
BudgetItemDefinitionId = i.BudgetItemDefinitionId,
|
||||
PaymentStatus = i.PaymentStatus
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
};
|
||||
@@ -73,6 +74,21 @@ namespace Aberwyn.Controllers
|
||||
return StatusCode(500, $"Fel: {ex.Message} \n{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
[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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
848
Aberwyn/Migrations/20250618203117_AddPaymentStatusToBudgetItem.Designer.cs
generated
Normal file
848
Aberwyn/Migrations/20250618203117_AddPaymentStatusToBudgetItem.Designer.cs
generated
Normal file
@@ -0,0 +1,848 @@
|
||||
// <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("20250618203117_AddPaymentStatusToBudgetItem")]
|
||||
partial class AddPaymentStatusToBudgetItem
|
||||
{
|
||||
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<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.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.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");
|
||||
});
|
||||
#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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,6 +181,9 @@ namespace Aberwyn.Migrations
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("PaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
@@ -199,6 +202,9 @@ namespace Aberwyn.Migrations
|
||||
b.Property<string>("DefaultCategory")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("DefaultPaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
@@ -688,7 +694,7 @@ namespace Aberwyn.Migrations
|
||||
|
||||
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)
|
||||
@@ -698,8 +704,6 @@ namespace Aberwyn.Migrations
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetItemDefinitionId");
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
|
||||
b.Navigation("BudgetItemDefinition");
|
||||
});
|
||||
|
||||
|
||||
@@ -47,7 +47,16 @@ namespace Aberwyn.Models
|
||||
|
||||
[JsonIgnore]
|
||||
[ValidateNever]
|
||||
public BudgetCategory BudgetCategory { get; set; }
|
||||
|
||||
|
||||
public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.None;
|
||||
|
||||
}
|
||||
public enum PaymentStatus
|
||||
{
|
||||
None = 0,
|
||||
Due = 1,
|
||||
Paid = 2
|
||||
}
|
||||
// DTOs/BudgetDto.cs
|
||||
public class BudgetDto
|
||||
@@ -84,6 +93,7 @@ namespace Aberwyn.Models
|
||||
|
||||
public bool IsExpense { get; set; }
|
||||
public bool IncludeInSummary { get; set; }
|
||||
public PaymentStatus PaymentStatus { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +101,11 @@ namespace Aberwyn.Models
|
||||
{
|
||||
public List<BudgetItem> BudgetItems { get; set; } = new List<BudgetItem>();
|
||||
}
|
||||
public class PaymentStatusUpdateDto
|
||||
{
|
||||
public int ItemId { get; set; }
|
||||
public PaymentStatus Status { get; set; }
|
||||
}
|
||||
|
||||
public class BudgetItemDefinition
|
||||
{
|
||||
@@ -99,6 +114,8 @@ namespace Aberwyn.Models
|
||||
public string? DefaultCategory { get; set; } // valfritt, kan föreslå "Bilar"
|
||||
public bool IsExpense { get; set; }
|
||||
public bool IncludeInSummary { get; set; }
|
||||
public PaymentStatus? DefaultPaymentStatus { get; set; }
|
||||
|
||||
}
|
||||
public class BudgetCategoryDefinition
|
||||
{
|
||||
|
||||
@@ -125,7 +125,12 @@
|
||||
item="item"
|
||||
category="cat"
|
||||
on-item-drop="handleItemDrop(event, data, cat)"
|
||||
ng-class="{ dragging: dragInProgress && draggedItemId === item.id }">
|
||||
ng-class="{
|
||||
dragging: dragInProgress && draggedItemId === item.id,
|
||||
due: item.paymentStatus === 1,
|
||||
paid: item.paymentStatus === 2
|
||||
}"
|
||||
ng-click="ctrlClick($event, item)">
|
||||
<i class="fa fa-grip-lines drag-handle"
|
||||
ng-show="cat.editing"
|
||||
style="opacity: 0.5; padding-right: 6px; cursor: grab;"></i>
|
||||
|
||||
@@ -242,7 +242,35 @@ body {
|
||||
text-align: right;
|
||||
font-weight: 600;
|
||||
}
|
||||
@keyframes fadeRed {
|
||||
0% {
|
||||
color: rgb(200, 50, 50);
|
||||
}
|
||||
|
||||
100% {
|
||||
color: rgb(80, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeGreen {
|
||||
0% {
|
||||
color: rgb(50, 200, 50);
|
||||
}
|
||||
|
||||
100% {
|
||||
color: rgb(0, 80, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.item-row.due {
|
||||
animation: fadeRed 0.2s ease-in-out;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
.item-row.paid {
|
||||
animation: fadeGreen 0.2s ease-in-out;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
|
||||
.icon-button {
|
||||
|
||||
@@ -85,11 +85,32 @@ app.controller('BudgetController', function ($scope, $http) {
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('click', function () {
|
||||
document.addEventListener('click', function () {
|
||||
$scope.$apply(() => {
|
||||
$scope.menuOpen = false;
|
||||
});
|
||||
});
|
||||
$scope.ctrlClick = function (event, item) {
|
||||
if (!event.ctrlKey) return;
|
||||
|
||||
const current = typeof item.paymentStatus === 'number' && !isNaN(item.paymentStatus)
|
||||
? item.paymentStatus
|
||||
: 0;
|
||||
|
||||
item.paymentStatus = (current + 1) % 3;
|
||||
|
||||
$http.put("/api/budget/updatePaymentStatus", {
|
||||
itemId: item.id,
|
||||
status: item.paymentStatus
|
||||
}).then(() => {
|
||||
$scope.showToast("Betalstatus uppdaterad");
|
||||
}).catch(err => {
|
||||
console.error("Fel vid uppdatering:", err);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
$scope.showToast = function (message, isError = false) {
|
||||
const toast = document.createElement("div");
|
||||
@@ -128,7 +149,8 @@ app.controller('BudgetController', function ($scope, $http) {
|
||||
includeInSummary: item.IncludeInSummary === true,
|
||||
order: item.Order ?? index,
|
||||
budgetItemDefinitionId: item.BudgetItemDefinitionId,
|
||||
definitionName: definition?.Name || null
|
||||
definitionName: definition?.Name || null,
|
||||
paymentStatus: item.PaymentStatus
|
||||
};
|
||||
}).sort((a, b) => a.order - b.order)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user