feat(giving): match giver member name in single-giving search (spec §4.2)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -137,4 +137,25 @@ public class GivingServiceTests
|
|||||||
|
|
||||||
await Assert.ThrowsAsync<InvalidOperationException>(() => svc.DeleteAsync(giving.Id));
|
await Assert.ThrowsAsync<InvalidOperationException>(() => svc.DeleteAsync(giving.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetPagedAsync_MatchesByMemberName()
|
||||||
|
{
|
||||||
|
using var db = BuildDb();
|
||||||
|
var catId = await SeedCategoryAsync(db);
|
||||||
|
var member = new Member { FirstName_en = "Grace", LastName_en = "Lee" };
|
||||||
|
db.Members.Add(member);
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
var svc = new GivingService(db);
|
||||||
|
await svc.CreateAsync(new CreateGivingRequest
|
||||||
|
{
|
||||||
|
GivingCategoryId = catId, Amount = 75m, PaymentMethod = "Cash",
|
||||||
|
GivingDate = new DateOnly(2026, 5, 31), MemberId = member.Id,
|
||||||
|
});
|
||||||
|
|
||||||
|
var page = await svc.GetPagedAsync(1, 20, "grace", null, null, null);
|
||||||
|
|
||||||
|
Assert.Equal(1, page.TotalCount);
|
||||||
|
Assert.Equal(member.Id, page.Items[0].MemberId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,14 @@ public class GivingService : IGivingService
|
|||||||
if (!string.IsNullOrWhiteSpace(search))
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
{
|
{
|
||||||
var s = search.Trim().ToLower();
|
var s = search.Trim().ToLower();
|
||||||
|
var term = search.Trim();
|
||||||
query = query.Where(g =>
|
query = query.Where(g =>
|
||||||
(g.CheckNumber != null && g.CheckNumber.ToLower().Contains(s)) ||
|
(g.CheckNumber != null && g.CheckNumber.ToLower().Contains(s)) ||
|
||||||
(g.Notes != null && g.Notes.ToLower().Contains(s)));
|
(g.Notes != null && g.Notes.ToLower().Contains(s)) ||
|
||||||
|
(g.Member != null && (
|
||||||
|
(g.Member.FirstName_en + " " + g.Member.LastName_en).ToLower().Contains(s) ||
|
||||||
|
(g.Member.FirstName_zh != null && g.Member.FirstName_zh.Contains(term)) ||
|
||||||
|
(g.Member.LastName_zh != null && g.Member.LastName_zh.Contains(term)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
var total = await query.CountAsync();
|
var total = await query.CountAsync();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<kendo-textbox placeholder="Search check # / notes" [(ngModel)]="search" (keydown.enter)="onSearch()"></kendo-textbox>
|
<kendo-textbox placeholder="Search name / check # / notes" [(ngModel)]="search" (keydown.enter)="onSearch()"></kendo-textbox>
|
||||||
<kendo-dropdownlist [data]="categories" textField="name_en" valueField="id"
|
<kendo-dropdownlist [data]="categories" textField="name_en" valueField="id"
|
||||||
[valuePrimitive]="true" [(ngModel)]="filterCategoryId" (valueChange)="onSearch()"
|
[valuePrimitive]="true" [(ngModel)]="filterCategoryId" (valueChange)="onSearch()"
|
||||||
[defaultItem]="{ id: null, name_en: 'All types' }"></kendo-dropdownlist>
|
[defaultItem]="{ id: null, name_en: 'All types' }"></kendo-dropdownlist>
|
||||||
|
|||||||
Reference in New Issue
Block a user