Skip to content

Commit 7a78b59

Browse files
committed
Billing v1
1 parent 9413364 commit 7a78b59

43 files changed

Lines changed: 5993 additions & 70 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

EatSomewhere/Data/Assembly.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ public class Assembly
1515
public string Name { get; set; }
1616
public string Description { get; set; }
1717
public List<User> Admins { get; set; }= new();
18-
[JsonIgnore] public List<Food> Foods { get; set; } = new();
19-
[JsonIgnore] public List<FoodEntry> FoodEntries { get; set; }
18+
[JsonIgnore] public IEnumerable<Food> Foods { get; set; }
19+
[JsonIgnore] public IEnumerable<FoodEntry> FoodEntries { get; set; }
2020

21-
[JsonIgnore] public List<Ingredient> Ingredients = new();
21+
[JsonIgnore] public IEnumerable<Ingredient> Ingredients { get; set; }
2222
}

EatSomewhere/Data/Bill.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.ComponentModel.DataAnnotations.Schema;
2+
using System.Text.Json.Serialization;
3+
using EatSomewhere.Users;
4+
5+
namespace EatSomewhere.Data;
6+
7+
public class Bill
8+
{
9+
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
10+
public string? Id { get; set; }
11+
/// <summary>
12+
/// Person which ows money
13+
/// </summary>
14+
public User? User { get; set; }
15+
/// <summary>
16+
/// The person which receives the money
17+
/// </summary>
18+
public User Recipient { get; set; }
19+
[JsonIgnore]
20+
public FoodEntry FoodEntry { get; set; }
21+
public int Amount { get; set; }
22+
}

EatSomewhere/Data/BillManager.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using EatSomewhere.Database;
2+
using EatSomewhere.Users;
3+
4+
namespace EatSomewhere.Data;
5+
6+
public class BillManager
7+
{
8+
public static List<Bill> GetTotalBills(User user, string assemblyId, bool first = true)
9+
{
10+
using var d = new AppDbContext();
11+
d.Attach(user);
12+
List<Bill> total = d.Bills
13+
.Where(x => x.User == user && x.FoodEntry.Assembly.Id == assemblyId)
14+
.GroupBy(x => x.Recipient)
15+
.Select(x => new Bill
16+
{
17+
Amount = x.Sum(y => y.Amount),
18+
Recipient = x.Key,
19+
User = user,
20+
FoodEntry = x.First().FoodEntry,
21+
}).ToList();
22+
if (first)
23+
{
24+
foreach (var bill in total)
25+
{
26+
Bill? theirBill = d.Bills
27+
.Where(x => x.User == bill.Recipient && x.Recipient == user && x.FoodEntry.Assembly.Id == assemblyId)
28+
.GroupBy(x => x.Recipient)
29+
.Select(x => new Bill
30+
{
31+
Amount = x.Sum(y => y.Amount),
32+
Recipient = x.Key,
33+
User = user,
34+
FoodEntry = x.First().FoodEntry,
35+
}).ToList().FirstOrDefault();
36+
bill.Amount -= theirBill?.Amount ?? 0;
37+
}
38+
}
39+
40+
return total;
41+
}
42+
}

EatSomewhere/Data/FoodEntry.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,27 @@ public class FoodEntry
99
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
1010
public string Id { get; set; }
1111
public DateTime Date { get; set; }
12-
public string Comment { get; set; }
12+
public string? Comment { get; set; }
1313
public Food Food { get; set; }
1414
public int EstimatedCost => (int)double.Ceiling(Food.EstimatedCost / (double)Food.PersonCount * PersonCount);
1515
public int Cost { get; set; }
1616

1717
public int CostPerPerson => (int)double.Ceiling(Cost / (double)PersonCount);
1818

