profileShare

rasmusjy / splitapp-backend-microservices

Read-only snapshot

No repository description.

main default branch 501 files Expires Sep 13, 2026, 9:06 AM
AppDataInit.cs 6,697 bytes
1 using SplitApp.Modules.Expenses.Domain.Entities;
2 using SplitApp.Modules.Expenses.Domain.Enums;
3 using SplitApp.Modules.Expenses.Infrastructure.Persistence;
4 using SplitApp.Modules.Trips.Domain.Entities;
5 using SplitApp.Modules.Trips.Domain.Enums;
6 using SplitApp.Modules.Trips.Infrastructure.Persistence;
7 using SplitApp.Shared.Kernel.Localization;
8 using SplitApp.WebApp.Application.UsersService;
9
10 namespace SplitApp.WebApp.Hosting;
11
12 public static class AppDataInit
13 {
14 public static void SeedExampleData(IServiceProvider services)
15 {
16 using var scope = services.CreateScope();
17 var usersClient = scope.ServiceProvider.GetRequiredService<IUsersServiceClient>();
18 var trips = scope.ServiceProvider.GetRequiredService<TripsDbContext>();
19 var expenses = scope.ServiceProvider.GetRequiredService<ExpensesDbContext>();
20
21 if (trips.Trips.Any()) return;
22
23 // Users live in the Users service now — fetch them via HTTP. The compose healthcheck
24 // gates webapp on users-service:service_healthy, so the seed users should already be
25 // present here. If the call times out, just skip example seeding (operator can rerun).
26 List<SplitApp.WebApp.Application.UsersService.Dtos.AdminUserListItem> allUsers;
27 try
28 {
29 allUsers = usersClient.ListUsersAsync().GetAwaiter().GetResult().ToList();
30 }
31 catch
32 {
33 return;
34 }
35
36 Guid IdOf(string email) => allUsers.FirstOrDefault(u =>
37 string.Equals(u.Email, email, StringComparison.OrdinalIgnoreCase))?.Id ?? Guid.Empty;
38
39 var admin = IdOf("admin@example.com");
40 var testUser = IdOf("user@example.com");
41 var alice = IdOf("alice@example.com");
42 var bob = IdOf("bob@example.com");
43 var charlie = IdOf("charlie@example.com");
44 var diana = IdOf("diana@example.com");
45
46 if (admin == Guid.Empty || testUser == Guid.Empty || alice == Guid.Empty
47 || bob == Guid.Empty || charlie == Guid.Empty || diana == Guid.Empty)
48 {
49 return;
50 }
51
52 var eur = expenses.Currencies.First(c => c.Code == "EUR").Id;
53 var usd = expenses.Currencies.First(c => c.Code == "USD").Id;
54 var gbp = expenses.Currencies.First(c => c.Code == "GBP").Id;
55
56 var now = DateTime.UtcNow;
57
58 var trip1 = new Trip
59 {
60 Name = "Barcelona Weekend",
61 Description = "A long weekend exploring Barcelona with friends",
62 Destination = "Barcelona, Spain",
63 StartDate = new DateTime(2026, 4, 10, 0, 0, 0, DateTimeKind.Utc),
64 EndDate = new DateTime(2026, 4, 13, 0, 0, 0, DateTimeKind.Utc),
65 Status = ETripStatus.Active,
66 DefaultCurrencyId = eur,
67 CreatedById = admin,
68 };
69 trips.Trips.Add(trip1);
70
71 trips.TripParticipants.AddRange(
72 new TripParticipant { TripId = trip1.Id, UserId = admin, Role = EParticipantRole.Organizer, JoinedAt = now.AddDays(-10), IsActive = true },
73 new TripParticipant { TripId = trip1.Id, UserId = alice, Role = EParticipantRole.Participant, JoinedAt = now.AddDays(-9), IsActive = true },
74 new TripParticipant { TripId = trip1.Id, UserId = bob, Role = EParticipantRole.Participant, JoinedAt = now.AddDays(-8), IsActive = true },
75 new TripParticipant { TripId = trip1.Id, UserId = charlie, Role = EParticipantRole.Participant, JoinedAt = now.AddDays(-7), IsActive = true });
76
77 var cat1Food = new BudgetCategory { TripId = trip1.Id, Name = Lang("Food & Drinks", "Toit ja joogid"), IconName = "cup-hot", PlannedAmount = 400m, DisplayOrder = 0 };
78 var cat1Transport = new BudgetCategory { TripId = trip1.Id, Name = Lang("Transport", "Transport"), IconName = "bus-front", PlannedAmount = 150m, DisplayOrder = 1 };
79 var cat1Activities = new BudgetCategory { TripId = trip1.Id, Name = Lang("Activities", "Tegevused"), IconName = "binoculars", PlannedAmount = 200m, DisplayOrder = 2 };
80 var cat1Accommodation = new BudgetCategory { TripId = trip1.Id, Name = Lang("Accommodation", "Majutus"), IconName = "house", PlannedAmount = 500m, DisplayOrder = 3 };
81 trips.BudgetCategories.AddRange(cat1Food, cat1Transport, cat1Activities, cat1Accommodation);
82
83 trips.SaveChanges();
84
85 // Slimmed seed: keep one trip with example expenses so the UX has data on first boot.
86 // The full phase-3 fixture is preserved in source history; truncated here to keep the
87 // post-extraction monolith boot path simple.
88 var trip1Members = new[] { admin, alice, bob, charlie };
89 var trip1Expenses = new (string desc, decimal amount, Guid paidBy, Guid? catId, DateTime date, ESplitMethod split)[]
90 {
91 ("Airbnb apartment (3 nights)", 480.00m, admin, cat1Accommodation.Id, now.AddDays(-5), ESplitMethod.EqualAll),
92 ("Airport taxi", 35.00m, alice, cat1Transport.Id, now.AddDays(-5), ESplitMethod.EqualAll),
93 ("Grocery shopping", 62.50m, bob, cat1Food.Id, now.AddDays(-4), ESplitMethod.EqualAll),
94 ("Sagrada Familia tickets", 104.00m, charlie, cat1Activities.Id, now.AddDays(-3), ESplitMethod.EqualAll),
95 };
96
97 foreach (var (desc, amount, paidBy, catId, date, split) in trip1Expenses)
98 {
99 var ex = new Expense
100 {
101 TripId = trip1.Id, PaidByUserId = paidBy, Amount = amount,
102 Description = desc, ExpenseDate = date, BudgetCategoryId = catId,
103 CurrencyId = eur, SplitMethod = split,
104 };
105 expenses.Expenses.Add(ex);
106 AddEqualSplits(expenses, ex, trip1Members);
107 }
108
109 expenses.SaveChanges();
110
111 _ = testUser; _ = diana; _ = usd; _ = gbp;
112 }
113
114 private static LangStr Lang(string en, string et)
115 {
116 var s = new LangStr(en, "en");
117 s["et"] = et;
118 return s;
119 }
120
121 private static void AddEqualSplits(ExpensesDbContext db, Expense expense, Guid[] memberIds)
122 {
123 var count = memberIds.Length;
124 var baseAmt = Math.Floor(expense.Amount / count * 100m) / 100m;
125 var remainderCents = (int)Math.Round((expense.Amount - baseAmt * count) * 100m);
126
127 for (var i = 0; i < count; i++)
128 {
129 var splitAmt = baseAmt + (i < remainderCents ? 0.01m : 0m);
130 db.ExpenseSplits.Add(new ExpenseSplit
131 {
132 ExpenseId = expense.Id,
133 UserId = memberIds[i],
134 Amount = splitAmt,
135 });
136 }
137 }
138 }
139