|
11 | 11 | from sqlalchemy.orm import aliased, relationship |
12 | 12 | from sqlalchemy.sql.functions import func |
13 | 13 |
|
14 | | -from testgen.common.enums import Disposition |
| 14 | +from testgen.common.enums import Disposition, IssueLikelihood, PiiRisk |
15 | 15 | from testgen.common.models import Base, get_current_session |
16 | 16 | from testgen.common.models.entity import Entity |
17 | 17 | from testgen.common.models.job_execution import JobExecution |
|
23 | 23 |
|
24 | 24 |
|
25 | 25 | @dataclass |
26 | | -class IssueLikelihoodCounts: |
27 | | - """Counts of hygiene issues by likelihood category, with dismissed/inactive separated.""" |
| 26 | +class HygieneIssueCounts: |
| 27 | + """Counts of active data-quality hygiene issues by likelihood category.""" |
28 | 28 |
|
29 | 29 | definite: int = 0 |
30 | 30 | likely: int = 0 |
31 | 31 | possible: int = 0 |
| 32 | + |
| 33 | + |
| 34 | +@dataclass |
| 35 | +class PotentialPiiCounts: |
| 36 | + """Counts of active Potential PII findings by risk level.""" |
| 37 | + |
| 38 | + high: int = 0 |
| 39 | + moderate: int = 0 |
| 40 | + |
| 41 | + |
| 42 | +@dataclass |
| 43 | +class IssueCounts: |
| 44 | + """Profiling-finding breakdown: active counts by kind, plus a single dismissed total.""" |
| 45 | + |
| 46 | + hygiene_issues: HygieneIssueCounts |
| 47 | + potential_pii: PotentialPiiCounts |
32 | 48 | dismissed: int = 0 |
33 | 49 |
|
34 | 50 |
|
@@ -202,27 +218,37 @@ def select_count_by_priority(cls, profiling_run_id: UUID) -> dict[str, IssueCoun |
202 | 218 | return result |
203 | 219 |
|
204 | 220 | @classmethod |
205 | | - def count_by_likelihood(cls, profile_run_id: UUID) -> IssueLikelihoodCounts: |
206 | | - """Count hygiene issues by likelihood category for a single profiling run.""" |
207 | | - dismissed = func.coalesce(cls.disposition, "Confirmed").in_(("Dismissed", "Inactive")) |
| 221 | + def count_for_run(cls, profile_run_id: UUID) -> IssueCounts: |
| 222 | + """Count profiling findings for a single run: active hygiene issues by likelihood, |
| 223 | + active Potential PII findings by risk level, and a single dismissed total.""" |
| 224 | + dismissed = func.coalesce(cls.disposition, Disposition.CONFIRMED).in_( |
| 225 | + (Disposition.DISMISSED, Disposition.INACTIVE) |
| 226 | + ) |
| 227 | + is_pii = HygieneIssueType.likelihood == IssueLikelihood.POTENTIAL_PII |
208 | 228 |
|
209 | | - def _count_active(likelihood_values: tuple[str, ...]): |
210 | | - return func.sum(case((~dismissed & HygieneIssueType.likelihood.in_(likelihood_values), 1), else_=0)) |
| 229 | + def _count(condition): |
| 230 | + return func.coalesce(func.sum(case((condition, 1), else_=0)), 0) |
211 | 231 |
|
212 | 232 | query = ( |
213 | 233 | select( |
214 | | - _count_active(("Definite",)).label("definite"), |
215 | | - _count_active(("Likely",)).label("likely"), |
216 | | - _count_active(("Possible", "Potential PII")).label("possible"), |
217 | | - func.sum(case((dismissed, 1), else_=0)).label("dismissed"), |
| 234 | + _count(~dismissed & (HygieneIssueType.likelihood == IssueLikelihood.DEFINITE)).label("definite"), |
| 235 | + _count(~dismissed & (HygieneIssueType.likelihood == IssueLikelihood.LIKELY)).label("likely"), |
| 236 | + _count(~dismissed & (HygieneIssueType.likelihood == IssueLikelihood.POSSIBLE)).label("possible"), |
| 237 | + _count(~dismissed & is_pii & (cls.priority == PiiRisk.HIGH)).label("high"), |
| 238 | + _count(~dismissed & is_pii & (cls.priority == PiiRisk.MODERATE)).label("moderate"), |
| 239 | + _count(dismissed).label("dismissed"), |
218 | 240 | ) |
219 | 241 | .select_from(cls) |
220 | 242 | .join(HygieneIssueType, HygieneIssueType.id == cls.type_id) |
221 | 243 | .where(cls.profile_run_id == profile_run_id) |
222 | 244 | ) |
223 | 245 |
|
224 | 246 | row = get_current_session().execute(query).first() |
225 | | - return IssueLikelihoodCounts(**{k: v for k, v in row._mapping.items() if v is not None}) |
| 247 | + return IssueCounts( |
| 248 | + hygiene_issues=HygieneIssueCounts(definite=row.definite, likely=row.likely, possible=row.possible), |
| 249 | + potential_pii=PotentialPiiCounts(high=row.high, moderate=row.moderate), |
| 250 | + dismissed=row.dismissed, |
| 251 | + ) |
226 | 252 |
|
227 | 253 | @classmethod |
228 | 254 | def _priority_order(cls): |
|
0 commit comments