def setUp(self): user_details = { 'username': '******', 'password': '******', 'email': '*****@*****.**', 'first_name': 'Test', 'last_name': 'User', } self.user = User.objects.create_user(**user_details) self.org_a, _, _ = create_organization(self.user) self.org_b, _, _ = create_organization(self.user) cycle_a = FakeCycleFactory(organization=self.org_a, user=self.user).get_cycle(name="Cycle Org A") cycle_b = FakeCycleFactory(organization=self.org_b, user=self.user).get_cycle(name="Cycle Org B") self.analysis_a = ( FakeAnalysisFactory(organization=self.org_a, user=self.user).get_analysis( name='Quite neat', service=Analysis.BSYNCR, ) ) view_factory_a = FakePropertyViewFactory(cycle=cycle_a, organization=self.org_a, user=self.user) self.property_views_a = [ view_factory_a.get_property_view( # override unitted fields so that hashes are correct site_eui=ureg.Quantity( float(view_factory_a.fake.random_int(min=50, max=600)), "kilobtu / foot ** 2 / year" ), gross_floor_area=ureg.Quantity( float(view_factory_a.fake.random_number(digits=6)), "foot ** 2" ), ) for i in range(2)] view_factory_b = FakePropertyViewFactory(cycle=cycle_b, organization=self.org_b, user=self.user) self.property_views_b = [ view_factory_b.get_property_view( # override unitted fields so that hashes are correct site_eui=ureg.Quantity( float(view_factory_b.fake.random_int(min=50, max=600)), "kilobtu / foot ** 2 / year" ), gross_floor_area=ureg.Quantity( float(view_factory_b.fake.random_number(digits=6)), "foot ** 2" ), ) for i in range(2)]
class TestNotes(TestCase): def setUp(self): self.user = User.objects.create_superuser('*****@*****.**', '*****@*****.**', 'test_pass') self.org, _, _ = create_organization(self.user) # Fake Factories self.property_view_factory = FakePropertyViewFactory( organization=self.org) self.note_factory = FakeNoteFactory(organization=self.org, user=self.user) def test_note_assignments(self): """Make sure that properties can contain notes""" pv = self.property_view_factory.get_property_view( organization=self.org) note1 = self.note_factory.get_note() note2 = self.note_factory.get_note() pv.notes.add(note1) pv.notes.add(note2) self.assertTrue(pv) self.assertIn(note1, pv.notes.all()) self.assertIn(note2, pv.notes.all())
class TestNotes(TestCase): def setUp(self): user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org = Organization.objects.create() OrganizationUser.objects.create(user=self.user, organization=self.org) # Fake Factories self.property_view_factory = FakePropertyViewFactory( organization=self.org) self.note_factory = FakeNoteFactory(organization=self.org, user=self.user) def test_note_assignments(self): """Make sure that properties can contain notes""" pv = self.property_view_factory.get_property_view( organization=self.org) note1 = self.note_factory.get_note() note2 = self.note_factory.get_note() pv.notes.add(note1) pv.notes.add(note2) self.assertTrue(pv) self.assertIn(note1, pv.notes.all()) self.assertIn(note2, pv.notes.all())
def test_labels_inventory_specific_filter_endpoint_provides_IDs_for_records_where_label_is_applied(self): user = User.objects.create_superuser( email='*****@*****.**', username='******', password='******', ) organization_a, _, _ = create_organization(user, "test-organization-a") # Ensures that at least a single label exists to ensure that we are not # relying on auto-creation of labels for this test to pass. new_label = Label.objects.create( color="red", name="test_label-a", super_organization=organization_a, ) # Create 2 properties and 2 tax lots. Then, apply that label to one of each property_view_factory = FakePropertyViewFactory(organization=organization_a, user=user) p_view_1 = property_view_factory.get_property_view() p_view_1.labels.add(new_label) property_view_factory.get_property_view() taxlot_view_factory = FakeTaxLotViewFactory(organization=organization_a, user=user) tl_view_1 = taxlot_view_factory.get_taxlot_view() tl_view_1.labels.add(new_label) taxlot_view_factory.get_taxlot_view() client = APIClient() client.login(username=user.username, password='******') url = reverse('api:v3:properties-labels') response_a = client.post(url + '?organization_id={}'.format(organization_a.pk)) data = json.loads(response_a.content) for label in data: if label.get('name') != 'test_label-a': self.assertCountEqual(label.get('is_applied'), []) else: self.assertCountEqual(label.get('is_applied'), [p_view_1.id])
class TestGreenAssessmentPropertySerializer(DeleteModelsTestCase): def setUp(self): self.maxDiff = None user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org, _, _ = create_organization(self.user) self.property_view_factory = FakePropertyViewFactory( organization=self.org, user=self.user) self.ga_factory = FakeGreenAssessmentFactory(organization=self.org) self.gap_factory = FakeGreenAssessmentPropertyFactory( organization=self.org, user=self.user) self.assessment = self.ga_factory.get_green_assessment() self.property_view = self.property_view_factory.get_property_view() self.data = { 'source': 'test', 'status': 'complete', 'status_date': '2017-01-01', 'metric': 5, 'version': '0.1', 'date': '2016-01-01', 'eligibility': True, 'assessment': self.assessment, 'view': self.property_view, } self.urls = ['http://example.com', 'http://example.org'] @mock.patch('seed.serializers.certification.GreenAssessmentURL') def test_create(self, mock_url_model): """Test (overridden) create method.""" serializer = GreenAssessmentPropertySerializer() data = self.data.copy() data['urls'] = self.urls instance = serializer.create(data) mock_url_model.objects.bulk_create.assert_called_with([ mock_url_model(property_assessment=instance, url=url[0], description=url[1]) for url in self.urls ]) @mock.patch('seed.serializers.certification.GreenAssessmentURL') def test_update(self, mock_url_model): """Test (overridden) update method.""" data = self.data.copy() data['urls'] = self.urls[:1] gap = self.gap_factory.get_green_assessment_property(**data) serializer = GreenAssessmentPropertySerializer() data['urls'] = self.urls[1:] instance = serializer.update(gap, data) mock_url_model.objects.filter.assert_called_with( property_assessment=instance) mock_url_model.assert_called_with(url='http://example.org', property_assessment=gap) def test_validate(self): """Test (overriden) validate method""" serializer = GreenAssessmentPropertySerializer() # add context mock_request = mock.MagicMock() mock_request.user = self.user serializer.context = {'request': mock_request} # assert raises error if rating and metric supplied data = self.data.copy() data['rating'] = 'Gold Star' with self.assertRaises(ValidationError) as conm: serializer.validate(data) exception = conm.exception expected = "['Only one of metric or rating can be supplied.']" self.assertEqual(expected, str(exception)) # assert raises error if metric is expected del data['metric'] data['rating'] = '5' with self.assertRaises(ValidationError) as conm: serializer.validate(data) exception = conm.exception expected = "['{} uses a metric (numeric score).']".format( self.assessment.name) self.assertEqual(expected, str(exception)) # assert raises error if metric is of wrong type del data['rating'] data['metric'] = '5 stars' with self.assertRaises(ValidationError) as conm: serializer.validate(data) exception = conm.exception expected = "['Metric must be a number.']" self.assertEqual(expected, str(exception)) # assert raises error if rating expected self.assessment.is_numeric_score = False data['metric'] = 5 with self.assertRaises(ValidationError) as conm: serializer.validate(data) exception = conm.exception expected = "['{} uses a rating (non-numeric score).']".format( self.assessment.name) # assert raises error if rating is of wrong type del data['metric'] data['rating'] = 5 with self.assertRaises(ValidationError) as conm: serializer.validate(data) exception = conm.exception expected = "['Rating must be a string.']" self.assertEqual(expected, str(exception)) # assert converts ints to floats self.assessment.is_numeric_score = True del data['rating'] data['metric'] = 5 result = serializer.validate(data) self.assertEqual(result, data) # assert raises error if integer expected data['metric'] = 3.5 with self.assertRaises(ValidationError) as conm: serializer.validate(data) exception = conm.exception expected = "['Metric must be an integer.']" self.assertEqual(expected, str(exception)) # assert raises error if assessment missing del data['assessment'] with self.assertRaises(ValidationError) as conm: serializer.validate(data) exception = conm.exception expected = "['Could not find assessment.']" self.assertEqual(expected, str(exception))
class NoteViewTests(TestCase): def setUp(self): user_details = { 'username': '******', 'password': '******', 'email': '*****@*****.**', } self.user = User.objects.create_superuser(**user_details) self.org = Organization.objects.create() OrganizationUser.objects.create(user=self.user, organization=self.org) # Fake Factories self.property_view_factory = FakePropertyViewFactory( organization=self.org) self.taxlot_view_factory = FakeTaxLotViewFactory(organization=self.org) self.note_factory = FakeNoteFactory(organization=self.org, user=self.user) self.client.login(**user_details) # create a property view with some notes self.pv = self.property_view_factory.get_property_view( organization=self.org) self.note1 = self.note_factory.get_note() self.note2 = self.note_factory.get_log_note() self.pv.notes.add(self.note1) self.pv.notes.add(self.note2) # create a taxlot with some views self.tl = self.taxlot_view_factory.get_taxlot_view( organization=self.org) self.note3 = self.note_factory.get_note() self.note4 = self.note_factory.get_log_note() self.tl.notes.add(self.note3) self.tl.notes.add(self.note4) def test_get_notes_property(self): url = reverse('api:v2.1:property-notes-list', args=[self.pv.pk]) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) result = json.loads(response.content) results = result['results'] self.assertEqual(len(results), 2) self.assertEqual(results[0]['note_type'], 'Log') self.assertEqual(results[0]['user_id'], self.user.pk) # most recent log is displayed first expected_log_data = { u'property_state': [{ u'field': u'address_line_1', u'previous_value': u'123 Main Street', u'new_value': u'742 Evergreen Terrace' }] } self.assertEqual(results[0]['log_data'], expected_log_data) self.assertEqual(results[1]['note_type'], 'Note') def test_create_note_property(self): url = reverse('api:v2.1:property-notes-list', args=[self.pv.pk]) payload = { "note_type": "Note", "name": "A New Note", "text": "This building is much bigger than reported", } response = self.client.post(url, data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) result = json.loads(response.content) # check that the note was attached to the property self.assertEqual(result['note_type'], 'Note') self.assertEqual(result['text'], payload['text']) self.assertEqual(result['property_view_id'], self.pv.pk) self.assertIsNone(result['taxlot_view_id']) self.assertEqual(result['organization_id'], self.org.pk) self.assertEqual(result['user_id'], self.user.pk) def test_create_note_taxlot(self): url = reverse('api:v2.1:taxlot-notes-list', args=[self.tl.pk]) payload = { "note_type": "Note", "name": "A New Note", "text": "The taxlot is not correct", } response = self.client.post(url, data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) result = json.loads(response.content) # check that the note was attached to the property self.assertEqual(result['note_type'], 'Note') self.assertEqual(result['text'], payload['text']) self.assertIsNone(result['property_view_id']) self.assertEqual(result['taxlot_view_id'], self.tl.pk) def test_update_note(self): url = reverse('api:v2.1:taxlot-notes-detail', args=[self.tl.pk, self.note3.pk]) payload = {"name": "update, validation should fail"} response = self.client.put(url, data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( json.loads(response.content), { "text": ["This field is required."], "note_type": ["This field is required."] }) payload = { "name": "update", "text": "new data with put", "note_type": "Note" } response = self.client.put(url, data=json.dumps(payload), content_type='application/json') result = json.loads(response.content) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(result['name'], payload['name']) self.assertEqual(result['text'], payload['text']) def test_patch_note(self): url = reverse('api:v2.1:taxlot-notes-detail', args=[self.tl.pk, self.note4.pk]) payload = {"name": "new note name that is meaningless"} response = self.client.patch(url, data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, status.HTTP_200_OK) result = json.loads(response.content) self.assertEqual(result['name'], payload['name']) def test_get_detail_and_delete_note(self): note5 = self.note_factory.get_note() self.pv.notes.add(note5) url = reverse('api:v2.1:property-notes-detail', args=[self.pv.pk, note5.pk]) response = self.client.get(url, content_type='application/json') self.assertEqual(response.status_code, status.HTTP_200_OK) result = json.loads(response.content) self.assertEqual(result['property_view_id'], self.pv.pk) self.assertEqual(result['id'], note5.pk) # now delete the note response = self.client.delete(url, content_type='application/json') # delete returns no content self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # note should return nothing now response = self.client.get(url, content_type='application/json') self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
class TestPropertySerializers(DeleteModelsTestCase): def setUp(self): self.maxDiff = None user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org, _, _ = create_organization(self.user) self.audit_log_factory = FakePropertyAuditLogFactory( organization=self.org, user=self.user) self.property_factory = FakePropertyFactory(organization=self.org) self.property_state_factory = FakePropertyStateFactory( organization=self.org) self.property_view_factory = FakePropertyViewFactory( organization=self.org, user=self.user) self.ga_factory = FakeGreenAssessmentFactory(organization=self.org) self.gap_factory = FakeGreenAssessmentPropertyFactory( organization=self.org, user=self.user) self.label_factory = FakeStatusLabelFactory(organization=self.org) self.assessment = self.ga_factory.get_green_assessment() self.property_view = self.property_view_factory.get_property_view() self.gap_data = { 'source': 'test', 'status': 'complete', 'status_date': datetime.date(2017, 0o1, 0o1), 'metric': 5, 'version': '0.1', 'date': datetime.date(2016, 0o1, 0o1), 'eligibility': True, 'assessment': self.assessment, 'view': self.property_view, } self.urls = ['http://example.com', 'http://example.org'] def test_audit_log_serializer(self): """Test to_representation method.""" # test with AUDIT_USER_CREATE audit_log = self.audit_log_factory.get_property_audit_log() result = PropertyAuditLogReadOnlySerializer(audit_log).data self.assertEqual(result['description'], 'test audit log') self.assertEqual(result['date_edited'], audit_log.created.ctime()) self.assertEqual(result['source'], 'UserCreate') self.assertIsNone(result['changed_fields']) self.assertEqual(result['state']['city'], 'Boring') # test with AUDIT_USER_EDIT changed_fields = ['a', 'b', 'c'] audit_log = self.audit_log_factory.get_property_audit_log( record_type=AUDIT_USER_EDIT, description=json.dumps(changed_fields)) result = PropertyAuditLogReadOnlySerializer(audit_log).data self.assertEqual(result['description'], 'User edit') self.assertEqual(result['source'], 'UserEdit') self.assertEqual(result['changed_fields'], changed_fields) def test_property_view_list_serializer(self): """Test to_representation method.""" property_view_1 = self.property_view_factory.get_property_view() property_view_2 = self.property_view_factory.get_property_view() gap1_data = self.gap_data.copy() gap2_data = self.gap_data.copy() gap1_data['view'] = property_view_1 gap2_data['view'] = property_view_2 gap2_data['metric'] = 4 self.gap_factory.get_green_assessment_property(**gap1_data) self.gap_factory.get_green_assessment_property(**gap2_data) serializer = PropertyViewListSerializer(child=PropertyViewSerializer()) result = serializer.to_representation( [property_view_1, property_view_2]) self.assertEqual(result[0]['cycle']['id'], property_view_1.cycle_id) self.assertEqual(result[1]['cycle']['id'], property_view_2.cycle_id) self.assertEqual(result[0]['state']['id'], property_view_1.state_id) self.assertEqual(result[1]['state']['id'], property_view_2.state_id) self.assertEqual(result[0]['certifications'][0]['score'], 5) self.assertEqual(result[1]['certifications'][0]['score'], 4) self.assertEqual(result[0]['certifications'][0]['assessment']['name'], self.assessment.name) self.assertEqual(result[1]['certifications'][0]['assessment']['name'], self.assessment.name) # with queryset serializer = PropertyViewListSerializer(child=PropertyViewSerializer()) queryset = PropertyView.objects.filter( id__in=[property_view_1.id, property_view_2.id]).order_by('id') result = serializer.to_representation(queryset) self.assertEqual(result[0]['cycle']['id'], property_view_1.cycle_id) self.assertEqual(result[1]['cycle']['id'], property_view_2.cycle_id) self.assertEqual(result[0]['state']['id'], property_view_1.state_id) self.assertEqual(result[1]['state']['id'], property_view_2.state_id) self.assertEqual(result[0]['certifications'][0]['score'], 5) self.assertEqual(result[1]['certifications'][0]['score'], 4) self.assertEqual(result[0]['certifications'][0]['assessment']['name'], self.assessment.name) self.assertEqual(result[1]['certifications'][0]['assessment']['name'], self.assessment.name) def test_property_list_serializer(self): """Test PropertyListSerializer.to_representation""" # TODO test to representation property1 = self.property_factory.get_property() property2 = self.property_factory.get_property() expected = [ OrderedDict([ ('id', property1.id), ('campus', False), ('parent_property', None), ]), OrderedDict([ ('id', property2.id), ('campus', False), ('parent_property', None), ]), ] serializer = PropertyListSerializer(child=PropertyMinimalSerializer()) result = serializer.to_representation([property1, property2]) self.assertEqual(expected, result)
class TestPropertyViewAsStateSerializers(DeleteModelsTestCase): def setUp(self): self.maxDiff = None user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org, _, _ = create_organization(self.user) self.audit_log_factory = FakePropertyAuditLogFactory( organization=self.org, user=self.user) self.cycle_factory = FakeCycleFactory(organization=self.org, user=self.user) self.property_state_factory = FakePropertyStateFactory( organization=self.org) self.property_view_factory = FakePropertyViewFactory( organization=self.org, user=self.user) self.ga_factory = FakeGreenAssessmentFactory(organization=self.org) self.gap_factory = FakeGreenAssessmentPropertyFactory( organization=self.org, user=self.user) self.taxlot_property_factory = FakeTaxLotPropertyFactory( organization=self.org, user=self.user) self.taxlot_state_factory = FakeTaxLotStateFactory( organization=self.org) self.taxlot_view_factory = FakeTaxLotViewFactory(organization=self.org, user=self.user) self.assessment = self.ga_factory.get_green_assessment() self.cycle = self.cycle_factory.get_cycle() self.property_state = self.property_state_factory.get_property_state() self.property_view = self.property_view_factory.get_property_view( state=self.property_state, cycle=self.cycle) self.taxlot_state = self.taxlot_state_factory.get_taxlot_state() self.taxlot_view = self.taxlot_view_factory.get_taxlot_view( state=self.taxlot_state, cycle=self.cycle) self.audit_log = self.audit_log_factory.get_property_audit_log( state=self.property_state, view=self.property_view, record_type=AUDIT_USER_EDIT, description=json.dumps(['a', 'b'])) self.audit_log2 = self.audit_log_factory.get_property_audit_log( view=self.property_view) self.gap_data = { 'source': 'test', 'status': 'complete', 'status_date': datetime.date(2017, 0o1, 0o1), 'metric': 5, 'version': '0.1', 'date': datetime.date(2016, 0o1, 0o1), 'eligibility': True, 'assessment': self.assessment, 'view': self.property_view, } self.urls = ['http://example.com', 'http://example.org'] self.gap = self.gap_factory.get_green_assessment_property( **self.gap_data) self.serializer = PropertyViewAsStateSerializer( instance=self.property_view) def test_init(self): """Test __init__.""" expected = PropertyAuditLogReadOnlySerializer(self.audit_log).data # for now convert the site_eui to a magnitude to get the test to pass # this really needs to be at another level data = self.serializer.current # data['state']['site_eui'] = data['state']['site_eui'].magnitude self.assertEqual(data, expected) def test_get_certifications(self): """Test get_certifications""" expected = [GreenAssessmentPropertyReadOnlySerializer(self.gap).data] self.assertEqual( self.serializer.get_certifications(self.property_view), expected) def test_get_changed_fields(self): """Test get_changed_fields""" expected = ['a', 'b'] self.assertEqual(self.serializer.get_changed_fields(None), expected) def test_get_date_edited(self): """Test get_date_edited""" expected = self.audit_log.created.ctime() self.assertEqual(self.serializer.get_date_edited(None), expected) def test_get_filename(self): """Test get_filename""" expected = self.audit_log.import_filename self.assertEqual(self.serializer.get_filename(None), expected) def test_get_history(self): """Test get_history""" obj = mock.MagicMock() obj.state = self.property_state data = self.serializer.get_history(obj) # Really need to figure out how to get the serializer to save the magnitude correctly. # data[0]['state']['site_eui'] = data[0]['state']['site_eui'].magnitude expected = [PropertyAuditLogReadOnlySerializer(self.audit_log2).data] self.assertEqual(data, expected) def test_get_state(self): obj = mock.MagicMock() obj.state = self.property_state def test_get_source(self): """Test get_source""" expected = self.audit_log.get_record_type_display() self.assertEqual(self.serializer.get_source(None), expected) def test_get_taxlots(self): """Test get_taxlots""" self.taxlot_property_factory.get_taxlot_property( cycle=self.cycle, property_view=self.property_view, taxlot_view=self.taxlot_view) result = self.serializer.get_taxlots(self.property_view) self.assertEqual(result[0]['state']['id'], self.taxlot_state.id) @mock.patch('seed.serializers.properties.PropertyView') @mock.patch('seed.serializers.properties.PropertyStateWritableSerializer') def test_create(self, mock_serializer, mock_pview): """Test create""" mock_serializer.return_value.is_valid.return_value = True mock_serializer.return_value.save.return_value = self.property_state mock_pview.objects.create.return_value = self.property_view data = {'org_id': 1, 'cycle': 2, 'state': {'test': 3}, 'property': 4} serializer = PropertyViewAsStateSerializer() serializer.create(data) mock_serializer.assert_called_with(data={'test': 3}) self.assertTrue(mock_serializer.return_value.save.called) mock_pview.objects.create.assert_called_with(state=self.property_state, cycle_id=2, property_id=4, org_id=1) @mock.patch('seed.serializers.properties.PropertyStateWritableSerializer') def test_update_put(self, mock_serializer): """Test update with PUT""" mock_serializer.return_value.is_valid.return_value = True mock_serializer.return_value.save.return_value = self.property_state mock_request = mock.MagicMock() data = {'org_id': 1, 'cycle': 2, 'state': {'test': 3}, 'property': 4} serializer = PropertyViewAsStateSerializer( context={'request': mock_request}) mock_request.METHOD = 'PUT' serializer.update(self.property_view, data) mock_serializer.assert_called_with(data={'test': 3}) self.assertTrue(mock_serializer.return_value.save.called) @mock.patch('seed.serializers.properties.PropertyStateWritableSerializer') def test_update_patch(self, mock_serializer): """Test update with PATCH""" mock_serializer.return_value.is_valid.return_value = True mock_serializer.return_value.save.return_value = self.property_state mock_request = mock.MagicMock() mock_request.method = 'PATCH' data = {'org_id': 1, 'cycle': 2, 'state': {'test': 3}, 'property': 4} serializer = PropertyViewAsStateSerializer( context={'request': mock_request}) serializer.update(self.property_view, data) mock_serializer.assert_called_with(self.property_state, data={'test': 3}) self.assertTrue(mock_serializer.return_value.save.called)
class GeocodeViewTests(TestCase): def setUp(self): user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser( email='*****@*****.**', **user_details ) self.org, _, _ = create_organization(self.user) self.client.login(**user_details) self.property_state_factory = FakePropertyStateFactory(organization=self.org) self.tax_lot_state_factory = FakeTaxLotStateFactory(organization=self.org) self.property_view_factory = FakePropertyViewFactory(organization=self.org) self.taxlot_view_factory = FakeTaxLotViewFactory(organization=self.org) def test_geocode_endpoint_base_with_prepopulated_lat_long_no_api_request(self): property_details = self.property_state_factory.get_details() property_details['organization_id'] = self.org.id property_details['latitude'] = 39.765251 property_details['longitude'] = -104.986138 property = PropertyState(**property_details) property.save() property_view = self.property_view_factory.get_property_view(state=property) post_params = { 'property_view_ids': [property_view.id], 'taxlot_view_ids': [] } url = reverse('api:v3:geocode-geocode-by-ids') + '?organization_id=%s' % self.org.pk self.client.post(url, post_params) refreshed_property = PropertyState.objects.get(pk=property.id) self.assertEqual('POINT (-104.986138 39.765251)', long_lat_wkt(refreshed_property)) def test_geocode_confidence_summary_returns_summary_dictionary(self): property_none_details = self.property_state_factory.get_details() property_none_details["organization_id"] = self.org.id property_none = PropertyState(**property_none_details) property_none.save() property_none_view = self.property_view_factory.get_property_view(state=property_none) property_high_details = self.property_state_factory.get_details() property_high_details["organization_id"] = self.org.id property_high_details["geocoding_confidence"] = "High (P1AAA)" property_high = PropertyState(**property_high_details) property_high.save() property_high_view = self.property_view_factory.get_property_view(state=property_high) property_low_details = self.property_state_factory.get_details() property_low_details["organization_id"] = self.org.id property_low_details["geocoding_confidence"] = "Low (P1CCC)" property_low = PropertyState(**property_low_details) property_low.save() property_low_view = self.property_view_factory.get_property_view(state=property_low) property_manual_details = self.property_state_factory.get_details() property_manual_details["organization_id"] = self.org.id property_manual_details["geocoding_confidence"] = "Manually geocoded (N/A)" property_manual = PropertyState(**property_manual_details) property_manual.save() property_manual_view = self.property_view_factory.get_property_view(state=property_manual) property_missing_details = self.property_state_factory.get_details() property_missing_details["organization_id"] = self.org.id property_missing_details["geocoding_confidence"] = "Missing address components (N/A)" property_missing = PropertyState(**property_missing_details) property_missing.save() property_missing_view = self.property_view_factory.get_property_view(state=property_missing) tax_lot_none_details = self.tax_lot_state_factory.get_details() tax_lot_none_details["organization_id"] = self.org.id tax_lot_none = TaxLotState(**tax_lot_none_details) tax_lot_none.save() taxlot_none_view = self.taxlot_view_factory.get_taxlot_view(state=tax_lot_none) tax_lot_high_details = self.tax_lot_state_factory.get_details() tax_lot_high_details["organization_id"] = self.org.id tax_lot_high_details["geocoding_confidence"] = "High (P1AAA)" tax_lot_high = TaxLotState(**tax_lot_high_details) tax_lot_high.save() taxlot_high_view = self.taxlot_view_factory.get_taxlot_view(state=tax_lot_high) tax_lot_low_details = self.tax_lot_state_factory.get_details() tax_lot_low_details["organization_id"] = self.org.id tax_lot_low_details["geocoding_confidence"] = "Low (P1CCC)" tax_lot_low = TaxLotState(**tax_lot_low_details) tax_lot_low.save() taxlot_low_view = self.taxlot_view_factory.get_taxlot_view(state=tax_lot_low) tax_lot_manual_details = self.tax_lot_state_factory.get_details() tax_lot_manual_details["organization_id"] = self.org.id tax_lot_manual_details["geocoding_confidence"] = "Manually geocoded (N/A)" tax_lot_manual = TaxLotState(**tax_lot_manual_details) tax_lot_manual.save() taxlot_manual_view = self.taxlot_view_factory.get_taxlot_view(state=tax_lot_manual) tax_lot_missing_details = self.tax_lot_state_factory.get_details() tax_lot_missing_details["organization_id"] = self.org.id tax_lot_missing_details["geocoding_confidence"] = "Missing address components (N/A)" tax_lot_missing = TaxLotState(**tax_lot_missing_details) tax_lot_missing.save() taxlot_missing_view = self.taxlot_view_factory.get_taxlot_view(state=tax_lot_missing) url = reverse('api:v3:geocode-confidence-summary') post_params = { 'organization_id': self.org.pk, 'property_view_ids': [ property_none_view.id, property_high_view.id, property_low_view.id, property_manual_view.id, property_missing_view.id ], 'taxlot_view_ids': [ taxlot_none_view.id, taxlot_high_view.id, taxlot_low_view.id, taxlot_manual_view.id, taxlot_missing_view.id ] } result = self.client.post(url, post_params) result_dict = ast.literal_eval(result.content.decode("utf-8")) expectation = { "properties": { "not_geocoded": 1, "high_confidence": 1, "low_confidence": 1, "manual": 1, "missing_address_components": 1 }, "tax_lots": { "not_geocoded": 1, "high_confidence": 1, "low_confidence": 1, "manual": 1, "missing_address_components": 1 } } self.assertEqual(result_dict, expectation) def test_api_key_endpoint_returns_true_or_false_if_org_has_api_key(self): url = reverse("api:v3:organizations-geocode-api-key-exists", args=[self.org.pk]) post_params_false = {'organization_id': self.org.pk} false_result = self.client.get(url, post_params_false) self.assertEqual(b'false', false_result.content) org_with_key, _, _ = create_organization(self.user) org_with_key.mapquest_api_key = "somekey" org_with_key.save() url = reverse("api:v3:organizations-geocode-api-key-exists", args=[org_with_key.id]) post_params_true = {'organization_id': org_with_key.id} true_result = self.client.get(url, post_params_true) self.assertEqual(b'true', true_result.content)
class TestTaxLotProperty(DataMappingBaseTestCase): """Tests for exporting data to various formats.""" def setUp(self): self.properties = [] self.maxDiff = None user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org, _, _ = create_organization(self.user) # create a default cycle self.cycle = Cycle.objects.filter(organization_id=self.org).first() self.property_factory = FakePropertyFactory(organization=self.org) self.property_state_factory = FakePropertyStateFactory( organization=self.org) self.property_view_factory = FakePropertyViewFactory( organization=self.org, user=self.user) self.label_factory = FakeStatusLabelFactory(organization=self.org) self.property_view = self.property_view_factory.get_property_view() self.urls = ['http://example.com', 'http://example.org'] self.client.login(**user_details) def test_tax_lot_property_get_related(self): """Test to make sure get_related returns the fields""" for i in range(50): p = self.property_view_factory.get_property_view() self.properties.append(p.id) qs_filter = {"pk__in": self.properties} qs = PropertyView.objects.filter(**qs_filter) columns = [ 'address_line_1', 'generation_date', 'energy_alerts', 'space_alerts', 'building_count', 'owner', 'source_eui', 'jurisdiction_tax_lot_id', 'city', 'district', 'site_eui', 'building_certification', 'modified', 'match_type', 'source_eui_weather_normalized', 'id', 'property_name', 'conditioned_floor_area', 'pm_property_id', 'use_description', 'source_type', 'year_built', 'release_date', 'gross_floor_area', 'owner_city_state', 'owner_telephone', 'recent_sale_date', ] columns_from_database = Column.retrieve_all(self.org.id, 'property', False) data = TaxLotProperty.get_related(qs, columns, columns_from_database) self.assertEqual(len(data), 50) self.assertEqual(len(data[0]['related']), 0) def test_csv_export(self): """Test to make sure get_related returns the fields""" for i in range(50): p = self.property_view_factory.get_property_view() self.properties.append(p.id) columns = [] for c in Column.retrieve_all(self.org.id, 'property', False): columns.append(c['name']) # call the API url = reverse_lazy('api:v2.1:tax_lot_properties-export') response = self.client.post(url + '?{}={}&{}={}&{}={}'.format( 'organization_id', self.org.pk, 'cycle_id', self.cycle, 'inventory_type', 'properties'), data=json.dumps({ 'columns': columns, 'export_type': 'csv' }), content_type='application/json') # parse the content as array data = response.content.decode('utf-8').split('\n') self.assertTrue('Address Line 1' in data[0].split(',')) self.assertTrue('Property Labels\r' in data[0].split(',')) self.assertEqual(len(data), 53) # last row should be blank self.assertEqual(data[52], '') def test_csv_export_with_notes(self): multi_line_note = self.property_view.notes.create( name='Manually Created', note_type=Note.NOTE, text='multi\nline\nnote') single_line_note = self.property_view.notes.create( name='Manually Created', note_type=Note.NOTE, text='single line') self.properties.append(self.property_view.id) columns = [] for c in Column.retrieve_all(self.org.id, 'property', False): columns.append(c['name']) # call the API url = reverse_lazy('api:v2.1:tax_lot_properties-export') response = self.client.post(url + '?{}={}&{}={}&{}={}'.format( 'organization_id', self.org.pk, 'cycle_id', self.cycle, 'inventory_type', 'properties'), data=json.dumps({ 'columns': columns, 'export_type': 'csv' }), content_type='application/json') # parse the content as array data = response.content.decode('utf-8').split('\r\n') notes_string = (multi_line_note.created.astimezone().strftime( "%Y-%m-%d %I:%M:%S %p") + "\n" + multi_line_note.text + "\n----------\n" + single_line_note.created.astimezone().strftime( "%Y-%m-%d %I:%M:%S %p") + "\n" + single_line_note.text) self.assertEqual(len(data), 3) self.assertTrue('Property Notes' in data[0].split(',')) self.assertTrue(notes_string in data[1]) def test_xlxs_export(self): for i in range(50): p = self.property_view_factory.get_property_view() self.properties.append(p.id) columns = [] for c in Column.retrieve_all(self.org.id, 'property', False): columns.append(c['name']) # call the API url = reverse_lazy('api:v2.1:tax_lot_properties-export') response = self.client.post(url + '?{}={}&{}={}&{}={}'.format( 'organization_id', self.org.pk, 'cycle_id', self.cycle, 'inventory_type', 'properties'), data=json.dumps({ 'columns': columns, 'export_type': 'xlsx' }), content_type='application/json') # parse the content as array wb = open_workbook(file_contents=response.content) data = [row.value for row in wb.sheet_by_index(0).row(0)] self.assertTrue('Address Line 1' in data) self.assertTrue('Property Labels' in data) self.assertEqual(len([r for r in wb.sheet_by_index(0).get_rows()]), 52) def test_json_export(self): """Test to make sure get_related returns the fields""" for i in range(50): p = self.property_view_factory.get_property_view() self.properties.append(p.id) columns = [] for c in Column.retrieve_all(self.org.id, 'property', False): columns.append(c['name']) # call the API url = reverse_lazy('api:v2.1:tax_lot_properties-export') response = self.client.post(url + '?{}={}&{}={}&{}={}'.format( 'organization_id', self.org.pk, 'cycle_id', self.cycle, 'inventory_type', 'properties'), data=json.dumps({ 'columns': columns, 'export_type': 'geojson' }), content_type='application/json') # parse the content as dictionary data = json.loads(response.content) first_level_keys = list(data.keys()) self.assertIn("type", first_level_keys) self.assertIn("crs", first_level_keys) self.assertIn("features", first_level_keys) record_level_keys = list(data['features'][0]['properties'].keys()) self.assertIn('Address Line 1', record_level_keys) self.assertTrue('Gross Floor Area', record_level_keys) # ids 52 up to and including 102 self.assertEqual(len(data['features']), 51) def tearDown(self): for x in self.properties: PropertyView.objects.get(pk=x).delete()
class PropertyViewTests(DeleteModelsTestCase): def setUp(self): user_details = { 'username': '******', 'password': '******', 'email': '*****@*****.**' } self.user = User.objects.create_superuser(**user_details) self.org, self.org_user, _ = create_organization(self.user) self.column_factory = FakeColumnFactory(organization=self.org) self.cycle_factory = FakeCycleFactory(organization=self.org, user=self.user) self.property_factory = FakePropertyFactory(organization=self.org) self.property_state_factory = FakePropertyStateFactory(organization=self.org) self.property_view_factory = FakePropertyViewFactory(organization=self.org) self.taxlot_state_factory = FakeTaxLotStateFactory(organization=self.org) self.cycle = self.cycle_factory.get_cycle( start=datetime(2010, 10, 10, tzinfo=timezone.get_current_timezone())) self.client.login(**user_details) def test_get_and_edit_properties(self): state = self.property_state_factory.get_property_state() prprty = self.property_factory.get_property() view = PropertyView.objects.create( property=prprty, cycle=self.cycle, state=state ) params = { 'organization_id': self.org.pk, 'page': 1, 'per_page': 999999999, 'columns': COLUMNS_TO_SEND, } url = reverse('api:v2.1:properties-list') + '?cycle_id={}'.format(self.cycle.pk) response = self.client.get(url, params) data = json.loads(response.content) self.assertEqual(len(data['properties']), 1) result = data['properties'][0] self.assertEqual(result['state']['address_line_1'], state.address_line_1) db_created_time = result['created'] db_updated_time = result['updated'] self.assertTrue(db_created_time is not None) self.assertTrue(db_updated_time is not None) # update the address new_data = { "state": { "address_line_1": "742 Evergreen Terrace" } } url = reverse('api:v2:properties-detail', args=[view.id]) + '?organization_id={}'.format(self.org.pk) response = self.client.put(url, json.dumps(new_data), content_type='application/json') data = json.loads(response.content) self.assertEqual(data['status'], 'success') # the above call returns data from the PropertyState, need to get the Property -- # call the get on the same API to retrieve it response = self.client.get(url, content_type='application/json') data = json.loads(response.content) # make sure the address was updated and that the datetimes were modified self.assertEqual(data['status'], 'success') self.assertEqual(data['state']['address_line_1'], '742 Evergreen Terrace') self.assertEqual(datetime.strptime(db_created_time, "%Y-%m-%dT%H:%M:%S.%fZ").replace(microsecond=0), datetime.strptime(data['property']['created'], "%Y-%m-%dT%H:%M:%S.%fZ").replace( microsecond=0)) self.assertGreater(datetime.strptime(data['property']['updated'], "%Y-%m-%dT%H:%M:%S.%fZ"), datetime.strptime(db_updated_time, "%Y-%m-%dT%H:%M:%S.%fZ")) def test_search_identifier(self): self.property_view_factory.get_property_view(cycle=self.cycle, custom_id_1='123456') self.property_view_factory.get_property_view(cycle=self.cycle, custom_id_1='987654 Long Street') self.property_view_factory.get_property_view(cycle=self.cycle, address_line_1='123 Main Street') self.property_view_factory.get_property_view(cycle=self.cycle, address_line_1='Hamilton Road', analysis_state=PropertyState.ANALYSIS_STATE_QUEUED) self.property_view_factory.get_property_view(cycle=self.cycle, custom_id_1='long road', analysis_state=PropertyState.ANALYSIS_STATE_QUEUED) # Typically looks like this # http://localhost:8000/api/v2.1/properties/?organization_id=265&cycle=219&identifier=09-IS # check for all items query_params = "?cycle={}&organization_id={}".format(self.cycle.pk, self.org.pk) url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 5) # check for 2 items with 123 query_params = "?cycle={}&organization_id={}&identifier={}".format(self.cycle.pk, self.org.pk, '123') url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] # print out the result of this when there are more than two in an attempt to catch the # non-deterministic part of this test if len(results) > 2: print results self.assertEqual(len(results), 2) # check the analysis states query_params = "?cycle={}&organization_id={}&analysis_state={}".format(self.cycle.pk, self.org.pk, 'Completed') url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 0) query_params = "?cycle={}&organization_id={}&analysis_state={}".format( self.cycle.pk, self.org.pk, 'Not Started' ) url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 3) query_params = "?cycle={}&organization_id={}&analysis_state={}".format( self.cycle.pk, self.org.pk, 'Queued' ) url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 2) # check the combination of both the identifier and the analysis state query_params = "?cycle={}&organization_id={}&identifier={}&analysis_state={}".format( self.cycle.pk, self.org.pk, 'Long', 'Queued' ) url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 1)
class PropertyViewTests(DeleteModelsTestCase): def setUp(self): user_details = { 'username': '******', 'password': '******', 'email': '*****@*****.**' } self.user = User.objects.create_superuser(**user_details) self.org, self.org_user, _ = create_organization(self.user) self.column_factory = FakeColumnFactory(organization=self.org) self.cycle_factory = FakeCycleFactory(organization=self.org, user=self.user) self.property_factory = FakePropertyFactory(organization=self.org) self.property_state_factory = FakePropertyStateFactory( organization=self.org) self.property_view_factory = FakePropertyViewFactory( organization=self.org) self.taxlot_state_factory = FakeTaxLotStateFactory( organization=self.org) self.cycle = self.cycle_factory.get_cycle( start=datetime(2010, 10, 10, tzinfo=get_current_timezone())) self.column_list_factory = FakeColumnListSettingsFactory( organization=self.org) self.client.login(**user_details) def test_get_and_edit_properties(self): state = self.property_state_factory.get_property_state() prprty = self.property_factory.get_property() view = PropertyView.objects.create(property=prprty, cycle=self.cycle, state=state) params = { 'organization_id': self.org.pk, 'page': 1, 'per_page': 999999999, 'columns': COLUMNS_TO_SEND, } url = reverse('api:v2.1:properties-list') + '?cycle_id={}'.format( self.cycle.pk) response = self.client.get(url, params) data = json.loads(response.content) self.assertEqual(len(data['properties']), 1) result = data['properties'][0] self.assertEqual(result['state']['address_line_1'], state.address_line_1) db_created_time = result['created'] db_updated_time = result['updated'] self.assertTrue(db_created_time is not None) self.assertTrue(db_updated_time is not None) # update the address new_data = {"state": {"address_line_1": "742 Evergreen Terrace"}} url = reverse('api:v2:properties-detail', args=[ view.id ]) + '?organization_id={}'.format(self.org.pk) response = self.client.put(url, json.dumps(new_data), content_type='application/json') data = json.loads(response.content) self.assertEqual(data['status'], 'success') # the above call returns data from the PropertyState, need to get the Property -- # call the get on the same API to retrieve it response = self.client.get(url, content_type='application/json') data = json.loads(response.content) # make sure the address was updated and that the datetimes were modified self.assertEqual(data['status'], 'success') self.assertEqual(data['state']['address_line_1'], '742 Evergreen Terrace') self.assertEqual( datetime.strptime(db_created_time, "%Y-%m-%dT%H:%M:%S.%fZ").replace(microsecond=0), datetime.strptime(data['property']['created'], "%Y-%m-%dT%H:%M:%S.%fZ").replace(microsecond=0)) self.assertGreater( datetime.strptime(data['property']['updated'], "%Y-%m-%dT%H:%M:%S.%fZ"), datetime.strptime(db_updated_time, "%Y-%m-%dT%H:%M:%S.%fZ")) def test_list_properties_with_profile_id(self): state = self.property_state_factory.get_property_state( extra_data={"field_1": "value_1"}) prprty = self.property_factory.get_property() PropertyView.objects.create(property=prprty, cycle=self.cycle, state=state) # save all the columns in the state to the database so we can setup column list settings Column.save_column_names(state) # get the columnlistsetting (default) for all columns columnlistsetting = self.column_list_factory.get_columnlistsettings( columns=['address_line_1', 'field_1']) params = { 'organization_id': self.org.pk, 'profile_id': columnlistsetting.id, } url = reverse('api:v2.1:properties-list') + '?cycle_id={}'.format( self.cycle.pk) response = self.client.get(url, params) data = response.json() self.assertEqual(len(data['properties']), 1) result = data['properties'][0] self.assertEqual(result['state']['address_line_1'], state.address_line_1) self.assertEqual(result['state']['extra_data']['field_1'], 'value_1') self.assertFalse(result['state'].get('city', None)) def test_search_identifier(self): self.property_view_factory.get_property_view(cycle=self.cycle, custom_id_1='123456') self.property_view_factory.get_property_view( cycle=self.cycle, custom_id_1='987654 Long Street') self.property_view_factory.get_property_view( cycle=self.cycle, address_line_1='123 Main Street') self.property_view_factory.get_property_view( cycle=self.cycle, address_line_1='Hamilton Road', analysis_state=PropertyState.ANALYSIS_STATE_QUEUED) self.property_view_factory.get_property_view( cycle=self.cycle, custom_id_1='long road', analysis_state=PropertyState.ANALYSIS_STATE_QUEUED) # Typically looks like this # http://localhost:8000/api/v2.1/properties/?organization_id=265&cycle=219&identifier=09-IS # check for all items query_params = "?cycle={}&organization_id={}".format( self.cycle.pk, self.org.pk) url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 5) # check for 2 items with 123 query_params = "?cycle={}&organization_id={}&identifier={}".format( self.cycle.pk, self.org.pk, '123') url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] # print out the result of this when there are more than two in an attempt to catch the # non-deterministic part of this test if len(results) > 2: print(results) self.assertEqual(len(results), 2) # check the analysis states query_params = "?cycle={}&organization_id={}&analysis_state={}".format( self.cycle.pk, self.org.pk, 'Completed') url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 0) query_params = "?cycle={}&organization_id={}&analysis_state={}".format( self.cycle.pk, self.org.pk, 'Not Started') url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 3) query_params = "?cycle={}&organization_id={}&analysis_state={}".format( self.cycle.pk, self.org.pk, 'Queued') url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 2) # check the combination of both the identifier and the analysis state query_params = "?cycle={}&organization_id={}&identifier={}&analysis_state={}".format( self.cycle.pk, self.org.pk, 'Long', 'Queued') url = reverse('api:v2.1:properties-list') + query_params response = self.client.get(url) result = json.loads(response.content) self.assertEqual(result['status'], 'success') results = result['properties'] self.assertEqual(len(results), 1) def test_meters_exist(self): # Create a property set with meters state_1 = self.property_state_factory.get_property_state() property_1 = self.property_factory.get_property() PropertyView.objects.create(property=property_1, cycle=self.cycle, state=state_1) import_record = ImportRecord.objects.create( owner=self.user, last_modified_by=self.user, super_organization=self.org) filename = "example-GreenButton-data.xml" filepath = os.path.dirname( os.path.abspath(__file__)) + "/data/" + filename import_file = ImportFile.objects.create( import_record=import_record, source_type="GreenButton", uploaded_filename=filename, file=SimpleUploadedFile(name=filename, content=open(filepath, 'rb').read()), cycle=self.cycle, matching_results_data={ "property_id": property_1.id } # this is how target property is specified ) gb_import_url = reverse("api:v2:import_files-save-raw-data", args=[import_file.id]) gb_import_post_params = { 'cycle_id': self.cycle.pk, 'organization_id': self.org.pk, } self.client.post(gb_import_url, gb_import_post_params) # Create a property set without meters state_2 = self.property_state_factory.get_property_state() property_2 = self.property_factory.get_property() PropertyView.objects.create(property=property_2, cycle=self.cycle, state=state_2) url = reverse('api:v2:properties-meters-exist') true_post_params = json.dumps( {'inventory_ids': [property_2.pk, property_1.pk]}) true_result = self.client.post(url, true_post_params, content_type='application/json') self.assertEqual(b'true', true_result.content) false_post_params = json.dumps({'inventory_ids': [property_2.pk]}) false_result = self.client.post(url, false_post_params, content_type='application/json') self.assertEqual(b'false', false_result.content)
class StateFieldsTest(TestCase): """Tests that our logic for constructing cleaners works.""" def setUp(self): self.maxDiff = None user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser( email='*****@*****.**', **user_details ) self.org, _, _ = create_organization(self.user) self.taxlot_view_factory = FakeTaxLotViewFactory(organization=self.org) self.property_view_factory = FakePropertyViewFactory(organization=self.org, user=self.user) def test_get_state_attrs(self): # create the column for data_1 Column.objects.create( column_name='data_1', table_name='TaxLotState', organization=self.org, is_extra_data=True, ) tlv1 = self.taxlot_view_factory.get_taxlot_view(extra_data={"data_1": "value_1"}) tlv2 = self.taxlot_view_factory.get_taxlot_view(extra_data={"data_1": "value_2"}) self.assertEqual(tlv1.state.extra_data['data_1'], 'value_1') self.assertEqual(tlv2.state.extra_data['data_1'], 'value_2') res = get_state_attrs([tlv1.state, tlv2.state]) self.assertEqual(res['custom_id_1'], {tlv2.state: None, tlv1.state: None}) self.assertEqual(res['postal_code'], {tlv2.state: tlv2.state.postal_code, tlv1.state: tlv1.state.postal_code}) self.assertTrue('data_1' not in res) def test_property_state(self): self.property_view_factory.get_property_view() self.taxlot_view_factory.get_taxlot_view() expected = (('address_line_1', 'address_line_1'), ('address_line_2', 'address_line_2'), ('analysis_end_time', 'analysis_end_time'), ('analysis_start_time', 'analysis_start_time'), ('analysis_state_message', 'analysis_state_message'), ('building_certification', 'building_certification'), ('building_count', 'building_count'), ('city', 'city'), ('conditioned_floor_area', 'conditioned_floor_area'), ('custom_id_1', 'custom_id_1'), ('energy_alerts', 'energy_alerts'), ('energy_score', 'energy_score'), ('generation_date', 'generation_date'), ('geocoding_confidence', 'geocoding_confidence'), ('gross_floor_area', 'gross_floor_area'), ('home_energy_score_id', 'home_energy_score_id'), ('jurisdiction_property_id', 'jurisdiction_property_id'), ('latitude', 'latitude'), ('long_lat', 'long_lat'), ('longitude', 'longitude'), ('lot_number', 'lot_number'), ('occupied_floor_area', 'occupied_floor_area'), ('owner', 'owner'), ('owner_address', 'owner_address'), ('owner_city_state', 'owner_city_state'), ('owner_email', 'owner_email'), ('owner_postal_code', 'owner_postal_code'), ('owner_telephone', 'owner_telephone'), ('pm_parent_property_id', 'pm_parent_property_id'), ('pm_property_id', 'pm_property_id'), ('postal_code', 'postal_code'), ('property_footprint', 'property_footprint'), ('property_name', 'property_name'), ('property_notes', 'property_notes'), ('property_type', 'property_type'), ('recent_sale_date', 'recent_sale_date'), ('release_date', 'release_date'), ('site_eui', 'site_eui'), ('site_eui_modeled', 'site_eui_modeled'), ('site_eui_weather_normalized', 'site_eui_weather_normalized'), ('source_eui', 'source_eui'), ('source_eui_modeled', 'source_eui_modeled'), ('source_eui_weather_normalized', 'source_eui_weather_normalized'), ('space_alerts', 'space_alerts'), ('state', 'state'), ('ubid', 'ubid'), ('use_description', 'use_description'), ('year_built', 'year_built'), ('year_ending', 'year_ending')) result = get_state_to_state_tuple('PropertyState') self.assertSequenceEqual(expected, result) def test_taxlot_state(self): expected = ( ('address_line_1', 'address_line_1'), ('address_line_2', 'address_line_2'), ('block_number', 'block_number'), ('city', 'city'), ('custom_id_1', 'custom_id_1'), ('district', 'district'), ('geocoding_confidence', 'geocoding_confidence'), ('jurisdiction_tax_lot_id', 'jurisdiction_tax_lot_id'), ('latitude', 'latitude'), ('long_lat', 'long_lat'), ('longitude', 'longitude'), ('number_properties', 'number_properties'), ('postal_code', 'postal_code'), ('state', 'state'), ('taxlot_footprint', 'taxlot_footprint'), ('ulid', 'ulid')) result = get_state_to_state_tuple('TaxLotState') self.assertSequenceEqual(expected, result) def test_merge_state_favor_existing(self): pv1 = self.property_view_factory.get_property_view( address_line_1='original_address', address_line_2='orig', extra_data={'field_1': 'orig_value'} ) pv2 = self.property_view_factory.get_property_view( address_line_1='new_address', address_line_2='new', extra_data={'field_1': 'new_value'} ) # Do not set priority for address_line_2 to make sure that it chooses t column_priorities = { 'address_line_1': 'Favor Existing', 'extra_data': {'field_1': 'Favor Existing'} } result = merging.merge_state(pv1.state, pv1.state, pv2.state, column_priorities) self.assertEqual(result.address_line_1, 'original_address') self.assertEqual(result.address_line_2, 'new') self.assertEqual(result.extra_data['field_1'], 'orig_value') def test_merge_geocoding_results_no_merge_protection(self): """ When merging records that have geocoding results, if none of the geocoding results columns have merge protection but both records have some form of geocoding results, completely "take" the results from the "new" state. """ pv1 = self.property_view_factory.get_property_view( address_line_1='original_address', latitude=39.765251, longitude=-104.986138, geocoding_confidence='High (P1AAA)', long_lat='POINT (-104.986138 39.765251)', ) pv2 = self.property_view_factory.get_property_view( address_line_1='new_address', geocoding_confidence='Low - check address (Z1XAA)', ) # Column priorities while purposely leaving out long_lat (as it's not available to users) column_priorities = { 'address_line_1': 'Favor New', 'geocoding_confidence': 'Favor New', 'latitude': 'Favor New', 'longitude': 'Favor New', 'extra_data': {} } result = merging.merge_state(pv1.state, pv1.state, pv2.state, column_priorities) self.assertEqual(result.geocoding_confidence, 'Low - check address (Z1XAA)') self.assertIsNone(result.latitude) self.assertIsNone(result.longitude) self.assertIsNone(result.long_lat) def test_merge_geocoding_results_with_merge_protection(self): """ When merging records that have geocoding results, if any of the geocoding results columns have merge protection, and both records have some form of geocoding results, completely "take" the results from the "existing" state. """ pv1 = self.property_view_factory.get_property_view( address_line_1='original_address', latitude=39.765251, longitude=-104.986138, geocoding_confidence='High (P1AAA)', long_lat='POINT (-104.986138 39.765251)', ) pv2 = self.property_view_factory.get_property_view( address_line_1='new_address', geocoding_confidence='Low - check address (Z1XAA)', ) # Column priorities while purposely leaving out long_lat (as it's not available to users) column_priorities = { 'address_line_1': 'Favor New', 'geocoding_confidence': 'Favor Existing', 'latitude': 'Favor New', 'longitude': 'Favor New', 'extra_data': {} } result = merging.merge_state(pv1.state, pv1.state, pv2.state, column_priorities) self.assertEqual(result.geocoding_confidence, 'High (P1AAA)') self.assertEqual(result.latitude, 39.765251) self.assertEqual(result.longitude, -104.986138) self.assertEqual(long_lat_wkt(result), 'POINT (-104.986138 39.765251)') def test_merge_geocoding_results_unpopulated_existing_state_ignores_merge_protections(self): """ When merging records with geocoding columns that have merge protection active, if only one record has geocoding results, always take the geocoding results from the one record, regardless of merge protection settings. """ pv1 = self.property_view_factory.get_property_view( address_line_1='original_address', ) pv2 = self.property_view_factory.get_property_view( address_line_1='new_address', geocoding_confidence='Low - check address (Z1XAA)', ) # Column priorities while purposely leaving out long_lat (as it's not available to users) column_priorities = { 'address_line_1': 'Favor New', 'geocoding_confidence': 'Favor Existing', 'latitude': 'Favor Existing', 'longitude': 'Favor Existing', 'extra_data': {} } result = merging.merge_state(pv1.state, pv1.state, pv2.state, column_priorities) self.assertEqual(result.geocoding_confidence, 'Low - check address (Z1XAA)') self.assertIsNone(result.latitude) self.assertIsNone(result.longitude) self.assertIsNone(result.long_lat) def test_merge_geocoding_results_no_merge_protection_unpopulated_existing_state(self): """ When merging records with geocoding columns that have merge protection active, if only one record has geocoding results, always take the geocoding results from the one record, regardless of merge protection settings. """ pv1 = self.property_view_factory.get_property_view( address_line_1='original_address', geocoding_confidence='Low - check address (Z1XAA)', ) pv2 = self.property_view_factory.get_property_view( address_line_1='new_address', ) # Column priorities while purposely leaving out long_lat (as it's not available to users) column_priorities = { 'address_line_1': 'Favor New', 'geocoding_confidence': 'Favor New', 'latitude': 'Favor New', 'longitude': 'Favor New', 'extra_data': {} } result = merging.merge_state(pv1.state, pv1.state, pv2.state, column_priorities) self.assertEqual(result.geocoding_confidence, 'Low - check address (Z1XAA)') self.assertIsNone(result.latitude) self.assertIsNone(result.longitude) self.assertIsNone(result.long_lat) def test_merge_geocoding_ignore_merge_protection(self): """ When merging records with geocoding columns including the ignore_merge_protection flag as True always takes the "new" state's geocoding results regardless of geocoding columns merge protection setting. """ pv1 = self.property_view_factory.get_property_view( address_line_1='original_address', geocoding_confidence='Low - check address (Z1XAA)', ) pv2 = self.property_view_factory.get_property_view( address_line_1='new_address', latitude=39.765251, longitude=-104.986138, geocoding_confidence='High (P1AAA)', long_lat='POINT (-104.986138 39.765251)', ) # Column priorities while purposely leaving out long_lat (as it's not available to users) column_priorities = { 'address_line_1': 'Favor New', 'geocoding_confidence': 'Favor Existing', 'latitude': 'Favor New', 'longitude': 'Favor New', 'extra_data': {} } result = merging.merge_state(pv1.state, pv1.state, pv2.state, column_priorities, True) self.assertEqual(result.geocoding_confidence, 'High (P1AAA)') self.assertEqual(result.latitude, 39.765251) self.assertEqual(result.longitude, -104.986138) self.assertEqual(long_lat_wkt(result), 'POINT (-104.986138 39.765251)') def test_merge_extra_data(self): ed1 = {'field_1': 'orig_value_1', 'field_2': 'orig_value_1', 'field_3': 'only_in_ed1'} ed2 = {'field_1': 'new_value_1', 'field_2': 'new_value_2', 'field_4': 'only_in_ed2'} # this also tests a priority on the new field but with an existing value that doesn't exist # in the new data. priorities = {'field_1': 'Favor Existing', 'field_3': 'Favor New'} result = merging._merge_extra_data(ed1, ed2, priorities, []) expected = { 'field_1': 'orig_value_1', 'field_2': 'new_value_2', 'field_3': 'only_in_ed1', 'field_4': 'only_in_ed2' } self.assertDictEqual(result, expected) def test_recognize_empty_column_setting_allows_empty_values_to_overwrite_nonempty_values(self): # create 2 records pv1 = self.property_view_factory.get_property_view( address_line_1='original_address', energy_score=None, extra_data={ 'ed_field_1': 'ed_original_value', 'ed_field_2': None } ) pv2 = self.property_view_factory.get_property_view( address_line_1=None, energy_score=86, extra_data={ 'ed_field_1': None, 'ed_field_2': 'ED eighty-six' } ) # Update and create columns with recognize_empty = True self.org.column_set.filter( table_name='PropertyState', column_name__in=['address_line_1', 'energy_score'] ).update(recognize_empty=True) Column.objects.create( column_name='ed_field_1', table_name='PropertyState', organization=self.org, is_extra_data=True, recognize_empty=True ) Column.objects.create( column_name='ed_field_2', table_name='PropertyState', organization=self.org, is_extra_data=True, recognize_empty=True ) # Treat pv1.state as "newer" result = merging.merge_state(pv2.state, pv2.state, pv1.state, {'extra_data': {}}) # should be all the values from state 1 self.assertEqual(result.address_line_1, 'original_address') self.assertIsNone(result.energy_score) self.assertEqual(result.extra_data['ed_field_1'], 'ed_original_value') self.assertIsNone(result.extra_data['ed_field_2']) def test_recognize_empty_and_favor_new_column_settings_together(self): # create 2 records pv1 = self.property_view_factory.get_property_view( address_line_1='original_address', energy_score=None, extra_data={ 'ed_field_1': 'ed_original_value', 'ed_field_2': None } ) pv2 = self.property_view_factory.get_property_view( address_line_1=None, energy_score=86, extra_data={ 'ed_field_1': None, 'ed_field_2': 'ED eighty-six' } ) # Update and create columns with recognize_empty = True self.org.column_set.filter( table_name='PropertyState', column_name__in=['address_line_1', 'energy_score'] ).update(recognize_empty=True) Column.objects.create( column_name='ed_field_1', table_name='PropertyState', organization=self.org, is_extra_data=True, recognize_empty=True ) Column.objects.create( column_name='ed_field_2', table_name='PropertyState', organization=self.org, is_extra_data=True, recognize_empty=True ) # Treat pv1.state as "newer" and favor existing for all priorities priorities = { 'address_line_1': 'Favor Existing', 'energy_score': 'Favor Existing', 'extra_data': { 'ed_field_1': 'Favor Existing', 'ed_field_2': 'Favor Existing' } } result = merging.merge_state(pv2.state, pv2.state, pv1.state, priorities) # should be all the values from state 2 self.assertIsNone(result.address_line_1) self.assertEqual(result.energy_score, 86) self.assertIsNone(result.extra_data['ed_field_1']) self.assertEqual(result.extra_data['ed_field_2'], 'ED eighty-six')
class TestFields(DeleteModelsTestCase): def get_date_string(self, dtobj): """Get YY-MM-DD string""" return "{}-{}-{}".format(dtobj.year, dtobj.month, dtobj.day) def setUp(self): self.maxDiff = None user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org, _, _ = create_organization(self.user) self.property_view_factory = FakePropertyViewFactory( organization=self.org, user=self.user) def test_url_field(self): """Test GreenAssessmentURLField""" field = GreenAssessmentURLField() url1 = mock.MagicMock() url1.url = 'http://example.com' url1.description = 'example.com' url2 = mock.MagicMock() url2.url = 'http://example.org' url2.description = 'example.org' mock_obj = mock.MagicMock() mock_obj.all.return_value = [url1, url2] expected = [('http://example.com', 'example.com'), ('http://example.org', 'example.org')] result = field.to_representation(mock_obj) self.assertEqual(expected, result) def test_property_view_field(self): """Test PropertyViewField""" property_view = self.property_view_factory.get_property_view() state = property_view.state cycle = OrderedDict( (('id', property_view.cycle.id), ('start', self.get_date_string(property_view.cycle.start)), ('end', self.get_date_string(property_view.cycle.end)))) expected = OrderedDict( (('id', property_view.pk), ('address_line_1', titlecase(state.normalized_address)), ('address_line_2', state.address_line_2), ('city', state.city), ('state', state.state), ('postal_code', state.postal_code), ('property', property_view.property.id), ('cycle', cycle))) field = PropertyViewField(read_only=True) result = field.to_representation(property_view) self.assertEqual(expected, result) def test_validity_duration_field_to_representation(self): """Test ValidityDurationField.to_representation()""" ga_factory = FakeGreenAssessmentFactory(organization=self.org) green_assessment = ga_factory.get_green_assessment( validity_duration=365) field = ValidityDurationField() result = field.to_representation(green_assessment.validity_duration) self.assertEqual(result, 365) def test_validity_duration_field_to_internal_value(self): """Test ValidityDurationField.to_internal_value()""" field = ValidityDurationField() result = field.to_internal_value(365) expected = datetime.timedelta(365) self.assertEqual(result, expected) result = field.to_internal_value('365') self.assertEqual(result, expected) result = field.to_internal_value(None) expected = None self.assertEqual(result, expected) self.assertRaises(ValidationError, field.to_internal_value, 1.54) self.assertRaises(ValidationError, field.to_internal_value, 'ten') self.assertRaises(ValidationError, field.to_internal_value, 0) self.assertRaises(ValidationError, field.to_internal_value, -10)
def setUp(self): user_details = { 'username': '******', 'password': '******', 'email': '*****@*****.**', 'first_name': 'Test', 'last_name': 'User', } self.user = User.objects.create_user(**user_details) self.org, _, _ = create_organization(self.user) property_state = ( FakePropertyStateFactory(organization=self.org).get_property_state( # fields required for analysis latitude=39.76550841416409, longitude=-104.97855661401148)) self.analysis_property_view = ( FakeAnalysisPropertyViewFactory( organization=self.org, user=self.user).get_analysis_property_view( property_state=property_state, # analysis args name='Quite neat', service=Analysis.BSYNCR, )) self.meter = Meter.objects.create( property=self.analysis_property_view.property, source=Meter.PORTFOLIO_MANAGER, source_id="Source ID", type=Meter.ELECTRICITY_GRID, ) tz_obj = timezone(TIME_ZONE) self.meter_reading = MeterReading.objects.create( meter=self.meter, start_time=make_aware(datetime(2018, 1, 1, 0, 0, 0), timezone=tz_obj), end_time=make_aware(datetime(2018, 1, 2, 0, 0, 0), timezone=tz_obj), reading=12345, source_unit='kWh', conversion_factor=1.00) # # Setup more properties with linked meters with 12 valid meter readings. # These properties, unmodified, should successfully run thorugh the bsyncr pipeline # property_view_factory = FakePropertyViewFactory(organization=self.org) self.good_property_views = [] self.num_good_property_views = 3 for i in range(self.num_good_property_views): pv = property_view_factory.get_property_view( # fields required for analysis latitude=39.76550841416409, longitude=-104.97855661401148, # override unitted fields so that hashes are correct site_eui=ureg.Quantity( float( property_view_factory.fake.random_int(min=50, max=600)), "kilobtu / foot ** 2 / year"), gross_floor_area=ureg.Quantity( float(property_view_factory.fake.random_number(digits=6)), "foot ** 2"), ) self.good_property_views.append(pv) self.analysis_b = (FakeAnalysisFactory(organization=self.org, user=self.user).get_analysis( name='Good Analysis', service=Analysis.BSYNCR)) self.good_meters = [] for i in range(self.num_good_property_views): self.good_meters.append( Meter.objects.create( property=self.good_property_views[i].property, source=Meter.PORTFOLIO_MANAGER, source_id="Source ID", type=Meter.ELECTRICITY_GRID, )) tz_obj = timezone(TIME_ZONE) for j in range(1, 13): MeterReading.objects.create( meter=self.good_meters[i], start_time=make_aware(datetime(2019, j, 1, 0, 0, 0), timezone=tz_obj), end_time=make_aware(datetime(2019, j, 28, 0, 0, 0), timezone=tz_obj), reading=12345, source_unit='kWh', conversion_factor=1.00)
class TestTaxLotProperty(TestCase): """Tests for exporting data to various formats.""" def setUp(self): self.properties = [] self.maxDiff = None user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org, _, _ = create_organization(self.user) # create a default cycle self.cycle = Cycle.objects.filter(organization_id=self.org).first() self.property_factory = FakePropertyFactory( organization=self.org ) self.property_state_factory = FakePropertyStateFactory( organization=self.org ) self.property_view_factory = FakePropertyViewFactory( organization=self.org, user=self.user ) self.label_factory = FakeStatusLabelFactory( organization=self.org ) self.property_view = self.property_view_factory.get_property_view() self.urls = ['http://example.com', 'http://example.org'] self.client.login(**user_details) def test_tax_lot_property_get_related(self): """Test to make sure get_related returns the fields""" for i in range(50): p = self.property_view_factory.get_property_view() self.properties.append(p.id) qs_filter = {"pk__in": self.properties} qs = PropertyView.objects.filter(**qs_filter) columns = [ 'address_line_1', 'generation_date', 'energy_alerts', 'space_alerts', 'building_count', 'owner', 'source_eui', 'jurisdiction_tax_lot_id', 'city', 'district', 'site_eui', 'building_certification', 'modified', 'match_type', 'source_eui_weather_normalized', 'id', 'property_name', 'conditioned_floor_area', 'pm_property_id', 'use_description', 'source_type', 'year_built', 'release_date', 'gross_floor_area', 'owner_city_state', 'owner_telephone', 'recent_sale_date', ] columns_from_database = Column.retrieve_all(self.org.id, 'property', False) data = TaxLotProperty.get_related(qs, columns, columns_from_database) self.assertEqual(len(data), 50) self.assertEqual(len(data[0]['related']), 0) def test_csv_export(self): """Test to make sure get_related returns the fields""" for i in range(50): p = self.property_view_factory.get_property_view() self.properties.append(p.id) columns = [] for c in Column.retrieve_all(self.org.id, 'property', False): columns.append(c['name']) # call the API url = reverse_lazy('api:v2.1:tax_lot_properties-csv') response = self.client.post( url + '?{}={}&{}={}&{}={}'.format( 'organization_id', self.org.pk, 'cycle_id', self.cycle, 'inventory_type', 'properties' ), data=json.dumps({'columns': columns}), content_type='application/json' ) # parse the content as array data = response.content.decode('utf-8').split('\n') self.assertTrue('Address Line 1' in data[0].split(',')) self.assertTrue('Property Labels\r' in data[0].split(',')) self.assertEqual(len(data), 53) # last row should be blank self.assertEqual(data[52], '') def tearDown(self): for x in self.properties: PropertyView.objects.get(pk=x).delete()
class StateFieldsTest(TestCase): """Tests that our logic for constructing cleaners works.""" def setUp(self): self.maxDiff = None user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org, _, _ = create_organization(self.user) self.taxlot_view_factory = FakeTaxLotViewFactory(organization=self.org) self.property_view_factory = FakePropertyViewFactory( organization=self.org, user=self.user) def test_get_state_attrs(self): # create the column for data_1 Column.objects.create( column_name=u'data_1', table_name=u'TaxLotState', organization=self.org, is_extra_data=True, ) tlv1 = self.taxlot_view_factory.get_taxlot_view( extra_data={"data_1": "value_1"}) tlv2 = self.taxlot_view_factory.get_taxlot_view( extra_data={"data_1": "value_2"}) self.assertEqual(tlv1.state.extra_data['data_1'], 'value_1') self.assertEqual(tlv2.state.extra_data['data_1'], 'value_2') res = get_state_attrs([tlv1.state, tlv2.state]) self.assertEqual(res['custom_id_1'], { tlv2.state: None, tlv1.state: None }) self.assertEqual(res['postal_code'], { tlv2.state: tlv2.state.postal_code, tlv1.state: tlv1.state.postal_code }) self.assertTrue('data_1' not in res.keys()) def test_property_state(self): self.property_view_factory.get_property_view() self.taxlot_view_factory.get_taxlot_view() expected = ((u'address_line_1', u'address_line_1'), (u'address_line_2', u'address_line_2'), (u'analysis_end_time', u'analysis_end_time'), (u'analysis_start_time', u'analysis_start_time'), (u'analysis_state', u'analysis_state'), (u'analysis_state_message', u'analysis_state_message'), (u'building_certification', u'building_certification'), (u'building_count', u'building_count'), (u'city', u'city'), (u'conditioned_floor_area', u'conditioned_floor_area'), (u'custom_id_1', u'custom_id_1'), (u'energy_alerts', u'energy_alerts'), (u'energy_score', u'energy_score'), (u'generation_date', u'generation_date'), (u'gross_floor_area', u'gross_floor_area'), (u'home_energy_score_id', u'home_energy_score_id'), (u'jurisdiction_property_id', u'jurisdiction_property_id'), (u'latitude', u'latitude'), (u'longitude', u'longitude'), (u'lot_number', u'lot_number'), (u'occupied_floor_area', u'occupied_floor_area'), (u'owner', u'owner'), (u'owner_address', u'owner_address'), (u'owner_city_state', u'owner_city_state'), (u'owner_email', u'owner_email'), (u'owner_postal_code', u'owner_postal_code'), (u'owner_telephone', u'owner_telephone'), (u'pm_parent_property_id', u'pm_parent_property_id'), (u'pm_property_id', u'pm_property_id'), (u'postal_code', u'postal_code'), (u'property_name', u'property_name'), (u'property_notes', u'property_notes'), (u'property_type', u'property_type'), (u'recent_sale_date', u'recent_sale_date'), (u'release_date', u'release_date'), (u'site_eui', u'site_eui'), (u'site_eui_modeled', u'site_eui_modeled'), (u'site_eui_weather_normalized', u'site_eui_weather_normalized'), (u'source_eui', u'source_eui'), (u'source_eui_modeled', u'source_eui_modeled'), (u'source_eui_weather_normalized', u'source_eui_weather_normalized'), (u'space_alerts', u'space_alerts'), (u'state', u'state'), (u'ubid', u'ubid'), (u'use_description', u'use_description'), (u'year_built', u'year_built'), (u'year_ending', u'year_ending')) result = get_state_to_state_tuple('PropertyState') self.assertSequenceEqual(expected, result) def test_taxlot_state(self): expected = ((u'address_line_1', u'address_line_1'), (u'address_line_2', u'address_line_2'), (u'block_number', u'block_number'), (u'city', u'city'), (u'custom_id_1', u'custom_id_1'), (u'district', u'district'), (u'jurisdiction_tax_lot_id', u'jurisdiction_tax_lot_id'), (u'number_properties', u'number_properties'), (u'postal_code', u'postal_code'), (u'state', u'state')) result = get_state_to_state_tuple(u'TaxLotState') self.assertSequenceEqual(expected, result)
class UbidViewTests(TestCase): def setUp(self): user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org, _, _ = create_organization(self.user) self.client.login(**user_details) self.property_state_factory = FakePropertyStateFactory( organization=self.org) self.taxlot_state_factory = FakeTaxLotStateFactory( organization=self.org) self.property_view_factory = FakePropertyViewFactory( organization=self.org) self.taxlot_view_factory = FakeTaxLotViewFactory(organization=self.org) def test_ubid_decode_by_id_endpoint_base(self): property_details = self.property_state_factory.get_details() property_details['organization_id'] = self.org.id property_details['ubid'] = '86HJPCWQ+2VV-1-3-2-3' property = PropertyState(**property_details) property.save() property_view = self.property_view_factory.get_property_view( state=property) url = reverse( 'api:v3:ubid-decode-by-ids') + '?organization_id=%s' % self.org.pk post_params = {'property_view_ids': [property_view.id]} self.client.post(url, post_params) refreshed_property = PropertyState.objects.get(pk=property.id) property_bounding_box_wkt = ( "POLYGON ((-87.56021875000002 41.74504999999999, " "-87.56021875000002 41.74514999999997, " "-87.56043749999996 41.74514999999997, " "-87.56043749999996 41.74504999999999, " "-87.56021875000002 41.74504999999999))") property_centroid_wkt = ( "POLYGON ((-87.56031249999999 41.74509999999998, " "-87.56031249999999 41.74512499999997, " "-87.56034374999999 41.74512499999997, " "-87.56034374999999 41.74509999999998, " "-87.56031249999999 41.74509999999998))") self.assertEqual(property_bounding_box_wkt, bounding_box_wkt(refreshed_property)) self.assertEqual(property_centroid_wkt, centroid_wkt(refreshed_property)) def test_decode_ubid_results_returns_a_summary_dictionary(self): property_none_details = self.property_state_factory.get_details() property_none_details["organization_id"] = self.org.id property_none = PropertyState(**property_none_details) property_none.save() property_none_view = self.property_view_factory.get_property_view( state=property_none) property_correctly_populated_details = self.property_state_factory.get_details( ) property_correctly_populated_details["organization_id"] = self.org.id property_correctly_populated_details['ubid'] = '86HJPCWQ+2VV-1-3-2-3' property_correctly_populated_details['bounding_box'] = ( "POLYGON ((-87.56021875000002 41.74504999999999, " "-87.56021875000002 41.74514999999997, " "-87.56043749999996 41.74514999999997, " "-87.56043749999996 41.74504999999999, " "-87.56021875000002 41.74504999999999))") property_correctly_populated_details['centroid'] = ( "POLYGON ((-87.56031249999999 41.74509999999998, " "-87.56031249999999 41.74512499999997, " "-87.56034374999999 41.74512499999997, " "-87.56034374999999 41.74509999999998, " "-87.56031249999999 41.74509999999998))") property_correctly_populated = PropertyState( **property_correctly_populated_details) property_correctly_populated.save() property_correctly_populated_view = self.property_view_factory.get_property_view( state=property_correctly_populated) property_not_decoded_details = self.property_state_factory.get_details( ) property_not_decoded_details["organization_id"] = self.org.id property_not_decoded_details['ubid'] = '86HJPCWQ+2VV-1-3-2-3' # bounding_box could be populated from a GeoJSON import property_not_decoded_details['bounding_box'] = ( "POLYGON ((-87.56021875000002 41.74504999999999, " "-87.56021875000002 41.74514999999997, " "-87.56043749999996 41.74514999999997, " "-87.56043749999996 41.74504999999999, " "-87.56021875000002 41.74504999999999))") property_not_decoded = PropertyState(**property_not_decoded_details) property_not_decoded.save() property_not_decoded_view = self.property_view_factory.get_property_view( state=property_not_decoded) url = reverse( 'api:v3:ubid-decode-results') + '?organization_id=%s' % self.org.pk post_params = { 'property_view_ids': [ property_none_view.id, property_correctly_populated_view.id, property_not_decoded_view.id ] } result = self.client.post(url, post_params) result_dict = ast.literal_eval(result.content.decode("utf-8")) expectation = { "ubid_unpopulated": 1, "ubid_successfully_decoded": 1, "ubid_not_decoded": 1, "ulid_unpopulated": 0, "ulid_successfully_decoded": 0, "ulid_not_decoded": 0 } self.assertEqual(result_dict, expectation) def test_decode_ulid_results_returns_a_summary_dictionary(self): taxlot_none_details = self.taxlot_state_factory.get_details() taxlot_none_details["organization_id"] = self.org.id taxlot_none = TaxLotState(**taxlot_none_details) taxlot_none.save() taxlot_none_view = self.taxlot_view_factory.get_taxlot_view( state=taxlot_none) taxlot_correctly_populated_details = self.taxlot_state_factory.get_details( ) taxlot_correctly_populated_details["organization_id"] = self.org.id taxlot_correctly_populated_details['ulid'] = '86HJPCWQ+2VV-1-3-2-3' taxlot_correctly_populated_details['bounding_box'] = ( "POLYGON ((-87.56021875000002 41.74504999999999, " "-87.56021875000002 41.74514999999997, " "-87.56043749999996 41.74514999999997, " "-87.56043749999996 41.74504999999999, " "-87.56021875000002 41.74504999999999))") taxlot_correctly_populated_details['centroid'] = ( "POLYGON ((-87.56031249999999 41.74509999999998, " "-87.56031249999999 41.74512499999997, " "-87.56034374999999 41.74512499999997, " "-87.56034374999999 41.74509999999998, " "-87.56031249999999 41.74509999999998))") taxlot_correctly_populated = TaxLotState( **taxlot_correctly_populated_details) taxlot_correctly_populated.save() taxlot_correctly_populated_view = self.taxlot_view_factory.get_taxlot_view( state=taxlot_correctly_populated) taxlot_not_decoded_details = self.taxlot_state_factory.get_details() taxlot_not_decoded_details["organization_id"] = self.org.id taxlot_not_decoded_details['ulid'] = '86HJPCWQ+2VV-1-3-2-3' # bounding_box could be populated from a GeoJSON import taxlot_not_decoded_details['bounding_box'] = ( "POLYGON ((-87.56021875000002 41.74504999999999, " "-87.56021875000002 41.74514999999997, " "-87.56043749999996 41.74514999999997, " "-87.56043749999996 41.74504999999999, " "-87.56021875000002 41.74504999999999))") taxlot_not_decoded = TaxLotState(**taxlot_not_decoded_details) taxlot_not_decoded.save() taxlot_not_decoded_view = self.taxlot_view_factory.get_taxlot_view( state=taxlot_not_decoded) url = reverse( 'api:v3:ubid-decode-results') + '?organization_id=%s' % self.org.pk post_params = { 'taxlot_view_ids': [ taxlot_none_view.id, taxlot_correctly_populated_view.id, taxlot_not_decoded_view.id ] } result = self.client.post(url, post_params) result_dict = ast.literal_eval(result.content.decode("utf-8")) expectation = { "ubid_unpopulated": 0, "ubid_successfully_decoded": 0, "ubid_not_decoded": 0, "ulid_unpopulated": 1, "ulid_successfully_decoded": 1, "ulid_not_decoded": 1 } self.assertEqual(result_dict, expectation)
class StateFieldsTest(TestCase): """Tests that our logic for constructing cleaners works.""" def setUp(self): self.maxDiff = None user_details = { 'username': '******', 'password': '******', } self.user = User.objects.create_superuser(email='*****@*****.**', **user_details) self.org, _, _ = create_organization(self.user) self.taxlot_view_factory = FakeTaxLotViewFactory(organization=self.org) self.property_view_factory = FakePropertyViewFactory( organization=self.org, user=self.user) def test_get_state_attrs(self): # create the column for data_1 Column.objects.create( column_name='data_1', table_name='TaxLotState', organization=self.org, is_extra_data=True, ) tlv1 = self.taxlot_view_factory.get_taxlot_view( extra_data={"data_1": "value_1"}) tlv2 = self.taxlot_view_factory.get_taxlot_view( extra_data={"data_1": "value_2"}) self.assertEqual(tlv1.state.extra_data['data_1'], 'value_1') self.assertEqual(tlv2.state.extra_data['data_1'], 'value_2') res = get_state_attrs([tlv1.state, tlv2.state]) self.assertEqual(res['custom_id_1'], { tlv2.state: None, tlv1.state: None }) self.assertEqual(res['postal_code'], { tlv2.state: tlv2.state.postal_code, tlv1.state: tlv1.state.postal_code }) self.assertTrue('data_1' not in res) def test_property_state(self): self.property_view_factory.get_property_view() self.taxlot_view_factory.get_taxlot_view() expected = (('address_line_1', 'address_line_1'), ('address_line_2', 'address_line_2'), ('analysis_end_time', 'analysis_end_time'), ('analysis_start_time', 'analysis_start_time'), ('analysis_state_message', 'analysis_state_message'), ('building_certification', 'building_certification'), ('building_count', 'building_count'), ('city', 'city'), ('conditioned_floor_area', 'conditioned_floor_area'), ('custom_id_1', 'custom_id_1'), ('energy_alerts', 'energy_alerts'), ('energy_score', 'energy_score'), ('generation_date', 'generation_date'), ('gross_floor_area', 'gross_floor_area'), ('home_energy_score_id', 'home_energy_score_id'), ('jurisdiction_property_id', 'jurisdiction_property_id'), ('latitude', 'latitude'), ('longitude', 'longitude'), ('lot_number', 'lot_number'), ('occupied_floor_area', 'occupied_floor_area'), ('owner', 'owner'), ('owner_address', 'owner_address'), ('owner_city_state', 'owner_city_state'), ('owner_email', 'owner_email'), ('owner_postal_code', 'owner_postal_code'), ('owner_telephone', 'owner_telephone'), ('pm_parent_property_id', 'pm_parent_property_id'), ('pm_property_id', 'pm_property_id'), ('postal_code', 'postal_code'), ('property_name', 'property_name'), ('property_notes', 'property_notes'), ('property_type', 'property_type'), ('recent_sale_date', 'recent_sale_date'), ('release_date', 'release_date'), ('site_eui', 'site_eui'), ('site_eui_modeled', 'site_eui_modeled'), ('site_eui_weather_normalized', 'site_eui_weather_normalized'), ('source_eui', 'source_eui'), ('source_eui_modeled', 'source_eui_modeled'), ('source_eui_weather_normalized', 'source_eui_weather_normalized'), ('space_alerts', 'space_alerts'), ('state', 'state'), ('ubid', 'ubid'), ('use_description', 'use_description'), ('year_built', 'year_built'), ('year_ending', 'year_ending')) result = get_state_to_state_tuple('PropertyState') self.assertSequenceEqual(expected, result) def test_taxlot_state(self): expected = (('address_line_1', 'address_line_1'), ('address_line_2', 'address_line_2'), ('block_number', 'block_number'), ('city', 'city'), ('custom_id_1', 'custom_id_1'), ('district', 'district'), ('jurisdiction_tax_lot_id', 'jurisdiction_tax_lot_id'), ('number_properties', 'number_properties'), ('postal_code', 'postal_code'), ('state', 'state')) result = get_state_to_state_tuple('TaxLotState') self.assertSequenceEqual(expected, result) def test_merge_state_favor_existing(self): pv1 = self.property_view_factory.get_property_view( address_line_1='original_address', address_line_2='orig', extra_data={'field_1': 'orig_value'}) pv2 = self.property_view_factory.get_property_view( address_line_1='new_address', address_line_2='new', extra_data={'field_1': 'new_value'}) # Do not set priority for address_line_2 to make sure that it chooses t column_priorities = { 'address_line_1': 'Favor Existing', 'extra_data': { 'field_1': 'Favor Existing' } } result = merging.merge_state(pv1.state, pv1.state, pv2.state, column_priorities) self.assertEqual(result.address_line_1, 'original_address') self.assertEqual(result.address_line_2, 'new') self.assertEqual(result.extra_data['field_1'], 'orig_value') def test_merge_extra_data(self): ed1 = { 'field_1': 'orig_value_1', 'field_2': 'orig_value_1', 'field_3': 'only_in_ed1' } ed2 = { 'field_1': 'new_value_1', 'field_2': 'new_value_2', 'field_4': 'only_in_ed2' } # this also tests a priority on the new field but with an existing value that doesn't exist # in the new data. priorities = {'field_1': 'Favor Existing', 'field_3': 'Favor New'} result = merging._merge_extra_data(ed1, ed2, priorities) expected = { 'field_1': 'orig_value_1', 'field_2': 'new_value_2', 'field_3': 'only_in_ed1', 'field_4': 'only_in_ed2' } self.assertDictEqual(result, expected)