using Dapper; using Npgsql; namespace Modules.ERP.Items.Search; public sealed class SearchItemsHandler(NpgsqlDataSource dataSource) { public async Task HandleAsync(SearchItemsRequest request, CancellationToken ct) { var page = Math.Max(request.Page, 1); var pageSize = Math.Clamp(request.PageSize, 1, 500); var offset = (page - 1) * pageSize; var keyword = string.IsNullOrWhiteSpace(request.Keyword) ? null : request.Keyword.Trim(); const string sql = """ select p.id, p.code, p.name, p.category_name as CategoryName, p.specification, p.unit, p.barcode, p.default_warehouse_id as DefaultWarehouseId, p.default_warehouse_name as DefaultWarehouseName, p.lot_managed as LotManaged, p.expiry_managed as ExpiryManaged, p.active, p.version from erp_item_search_projection p where (@Keyword is null or p.search_text ilike '%' || @Keyword || '%') order by p.code limit @PageSize offset @Offset; select count(*)::int from erp_item_search_projection p where (@Keyword is null or p.search_text ilike '%' || @Keyword || '%'); """; await using var connection = await dataSource.OpenConnectionAsync(ct); using var multi = await connection.QueryMultipleAsync(new CommandDefinition(sql, new { Keyword = keyword, PageSize = pageSize, Offset = offset }, cancellationToken: ct)); var items = (await multi.ReadAsync()).AsList(); var count = await multi.ReadSingleAsync(); return new(items, count); } }