コード例 #1
0
def remove_suffix_from_violation_ids(
        ingested_persons: List[schema.StatePerson]):
    """Removes SEO (sentence sequence numbers) and FSO (field sequence numbers) from the end of
    StateSupervisionViolation external_ids. This allows violations across sentences to be merged correctly by
    entity matching.
    """
    ssvs = get_all_entities_of_cls(ingested_persons, schema.StateSupervisionViolation)
    ssvrs = get_all_entities_of_cls(ingested_persons, schema.StateSupervisionViolationResponse)
    _remove_suffix_from_violation_entity(ssvs)
    _remove_suffix_from_violation_entity(ssvrs)
コード例 #2
0
def _move_periods_onto_sentences_for_sentence_group(
        sentence_group: schema.StateSentenceGroup,
        period_type: Type[schema.SchemaPeriodType]):
    """Looks at all SupervisionPeriods in the provided |sentence_group|, and attempts to match them to any
    corresponding sentences, based on date.
    """
    sentences = sentence_group.supervision_sentences + sentence_group.incarceration_sentences

    # Get all periods from sentence group
    periods = get_all_entities_of_cls([sentence_group], period_type)

    # Clear non-placeholder links from sentence to period. We will re-add/update these relationships below.
    for sentence in sentences:
        _only_keep_placeholder_periods_on_sentence(sentence, period_type)

    unmatched_periods = []
    matchable_sentences = _get_date_matchable_sentences(sentences)

    non_placeholder_periods = [p for p in periods if not is_placeholder(p)]

    # Match periods to non_placeholder_sentences by date.
    for p in non_placeholder_periods:
        matched = False
        p_start_date = _get_period_start_date(p)
        p_end_date = _get_period_end_date(p)

        for s in matchable_sentences:
            s_start_date = s.start_date
            if not s_start_date:
                continue

            s_completion_date = s.completion_date if s.completion_date else datetime.date.max

            if date_spans_overlap_exclusive(start_1=p_start_date,
                                            end_1=p_end_date,
                                            start_2=s_start_date,
                                            end_2=s_completion_date):
                matched = True
                _add_period_to_sentence(p, s)

        # Unmatched periods will be re-added to a placeholder sentence at the end.
        if not matched:
            unmatched_periods.append(p)

    # Add unmatched periods to a placeholder sentence
    if unmatched_periods:
        placeholder_sentences = [s for s in sentences if is_placeholder(s)]
        if not placeholder_sentences:
            placeholder_sentence = get_or_create_placeholder_child(
                sentence_group,
                'supervision_sentences',
                schema.StateSupervisionSentence,
                state_code=sentence_group.state_code,
                status=StateSentenceStatus.PRESENT_WITHOUT_INFO.value,
                person=sentence_group.person)
        else:
            placeholder_sentence = placeholder_sentences[0]
        for unmatched_period in unmatched_periods:
            _add_period_to_sentence(unmatched_period, placeholder_sentence)
