Beispiel #1
0
    def test_property_existing_in_multiple_cycles_can_have_meters_and_readings_associated_to_it(
            self):
        property_details = FakePropertyStateFactory(
            organization=self.org).get_details()
        property_details['organization_id'] = self.org.id

        # new state to be associated to new cycle using the same pm_property_id as state in old cycle
        property_details['pm_property_id'] = self.state_1.pm_property_id
        state = PropertyState(**property_details)
        state.save()
        new_property_state = PropertyState.objects.get(pk=state.id)

        new_cycle_factory = FakeCycleFactory(organization=self.org,
                                             user=self.user)
        new_cycle = new_cycle_factory.get_cycle(
            start=datetime(2010, 10, 10, tzinfo=get_current_timezone()))

        # new state and cycle associated to old property
        PropertyView.objects.create(property=self.property_1,
                                    cycle=new_cycle,
                                    state=new_property_state)

        url = reverse("api:v3:import_files-start-save-data",
                      args=[self.import_file.id])
        url += f'?organization_id={self.org.pk}'
        post_params = {
            'cycle_id': self.cycle.pk,
        }
        self.client.post(url, post_params)

        refreshed_property_1 = Property.objects.get(pk=self.property_1.id)
        self.assertEqual(refreshed_property_1.meters.all().count(), 2)
Beispiel #2
0
    def setUp(self):
        self.user_details = {
            'username': '******',
            'password': '******',
        }
        self.user = User.objects.create_superuser(email='*****@*****.**',
                                                  **self.user_details)
        self.org, _, _ = create_organization(self.user)
        self.property_state_factory = FakePropertyStateFactory(
            organization=self.org)

        property_details = self.property_state_factory.get_details()
        self.pm_property_id = '12345'
        property_details['pm_property_id'] = self.pm_property_id
        property_details['organization_id'] = self.org.id

        state = PropertyState(**property_details)
        state.save()
        self.state = PropertyState.objects.get(pk=state.id)

        self.cycle_factory = FakeCycleFactory(organization=self.org,
                                              user=self.user)
        self.cycle = self.cycle_factory.get_cycle(
            start=datetime(2010, 10, 10, tzinfo=get_current_timezone()))

        self.property_factory = FakePropertyFactory(organization=self.org)
        self.property = self.property_factory.get_property()

        self.property_view = PropertyView.objects.create(
            property=self.property, cycle=self.cycle, state=self.state)

        self.tz_obj = timezone(TIME_ZONE)
Beispiel #3
0
def merge_state(merged_state, state1, state2, priorities):
    """
    Set attributes on our Canonical model, saving differences.

    :param merged_state: PropertyState/TaxLotState model inst.
    :param state1: PropertyState/TaxLotState model inst. Left parent.
    :param state2: PropertyState/TaxLotState model inst. Right parent.
    :param priorities: dict, column names with favor new or existing
    :return: inst(``merged_state``), updated.
    """
    # Calculate the difference between the two states and save into a dictionary
    can_attrs = get_state_attrs([state1, state2])

    default = state2
    for attr in can_attrs:
        # Do we have any differences between these fields? - Check if not None instead of if value.
        attr_values = [
            value for value in list(can_attrs[attr].values())
            if value is not None
        ]
        attr_values = [v for v in attr_values if v is not None]

        attr_value = None
        # Two, differing values are set.
        if len(attr_values) > 1:
            # If we have more than one value for this field, choose based on the column priority
            col_prior = priorities.get(attr, 'Favor New')
            if col_prior == 'Favor New':
                attr_value = can_attrs[attr][state2]
            else:  # favor the existing field
                attr_value = can_attrs[attr][state1]

        # No values are set
        elif len(attr_values) < 1:
            attr_value = None

        # There is only one value set.
        else:
            attr_value = attr_values.pop()

        if callable(attr):
            # This callable will be responsible for setting the attribute value, not just returning it.
            attr(merged_state, default)
        else:
            setattr(merged_state, attr, attr_value)

    merged_state.extra_data = _merge_extra_data(state1.extra_data,
                                                state2.extra_data,
                                                priorities['extra_data'])

    # merge measures, scenarios, simulations
    if isinstance(merged_state, PropertyState):
        PropertyState.merge_relationships(merged_state, state1, state2)

    return merged_state
