Skip to content

Commit 3f4e028

Browse files
author
CIS Guru
committed
simple-start-refactor
1 parent 8cadd82 commit 3f4e028

55 files changed

Lines changed: 2246 additions & 433 deletions

Some content is hidden

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

2-Aquiis.Application/Services/PropertyService.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public async Task<decimal> CalculateOccupancyRateAsync()
238238
var organizationId = await _userContext.GetActiveOrganizationIdAsync();
239239

240240
var totalProperties = await _context.Properties
241-
.CountAsync(p => !p.IsDeleted && p.IsAvailable && p.OrganizationId == organizationId);
241+
.CountAsync(p => !p.IsDeleted && p.OrganizationId == organizationId);
242242

243243
if (totalProperties == 0)
244244
{
@@ -247,7 +247,6 @@ public async Task<decimal> CalculateOccupancyRateAsync()
247247

248248
var occupiedProperties = await _context.Properties
249249
.CountAsync(p => !p.IsDeleted &&
250-
p.IsAvailable &&
251250
p.OrganizationId == organizationId &&
252251
_context.Leases.Any(l =>
253252
l.PropertyId == p.Id &&
@@ -354,7 +353,21 @@ public async Task<decimal> CalculatePortfolioOccupancyRateAsync(DateTime? period
354353
}
355354

356355
// Calculate total occupied days and total available days across all properties
357-
var startDate = periodStart ?? new DateTime(DateTime.Today.Year, 4, 1);
356+
// Default to current fiscal year (April 1 - March 31)
357+
// If today is Jan-Mar, use April 1 of previous year
358+
// If today is Apr-Dec, use April 1 of current year
359+
DateTime startDate;
360+
if (periodStart.HasValue)
361+
{
362+
startDate = periodStart.Value;
363+
}
364+
else
365+
{
366+
var today = DateTime.Today;
367+
startDate = today.Month < 4
368+
? new DateTime(today.Year - 1, 4, 1)
369+
: new DateTime(today.Year, 4, 1);
370+
}
358371
var endDate = startDate.AddYears(1).AddDays(-1);
359372
var totalDays = (endDate - startDate).Days + 1;
360373

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<div class="col">
2+
<div class="card text-white @ColorClass">
3+
<div class="card-body">
4+
<div class="d-flex justify-content-between">
5+
<div>
6+
<h4>@Count</h4>
7+
<p class="card-text">@Title</p>
8+
</div>
9+
<div class="align-self-center">
10+
<i class="@IconCssClass" style="font-size: 2rem;"></i>
11+
</div>
12+
</div>
13+
</div>
14+
</div>
15+
</div>
16+
@code {
17+
[Parameter]
18+
public RenderFragment? ChildContent { get; set; }
19+
20+
[Parameter]
21+
public string Title { get; set; } = string.Empty;
22+
23+
[Parameter]
24+
public string Count { get; set; } = string.Empty;
25+
26+
[Parameter]
27+
public string? IconCssClass { get; set; }
28+
29+
[Parameter]
30+
public string? ColorClass { get; set; }
31+
32+
}

3-Aquiis.UI.Shared/Components/Entities/Documents/DocumentListView.razor

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@using Aquiis.Core.Entities
22

33
<div class="card">
4-
<div class="card-header d-flex justify-content-between align-items-center">
4+
<div class="card-header d-flex justify-content-between align-items-center @HeaderCssClass">
55
<h5 class="mb-0">
66
<i class="bi bi-file-earmark-text"></i> Documents
77
</h5>
@@ -68,6 +68,9 @@
6868
[Parameter]
6969
public bool ShowUploadButton { get; set; } = true;
7070

71+
[Parameter]
72+
public string HeaderCssClass { get; set; } = "";
73+
7174
[Parameter]
7275
public bool ShowGroupByType { get; set; } = false;
7376

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<div class="card mb-3">
2+
<div class="card-header d-flex justify-content-between align-items-center @HeaderCssClass">
3+
<h5 class="mb-0"><i class="bi bi-receipt"></i> @Title</h5>
4+
<button class="btn btn-sm btn-outline-primary" @onclick="() => OnViewAll.InvokeAsync()">View All</button>
5+
</div>
6+
<div class="card-body">
7+
@if (Invoices.Any())
8+
{
9+
<div class="list-group list-group-flush">
10+
@foreach (var invoice in Invoices)
11+
{
12+
<div class="list-group-item">
13+
<div class="d-flex w-100 justify-content-between">
14+
<h6 class="mb-1">
15+
<a href="#" class="text-decoration-none" @onclick="() => OnViewItem.InvokeAsync(invoice.Id)">
16+
@invoice.InvoiceNumber
17+
</a>
18+
</h6>
19+
<small>@invoice.InvoicedOn.ToString("MMM dd, yyyy")</small>
20+
</div>
21+
<p class="mb-1">@invoice.Lease?.Tenant?.FullName</p>
22+
<div class="d-flex justify-content-between">
23+
<div>
24+
<small class="text-muted">Due: @invoice.DueOn.ToString("MMM dd, yyyy")</small>
25+
@if (invoice.IsOverdue)
26+
{
27+
<br>
28+
<small class="text-danger">@invoice.DaysOverdue days overdue</small>
29+
}
30+
</div>
31+
<div class="text-end">
32+
<span class="badge @GetInvoiceStatusBadgeClass(invoice.Status)">@invoice.Status</span>
33+
<br>
34+
<small class="text-muted">@invoice.Amount.ToString("C")</small>
35+
</div>
36+
</div>
37+
</div>
38+
}
39+
</div>
40+
}
41+
else
42+
{
43+
<p class="text-muted">No outstanding invoices.</p>
44+
}
45+
</div>
46+
</div>
47+
@code {
48+
[Parameter, EditorRequired]
49+
50+
public List<Invoice> Invoices { get; set; } = new();
51+
52+
[Parameter]
53+
public string Title { get; set; } = "Invoices";
54+
55+
[Parameter]
56+
public string HeaderCssClass { get; set; } = "";
57+
58+
[Parameter]
59+
public EventCallback OnViewAll { get; set; }
60+
61+
[Parameter]
62+
public EventCallback<Guid> OnViewItem { get; set; }
63+
64+
private string GetInvoiceStatusBadgeClass(string status)
65+
{
66+
return status switch
67+
{
68+
ApplicationConstants.InvoiceStatuses.Paid => "bg-success",
69+
ApplicationConstants.InvoiceStatuses.PaidPartial => "bg-warning text-dark",
70+
ApplicationConstants.InvoiceStatuses.Overdue => "bg-danger",
71+
_ => "bg-secondary"
72+
};
73+
}
74+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
<div class="card">
2+
<div class="card-header d-flex justify-content-between align-items-center @HeaderCssClass">
3+
<h5 class="mb-0">
4+
<i class="bi bi-calendar-event"></i> @Title
5+
</h5>
6+
<NavLink href="propertymanagement/leases" class="btn btn-sm btn-outline-primary">
7+
View All
8+
</NavLink>
9+
</div>
10+
<div class="card-body">
11+
@if (isLoading)
12+
{
13+
<div class="text-center py-4">
14+
<div class="spinner-border spinner-border-sm" role="status">
15+
<span class="visually-hidden">Loading...</span>
16+
</div>
17+
</div>
18+
}
19+
else if (expiringLeases == null || !expiringLeases.Any())
20+
{
21+
<p class="text-muted mb-0">No leases expiring in the next 90 days.</p>
22+
}
23+
else
24+
{
25+
<div class="mb-2">
26+
<div class="btn-group btn-group-sm" role="group">
27+
<input type="radio" class="btn-check" name="renewalFilter" id="filter30" value="30"
28+
checked="@(selectedFilter == 30)" @onchange="() => FilterLeases(30)" />
29+
<label class="btn btn-outline-primary" for="filter30">
30+
30 Days <span class="badge bg-danger">@leases30Days.Count()</span>
31+
</label>
32+
33+
<input type="radio" class="btn-check" name="renewalFilter" id="filter60" value="60"
34+
checked="@(selectedFilter == 60)" @onchange="() => FilterLeases(60)" />
35+
<label class="btn btn-outline-primary" for="filter60">
36+
60 Days <span class="badge bg-warning">@leases60Days.Count()</span>
37+
</label>
38+
39+
<input type="radio" class="btn-check" name="renewalFilter" id="filter90" value="90"
40+
checked="@(selectedFilter == 90)" @onchange="() => FilterLeases(90)" />
41+
<label class="btn btn-outline-primary" for="filter90">
42+
90 Days <span class="badge bg-info">@leases90Days.Count()</span>
43+
</label>
44+
</div>
45+
</div>
46+
47+
<div class="list-group list-group-flush" style="max-height: 400px; overflow-y: auto;">
48+
@foreach (var lease in GetFilteredLeases())
49+
{
50+
var daysRemaining = (lease.EndDate - DateTime.Today).Days;
51+
var urgencyClass = daysRemaining <= 30 ? "danger" : daysRemaining <= 60 ? "warning" : "info";
52+
var urgencyIcon = daysRemaining <= 30 ? "exclamation-triangle-fill" : daysRemaining <= 60 ? "exclamation-circle-fill" : "info-circle-fill";
53+
54+
<div class="list-group-item list-group-item-action">
55+
<div class="d-flex w-100 justify-content-between align-items-start">
56+
<div class="flex-grow-1">
57+
<h6 class="mb-1">
58+
<i class="bi @urgencyIcon text-@urgencyClass"></i>
59+
@lease.Property?.Address
60+
</h6>
61+
<p class="mb-1 small">
62+
<strong>Tenant:</strong> @lease.Tenant?.FullName<br/>
63+
<strong>End Date:</strong> @lease.EndDate.ToString("MMM dd, yyyy")<br/>
64+
<strong>Current Rent:</strong> @lease.MonthlyRent.ToString("C")
65+
@if (lease.ProposedRenewalRent.HasValue)
66+
{
67+
<span class="text-muted"> → @lease.ProposedRenewalRent.Value.ToString("C")</span>
68+
}
69+
</p>
70+
@if (!string.IsNullOrEmpty(lease.RenewalStatus))
71+
{
72+
<span class="badge bg-@GetStatusBadgeClass(lease.RenewalStatus)">
73+
@lease.RenewalStatus
74+
</span>
75+
}
76+
</div>
77+
<div class="text-end ms-3">
78+
<span class="badge bg-@urgencyClass rounded-pill">
79+
@daysRemaining days
80+
</span>
81+
</div>
82+
</div>
83+
</div>
84+
}
85+
</div>
86+
87+
<div class="card-footer">
88+
<small class="text-muted">
89+
<i class="bi bi-info-circle"></i>
90+
Showing @GetFilteredLeases().Count() of @Leases.Count() leases
91+
</small>
92+
</div>
93+
}
94+
</div>
95+
</div>
96+
97+
@code {
98+
[Parameter]
99+
public string Title { get; set; } = "Leases";
100+
101+
[Parameter]
102+
public string HeaderCssClass { get; set; } = "";
103+
104+
[Parameter]
105+
public List<Lease> Leases { get; set; } = new();
106+
107+
private List<Lease> expiringLeases = new();
108+
private List<Lease> leases30Days = new();
109+
private List<Lease> leases60Days = new();
110+
private List<Lease> leases90Days = new();
111+
private bool isLoading = true;
112+
private int selectedFilter = 30;
113+
114+
115+
private async Task LoadExpiringLeases()
116+
{
117+
try
118+
{
119+
isLoading = true;
120+
var today = DateTime.Today;
121+
122+
expiringLeases = Leases
123+
.Where(l => l.Status == "Active" &&
124+
l.EndDate >= today &&
125+
l.EndDate <= today.AddDays(90))
126+
.OrderBy(l => l.EndDate)
127+
.ToList();
128+
129+
leases30Days = expiringLeases
130+
.Where(l => l.EndDate <= today.AddDays(30))
131+
.ToList();
132+
133+
leases60Days = expiringLeases
134+
.Where(l => l.EndDate <= today.AddDays(60))
135+
.ToList();
136+
137+
leases90Days = expiringLeases;
138+
}
139+
catch (Exception ex)
140+
{
141+
// Log error
142+
Console.WriteLine($"Error loading expiring leases: {ex.Message}");
143+
}
144+
finally
145+
{
146+
isLoading = false;
147+
}
148+
}
149+
150+
private void FilterLeases(int days)
151+
{
152+
selectedFilter = days;
153+
}
154+
155+
private List<Lease> GetFilteredLeases()
156+
{
157+
return selectedFilter switch
158+
{
159+
30 => leases30Days,
160+
60 => leases60Days,
161+
90 => leases90Days,
162+
_ => expiringLeases
163+
};
164+
}
165+
166+
private string GetStatusBadgeClass(string status)
167+
{
168+
return status switch
169+
{
170+
"Pending" => "secondary",
171+
"Offered" => "info",
172+
"Accepted" => "success",
173+
"Declined" => "danger",
174+
"Expired" => "dark",
175+
_ => "secondary"
176+
};
177+
}
178+
}

3-Aquiis.UI.Shared/Components/Entities/Leases/LeaseListView.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
{
6969
<div class="card-body p-0">
7070
<table class="table table-hover mb-0">
71-
<thead class="table-light">
71+
<thead class="table">
7272
<tr>
7373
<th>Tenant</th>
7474
<th>Start Date</th>

0 commit comments

Comments
 (0)