コード例 #3
0
def _move_supervision_periods_onto_sentences_for_sentence_group(
        sentence_group: schema.StateSentenceGroup):
    """Looks at all SupervisionPeriods in the provided |sentence_group|, and attempts to match them to any
    corresponding sentences, based on date.
    """
    sentences = sentence_group.supervision_sentences + sentence_group.incarceration_sentences

    # Get all supervision periods from sentence group
    supervision_periods = get_all_entities_of_cls([sentence_group], schema.StateSupervisionPeriod)

    # Clear non-placeholder links from sentence to supervision period. We will
    # re-add/update these relationships below.
    for sentence in sentences:
        placeholder_supervision_periods = [sp for sp in sentence.supervision_periods if is_placeholder(sp)]
        sentence.supervision_periods = placeholder_supervision_periods

    unmatched_sps = []
    non_placeholder_sentences = [s for s in sentences if not is_placeholder(s)]

    non_placeholder_supervision_periods = [sp for sp in supervision_periods if not is_placeholder(sp)]

    # Match SVs to non_placeholder_periods by date.
    for sp in non_placeholder_supervision_periods:
        matched = False
        sp_start_date = sp.start_date if sp.start_date else datetime.date.min
        sp_termination_date = sp.termination_date if sp.termination_date else datetime.date.max

        for s in non_placeholder_sentences:
            if not s.start_date:
                continue

            s_completion_date = s.completion_date if s.completion_date else datetime.date.max

            if (s.start_date <= sp_start_date < s_completion_date) \
                    or (s.start_date <= sp_termination_date < s_completion_date):
                matched = True
                s.supervision_periods.append(sp)

        # Unmatched SPs will be re-added to a placeholder sentence at the end.
        if not matched:
            unmatched_sps.append(sp)

    # Add unmatched supervision periods to a placeholder sentence
    if unmatched_sps:
        placeholder_sentences = [s for s in sentences if is_placeholder(s)]
        if not placeholder_sentences:
            # We may hit this case if an entity that has already been committed to the DB has a date updated in a later
            # run such that the dates of the existing sentences no longer line up with one of the existing supervision
            # periods.
            logging.info(
                'No placeholder sentences exist on sentence group [%s]([%s]), creating a new placeholder sentence.',
                sentence_group.external_id, sentence_group.sentence_group_id)
            new_placeholder_sentence = schema.StateSupervisionSentence(
                state_code=sentence_group.state_code,
                status=StateSentenceStatus.PRESENT_WITHOUT_INFO.value,
                person=sentence_group.person)
            placeholder_sentences.append(new_placeholder_sentence)
            sentence_group.supervision_sentences.append(new_placeholder_sentence)
        placeholder_sentences[0].supervision_periods = unmatched_sps
コード例 #4
0
def _move_events_onto_supervision_periods(
    source: DatabaseEntity, event_cls: Type[DatabaseEntity], event_field_name: str
) -> List[DatabaseEntity]:
    """Looks at all events of type |event_cls| in the provided |source|, and attempts to place them onto a matching
    SupervisionPeriod's |event_field_name| field. Matching is based on dates, and all unmatched events are returned
    to the caller to store.
    """
    supervision_periods = get_all_entities_of_cls(
        [source], schema.StateSupervisionPeriod
    )
    events = get_all_entities_of_cls(supervision_periods, event_cls)

    # Clear the links from supervision period to supervision violations. We will
    # re-add/update these relationships below.
    for supervision_period in supervision_periods:
        supervision_period.set_field(event_field_name, [])

    unmatched_events = []
    non_placeholder_periods = [
        sp for sp in supervision_periods if not is_placeholder(sp)
    ]

    # Match events onto to non_placeholder_periods by date.
    for event in events:
        matched = False
        event_date = _get_event_date(event)
        if event_date:
            for sp in non_placeholder_periods:
                sp_end_date = (
                    sp.termination_date if sp.termination_date else datetime.date.max
                )
                sp_start_date = sp.start_date
                if sp_start_date <= event_date < sp_end_date:
                    matched = True
                    sp_events = sp.get_field(event_field_name)
                    sp_events.append(event)
                    sp.set_field(event_field_name, sp_events)

        # Unmatched SVs will be returned
        if not matched:
            unmatched_events.append(event)

    return unmatched_events
コード例 #5
0
def associate_revocation_svrs_with_ips(
        merged_persons: List[schema.StatePerson]):
    """
    For each person in the provided |merged_persons|, attempts to associate
    StateSupervisionViolationResponses that result in revocation with their
    corresponding StateIncarcerationPeriod.
    """
    for person in merged_persons:
        svrs = get_all_entities_of_cls(
            [person], schema.StateSupervisionViolationResponse)
        ips = get_all_entities_of_cls([person],
                                      schema.StateIncarcerationPeriod)

        revocation_svrs: List[schema.StateSupervisionViolationResponse] = []
        for svr in svrs:
            svr = cast(schema.StateSupervisionViolationResponse, svr)
            if revoked_to_prison(svr) and svr.response_date:
                revocation_svrs.append(svr)
        revocation_ips: List[schema.StateIncarcerationPeriod] = []
        for ip in ips:
            ip = cast(schema.StateIncarcerationPeriod, ip)
            admission_reason = (StateIncarcerationPeriodAdmissionReason.
                                parse_from_canonical_string(
                                    ip.admission_reason))
            if isinstance(admission_reason,
                          StateIncarcerationPeriodAdmissionReason):
                if (is_commitment_from_supervision(
                        admission_reason, allow_ingest_only_enum_values=True)
                        and ip.admission_date):
                    revocation_ips.append(ip)

        if not revocation_svrs or not revocation_ips:
            continue

        sorted_svrs = sorted(revocation_svrs, key=lambda x: x.response_date)

        seen: Set[int] = set()
        for svr in sorted_svrs:
            closest_ip = _get_closest_matching_incarceration_period(
                svr, revocation_ips)
            if closest_ip and id(closest_ip) not in seen:
                seen.add(id(closest_ip))
                closest_ip.source_supervision_violation_response = svr
