fix(compare): date report cards with their own inspection date, never the legacy one
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB
This commit is contained in:
@@ -617,6 +617,11 @@ def _ofsted_block(o, urn: int) -> dict:
|
|||||||
block = {
|
block = {
|
||||||
"framework": o.framework,
|
"framework": o.framework,
|
||||||
"inspection_date": o.inspection_date.isoformat() if o.inspection_date else None,
|
"inspection_date": o.inspection_date.isoformat() if o.inspection_date else None,
|
||||||
|
"rc_inspection_date": (
|
||||||
|
o.rc_inspection_date.isoformat()
|
||||||
|
if getattr(o, "rc_inspection_date", None)
|
||||||
|
else None
|
||||||
|
),
|
||||||
"inspection_type": o.inspection_type,
|
"inspection_type": o.inspection_type,
|
||||||
"overall_effectiveness": overall,
|
"overall_effectiveness": overall,
|
||||||
"grade_source": grade_source,
|
"grade_source": grade_source,
|
||||||
|
|||||||
@@ -156,6 +156,9 @@ class FactOfstedInspection(Base):
|
|||||||
rc_leadership_governance = Column(Integer)
|
rc_leadership_governance = Column(Integer)
|
||||||
rc_early_years = Column(Integer)
|
rc_early_years = Column(Integer)
|
||||||
rc_sixth_form = Column(Integer)
|
rc_sixth_form = Column(Integer)
|
||||||
|
# Start date of the report-card inspection itself (renewed framework,
|
||||||
|
# Nov 2025+). Null for rows without report-card grades.
|
||||||
|
rc_inspection_date = Column(Date)
|
||||||
report_url = Column(Text)
|
report_url = Column(Text)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ labels, provider-page URL, graded-vs-carried-forward provenance, and the
|
|||||||
admissions preference/cross-LA detail promoted in the data-foundation PR."""
|
admissions preference/cross-LA detail promoted in the data-foundation PR."""
|
||||||
|
|
||||||
import types
|
import types
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
from backend.data_loader import _admissions_row_dict, _ofsted_block
|
from backend.data_loader import _admissions_row_dict, _ofsted_block
|
||||||
|
|
||||||
@@ -40,6 +41,25 @@ def test_grade_source_graded_vs_carried_forward():
|
|||||||
assert _ofsted_block(_row(), urn=1)["grade_source"] is None
|
assert _ofsted_block(_row(), urn=1)["grade_source"] is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_ofsted_block_carries_rc_inspection_date():
|
||||||
|
o = _row(
|
||||||
|
ungraded_grade=2,
|
||||||
|
rc_achievement=1,
|
||||||
|
rc_inspection_date=date(2026, 2, 3),
|
||||||
|
inspection_date=date(2021, 10, 7),
|
||||||
|
)
|
||||||
|
block = _ofsted_block(o, urn=138690)
|
||||||
|
assert block["rc_inspection_date"] == "2026-02-03"
|
||||||
|
# The legacy inspection date is still present, unchanged.
|
||||||
|
assert block["inspection_date"] == "2021-10-07"
|
||||||
|
|
||||||
|
|
||||||
|
def test_ofsted_block_rc_inspection_date_none_when_absent():
|
||||||
|
o = _row(overall_effectiveness=1, inspection_date=date(2021, 10, 13))
|
||||||
|
block = _ofsted_block(o, urn=136276)
|
||||||
|
assert block["rc_inspection_date"] is None
|
||||||
|
|
||||||
|
|
||||||
def test_ofsted_block_keeps_existing_keys():
|
def test_ofsted_block_keeps_existing_keys():
|
||||||
block = _ofsted_block(_row(overall_effectiveness=2, quality_of_education=2), urn=1)
|
block = _ofsted_block(_row(overall_effectiveness=2, quality_of_education=2), urn=1)
|
||||||
for key in ("framework", "inspection_date", "overall_effectiveness",
|
for key in ("framework", "inspection_date", "overall_effectiveness",
|
||||||
|
|||||||
@@ -96,6 +96,45 @@ describe('CompareOfsted', () => {
|
|||||||
expect(links[0]).toHaveAttribute('href', 'https://reports.ofsted.gov.uk/provider/21/1');
|
expect(links[0]).toHaveAttribute('href', 'https://reports.ofsted.gov.uk/provider/21/1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('dates a report card with the report-card inspection date, never the legacy date', () => {
|
||||||
|
const cardSchool = school(4, 'Dated Card School');
|
||||||
|
const cardData: Record<string, ComparisonData> = {
|
||||||
|
'4': {
|
||||||
|
school_info: cardSchool,
|
||||||
|
yearly_data: [],
|
||||||
|
ofsted: ofsted({
|
||||||
|
inspection_date: '2021-10-07',
|
||||||
|
rc_inspection_date: '2026-02-03',
|
||||||
|
rc_safeguarding_met: true,
|
||||||
|
report_card: { rc_achievement: { code: 1, label: 'Exceptional' } },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
render(<CompareOfsted schools={[cardSchool]} data={cardData} />);
|
||||||
|
expect(screen.getByText(/3 Feb 2026/)).toBeInTheDocument();
|
||||||
|
expect(screen.queryByText(/7 Oct 2021/)).toBeNull();
|
||||||
|
expect(screen.queryByText('4+ years ago')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows an em dash when a report card has no rc_inspection_date yet', () => {
|
||||||
|
const cardSchool = school(5, 'Undated Card School');
|
||||||
|
const cardData: Record<string, ComparisonData> = {
|
||||||
|
'5': {
|
||||||
|
school_info: cardSchool,
|
||||||
|
yearly_data: [],
|
||||||
|
ofsted: ofsted({
|
||||||
|
inspection_date: '2021-10-07',
|
||||||
|
rc_inspection_date: null,
|
||||||
|
rc_safeguarding_met: true,
|
||||||
|
report_card: { rc_achievement: { code: 1, label: 'Exceptional' } },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
render(<CompareOfsted schools={[cardSchool]} data={cardData} />);
|
||||||
|
expect(screen.getByText('—')).toBeInTheDocument();
|
||||||
|
expect(screen.queryByText(/7 Oct 2021/)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders a per-measure mobile tag with the short school name', () => {
|
it('renders a per-measure mobile tag with the short school name', () => {
|
||||||
render(<CompareOfsted schools={schools} data={data} />);
|
render(<CompareOfsted schools={schools} data={data} />);
|
||||||
// Each measure repeats the schools, so the short name ("Graded" from
|
// Each measure repeats the schools, so the short name ("Graded" from
|
||||||
|
|||||||
@@ -180,10 +180,18 @@ export function CompareOfsted({
|
|||||||
<Measure label="Inspected">
|
<Measure label="Inspected">
|
||||||
{schools.map((school, i) => {
|
{schools.map((school, i) => {
|
||||||
const ofsted = data[String(school.urn)]?.ofsted;
|
const ofsted = data[String(school.urn)]?.ofsted;
|
||||||
const age = yearsSince(ofsted?.inspection_date ?? null);
|
// A report card is dated by its OWN inspection date. The legacy
|
||||||
|
// inspection_date belongs to an older inspection and must never
|
||||||
|
// be shown against a report card (report cards exist only from
|
||||||
|
// Nov 2025).
|
||||||
|
const dateIso =
|
||||||
|
displays[i].kind === 'report_card'
|
||||||
|
? ofsted?.rc_inspection_date ?? null
|
||||||
|
: ofsted?.inspection_date ?? null;
|
||||||
|
const age = yearsSince(dateIso);
|
||||||
return (
|
return (
|
||||||
<Cell key={school.urn} school={school} index={i}>
|
<Cell key={school.urn} school={school} index={i}>
|
||||||
{formatInspectionDate(ofsted?.inspection_date ?? null)}{' '}
|
{formatInspectionDate(dateIso)}{' '}
|
||||||
{age != null && age > 4 && <Chip tone="neutral">4+ years ago</Chip>}
|
{age != null && age > 4 && <Chip tone="neutral">4+ years ago</Chip>}
|
||||||
</Cell>
|
</Cell>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ export interface School {
|
|||||||
export interface OfstedInspection {
|
export interface OfstedInspection {
|
||||||
framework: 'OEIF' | 'ReportCard' | null;
|
framework: 'OEIF' | 'ReportCard' | null;
|
||||||
inspection_date: string | null;
|
inspection_date: string | null;
|
||||||
|
/** Start date of the report-card inspection itself (Nov 2025+); null otherwise. */
|
||||||
|
rc_inspection_date?: string | null;
|
||||||
inspection_type: string | null;
|
inspection_type: string | null;
|
||||||
// OEIF fields (old framework, pre-Nov 2025)
|
// OEIF fields (old framework, pre-Nov 2025)
|
||||||
overall_effectiveness: 1 | 2 | 3 | 4 | null;
|
overall_effectiveness: 1 | 2 | 3 | 4 | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user