예제 #1
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)
예제 #2
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)
예제 #3
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)
예제 #4
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)
예제 #5
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