コード例 #6
0
def _move_violations_onto_supervision_periods_for_sentence(
        sentence: Union[StateSupervisionSentence, StateIncarcerationSentence]):
    """Looks at all SupervisionViolations in the provided |sentence|, and attempts to match them to the corresponding
    SupervisionPeriod, based on date.
    """
    supervision_periods = sentence.supervision_periods

    # Get all supervision violations from supervision periods
    supervision_violations = get_all_entities_of_cls(supervision_periods, StateSupervisionViolation)

    # Clear the links from supervision period to supervision violations. We will
    # re-add/update these relationships below.
    for supervision_period in supervision_periods:
        supervision_period.supervision_violation_entries = []

    unmatched_svs = []
    non_placeholder_periods = [sp for sp in supervision_periods if not is_placeholder(sp)]

    # Match SVs to non_placeholder_periods by date.
    for sv in supervision_violations:
        matched = False
        violation_date = _get_approximate_violation_date(sv)
        if violation_date:
            for sp in non_placeholder_periods:
                sp_end_date = sp.termination_date if sp.termination_date else datetime.date.max
                sp_start_date = sp.start_date
                if sp_start_date <= violation_date <= sp_end_date:
                    matched = True
                    sp.supervision_violation_entries.append(sv)

        # Unmatched SVs will be re-added to a placeholder period at the end.
        if not matched:
            unmatched_svs.append(sv)

    # Add unmatched supervision violations to a placeholder period
    if unmatched_svs:
        placeholder_periods = [sp for sp in supervision_periods if is_placeholder(sp)]

        if not placeholder_periods:
            # We may hit this case if an entity that has already been committed to the DB has a date updated in a later
            # run such that the dates of the existing supervision periods no longer line up with one of the existing
            # supervision violations.
            logging.info(
                'No placeholder supervision periods exist on sentence [%s]([%s]), creating a new placeholder '
                'supervision period.',
                sentence.external_id, sentence.get_id())
            new_placeholder_supervision_period = schema.StateSupervisionPeriod(
                state_code=sentence.state_code,
                status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO.value,
                person=sentence.person
            )
            placeholder_periods.append(new_placeholder_supervision_period)
            sentence.supervision_periods.append(new_placeholder_supervision_period)

        placeholder_periods[0].supervision_violation_entries = unmatched_svs
コード例 #7
0
def add_supervising_officer_to_open_supervision_periods(persons: List[schema.StatePerson]):
    """For each person in the provided |persons|, adds the supervising_officer from the person entity onto all open
    StateSupervisionPeriods.
    """
    for person in persons:
        if not person.supervising_officer:
            continue

        supervision_periods = get_all_entities_of_cls([person], schema.StateSupervisionPeriod)
        for supervision_period in supervision_periods:
            # Skip placeholders
            if is_placeholder(supervision_period):
                continue

            if not supervision_period.termination_date:
                supervision_period.supervising_officer = person.supervising_officer
コード例 #8
0
def set_current_supervising_officer_from_supervision_periods(
        matched_persons: List[schema.StatePerson]):
    """For every matched person, update the supervising_officer field to pull in the supervising_officer from the latest
    supervision period (sorted by termination date).
    """
    for person in matched_persons:

        sps = get_all_entities_of_cls(person.sentence_groups, schema.StateSupervisionPeriod)

        non_placeholder_sps = [sp for sp in sps if not is_placeholder(sp)]

        if not non_placeholder_sps:
            continue

        non_placeholder_sps.sort(key=lambda sp: sp.termination_date if sp.termination_date else datetime.date.max)

        latest_supervision_period = non_placeholder_sps[-1]
        person.supervising_officer = latest_supervision_period.supervising_officer