/// <summary> /// Get an array of parcels within the specified filter. /// Will not return sensitive parcels unless the user has the `sensitive-view` claim and belongs to the owning agency. /// </summary> /// <param name="filter"></param> /// <returns></returns> public Paged <Parcel> Get(ParcelFilter filter) { filter.ThrowIfNull(nameof(filter)); this.User.ThrowIfNotAuthorized(Permissions.SystemAdmin, Permissions.AgencyAdmin); if (filter.Page < 1) { throw new ArgumentException("Argument must be greater than or equal to 1.", nameof(filter.Page)); } if (filter.Quantity < 1) { throw new ArgumentException("Argument must be greater than or equal to 1.", nameof(filter.Quantity)); } // Check if user has the ability to view sensitive properties. var userAgencies = this.User.GetAgenciesAsNullable(); var viewSensitive = this.User.HasPermission(Security.Permissions.SensitiveView); // Users may only view sensitive properties if they have the `sensitive-view` claim and belong to the owning agency. var query = this.Context.Parcels.AsNoTracking(); if (filter.NELatitude.HasValue && filter.NELongitude.HasValue && filter.SWLatitude.HasValue && filter.SWLongitude.HasValue) { query = query.Where(p => p.Latitude != 0 && p.Longitude != 0 && p.Latitude <= filter.NELatitude && p.Latitude >= filter.SWLatitude && p.Longitude <= filter.NELongitude && p.Longitude >= filter.SWLongitude); } if (filter.Agencies?.Any() == true) { var filterAgencies = filter.Agencies.Select(a => (int?)a); query = query.Where(p => filterAgencies.Contains(p.AgencyId)); } if (filter.ClassificationId.HasValue) { query = query.Where(p => p.ClassificationId == filter.ClassificationId); } if (!String.IsNullOrWhiteSpace(filter.ProjectNumber)) { query = query.Where(p => EF.Functions.Like(p.ProjectNumber, $"{filter.ProjectNumber}%")); } if (!String.IsNullOrWhiteSpace(filter.Description)) { query = query.Where(p => EF.Functions.Like(p.Description, $"%{filter.Description}%")); } if (!String.IsNullOrWhiteSpace(filter.Municipality)) { query = query.Where(p => EF.Functions.Like(p.Municipality, $"%{filter.Municipality}%")); } if (!String.IsNullOrWhiteSpace(filter.Zoning)) { query = query.Where(p => EF.Functions.Like(p.Zoning, $"%{filter.Zoning}%")); } if (!String.IsNullOrWhiteSpace(filter.ZoningPotential)) { query = query.Where(p => EF.Functions.Like(p.ZoningPotential, $"%{filter.ZoningPotential}%")); } // TODO: Parse the address information by City, Postal, etc. if (!String.IsNullOrWhiteSpace(filter.Address)) { query = query.Where(p => EF.Functions.Like(p.Address.Address1, $"%{filter.Address}%") || EF.Functions.Like(p.Address.City.Name, $"%{filter.Address}%")); } if (filter.MinLandArea.HasValue) { query = query.Where(p => p.LandArea >= filter.MinLandArea); } if (filter.MaxLandArea.HasValue) { query = query.Where(p => p.LandArea <= filter.MaxLandArea); } // TODO: Review performance of the evaluation query component. if (filter.MinEstimatedValue.HasValue) { query = query.Where(p => filter.MinEstimatedValue <= p.Fiscals .FirstOrDefault(e => e.FiscalYear == this.Context.ParcelFiscals .Where(pe => pe.ParcelId == p.Id && e.Key == FiscalKeys.Estimated) .Max(pe => pe.FiscalYear)) .Value); } if (filter.MaxEstimatedValue.HasValue) { query = query.Where(p => filter.MaxEstimatedValue >= p.Fiscals .FirstOrDefault(e => e.FiscalYear == this.Context.ParcelFiscals .Where(pe => pe.ParcelId == p.Id && e.Key == FiscalKeys.Estimated) .Max(pe => pe.FiscalYear)) .Value); } // TODO: Review performance of the evaluation query component. if (filter.MinAssessedValue.HasValue) { query = query.Where(p => filter.MinAssessedValue <= p.Evaluations .FirstOrDefault(e => e.Date == this.Context.ParcelEvaluations .Where(pe => pe.ParcelId == p.Id && e.Key == EvaluationKeys.Assessed) .Max(pe => pe.Date)) .Value); } if (filter.MaxAssessedValue.HasValue) { query = query.Where(p => filter.MaxAssessedValue >= p.Evaluations .FirstOrDefault(e => e.Date == this.Context.ParcelEvaluations .Where(pe => pe.ParcelId == p.Id && e.Key == EvaluationKeys.Assessed) .Max(pe => pe.Date)) .Value); } if (filter.Sort?.Any() == true) { query = query.OrderByProperty(filter.Sort); } var pagedEntities = query.Skip((filter.Page - 1) * filter.Quantity).Take(filter.Quantity); return(new Paged <Parcel>(pagedEntities, filter.Page, filter.Quantity, query.Count())); }