The admin contract
The admin controller lives in the host, because it derives from the host framework's admin base
class (such as WAF's BaseAdminAPIController), which this package does not reference. Routed as
wafapi/Donations/{action}, its list action looks like this:
using Relatude.CMS.Models.Donations.Admin;
[HttpPost]
public DonationListResult List(int pageSize = 25, int pageIndex = 0, string? sortBy = null, bool sortDesc = true,
string? categories = null, string? statuses = null, string? paymentMethods = null, string? search = null) {
_ = Context.Session; // WAF's admin check: 403 without a session
var query = _cx.Database.Query<IMyDonation>() // plus WhereIn(d => d.Status, …) for each filter given
.OrderBy(DonationAdminProjection.SortExpression<IMyDonation>(sortBy), sortDesc);
var page = query.Page(pageIndex, pageSize).Execute();
return new DonationListResult { Rows = page.Values.Select(d => DonationAdminProjection.ToRow(d)).ToList(), TotalCount = page.TotalCount };
}Get(id) reads the donation with TryGet<IMyDonation> and returns
DonationAdminProjection.ToDetail(d, formGuid: …), with the form's content guid found from
FormId. When a donation is created, the host copies the form's name into FormName, so the list
can sort and search by it.
DonationAdminProjection |
Does |
|---|---|
SortExpression<T>(sortBy) |
the sort for a column key (Amount, Status, Name, Reference, DonorFirstName, DonorLastName, DonorEmail, PaymentMethod, GiftType, FormName); CreatedUtc otherwise |
ToRow(d), ToDetail(d, …, formGuid) |
the list row and the detail view |
DisplayName(d) |
the company, "Anonymous donor", the donor's name or "(no name)" |
MatchesCategory(d, categories) |
onetime, recurring or business |
MatchesSearch(d, term) |
reference, donor names, email, company and form name, ignoring case |
Split(csv) |
a comma-separated filter as an array |
Category and free-text search have no query form. When either is active, the host executes the
ordered query, filters with MatchesCategory and MatchesSearch, and then pages.