19-
public int PersonCount => Participants.Sum(x => x.AdditionalPersons + 1);
19+
public int PersonCount => Participants.Sum(x => x.Persons);
2020
public List<FoodParticipant> Participants { get; set; }
2121
public User PayedBy { get; set; }
22-
[JsonIgnore]
2322
public Assembly Assembly { get; set; }
24-
2523
public User CreatedBy { get; set; }
24+
public List<Bill> Bills { get; set; }
25+
26+
public List<Bill> CalculateBills()
27+
{
28+
return Participants.Select(x => new Bill
29+
{
30+
User = x.User ?? null,
31+
Amount = CostPerPerson * x.Persons,
32+
Recipient = PayedBy,
33+
}).ToList();
34+
}
2635
}

EatSomewhere/Data/FoodParticipant.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ namespace EatSomewhere.Data;
77
public class FoodParticipant
88
{
99
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
10-
public string Id;
11-
public User User;
12-
public int AdditionalPersons;
10+
public string Id { get; set; }
11+
public User? User { get; set; }
12+
public int AdditionalPersons { get; set; }
1313
[JsonIgnore]
14-
public Food Food;
14+
public FoodEntry FoodEntry { get; set; }
15+
[NotMapped]
1516
[JsonIgnore]
16-
public Assembly Assembly;
17+
public int Persons => AdditionalPersons + 1;
1718
}

EatSomewhere/Database/AppDbContext.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class AppDbContext : DbContext
1313
public DbSet<IngredientEntry> IngredientEntries { get; set; }
1414
public DbSet<Food> Foods { get; set; }
1515
public DbSet<FoodEntry> FoodEntries { get; set; }
16+
public DbSet<Bill> Bills { get; set; }
1617

1718
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
1819
{
@@ -36,6 +37,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
3637
modelBuilder.Entity<Assembly>().HasMany(x => x.Pending).WithMany();
3738
modelBuilder.Entity<Assembly>().HasMany(x => x.Ingredients).WithOne(x => x.Assembly);
3839
modelBuilder.Entity<Assembly>().HasMany(x => x.Foods).WithOne(x => x.Assembly);
40+
modelBuilder.Entity<Assembly>().HasMany(x => x.FoodEntries).WithOne(x => x.Assembly);
3941

4042
modelBuilder.Entity<Food>().HasKey(x => x.Id);
4143
modelBuilder.Entity<Food>().Navigation(x => x.CreatedBy).AutoInclude();
@@ -48,7 +50,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
4850
modelBuilder.Entity<FoodEntry>().HasKey(x => x.Id);
4951
modelBuilder.Entity<FoodEntry>().Navigation(x => x.Food).AutoInclude();
5052
modelBuilder.Entity<FoodEntry>().Navigation(x => x.Participants).AutoInclude();
51-
modelBuilder.Entity<FoodEntry>().HasMany(x => x.Participants).WithMany();
53+
modelBuilder.Entity<FoodEntry>().HasMany(x => x.Participants).WithOne(x => x.FoodEntry);
5254
modelBuilder.Entity<FoodEntry>().Navigation(x => x.PayedBy).AutoInclude();
5355
modelBuilder.Entity<FoodEntry>().Navigation(x => x.CreatedBy).AutoInclude();
5456
modelBuilder.Entity<FoodEntry>().HasOne(x => x.Assembly).WithMany(x => x.FoodEntries);
@@ -62,6 +64,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
6264
modelBuilder.Entity<IngredientEntry>().HasKey(x => x.Id);
6365
modelBuilder.Entity<IngredientEntry>().Navigation(x => x.Ingredient).AutoInclude();
6466
modelBuilder.Entity<IngredientEntry>().HasOne(x => x.Ingredient).WithMany(x=> x.IngredientEntries);
67+
68+
modelBuilder.Entity<Bill>().HasOne(x => x.Recipient).WithMany(x => x.ReceivedBills);
69+
modelBuilder.Entity<Bill>().HasOne(x => x.User).WithMany(x => x.Bills);
70+
modelBuilder.Entity<Bill>().HasOne(x => x.FoodEntry).WithMany(x => x.Bills);
6571

6672
modelBuilder.Entity<Tag>().HasKey(x => x.Id);
6773
}

