Beispiel #1
0
    def test_compute_allegation_metric(self):
        officer = OfficerFactory(id=1, appointed_date=date(2010, 3, 14))

        OfficerAllegationFactory(
            officer=officer,
            allegation__incident_date=datetime(2014, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer,
            allegation__incident_date=datetime(2016, 1, 16, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory(
            officer=officer,
            allegation__incident_date=datetime(2016, 7, 2, tzinfo=pytz.utc),
        )

        officers = officer_percentile._compute_metric(
            2016, PERCENTILE_ALLEGATION_GROUP)
        expect(officers).to.have.length(1)
        validate_object(
            officers[0], {
                'officer_id': 1,
                'year': 2016,
                'start_date': date(2015, 1, 1),
                'end_date': date(2016, 7, 1),
                'service_year': 1.4986,
                'num_allegation': 3,
                'metric_allegation': 2.0019,
            })
    def test_extract_datum_most_common_category(self):
        allegation = AllegationFactory()
        cat1 = AllegationCategoryFactory(
            category='Use Of Forces',
            allegation_name='Sub Force'
        )
        cat2 = AllegationCategoryFactory(
            category='Traffic',
            allegation_name='Sub traffic'
        )
        OfficerAllegationFactory.create_batch(
            2,
            allegation=allegation,
            allegation_category=cat1
        )

        OfficerAllegationFactory(
            allegation=allegation,
            allegation_category=cat2
        )

        rows = self.extract_data()
        expect(rows).to.have.length(1)
        expect(rows[0]['most_common_category']).to.eq({
            'category': 'Use Of Forces',
            'allegation_name': 'Sub Force'
        })
Beispiel #3
0
    def test_coaccused_count(self):
        allegation_1 = AllegationFactory()
        allegation_2 = AllegationFactory()
        OfficerAllegationFactory.create_batch(6, allegation=allegation_1)
        allegation_cache_manager.cache_data()
        allegation_1.refresh_from_db()
        allegation_2.refresh_from_db()

        expect(allegation_1.coaccused_count).to.eq(6)
        expect(allegation_2.coaccused_count).to.eq(0)
 def test_coaccused_counts(self):
     officer = OfficerFactory()
     OfficerAllegationFactory.create_batch(2, officer=officer, final_finding='SU')
     OfficerAllegationFactory(officer=officer, final_finding='NS')
     rows = self.extract_data()
     expect(rows).to.have.length(3)
     for row in rows:
         expect(row['coaccused']).to.have.length(1)
         expect(row['coaccused'][0]['allegation_count']).to.eq(3)
         expect(row['coaccused'][0]['sustained_count']).to.eq(2)
Beispiel #5
0
    def test_new_timeline_item_no_join(self):
        officer = OfficerFactory(id=123, appointed_date=None, rank='Police Officer')

        unit = PoliceUnitFactory(unit_name='001', description='unit_001')
        OfficerHistoryFactory(officer=officer, unit=unit, effective_date=date(2010, 1, 1), end_date=date(2011, 12, 31))

        allegation = AllegationFactory(
            crid='123456',
            coaccused_count=4,
            incident_date=datetime(2011, 8, 23, tzinfo=pytz.utc)
        )
        OfficerAllegationFactory(
            final_finding='UN', final_outcome='Unknown',
            officer=officer, allegation=allegation,
            allegation_category=AllegationCategoryFactory(category='category', allegation_name='sub category')
        )
        OfficerAllegationFactory.create_batch(3, allegation=allegation)

        SalaryFactory(officer=officer, year=2001, rank='Police Officer', spp_date=date(2001, 9, 23))

        cache_managers.cache_all()

        response = self.client.get(reverse('api-v2:officers-new-timeline-items', kwargs={'pk': 123}))

        expect(response.status_code).to.eq(status.HTTP_200_OK)
        expect(response.data).to.eq([
            {
                'date': '2011-08-23',
                'kind': 'CR',
                'crid': '123456',
                'category': 'category',
                'subcategory': 'sub category',
                'finding': 'Unfounded',
                'outcome': 'Unknown',
                'coaccused': 4,
                'unit_name': '001',
                'unit_description': 'unit_001',
                'rank': 'Police Officer',
                'victims': [],
                'attachments': [],
            }, {
                'date': '2010-01-01',
                'kind': 'UNIT_CHANGE',
                'unit_name': '001',
                'unit_description': 'unit_001',
                'rank': 'Police Officer',
            }, {
                'date': '2001-09-23',
                'kind': 'RANK_CHANGE',
                'unit_name': '',
                'unit_description': '',
                'rank': 'Police Officer',
            }
        ])
    def test_allegation_count(self):
        officer_1 = OfficerFactory()
        officer_2 = OfficerFactory()
        OfficerAllegationFactory.create_batch(2, final_finding='NS', officer=officer_1)
        OfficerAllegationFactory(final_finding='SU', officer=officer_1)
        officer_cache_manager.build_cached_columns()
        officer_1.refresh_from_db()
        officer_2.refresh_from_db()

        expect(officer_1.allegation_count).to.eq(3)
        expect(officer_2.allegation_count).to.eq(0)
    def test_discipline_count(self):
        officer_1 = OfficerFactory()
        officer_2 = OfficerFactory()
        OfficerAllegationFactory.create_batch(2, officer=officer_1, disciplined=True)
        OfficerAllegationFactory(officer=officer_1, disciplined=False)
        OfficerAllegationFactory(officer=officer_2, disciplined=False)
        officer_cache_manager.build_cached_columns()
        officer_1.refresh_from_db()
        officer_2.refresh_from_db()

        expect(officer_1.discipline_count).to.eq(2)
        expect(officer_2.discipline_count).to.eq(0)
    def test_police_witness_counts(self):
        officer = OfficerFactory()
        OfficerAllegationFactory.create_batch(2, officer=officer, final_finding='SU')
        OfficerAllegationFactory(officer=officer, final_finding='NS')
        allegation = AllegationFactory()
        PoliceWitnessFactory(officer=officer, allegation=allegation)

        rows = self.extract_data()

        expect(rows).to.have.length(4)
        expect({len(row['involvements']) for row in rows}).to.eq({0, 1})
        for row in rows:
            if len(row['involvements']) == 1:
                expect(row['involvements'][0]['allegation_count']).to.eq(3)
                expect(row['involvements'][0]['sustained_count']).to.eq(2)
Beispiel #9
0
    def test_most_common_category(self):
        allegation = AllegationFactory()
        category1, category2 = AllegationCategoryFactory.create_batch(2)

        OfficerAllegationFactory(allegation=allegation,
                                 allegation_category=category2)
        OfficerAllegationFactory.create_batch(2,
                                              allegation=allegation,
                                              allegation_category=category1)
        OfficerAllegationFactory.create_batch(3,
                                              allegation=allegation,
                                              allegation_category=None)
        allegation_cache_manager.cache_data()
        allegation.refresh_from_db()

        expect(allegation.most_common_category).to.eq(category1)
Beispiel #10
0
    def test_get_coaccused(self, coaccused_serializer_mock):
        allegation = AllegationFactory()
        officer_allegations = OfficerAllegationFactory.create_batch(2, allegation=allegation)

        result = CRSerializer(allegation).data
        officer_allegations_arg = coaccused_serializer_mock.call_args[0][0]
        expect(set(officer_allegations_arg)).to.eq(set(officer_allegations))
        expect(result['coaccused']).to.eq([{'id': 1}, {'id': 2}])
Beispiel #11
0
    def test_count(self):
        officer = OfficerFactory()
        OfficerAllegationFactory.create_batch(2,
                                              officer=officer,
                                              final_finding='NS')
        OfficerAllegationFactory.create_batch(2,
                                              officer=officer,
                                              final_finding='SU')

        subquery = OfficerAllegation.objects.filter(
            officer=models.OuterRef('officer_id'))
        results = list(OfficerAllegation.objects.all().annotate(
            allegation_count=SQCount(subquery.values('id'))).annotate(
                sustained_count=SQCount(
                    subquery.filter(final_finding='SU').values('id'))).values(
                        'allegation_count', 'sustained_count'))

        expect(results).to.have.length(4)
        for obj in results:
            expect(obj['allegation_count']).to.eq(4)
            expect(obj['sustained_count']).to.eq(2)
    def setUp(self):
        violation_category = AllegationCategoryFactory(category='Operation/Personnel Violations')
        use_of_force_category = AllegationCategoryFactory(category='Use Of Force')
        illegal_search_category = AllegationCategoryFactory(category='Illegal Search')
        false_arrest_category = AllegationCategoryFactory(category='False Arrest')

        before_min_date = datetime(1987, 12, 31, tzinfo=pytz.utc)
        valid_date = datetime(1988, 12, 31, tzinfo=pytz.utc)
        today = datetime.now(pytz.utc)

        for date in [before_min_date, valid_date, today]:
            OfficerAllegationFactory.create_batch(
                4,
                allegation_category=violation_category,
                allegation__incident_date=date,
                disciplined=True)
            OfficerAllegationFactory.create_batch(
                3,
                allegation_category=use_of_force_category,
                allegation__incident_date=date,
                disciplined=True)
            OfficerAllegationFactory.create_batch(
                2,
                allegation_category=illegal_search_category,
                allegation__incident_date=date,
                disciplined=False)
            OfficerAllegationFactory(
                allegation_category=false_arrest_category,
                allegation__incident_date=date,
                final_outcome='900')
    def test_extract_datum_percentiles(self):
        officer1 = OfficerFactory(id=1, appointed_date=date(2013, 1, 1))
        officer2 = OfficerFactory(id=2, appointed_date=date(2015, 3, 14))
        OfficerFactory(id=3,
                       appointed_date=date(2014, 3, 1),
                       resignation_date=date(2015, 4, 14))

        OfficerAllegationFactory(officer=officer1,
                                 allegation__incident_date=datetime(
                                     2015, 1, 1, tzinfo=pytz.utc),
                                 start_date=date(2015, 1, 1),
                                 allegation__is_officer_complaint=False)
        OfficerAllegationFactory(officer=officer1,
                                 start_date=date(2015, 1, 1),
                                 allegation__incident_date=datetime(
                                     2015, 1, 1, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=False)
        OfficerAllegationFactory(officer=officer1,
                                 start_date=date(2016, 1, 22),
                                 allegation__incident_date=datetime(
                                     2016, 1, 1, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=False)
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer2,
            start_date=date(2017, 10, 19),
            allegation__incident_date=datetime(2016, 1, 16, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        OfficerAllegationFactory(officer=officer2,
                                 start_date=date(2017, 10, 19),
                                 allegation__incident_date=datetime(
                                     2016, 3, 15, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=True)
        OfficerAllegationFactory(officer=officer2,
                                 start_date=date(2017, 10, 19),
                                 allegation__incident_date=datetime(
                                     2017, 3, 15, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=True)
        TRRFactory(
            officer=officer1,
            trr_datetime=datetime(2017, 3, 15, tzinfo=pytz.utc),
        )
        TRRFactory(
            officer=officer1,
            trr_datetime=datetime(2016, 3, 15, tzinfo=pytz.utc),
        )
        rows = sorted(self.extract_data(), key=itemgetter('id'))
        expect(rows).to.have.length(3)
        expect(rows[0]['current_allegation_percentile']).to.eq('33.3333')
        expect(rows[0]['percentiles']).to.eq([{
            'id':
            1,
            'year':
            2014,
            'percentile_allegation':
            '0.0000',
            'percentile_allegation_civilian':
            '0.0000',
            'percentile_allegation_internal':
            '0.0000',
            'percentile_trr':
            '0.0000'
        }, {
            'id':
            1,
            'year':
            2015,
            'percentile_allegation':
            '50.0000',
            'percentile_allegation_civilian':
            '50.0000',
            'percentile_allegation_internal':
            '0.0000',
            'percentile_trr':
            '0.0000'
        }, {
            'id':
            1,
            'year':
            2016,
            'percentile_allegation':
            '33.3333',
            'percentile_allegation_civilian':
            '33.3333',
            'percentile_allegation_internal':
            '0.0000',
            'percentile_trr':
            '66.6667'
        }])
        expect(rows[1]['current_allegation_percentile']).to.eq('66.6667')
        expect(rows[1]['percentiles']).to.eq([{
            'id':
            2,
            'year':
            2016,
            'percentile_allegation':
            '66.6667',
            'percentile_allegation_civilian':
            '66.6667',
            'percentile_allegation_internal':
            '66.6667',
            'percentile_trr':
            '0.0000'
        }])
        expect(rows[2]['current_allegation_percentile']).to.eq('0.0000')
        expect(rows[2]['percentiles']).to.eq([{
            'id':
            3,
            'year':
            2015,
            'percentile_allegation':
            '0.0000',
            'percentile_allegation_civilian':
            '0.0000',
            'percentile_allegation_internal':
            '0.0000',
            'percentile_trr':
            '0.0000'
        }])
Beispiel #14
0
    def test_extract_datum(self):
        allegation = AllegationFactory(
            crid='123456',
            incident_date=datetime(2017, 7, 27, tzinfo=pytz.utc),
            summary='abc',
            add1='3000',
            add2='Michigan Ave',
            city='Chicago IL'
        )
        officer = OfficerFactory(
            id=10,
            first_name='Luke',
            last_name='Skywalker',
            allegation_count=4,
            complaint_percentile='99.70',
            trr_percentile='99.88',
            civilian_allegation_percentile='77.66',
            internal_allegation_percentile='66.55'
        )
        officer2 = OfficerFactory(
            id=11,
            first_name='John', last_name='Doe',
            allegation_count=2,
            complaint_percentile='70.33',
            trr_percentile='66.88',
            civilian_allegation_percentile='33.66',
            internal_allegation_percentile='22.55'
        )
        OfficerAllegationFactory(allegation=allegation, officer=officer)

        category1 = AllegationCategoryFactory(
            category='Operation/Personnel Violations',
            allegation_name='Secondary/Special Employment'
        )
        category2 = AllegationCategoryFactory(category='Use of Force', allegation_name='sub category')
        OfficerAllegationFactory(allegation=allegation, allegation_category=category2, officer=officer2)
        OfficerAllegationFactory.create_batch(2, allegation=allegation, allegation_category=category1, officer=None)
        OfficerAllegationFactory.create_batch(3, allegation=allegation, allegation_category=None, officer=None)

        VictimFactory(allegation=allegation, gender='F', race='Black', age=25)
        VictimFactory(allegation=allegation, gender='', race='Black', age=25)
        VictimFactory(allegation=allegation, gender='F', race='Black', age=None)

        AttachmentFileFactory(id=1, allegation=allegation, text_content='')
        AttachmentFileFactory(
            id=2, allegation=allegation, show=False,
            text_content="CHICAGO POLICE DEPARTMENT RD I HT334604"
        )
        AttachmentFileFactory(id=3, allegation=allegation, text_content='CHICAGO POLICE DEPARTMENT RD I HT334604')

        setattr(allegation, 'investigator_names', ['Jerome Finnigan'])
        allegation_cache_manager.cache_data()
        allegation.refresh_from_db()

        datum = CrIndexer().extract_datum(allegation)
        datum['victims'] = sorted(
            datum['victims'],
            key=lambda victim: (victim['gender'], victim['race'], victim.get('age', 0))
        )

        expect(datum).to.eq({
            'crid': '123456',
            'category': 'Operation/Personnel Violations',
            'sub_category': 'Secondary/Special Employment',
            'incident_date': '2017-07-27',
            'address': '3000 Michigan Ave, Chicago IL',
            'summary': 'abc',
            'to': '/complaint/123456/',
            'investigator_names': ['Jerome Finnigan'],
            'victims': [
                {'gender': '', 'race': 'Black', 'age': 25},
                {'gender': 'Female', 'race': 'Black'},
                {'gender': 'Female', 'race': 'Black', 'age': 25},
            ],
            'coaccused': [
                {
                    'id': 10, 'full_name': 'Luke Skywalker', 'allegation_count': 4,
                    'percentile_allegation': '99.7000',
                    'percentile_allegation_civilian': '77.6600',
                    'percentile_allegation_internal': '66.5500',
                    'percentile_trr': '99.8800',
                },
                {
                    'id': 11, 'full_name': 'John Doe', 'allegation_count': 2,
                    'percentile_allegation': '70.3300',
                    'percentile_allegation_civilian': '33.6600',
                    'percentile_allegation_internal': '22.5500',
                    'percentile_trr': '66.8800',
                }
            ],
            'attachment_files': [
                {'id': 3, 'text_content': 'CHICAGO POLICE DEPARTMENT RD I HT334604'}
            ]
        })
Beispiel #15
0
    def test_latest_year_percentile(self):
        officer1 = OfficerFactory(id=1, appointed_date=date(1990, 3, 14))
        officer2 = OfficerFactory(id=2,
                                  appointed_date=date(1990, 3, 14),
                                  resignation_date=date(2014, 7, 1))
        officer3 = OfficerFactory(id=3, appointed_date=date(1990, 3, 14))
        officer4 = OfficerFactory(id=4,
                                  appointed_date=date(1990, 3, 14),
                                  resignation_date=date(2010, 7, 1))

        # officer1 have all data
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer1,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer1,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True)
        OfficerAllegationFactory.create_batch(
            4,
            officer=officer1,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        TRRFactory.create_batch(2,
                                officer=officer1,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))
        AwardFactory(officer=officer1,
                     award_type='Complimentary Letter',
                     start_date=datetime(2013, 1, 1))
        AwardFactory.create_batch(3,
                                  officer=officer1,
                                  award_type='Honorable Mention',
                                  start_date=datetime(2015, 1, 1))

        # officer2 don't have trr
        OfficerAllegationFactory(
            officer=officer2,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory(officer=officer2,
                                 allegation__incident_date=datetime(
                                     2014, 7, 2, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=True)
        OfficerAllegationFactory(officer=officer2,
                                 allegation__incident_date=datetime(
                                     2014, 7, 2, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=False)
        AwardFactory(officer=officer2,
                     award_type='Complimentary Letter',
                     start_date=datetime(2013, 1, 1))
        AwardFactory.create_batch(3,
                                  officer=officer2,
                                  award_type='Honorable Mention',
                                  start_date=datetime(2014, 1, 1))

        # officer3 don't have allegation in ALLEGATION_MIN - ALLEGATION_MAX
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer3,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True)
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer3,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        TRRFactory.create_batch(3,
                                officer=officer3,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        # officer4 have all data but is out of data range
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer4,
            allegation__incident_date=datetime(2009, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer4,
            allegation__incident_date=datetime(2009, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True)
        OfficerAllegationFactory.create_batch(
            4,
            officer=officer4,
            allegation__incident_date=datetime(2009, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        TRRFactory.create_batch(2,
                                officer=officer4,
                                trr_datetime=datetime(2009,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        expected_dict = {
            1: {
                'officer_id': 1,
                'year': 2017,
                'metric_allegation': 3.0,
                'metric_allegation_civilian': 2.0,
                'metric_allegation_internal': 1.0,
                'metric_trr': 0.6667,
                'metric_honorable_mention': 1.0,
                'percentile_allegation': 66.6667,
                'percentile_allegation_civilian': 66.6667,
                'percentile_allegation_internal': 66.6667,
                'percentile_trr': 33.3333,
                'percentile_honorable_mention': 33.3333,
            },
            2: {
                'officer_id': 2,
                'year': 2014,
                'metric_allegation': 2.0055,
                'metric_allegation_civilian': 1.337,
                'metric_allegation_internal': 0.6685,
                'metric_trr': 0.0,
                'metric_honorable_mention': 2.0055,
                'percentile_allegation': 66.6667,
                'percentile_allegation_civilian': 66.6667,
                'percentile_allegation_internal': 66.6667,
                'percentile_trr': 0.0,
                'percentile_honorable_mention': 66.6667
            },
            3: {
                'officer_id': 3,
                'year': 2017,
                'metric_allegation': 1.6667,
                'metric_allegation_civilian': 1.0,
                'metric_allegation_internal': 0.6667,
                'metric_trr': 1.0,
                'metric_honorable_mention': 0.0,
                'percentile_allegation': 0.0,
                'percentile_allegation_civilian': 0.0,
                'percentile_allegation_internal': 0.0,
                'percentile_trr': 66.6667,
                'percentile_honorable_mention': 0.0
            }
        }

        officers = officer_percentile.latest_year_percentile()
        expect(officers).to.have.length(3)
        for officer in officers:
            validate_object(officer, expected_dict[officer.id])
Beispiel #16
0
    def test_top_percentile_not_enough_service_year(self):
        officer1 = OfficerFactory(id=1, appointed_date=date(1990, 3, 14))
        officer2 = OfficerFactory(id=2,
                                  appointed_date=date(1990, 3, 14),
                                  resignation_date=date(2014, 5, 1))
        officer3 = OfficerFactory(id=3, appointed_date=date(2013, 3, 14))
        officer4 = OfficerFactory(id=4,
                                  appointed_date=date(1990, 3, 14),
                                  resignation_date=date(2015, 5, 1))

        # officer1 have all data
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer1,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer1,
            allegation__incident_date=datetime(2014, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True)
        OfficerAllegationFactory.create_batch(
            4,
            officer=officer1,
            allegation__incident_date=datetime(2014, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        TRRFactory.create_batch(2,
                                officer=officer1,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        # officer2 don't have trr
        OfficerAllegationFactory(
            officer=officer2,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory(officer=officer2,
                                 allegation__incident_date=datetime(
                                     2014, 2, 2, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=True)
        OfficerAllegationFactory(officer=officer2,
                                 allegation__incident_date=datetime(
                                     2014, 3, 2, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=False)

        # officer3 don't have allegation in ALLEGATION_MIN - ALLEGATION_MAX
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer3,
            allegation__incident_date=datetime(2014, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True)
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer3,
            allegation__incident_date=datetime(2014, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        TRRFactory.create_batch(3,
                                officer=officer3,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        # officer4 don't have allegation in INTERNAL_CIVILIAN_ALLEGATION year range
        OfficerAllegationFactory.create_batch(
            5,
            officer=officer4,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        TRRFactory.create_batch(6,
                                officer=officer4,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        expected_dict = {
            1: {
                'officer_id': 1,
                'year': 2016,
                'metric_allegation': 2,
                'metric_allegation_civilian': 4,
                'metric_allegation_internal': 3,
                'metric_trr': 2,
                'percentile_allegation': 33.3333,
                'percentile_allegation_civilian': 66.6667,
                'percentile_allegation_internal': 66.6667,
                'percentile_trr': 0.0
            },
            2: {
                'officer_id': 2,
                'year': 2016,
                'metric_allegation': 1,
                'metric_allegation_civilian': None,
                'metric_allegation_internal': None,
                'metric_trr': None,
                'percentile_allegation': 0.0,
                'percentile_allegation_civilian': None,
                'percentile_allegation_internal': None,
                'percentile_trr': None
            },
            3: {
                'officer_id': 3,
                'year': 2016,
                'metric_allegation': None,
                'metric_allegation_civilian': 3,
                'metric_allegation_internal': 2,
                'metric_trr': 3,
                'percentile_allegation': None,
                'percentile_allegation_civilian': 33.3333,
                'percentile_allegation_internal': 33.3333,
                'percentile_trr': 50.0
            },
            4: {
                'officer_id': 4,
                'year': 2016,
                'metric_allegation': 5,
                'metric_allegation_civilian': 0.0,
                'metric_allegation_internal': 0.0,
                'metric_trr': None,
                'percentile_allegation': 66.6667,
                'percentile_allegation_civilian': 0.0,
                'percentile_allegation_internal': 0.0,
                'percentile_trr': None
            }
        }

        officers = officer_percentile.top_percentile(2016)
        for officer in officers:
            validate_object(officer, expected_dict[officer.id])
Beispiel #17
0
    def test_top_percentile_with_types(self):
        officer1 = OfficerFactory(id=1, appointed_date=date(1990, 3, 14))
        officer2 = OfficerFactory(id=2, appointed_date=date(1990, 3, 14))
        officer3 = OfficerFactory(id=3, appointed_date=date(1990, 3, 14))
        officer4 = OfficerFactory(id=4, appointed_date=date(1990, 3, 14))

        # officer1 have all data
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer1,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer1,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True)
        OfficerAllegationFactory.create_batch(
            4,
            officer=officer1,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        TRRFactory.create_batch(2,
                                officer=officer1,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        # officer2 don't have trr
        OfficerAllegationFactory(
            officer=officer2,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory(officer=officer2,
                                 allegation__incident_date=datetime(
                                     2015, 7, 2, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=True)
        OfficerAllegationFactory(officer=officer2,
                                 allegation__incident_date=datetime(
                                     2015, 7, 2, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=False)

        # officer3 don't have allegation in ALLEGATION_MIN - ALLEGATION_MAX
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer3,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True)
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer3,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        TRRFactory.create_batch(3,
                                officer=officer3,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        # officer4 don't have allegation in INTERNAL_CIVILIAN_ALLEGATION year range
        OfficerAllegationFactory.create_batch(
            5,
            officer=officer4,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        TRRFactory.create_batch(6,
                                officer=officer4,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        expected_dict = {
            1: {
                'officer_id': 1,
                'year': 2016,
                'metric_allegation_civilian': 4,
                'metric_allegation_internal': 3,
                'metric_trr': 2,
                'percentile_allegation': None,
                'percentile_allegation_civilian': 75.0,
                'percentile_allegation_internal': 75.0,
                'percentile_trr': 25.0
            },
            2: {
                'officer_id': 2,
                'year': 2016,
                'metric_allegation_civilian': 1,
                'metric_allegation_internal': 1,
                'metric_trr': 0.0,
                'percentile_allegation': None,
                'percentile_allegation_civilian': 25.0,
                'percentile_allegation_internal': 25.0,
                'percentile_trr': 0.0
            },
            3: {
                'officer_id': 3,
                'year': 2016,
                'metric_allegation_civilian': 3,
                'metric_allegation_internal': 2,
                'metric_trr': 3,
                'percentile_allegation': None,
                'percentile_allegation_civilian': 50.0,
                'percentile_allegation_internal': 50.0,
                'percentile_trr': 50.0
            },
            4: {
                'officer_id': 4,
                'year': 2016,
                'metric_allegation_civilian': 0.0,
                'metric_allegation_internal': 0.0,
                'metric_trr': 6,
                'percentile_allegation': None,
                'percentile_allegation_civilian': 0.0,
                'percentile_allegation_internal': 0.0,
                'percentile_trr': 75.0
            }
        }

        visual_token_percentile_groups = [
            PERCENTILE_ALLEGATION_INTERNAL_CIVILIAN_GROUP, PERCENTILE_TRR_GROUP
        ]
        officers = officer_percentile.top_percentile(
            2016, percentile_groups=visual_token_percentile_groups)
        for officer in officers:
            validate_object(officer, expected_dict[officer.id])
Beispiel #18
0
    def test_top_percentile(self):
        officer1 = OfficerFactory(id=1, appointed_date=date(1990, 3, 14))
        officer2 = OfficerFactory(id=2, appointed_date=date(1990, 3, 14))
        officer3 = OfficerFactory(id=3, appointed_date=date(1990, 3, 14))

        # officer1 have all data
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer1,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer1,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True)
        OfficerAllegationFactory.create_batch(
            4,
            officer=officer1,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        TRRFactory.create_batch(2,
                                officer=officer1,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        # officer2 don't have trr
        OfficerAllegationFactory(
            officer=officer2,
            allegation__incident_date=datetime(2013, 12, 31, tzinfo=pytz.utc),
        )
        OfficerAllegationFactory(officer=officer2,
                                 allegation__incident_date=datetime(
                                     2015, 7, 2, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=True)
        OfficerAllegationFactory(officer=officer2,
                                 allegation__incident_date=datetime(
                                     2015, 7, 2, tzinfo=pytz.utc),
                                 allegation__is_officer_complaint=False)

        # officer3 don't have allegation in ALLEGATION_MIN - ALLEGATION_MAX
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer3,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True)
        OfficerAllegationFactory.create_batch(
            3,
            officer=officer3,
            allegation__incident_date=datetime(2015, 7, 2, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        TRRFactory.create_batch(3,
                                officer=officer3,
                                trr_datetime=datetime(2015,
                                                      2,
                                                      1,
                                                      tzinfo=pytz.utc))

        expected_dict = {
            1: {
                'officer_id': 1,
                'year': 2016,
                'metric_allegation': 2,
                'metric_allegation_civilian': 4,
                'metric_allegation_internal': 3,
                'metric_trr': 2,
                'percentile_allegation': 66.6667,
                'percentile_allegation_civilian': 66.6667,
                'percentile_allegation_internal': 66.6667,
                'percentile_trr': 33.3333
            },
            2: {
                'officer_id': 2,
                'year': 2016,
                'metric_allegation': 1,
                'metric_allegation_civilian': 1,
                'metric_allegation_internal': 1,
                'metric_trr': 0.0,
                'percentile_allegation': 33.3333,
                'percentile_allegation_civilian': 0.0000,
                'percentile_allegation_internal': 0.0000,
                'percentile_trr': 0.0
            },
            3: {
                'officer_id': 3,
                'year': 2016,
                'metric_allegation': 0.0,
                'metric_allegation_civilian': 3,
                'metric_allegation_internal': 2,
                'metric_trr': 3,
                'percentile_allegation': 0.0,
                'percentile_allegation_civilian': 33.3333,
                'percentile_allegation_internal': 33.3333,
                'percentile_trr': 66.6667,
            }
        }

        officers = officer_percentile.top_percentile(2016)
        for officer in officers:
            validate_object(officer, expected_dict[officer.id])
    def test_build_cached_yearly_percentiles(self):
        officer_1 = OfficerFactory(id=1, appointed_date=date(2013, 1, 1))
        officer_2 = OfficerFactory(id=2, appointed_date=date(2015, 3, 14))
        officer_3 = OfficerFactory(id=3, appointed_date=date(2014, 3, 1), resignation_date=date(2015, 4, 14))

        OfficerAllegationFactory(
            officer=officer_1,
            allegation__incident_date=datetime(2015, 1, 1, tzinfo=pytz.utc),
            start_date=datetime(2015, 1, 1),
            allegation__is_officer_complaint=False)
        OfficerAllegationFactory(
            officer=officer_1,
            start_date=date(2015, 1, 1),
            allegation__incident_date=datetime(2015, 1, 1, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        OfficerAllegationFactory(
            officer=officer_1,
            start_date=date(2016, 1, 22),
            allegation__incident_date=datetime(2016, 1, 1, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False)
        OfficerAllegationFactory.create_batch(
            2,
            officer=officer_2,
            start_date=date(2017, 10, 19),
            allegation__incident_date=datetime(2016, 1, 16, tzinfo=pytz.utc),
            allegation__is_officer_complaint=False
        )
        OfficerAllegationFactory(
            officer=officer_2,
            start_date=date(2017, 10, 19),
            allegation__incident_date=datetime(2016, 3, 15, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True
        )
        OfficerAllegationFactory(
            officer=officer_2,
            start_date=date(2017, 10, 19),
            allegation__incident_date=datetime(2017, 3, 15, tzinfo=pytz.utc),
            allegation__is_officer_complaint=True
        )
        TRRFactory(
            officer=officer_1,
            trr_datetime=datetime(2017, 3, 15, tzinfo=pytz.utc),
        )
        TRRFactory(
            officer=officer_1,
            trr_datetime=datetime(2016, 3, 15, tzinfo=pytz.utc),
        )
        officer_cache_manager.build_cached_yearly_percentiles()

        expected_officer_yearly_percentiles = {
            officer_1.id: {
                2014: {
                    'percentile_allegation': Decimal(0.0),
                    'percentile_allegation_civilian': Decimal(0.0),
                    'percentile_allegation_internal': Decimal(0.0),
                    'percentile_trr': Decimal(0.0),
                },
                2015: {
                    'percentile_allegation': Decimal(50.0),
                    'percentile_allegation_civilian': Decimal(50.0),
                    'percentile_allegation_internal': Decimal(0.0),
                    'percentile_trr': Decimal(0.0),
                },
                2016: {
                    'percentile_allegation': Decimal(33.3333),
                    'percentile_allegation_civilian': Decimal(33.3333),
                    'percentile_allegation_internal': Decimal(0.0),
                    'percentile_trr': Decimal(66.6667),
                }
            },
            officer_2.id: {
                2016: {
                    'percentile_allegation': Decimal(66.6667),
                    'percentile_allegation_civilian': Decimal(66.6667),
                    'percentile_allegation_internal': Decimal(66.6667),
                    'percentile_trr': Decimal(0.0),
                }
            },
            officer_3.id: {
                2015: {
                    'percentile_allegation': Decimal(0.0),
                    'percentile_allegation_civilian': Decimal(0.0),
                    'percentile_allegation_internal': Decimal(0.0),
                    'percentile_trr': Decimal(0.0),
                }
            }
        }
        for officer_id, expected_yearly_percentiles in expected_officer_yearly_percentiles.items():
            yearly_percentiles = OfficerYearlyPercentile.objects.filter(officer_id=officer_id)
            expect(yearly_percentiles.count()).to.eq(len(expected_yearly_percentiles.keys()))
            for year, expected_percentile in expected_yearly_percentiles.items():
                percentile = yearly_percentiles.get(year=year)
                for attr, value in expected_percentile.items():
                    expect(f'{getattr(percentile, attr):.2f}').to.eq(f'{value:.2f}')
Beispiel #20
0
    def test_new_timeline_item(self):
        officer = OfficerFactory(id=123, appointed_date=date(2000, 1, 1), rank='Police Officer')

        unit1 = PoliceUnitFactory(unit_name='001', description='unit_001')
        unit2 = PoliceUnitFactory(unit_name='002', description='unit_002')
        OfficerHistoryFactory(officer=officer, unit=unit1, effective_date=date(2010, 1, 1), end_date=date(2011, 12, 31))
        OfficerHistoryFactory(officer=officer, unit=unit2, effective_date=date(2012, 1, 1), end_date=None)

        AwardFactory(officer=officer, start_date=date(2011, 3, 23), award_type='Honorable Mention')
        AwardFactory(officer=officer, start_date=date(2015, 3, 23), award_type='Complimentary Letter')
        AwardFactory(officer=officer, start_date=date(2011, 3, 23), award_type='Life Saving Award')
        allegation = AllegationFactory(
            crid='123456',
            coaccused_count=4,
            incident_date=datetime(2011, 8, 23, tzinfo=pytz.utc)
        )
        VictimFactory(allegation=allegation, gender='M', race='White', age=34)
        OfficerAllegationFactory(
            final_finding='UN', final_outcome='Unknown',
            officer=officer, allegation=allegation,
            allegation_category=AllegationCategoryFactory(category='category', allegation_name='sub category')
        )
        OfficerAllegationFactory.create_batch(3, allegation=allegation)

        allegation2 = AllegationFactory(
            crid='654321',
            point=Point(35.5, 68.9),
            coaccused_count=1,
            incident_date=datetime(2015, 8, 23, tzinfo=pytz.utc)
        )
        OfficerAllegationFactory(
            final_finding='UN', final_outcome='9 Day Suspension',
            officer=officer, allegation=allegation2,
            allegation_category=AllegationCategoryFactory(category='Use of Force', allegation_name='sub category')
        )

        trr2011 = TRRFactory(
            officer=officer,
            trr_datetime=datetime(2011, 9, 23, tzinfo=pytz.utc),
            taser=True,
            firearm_used=False
        )
        trr2015 = TRRFactory(
            officer=officer,
            trr_datetime=datetime(2015, 9, 23, tzinfo=pytz.utc),
            taser=False,
            firearm_used=False
        )
        SalaryFactory(officer=officer, year=2001, rank='Police Officer', spp_date=date(2001, 9, 23))
        SalaryFactory(officer=officer, year=2000, rank='Junior Police Officer', spp_date=date(2000, 1, 1))

        cache_managers.cache_all()

        response = self.client.get(reverse('api-v2:officers-new-timeline-items', kwargs={'pk': 123}))

        expect(response.status_code).to.eq(status.HTTP_200_OK)
        expect(response.data).to.eq([
            {
                'trr_id': trr2015.id,
                'date': '2015-09-23',
                'kind': 'FORCE',
                'taser': False,
                'firearm_used': False,
                'unit_name': '002',
                'unit_description': 'unit_002',
                'rank': 'Police Officer',
            }, {
                'date': '2015-08-23',
                'kind': 'CR',
                'crid': '654321',
                'category': 'Use of Force',
                'subcategory': 'sub category',
                'finding': 'Unfounded',
                'outcome': '9 Day Suspension',
                'coaccused': 1,
                'unit_name': '002',
                'unit_description': 'unit_002',
                'rank': 'Police Officer',
                'point': {
                    'lon': 35.5,
                    'lat': 68.9
                },
                'victims': [],
                'attachments': []
            }, {
                'date': '2012-01-01',
                'kind': 'UNIT_CHANGE',
                'unit_name': '002',
                'unit_description': 'unit_002',
                'rank': 'Police Officer',
            }, {
                'trr_id': trr2011.id,
                'date': '2011-09-23',
                'kind': 'FORCE',
                'taser': True,
                'firearm_used': False,
                'unit_name': '001',
                'unit_description': 'unit_001',
                'rank': 'Police Officer',
            }, {
                'date': '2011-08-23',
                'kind': 'CR',
                'crid': '123456',
                'category': 'category',
                'subcategory': 'sub category',
                'finding': 'Unfounded',
                'outcome': 'Unknown',
                'coaccused': 4,
                'unit_name': '001',
                'unit_description': 'unit_001',
                'rank': 'Police Officer',
                'victims': [
                    {
                        'race': 'White',
                        'age': 34,
                        'gender': 'Male',
                    }
                ],
                'attachments': [],
            }, {
                'date': '2011-03-23',
                'kind': 'AWARD',
                'award_type': 'Life Saving Award',
                'unit_name': '001',
                'unit_description': 'unit_001',
                'rank': 'Police Officer',
            }, {
                'date': '2010-01-01',
                'kind': 'UNIT_CHANGE',
                'unit_name': '001',
                'unit_description': 'unit_001',
                'rank': 'Police Officer',
            }, {
                'date': '2001-09-23',
                'kind': 'RANK_CHANGE',
                'unit_name': '',
                'unit_description': '',
                'rank': 'Police Officer',
            }, {
                'date': '2000-01-01',
                'kind': 'JOINED',
                'unit_name': '',
                'unit_description': '',
                'rank': 'Junior Police Officer',
            },
        ])
Beispiel #21
0
    def test_list_item_content(self):
        officer1 = OfficerFactory(
            first_name='Jerome',
            last_name='Finnigan',
            birth_year=1950,
            race='Asian',
            gender='M',
            appointed_date=datetime(2011, 1, 1, tzinfo=pytz.utc),
            complaint_percentile=50.0,
            allegation_count=6,
            sustained_count=2,
            rank='Police Officer',
        )
        officer2 = OfficerFactory(
            first_name='Raymond',
            last_name='Piwinicki',
            birth_year=1960,
            race='White',
            gender='M',
            appointed_date=datetime(2012, 1, 1, tzinfo=pytz.utc),
            complaint_percentile=0.0,
            allegation_count=1,
            sustained_count=1,
            rank='Police Officer',
        )
        allegation = AllegationFactory(incident_date=datetime(2014, 1, 1, tzinfo=pytz.utc))
        OfficerAllegationFactory(
            officer=officer1,
            allegation=allegation,
            final_finding='SU',
            start_date=date(2014, 1, 1),
        )
        OfficerAllegationFactory(
            officer=officer2,
            allegation=allegation,
            final_finding='SU',
            start_date=date(2014, 1, 1),
        )
        OfficerAllegationFactory(
            officer=officer1,
            final_finding='SU',
            allegation__incident_date=datetime(2016, 1, 1, tzinfo=pytz.utc),
            start_date=date(2016, 1, 1)
        )
        OfficerAllegationFactory.create_batch(
            4,
            officer=officer1,
            final_finding='NS',
            start_date=date(2015, 1, 1),
            allegation__incident_date=datetime(2015, 2, 20, tzinfo=pytz.utc)
        )
        ActivityCardFactory(officer=officer1, last_activity=datetime(2018, 12, 22, tzinfo=pytz.utc))
        ActivityCardFactory(officer=officer2, last_activity=datetime(2018, 10, 15, tzinfo=pytz.utc))
        ActivityPairCardFactory(
            officer1=officer1, officer2=officer2, last_activity=datetime(2018, 5, 20, tzinfo=pytz.utc)
        )

        cache_all()

        url = reverse('api-v2:activity-grid-list')
        response = self.client.get(url)

        expect(response.status_code).to.eq(status.HTTP_200_OK)
        expect(response.data).to.eq([{
            'id': officer1.id,
            'full_name': 'Jerome Finnigan',
            'complaint_count': 6,
            'sustained_count': 2,
            'birth_year': 1950,
            'race': 'Asian',
            'gender': 'Male',
            'rank': 'Police Officer',
            'percentile_trr': '0.0000',
            'percentile_allegation_internal': '0.0000',
            'percentile_allegation_civilian': '50.0000',
            'percentile_allegation': '50.0000',
            'kind': 'single_officer',
        }, {
            'id': officer2.id,
            'full_name': 'Raymond Piwinicki',
            'complaint_count': 1,
            'sustained_count': 1,
            'birth_year': 1960,
            'race': 'White',
            'gender': 'Male',
            'rank': 'Police Officer',
            'percentile_trr': '0.0000',
            'percentile_allegation_internal': '0.0000',
            'percentile_allegation_civilian': '0.0000',
            'percentile_allegation': '0.0000',
            'kind': 'single_officer',
        }, {
            'officer1': {
                'id': officer1.id,
                'full_name': 'Jerome Finnigan',
                'birth_year': 1950,
                'race': 'Asian',
                'gender': 'Male',
                'rank': 'Police Officer',
                'percentile_trr': '0.0000',
                'percentile_allegation_internal': '0.0000',
                'percentile_allegation_civilian': '50.0000',
                'percentile_allegation': '50.0000',
                'complaint_count': 6,
                'sustained_count': 2,
            },
            'officer2': {
                'id': officer2.id,
                'full_name': 'Raymond Piwinicki',
                'birth_year': 1960,
                'race': 'White',
                'gender': 'Male',
                'rank': 'Police Officer',
                'percentile_trr': '0.0000',
                'percentile_allegation_internal': '0.0000',
                'percentile_allegation_civilian': '0.0000',
                'percentile_allegation': '0.0000',
                'complaint_count': 1,
                'sustained_count': 1,
            },
            'coaccusal_count': 1,
            'kind': 'coaccused_pair',
        }])