Beispiel #4
0
def merge_state(merged_state, state1, state2, can_attrs, default=None):
    """
    Set attributes on our Canonical model, saving differences.

    :param merged_state: PropertyState/TaxLotState model inst.
    :param state1: PropertyState/TaxLotState model inst. Left parent.
    :param state2: PropertyState/TaxLotState model inst. Right parent.
    :param can_attrs:  dict of dicts, {'attr_name': {'dataset1': 'value'...}}.
    :param default: (optional), which dataset's value to default to.
    :return: inst(``merged_state``), updated.
    """
    default = default or state2
    changes = []
    for attr in can_attrs:
        # Do we have any differences between these fields? - Check if not None instead of if value.
        attr_values = list(
            set([
                value for value in can_attrs[attr].values()
                if value is not None
            ]))
        attr_values = [v for v in attr_values if v is not None]

        attr_value = None
        # Two, differing values are set.
        if len(attr_values) > 1:
            # If we have more than one value for this field, save each of the field options in the DB,
            # but opt for the default when there is a difference.
            attr_value = can_attrs[attr][default]

        # No values are set
        elif len(attr_values) < 1:
            attr_value = None

        # There is only one value set.
        else:
            attr_value = attr_values.pop()

        if callable(attr):
            # This callable will be responsible for setting the attribute value, not just returning it.
            attr(merged_state, default)
        else:
            setattr(merged_state, attr, attr_value)

    merged_extra_data, merged_extra_data_sources = _merge_extra_data(
        state1, state2, default=default)
    merged_state.extra_data = merged_extra_data

    # merge measures, scenarios, simulations
    if isinstance(merged_state, PropertyState):
        PropertyState.merge_relationships(merged_state, state1, state2)

    return merged_state, changes
    def test_hash(self):
        self.assertEqual(
            tasks.hash_state_object(PropertyState()),
            tasks.hash_state_object(PropertyState(organization=self.org)))

        self.assertEqual(
            tasks.hash_state_object(TaxLotState()),
            tasks.hash_state_object(TaxLotState(organization=self.org)))

        ps1 = PropertyState(address_line_1='123 fake st',
                            extra_data={"a": "100"})
        ps2 = PropertyState(address_line_1='123 fake st',
                            extra_data={"a": "200"})
        ps3 = PropertyState(extra_data={"a": "200"})
        ps4 = PropertyState(extra_data={"a": "100"})
        ps5 = PropertyState(address_line_1='123 fake st')

        self.assertEqual(
            len(set(map(tasks.hash_state_object, [ps1, ps2, ps3, ps4, ps5]))),
            5)

        # large PropertyState objects -- make sure size is still 32 (why wouldn't it be?)
        extra_data = {}
        for i in range(1000):
            extra_data["entry_%s" % i] = "Value as string %s" % i

        ps6 = PropertyState(address_line_1='123 fake st',
                            extra_data=extra_data)
        hash_res = tasks.hash_state_object(ps6)
        self.assertEqual(len(hash_res), 32)