EatSomewhere/Manager/FoodManager.cs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ public static List<FoodEntry> GetFoodEntries(User user, string assemblyId, int s
1515
d.Attach(user);
1616
Assembly? assembly = d.Assemblies.Where(x => x.Id == assemblyId)
1717
.Include(x => x.Users)
18-
.Include(x => x.FoodEntries)
19-
.ThenInclude(x => x.Participants)
20-
.ThenInclude(x => x.User)
2118
.FirstOrDefault();
2219
if (assembly == null)
2320
{
@@ -27,7 +24,9 @@ public static List<FoodEntry> GetFoodEntries(User user, string assemblyId, int s
2724
{
2825
return new List<FoodEntry>();
2926
}
30-
return assembly.FoodEntries
27+
return d.FoodEntries.Where(x => x.Assembly.Id == assemblyId)
28+
.Include(x => x.Participants)
29+
.Include(x => x.Bills)
3130
.OrderByDescending(x => x.Date)
3231
.Skip(skip)
3332
.Take(count)
@@ -150,7 +149,10 @@ public static ApiResponse<FoodEntry> CreateFoodEntry(User user, FoodEntry food)
150149
{
151150
using var d = new AppDbContext();
152151
d.Attach(user);
153-
Assembly? a = d.Assemblies.FirstOrDefault(x => x.Id == food.Assembly.Id);
152+
Assembly? a = d.Assemblies.Where(x => x.Id == food.Assembly.Id)
153+
.Include(x => x.Users)
154+
.Include(x => x.Admins)
155+
.FirstOrDefault();
154156
if (a == null)
155157
{
156158
return new ApiResponse<FoodEntry>
@@ -162,7 +164,9 @@ public static ApiResponse<FoodEntry> CreateFoodEntry(User user, FoodEntry food)
162164

163165
foreach (FoodParticipant p in food.Participants)
164166
{
165-
User? foundUser = a.Users.FirstOrDefault(x => x.Id == p.User.Id);
167+
User? foundUser = a.Users.FirstOrDefault(x => x.Id == p.User?.Id);
168+
if (p.AdditionalPersons < 0) p.AdditionalPersons = 0;
169+
p.FoodEntry = food;
166170
if (foundUser == null)
167171
{
168172
return new ApiResponse<FoodEntry>
@@ -196,9 +200,10 @@ public static ApiResponse<FoodEntry> CreateFoodEntry(User user, FoodEntry food)
196200
food.PayedBy = foundPayedBy;
197201
food.CreatedBy = user;
198202
food.Assembly = a;
203+
food.Bills = food.CalculateBills();
199204

200205
// Check if food already exists and if yes, update it instead of creating it
201-
FoodEntry? existingEntry = d.FoodEntries.FirstOrDefault(x => x.Id == food.Id);
206+
FoodEntry? existingEntry = d.FoodEntries.Where(x => x.Id == food.Id).Include(x => x.Bills).FirstOrDefault();
202207
if (existingEntry != null)
203208
{
204209
if (existingEntry.CreatedBy.Id != user.Id && !CanAdministrateAssembly(user, a))
@@ -209,6 +214,12 @@ public static ApiResponse<FoodEntry> CreateFoodEntry(User user, FoodEntry food)
209214
Error = "You are not allowed to edit this food"
210215
};
211216
}
217+
// Remove all previous bills
218+
foreach (Bill bill in existingEntry.Bills)
219+
{
220+
d.Remove(bill);
221+
}
222+
existingEntry.Bills.Clear();
212223
// Replace existing database entry with new one
213224
existingEntry.Date = food.Date;
214225
existingEntry.Comment = food.Comment;
@@ -218,11 +229,16 @@ public static ApiResponse<FoodEntry> CreateFoodEntry(User user, FoodEntry food)
218229
existingEntry.PayedBy = food.PayedBy;
219230
existingEntry.Assembly = food.Assembly;
220231
existingEntry.CreatedBy = food.CreatedBy;
232+
existingEntry.Bills = food.Bills;
221233
}
222234
else
223235
{
224236
d.FoodEntries.Add(food);
225237
}
238+
239+
// All previous Bills are invalid now
240+
241+
226242

227243
d.SaveChanges();
228244

0 commit comments

Comments
 (0)