Beispiel #6
0
    def setUp(self):
        self.user_details = {
            'username': '******',
            'password': '******',
        }
        self.user = User.objects.create_superuser(email='*****@*****.**',
                                                  **self.user_details)
        self.org, _, _ = create_organization(self.user)
        self.client.login(**self.user_details)

        self.property_state_factory = FakePropertyStateFactory(
            organization=self.org)
        property_details = self.property_state_factory.get_details()
        property_details['organization_id'] = self.org.id
        state_1 = PropertyState(**property_details)
        state_1.save()
        self.state_1 = PropertyState.objects.get(pk=state_1.id)

        self.cycle_factory = FakeCycleFactory(organization=self.org,
                                              user=self.user)
        self.cycle = self.cycle_factory.get_cycle(
            start=datetime(2010, 10, 10, tzinfo=get_current_timezone()))

        self.property_factory = FakePropertyFactory(organization=self.org)
        self.property_1 = self.property_factory.get_property()

        self.property_view_1 = PropertyView.objects.create(
            property=self.property_1, cycle=self.cycle, state=self.state_1)

        self.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

        self.import_file = ImportFile.objects.create(
            import_record=self.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": self.property_1.id})

        self.tz_obj = timezone(TIME_ZONE)
    def test_hash(self):

        # tasks.hash_state_object(TaxLotState())
        # tasks.hash_state_object(TaxLotState(organization=self.org))

        self.assertEqual(
            tasks.hash_state_object(PropertyState()),
            tasks.hash_state_object(PropertyState(organization=self.org)))

        self.assertEqual(
            tasks.hash_state_object(TaxLotState()),
            tasks.hash_state_object(TaxLotState(organization=self.org)))

        ps1 = PropertyState(address_line_1='123 fake st',
                            extra_data={"a": "100"})
        ps2 = PropertyState(address_line_1='123 fake st',
                            extra_data={"a": "200"})
        ps3 = PropertyState(extra_data={"a": "200"})
        ps4 = PropertyState(extra_data={"a": "100"})
        ps5 = PropertyState(address_line_1='123 fake st')

        self.assertEqual(
            len(set(map(tasks.hash_state_object, [ps1, ps2, ps3, ps4, ps5]))),
            5)

        return
Beispiel #8
0
    def test_pm_property_id_existing_across_two_different_orgs_wont_lead_to_misassociated_meters(
            self):
        new_org, _, _ = create_organization(self.user)

        property_details = FakePropertyStateFactory(
            organization=new_org).get_details()
        property_details['organization_id'] = new_org.id

        # new state to be associated to property of different organization but has the same pm_property_id
        property_details['pm_property_id'] = self.state_1.pm_property_id
        state = PropertyState(**property_details)
        state.save()
        new_property_state = PropertyState.objects.get(pk=state.id)

        new_cycle_factory = FakeCycleFactory(organization=new_org,
                                             user=self.user)
        new_cycle = new_cycle_factory.get_cycle(
            start=datetime(2010, 10, 10, tzinfo=get_current_timezone()))

        new_property = self.property_factory.get_property()

        PropertyView.objects.create(property=new_property,
                                    cycle=new_cycle,
                                    state=new_property_state)

        url = reverse("api:v3:import_files-start-save-data",
                      args=[self.import_file.id])
        url += f'?organization_id={self.org.pk}'
        post_params = {
            'cycle_id': self.cycle.pk,
        }
        self.client.post(url, post_params)

        # self.property_1 is associated to self.org, so according to post request, it should have 2 meters
        refreshed_property_1 = Property.objects.get(
            pk=self.property_1.id, organization_id__exact=self.org.pk)
        self.assertEqual(refreshed_property_1.meters.all().count(), 2)

        refreshed_new_property = Property.objects.get(pk=new_property.id)
        self.assertEqual(refreshed_new_property.meters.count(), 0)
Beispiel #9
0
    def test_meters_and_readings_are_associated_to_every_record_across_all_cycles_with_a_given_pm_property_id(
            self):
        # new, in-cycle state NOT associated to existing record but has same PM Property ID
        property_details_1 = FakePropertyStateFactory(
            organization=self.org).get_details()
        property_details_1['organization_id'] = self.org.id
        property_details_1['pm_property_id'] = self.state_1.pm_property_id
        property_details_1['custom_id_1'] = "values that forces non-match"
        new_property_1 = PropertyState(**property_details_1)
        new_property_1.save()

        property_3 = self.property_factory.get_property()
        PropertyView.objects.create(property=property_3,
                                    cycle=self.cycle,
                                    state=new_property_1)

        # new, out-cycle state NOT associated to existing record but has same PM Property ID
        property_details_2 = FakePropertyStateFactory(
            organization=self.org).get_details()
        property_details_2['organization_id'] = self.org.id
        property_details_2['pm_property_id'] = self.state_1.pm_property_id
        property_details_2[
            'custom_id_1'] = "second value that forces non-match"
        new_property_2 = PropertyState(**property_details_2)
        new_property_2.save()

        new_cycle = self.cycle_factory.get_cycle(
            start=datetime(2011, 10, 10, tzinfo=get_current_timezone()))
        property_4 = self.property_factory.get_property()
        PropertyView.objects.create(property=property_4,
                                    cycle=new_cycle,
                                    state=new_property_2)

        url = reverse("api:v3:import_files-start-save-data",
                      args=[self.import_file.id])
        url += f'?organization_id={self.org.pk}'
        post_params = {
            'cycle_id': self.cycle.pk,
        }
        self.client.post(url, post_params)

        refreshed_property_1 = Property.objects.get(pk=self.property_1.id)
        self.assertEqual(refreshed_property_1.meters.all().count(), 2)

        refreshed_property_3 = Property.objects.get(pk=property_3.id)
        self.assertEqual(refreshed_property_3.meters.all().count(), 2)

        refreshed_property_4 = Property.objects.get(pk=property_4.id)
        self.assertEqual(refreshed_property_4.meters.all().count(), 2)
Beispiel #10
0
    def test_coparent(self):
        # find a state id
        # get a specific test case with coparents
        property_state = PropertyState.objects.filter(
            use_description='Pizza House',
            import_file_id=self.import_file_2,
            data_state__in=[DATA_STATE_MAPPING, DATA_STATE_MATCHING],
            merge_state__in=[MERGE_STATE_UNKNOWN, MERGE_STATE_NEW]).first()

        coparent, count = PropertyState.coparent(property_state.id)

        self.assertEqual(count, 1)
        expected = PropertyState.objects.filter(
            use_description='Retail',
            address_line_1=property_state.address_line_1,
            import_file_id=self.import_file,
            data_state__in=[DATA_STATE_MAPPING, DATA_STATE_MATCHING],
            merge_state__in=[MERGE_STATE_UNKNOWN, MERGE_STATE_NEW]).first()

        self.assertEqual(expected.pk, coparent[0]['id'])
Beispiel #11
0
def create_models(data, import_file, cycle):
    """
    Create a PropertyState and a Meter. Then, create TimeSeries models for each meter
    reading in data.

    :param data: dict, building data from a Green Button XML file from xml_importer.building_data
    :param import_file: ImportFile, reference to Green Button XML file
    :param cycle: Cycle, the cycle from which the property view will be attached
    :returns: PropertyState
    """

    # cache data on import_file; this is a proof of concept and we
    # only have two example files available so we hardcode the only
    # heading present.

    # NL: Yuck, not sure that this makes much sense here, or anywhere in this method
    import_file.cached_first_row = ROW_DELIMITER.join(["address"])
    import_file.cached_second_to_fifth_row = ROW_DELIMITER.join(
        [data['address']])
    import_file.save()

    property_state = PropertyState()
    property_state.import_file = import_file
    property_state.organization = import_file.import_record.super_organization
    property_state.address_line_1 = data['address']
    property_state.source_type = GREEN_BUTTON_BS  # TODO: Green Button Fix -- prob can be removed
    property_state.save()

    pv = property_state.promote(cycle)

    # create meter for this dataset (each dataset is a single energy type)
    e_type = energy_type(data['service_category'])
    e_type_string = next(pair[1] for pair in Meter.ENERGY_TYPES
                         if pair[0] == e_type)

    m_name = "gb_{0}[{1}]".format(str(property_state.id), e_type_string)
    m_energy_units = energy_units(data['meter']['uom'])

    meter = Meter.objects.create(name=m_name,
                                 energy_type=e_type,
                                 energy_units=m_energy_units,
                                 property_view=pv)
    meter.save()

    # now time series data for the meter
    for reading in data['interval']['readings']:
        # how to deal with timezones?
        start_time = int(reading['start_time'])
        duration = int(reading['duration'])

        begin_time = datetime.fromtimestamp(start_time,
                                            tz=timezone.get_current_timezone())
        end_time = datetime.fromtimestamp(start_time + duration,
                                          tz=timezone.get_current_timezone())
        value = reading['value']
        cost = reading['cost']

        new_ts = TimeSeries.objects.create(
            begin_time=begin_time,
            end_time=end_time,
            reading=value,
            cost=cost,
            meter=meter,
        )
        new_ts.save()

    return pv
Beispiel #12
0
def merge_state(merged_state, state1, state2, priorities, ignore_merge_protection=False):
    """
    Set attributes on our Canonical model, saving differences.

    :param merged_state: PropertyState/TaxLotState model inst.
    :param state1: PropertyState/TaxLotState model inst. Left parent.
    :param state2: PropertyState/TaxLotState model inst. Right parent.
    :param priorities: dict, column names with favor new or existing
    :return: inst(``merged_state``), updated.
    """
    # Calculate the difference between the two states and save into a dictionary
    can_attrs = get_state_attrs([state1, state2])

    # Handle geocoding results first so that recognize_empty logic is not processed on them.
    _merge_geocoding_results(merged_state, state1, state2, priorities, can_attrs, ignore_merge_protection)

    recognize_empty_columns = state2.organization.column_set.filter(
        table_name=state2.__class__.__name__,
        recognize_empty=True,
        is_extra_data=False
    ).values_list('column_name', flat=True)

    default = state2
    for attr in can_attrs:
        recognize_empty = attr in recognize_empty_columns

        attr_values = [
            value
            for value
            in list(can_attrs[attr].values())
            if value is not None or recognize_empty
        ]

        attr_value = None
        # Two, differing values are set.
        if len(attr_values) > 1:
            # If we have more than one value for this field, choose based on the column priority
            col_prior = priorities.get(attr, 'Favor New')
            if ignore_merge_protection or col_prior == 'Favor New':
                attr_value = can_attrs[attr][state2]
            else:  # favor the existing field
                attr_value = can_attrs[attr][state1]

        # No values are set
        elif len(attr_values) < 1:
            attr_value = None

        # There is only one value set.
        else:
            attr_value = attr_values.pop()

        if callable(attr):
            # This callable will be responsible for setting the attribute value, not just returning it.
            attr(merged_state, default)
        else:
            setattr(merged_state, attr, attr_value)

    recognize_empty_ed_columns = state2.organization.column_set.filter(
        table_name=state2.__class__.__name__,
        recognize_empty=True,
        is_extra_data=True
    ).values_list('column_name', flat=True)

    merged_state.extra_data = _merge_extra_data(
        state1.extra_data,
        state2.extra_data,
        priorities['extra_data'],
        recognize_empty_ed_columns,
        ignore_merge_protection
    )

    # merge measures, scenarios, simulations
    if isinstance(merged_state, PropertyState):
        PropertyState.merge_relationships(merged_state, state1, state2)

    return merged_state
Beispiel #13
0
    def test_parse_meter_details_creates_entries_for_multiple_records_with_same_pm_property_id(
            self):
        property_details = self.property_state_factory.get_details()
        property_details['pm_property_id'] = self.pm_property_id
        property_details['custom_id_1'] = 'Force unmatched'
        property_details['organization_id'] = self.org.id

        state = PropertyState(**property_details)
        state.save()
        state_2 = PropertyState.objects.get(pk=state.id)

        property_2 = self.property_factory.get_property()

        PropertyView.objects.create(property=property_2,
                                    cycle=self.cycle,
                                    state=state_2)

        raw_meters = [{
            'Portfolio Manager ID': self.pm_property_id,
            'Portfolio Manager Meter ID': '123-PMMeterID',
            'Start Date': '2016-03-01 00:00:00',
            'End Date': '2016-04-01 00:00:00',
            'Meter Type': 'Electric - Grid',
            'Usage Units': 'kBtu (thousand Btu)',
            'Usage/Quantity': 100,
        }, {
            'Portfolio Manager ID': self.pm_property_id,
            'Portfolio Manager Meter ID': '123-PMMeterID',
            'Start Date': '2016-03-01 00:00:00',
            'End Date': '2016-04-01 00:00:00',
            'Meter Type': 'Natural Gas',
            'Usage Units': 'kBtu (thousand Btu)',
            'Usage/Quantity': 200,
        }]

        expected = [{
            'property_id':
            self.property.id,
            'source':
            Meter.PORTFOLIO_MANAGER,
            'source_id':
            '123-PMMeterID',
            'type':
            Meter.ELECTRICITY_GRID,
            'readings': [{
                'start_time':
                make_aware(datetime(2016, 3, 1, 0, 0, 0),
                           timezone=self.tz_obj),
                'end_time':
                make_aware(datetime(2016, 4, 1, 0, 0, 0),
                           timezone=self.tz_obj),
                'reading':
                100,
                'source_unit':
                'kBtu (thousand Btu)',
                'conversion_factor':
                1
            }]
        },
                    {
                        'property_id':
                        property_2.id,
                        'source':
                        Meter.PORTFOLIO_MANAGER,
                        'source_id':
                        '123-PMMeterID',
                        'type':
                        Meter.ELECTRICITY_GRID,
                        'readings': [{
                            'start_time':
                            make_aware(datetime(2016, 3, 1, 0, 0, 0),
                                       timezone=self.tz_obj),
                            'end_time':
                            make_aware(datetime(2016, 4, 1, 0, 0, 0),
                                       timezone=self.tz_obj),
                            'reading':
                            100,
                            'source_unit':
                            'kBtu (thousand Btu)',
                            'conversion_factor':
                            1
                        }]
                    }, {
                        'property_id':
                        self.property.id,
                        'source':
                        Meter.PORTFOLIO_MANAGER,
                        'source_id':
                        '123-PMMeterID',
                        'type':
                        Meter.NATURAL_GAS,
                        'readings': [{
                            'start_time':
                            make_aware(datetime(2016, 3, 1, 0, 0, 0),
                                       timezone=self.tz_obj),
                            'end_time':
                            make_aware(datetime(2016, 4, 1, 0, 0, 0),
                                       timezone=self.tz_obj),
                            'reading':
                            200,
                            'source_unit':
                            'kBtu (thousand Btu)',
                            'conversion_factor':
                            1
                        }]
                    }, {
                        'property_id':
                        property_2.id,
                        'source':
                        Meter.PORTFOLIO_MANAGER,
                        'source_id':
                        '123-PMMeterID',
                        'type':
                        Meter.NATURAL_GAS,
                        'readings': [{
                            'start_time':
                            make_aware(datetime(2016, 3, 1, 0, 0, 0),
                                       timezone=self.tz_obj),
                            'end_time':
                            make_aware(datetime(2016, 4, 1, 0, 0, 0),
                                       timezone=self.tz_obj),
                            'reading':
                            200,
                            'source_unit':
                            'kBtu (thousand Btu)',
                            'conversion_factor':
                            1
                        }]
                    }]

        meters_parser = MetersParser(self.org.id, raw_meters)

        self.assertEqual(meters_parser.meter_and_reading_objs, expected)
Beispiel #14
0
    def test_the_response_contains_expected_and_actual_reading_counts_by_property_id_even_in_the_same_cycle(
            self):
        property_details = FakePropertyStateFactory(
            organization=self.org).get_details()
        property_details['organization_id'] = self.org.id

        # Create new state NOT associated to existing record but has same PM Property ID
        property_details['pm_property_id'] = self.state_1.pm_property_id
        property_details['custom_id_1'] = "values that forces non-match"
        state = PropertyState(**property_details)
        state.save()
        new_property_state = PropertyState.objects.get(pk=state.id)

        # new state in cycle associated to old property
        property_3 = self.property_factory.get_property()
        PropertyView.objects.create(property=property_3,
                                    cycle=self.cycle,
                                    state=new_property_state)

        url = reverse("api:v3:import_files-start-save-data",
                      args=[self.import_file.id])
        url += f'?organization_id={self.org.pk}'
        post_params = {
            'cycle_id': self.cycle.pk,
        }
        response = self.client.post(url, post_params)

        result = json.loads(response.content)

        expectation = [
            {
                "property_id": self.property_1.id,
                "cycles": self.cycle.name,
                "pm_property_id": "5766973",
                "source_id": "5766973-0",
                "type": "Electric - Grid",
                "incoming": 2,
                "successfully_imported": 2,
            },
            {
                "property_id": property_3.id,
                "cycles": self.cycle.name,
                "pm_property_id": "5766973",
                "source_id": "5766973-0",
                "type": "Electric - Grid",
                "incoming": 2,
                "successfully_imported": 2,
            },
            {
                "property_id": self.property_1.id,
                "cycles": self.cycle.name,
                "pm_property_id": "5766973",
                "source_id": "5766973-1",
                "type": "Natural Gas",
                "incoming": 2,
                "successfully_imported": 2,
            },
            {
                "property_id": property_3.id,
                "cycles": self.cycle.name,
                "pm_property_id": "5766973",
                "source_id": "5766973-1",
                "type": "Natural Gas",
                "incoming": 2,
                "successfully_imported": 2,
            },
            {
                "property_id": self.property_2.id,
                "cycles": self.cycle.name,
                "pm_property_id": "5766975",
                "source_id": "5766975-0",
                "type": "Electric - Grid",
                "incoming": 2,
                "successfully_imported": 2,
            },
            {
                "property_id": self.property_2.id,
                "cycles": self.cycle.name,
                "pm_property_id": "5766975",
                "source_id": "5766975-1",
                "type": "Natural Gas",
                "incoming": 2,
                "successfully_imported": 2,
            },
        ]

        self.assertCountEqual(result['message'], expectation)
Beispiel #15
0
    def test_the_response_contains_expected_and_actual_reading_counts_across_cycles_for_linked_properties(
            self):
        property_details = FakePropertyStateFactory(
            organization=self.org).get_details()
        property_details['organization_id'] = self.org.id

        # new state will be linked to existing record and has same PM Property ID
        property_details['pm_property_id'] = self.state_1.pm_property_id
        state = PropertyState(**property_details)
        state.save()

        new_property_state = PropertyState.objects.get(pk=state.id)
        new_cycle = self.cycle_factory.get_cycle(
            start=datetime(2011, 10, 10, tzinfo=get_current_timezone()))

        PropertyView.objects.create(property=self.property_1,
                                    cycle=new_cycle,
                                    state=new_property_state)

        url = reverse("api:v3:import_files-start-save-data",
                      args=[self.import_file.id])
        url += f'?organization_id={self.org.pk}'
        post_params = {
            'cycle_id': self.cycle.pk,
        }
        response = self.client.post(url, post_params)

        result = json.loads(response.content)

        expectation = [
            {
                "property_id": self.property_1.id,
                "cycles": self.cycle.name + ", " + new_cycle.name,
                "pm_property_id": "5766973",
                "source_id": "5766973-0",
                "type": "Electric - Grid",
                "incoming": 2,
                "successfully_imported": 2,
            },
            {
                "property_id": self.property_1.id,
                "cycles": self.cycle.name + ", " + new_cycle.name,
                "pm_property_id": "5766973",
                "source_id": "5766973-1",
                "type": "Natural Gas",
                "incoming": 2,
                "successfully_imported": 2,
            },
            {
                "property_id": self.property_2.id,
                "cycles": self.cycle.name,
                "pm_property_id": "5766975",
                "source_id": "5766975-0",
                "type": "Electric - Grid",
                "incoming": 2,
                "successfully_imported": 2,
            },
            {
                "property_id": self.property_2.id,
                "cycles": self.cycle.name,
                "pm_property_id": "5766975",
                "source_id": "5766975-1",
                "type": "Natural Gas",
                "incoming": 2,
                "successfully_imported": 2,
            },
        ]

        self.assertCountEqual(result['message'], expectation)
Beispiel #16
0
    def setUp(self):
        self.user_details = {
            'username': '******',
            'password': '******',
        }
        self.user = User.objects.create_superuser(email='*****@*****.**',
                                                  **self.user_details)
        self.org, _, _ = create_organization(self.user)
        self.client.login(**self.user_details)

        self.property_state_factory = FakePropertyStateFactory(
            organization=self.org)
        property_details = self.property_state_factory.get_details()
        property_details['organization_id'] = self.org.id

        # pm_property_ids must match those within example-monthly-meter-usage.xlsx
        self.pm_property_id_1 = '5766973'
        self.pm_property_id_2 = '5766975'

        property_details['pm_property_id'] = self.pm_property_id_1
        state_1 = PropertyState(**property_details)
        state_1.save()
        self.state_1 = PropertyState.objects.get(pk=state_1.id)

        property_details['pm_property_id'] = self.pm_property_id_2
        state_2 = PropertyState(**property_details)
        state_2.save()
        self.state_2 = PropertyState.objects.get(pk=state_2.id)

        self.cycle_factory = FakeCycleFactory(organization=self.org,
                                              user=self.user)
        self.cycle = self.cycle_factory.get_cycle(
            start=datetime(2010, 10, 10, tzinfo=get_current_timezone()))

        self.property_factory = FakePropertyFactory(organization=self.org)
        self.property_1 = self.property_factory.get_property()
        self.property_2 = self.property_factory.get_property()

        self.property_view_1 = PropertyView.objects.create(
            property=self.property_1, cycle=self.cycle, state=self.state_1)
        self.property_view_2 = PropertyView.objects.create(
            property=self.property_2, cycle=self.cycle, state=self.state_2)

        self.import_record = ImportRecord.objects.create(
            owner=self.user,
            last_modified_by=self.user,
            super_organization=self.org)

        # This file has multiple tabs
        filename = "example-pm-monthly-meter-usage.xlsx"
        filepath = os.path.dirname(
            os.path.abspath(__file__)) + "/data/" + filename

        self.import_file = ImportFile.objects.create(
            import_record=self.import_record,
            source_type="PM Meter Usage",
            uploaded_filename=filename,
            file=SimpleUploadedFile(name=filename,
                                    content=open(filepath, 'rb').read()),
            cycle=self.cycle)

        self.tz_obj = timezone(TIME_ZONE)