def test_parse_meter_row_valueerror(self):
     """Test that parse_meter_row raises a ValueError when a field has an invalid value"""
     meter_row = {
         "PK": "not_an_int",  # ValueError occurs here
         "Tariff": "test_tariff",
         "ServiceType": "test_service",
         "PODid": "12345",
         "MeterNumber": "67890",
         "IntervalStart": date(2000, 2, 1),
         "IntervalEnd": date(2000, 3, 1),
     }
     with self.assertRaises(ValueError):
         UrjanetPyMySqlDataSource.parse_meter_row(meter_row)
 def test_parse_meter_row_keyerror(self):
     """Test that parse_meter_row raises a KeyError when a field is missing"""
     meter_row = {
         "PK": 1,
         "Tariff": "test_tariff",
         # Exclude this field"ServiceType": "test_service",
         "PODid": "12345",
         "MeterNumber": "67890",
         "IntervalStart": date(2000, 2, 1),
         "IntervalEnd": date(2000, 3, 1),
     }
     with self.assertRaises(KeyError):
         UrjanetPyMySqlDataSource.parse_meter_row(meter_row)
Example #3
0
    def load_meters(self, account_pk: int) -> List[Meter]:
        """Load all meters for an account."""
        query = """
            select *
            from Meter
            where Meter.AccountFK=%s and Meter.ServiceType in ('electric', 'natural_gas', 'lighting')
        """
        if self.meter_number:
            query += " AND (Meter.MeterNumber LIKE %s OR Meter.MeterNumber LIKE %s)"
            result_set = self.fetch_all(
                query,
                account_pk,
                "%{}%".format(self.said),
                "%{}".format(self.meter_number),
            )
        else:
            query += " AND Meter.MeterNumber LIKE %s"
            result_set = self.fetch_all(query, account_pk,
                                        "%{}%".format(self.said))

        if not result_set and self.service_type:
            # If no meters have been found for the account
            query = """
               select *
               from Meter
               where Meter.AccountFK=%s and Meter.ServiceType in (%s)
            """
            result_set = self.fetch_all(query, account_pk, self.service_type)
        return [
            UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
        ]
Example #4
0
    def load_meters(self, account_pk: int) -> List[Meter]:
        """Load meters based on the service id"""

        query = """SELECT * FROM Meter WHERE ServiceType = 'electric' AND AccountFK=%s
                and MeterNumber LIKE %s
                """
        result_set = self.fetch_all(query, account_pk, self.said)
        return [UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set]
    def load_meters(self, account_pk: int) -> List[UrjaMeter]:
        """Load all electric meters for an account"""

        query = "SELECT * FROM Meter WHERE ServiceType in ('electric') AND AccountFK=%s"
        result_set = self.fetch_all(query, account_pk)
        return [
            UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
        ]
 def load_meters(self, account_pk: int) -> List[Meter]:
     """Load meters based on the service id"""
     query = """
         select *
         from Meter
         where AccountFK=%s and ServiceType in ('water', 'sewer', 'irrigation', 'sanitation')
     """
     result_set = self.fetch_all(query, account_pk)
     return [UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set]
Example #7
0
    def load_meters(self, account_pk: int) -> List[UrjaMeter]:
        """Load all meters for an account

        Currently only has water meters.
        """

        query = "SELECT * FROM Meter WHERE ServiceType='water' AND AccountFK=%s"
        result_set = self.fetch_all(query, account_pk)
        return [UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set]
Example #8
0
    def load_meters(self, account_pk: int) -> List[UrjaMeter]:
        """Load all meters for an account

        Currently, water, sewer meters are loaded.
        """

        query = "SELECT * FROM Meter WHERE ServiceType in ('water', 'sewer', 'irrigation') AND AccountFK=%s"
        result_set = self.fetch_all(query, account_pk)
        return [
            UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
        ]
Example #9
0
 def load_meters(self, account_pk: int) -> List[Meter]:
     """Load meters based on the service id"""
     query = """
         SELECT *
         FROM Meter
         WHERE
             AccountFK=%s
             AND ServiceType='water'
             AND PODid=%s
     """
     result_set = self.fetch_all(query, account_pk, self.service_id)
     return [UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set]
Example #10
0
    def load_meters(self, account_pk: int) -> List[Meter]:
        """Load meters for an account, optionally filtering by meter ID

        Currently, both water and sewer meters are loaded.
        """

        query = "SELECT * FROM Meter WHERE ServiceType in ('water', 'sewer') AND AccountFK=%s"
        result_set = self.fetch_all(query, account_pk)

        return [
            UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
        ]
Example #11
0
 def load_meters(self, account_pk: int) -> List[UrjaMeter]:
     """Load meters matching a Gridium meter SAID.
     A bill can contain usage and charges for multiple meters. Select meters where the
     Urjanet Meter.MeterNumber matches a Gridium utility_service.service_id
     """
     # The utility may totalize submeters, and have two meter numbers for one set of charges.
     # In this case, the SAID should contain both meter ids, separated by commas.
     query = "SELECT * FROM Meter WHERE ServiceType='electric' AND AccountFK=%s AND MeterNumber in %s"
     result_set = self.fetch_all(query, account_pk, self.said.split(","))
     return [
         UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
     ]
Example #12
0
 def load_meters(self, account_pk: int) -> List[Meter]:
     """Load all meters for an account."""
     query = """
         select *
         from Meter
         where Meter.AccountFK=%s and Meter.ServiceType in ('electric', 'natural_gas')
             and Meter.MeterNumber LIKE %s
     """
     result_set = self.fetch_all(query, account_pk,
                                 "%{}%".format(self.said.replace(" ", "")))
     return [
         UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
     ]
Example #13
0
 def load_meters(self, account_pk: int) -> List[Meter]:
     """Load meters based on the service id"""
     query = """
         SELECT *
         FROM Meter
         WHERE
             AccountFK=%s
             AND ServiceType in ('electric', 'natural_gas', 'lighting')
             AND PODid LIKE %s
     """
     result_set = self.fetch_all(query, account_pk, self.meter_id)
     return [
         UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
     ]
Example #14
0
    def load_meters(self, account_pk: int) -> List[Meter]:
        """Load all meters for an account.

        Note: This is just for computing line items.
        For all the accounts we've provisioned thus far, statements
        and physical meters are in one to one correspondence (there
        are no submeters).
        """
        query = """
            select *
            from Meter
            where Meter.AccountFK=%s and Meter.ServiceType in ('electric', 'natural_gas')
        """
        result_set = self.fetch_all(query, account_pk)
        return [UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set]
Example #15
0
 def load_meters(self, account_pk: int) -> List[Meter]:
     """Load meters based on all SAID's we have on record, and any ESP Customer Numbers found."""
     query = """
        SELECT *
        FROM xmlmeter
        WHERE
            AccountFK=%s
            AND ServiceType in ('electric', 'natural_gas', 'lighting')
            AND PODid in ({})
     """.format(create_placeholders(self.service_ids))
     result_set = self.fetch_all(query, account_pk, *self.service_ids)
     results = [
         UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
     ]
     return results
Example #16
0
    def load_meters(self, account_pk: int) -> List[UrjaMeter]:
        """Load meters matching a Gridium meter SAID.

        A bill can contain usage and charges for multiple meters. Select meters where the
        Urjanet Meter.MeterNumber matches a Gridium utility_service.service_id
        """
        # The utility may totalize submeters, and have two meter numbers for one set of charges.
        # In this case, the SAID should contain both meter ids, separated by commas.
        saids = []
        # SAIDs may have a trailing letter that's not in the Urjanet version; try both versions
        for said in self.said.split(","):
            saids.append(said)
            saids.append(re.sub(r"[A-Z]$", "", said))
        query = "SELECT * FROM Meter WHERE ServiceType in %s AND AccountFK=%s AND MeterNumber in %s"
        result_set = self.fetch_all(query, self.commodity_type.value,
                                    account_pk, saids)
        return [
            UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
        ]
Example #17
0
    def load_meters(self, account_pk: int) -> List[Meter]:
        """Load all meters for an account.

        Note: This is just for computing line items.
        Urjanet appears to use the last 6 of our service ID as the
        meter number in their records.
        """
        query = """
            select *
            from Meter
            where Meter.AccountFK=%s and Meter.ServiceType in ('electric', 'natural_gas')
                and Meter.MeterNumber like %s
        """
        result_set = self.fetch_all(query, account_pk,
                                    "%{}%".format(self.said[-6:]))

        return [
            UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
        ]
Example #18
0
    def load_meters(self, account_pk: int) -> List[Meter]:
        """Load all meters for an account.

        PSE meter numbers tend to have a single-letter prefix, e.g. "Z".
        Urjanet sometimes stores the meter number without this prefix.
        Therefore, we look for bills with meter numbers that match either
        the prefix or non-prefixed meter number.
        """
        said_no_prefix = re.sub("^[A-Z]", "", self.said)
        query = """
            select *
            from Meter
            where AccountFK=%s and Meter.ServiceType in ('electric', 'natural_gas')
                and (Meter.MeterNumber like %s or Meter.MeterNumber like %s)
        """
        result_set = self.fetch_all(
            query, account_pk, "%{}%".format(self.said), "%{}%".format(said_no_prefix)
        )
        return [UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set]
Example #19
0
    def load_meters(self, account_pk: int) -> List[Meter]:
        """Load all meters for an account."""
        query = """
            select *
            from Meter
            where AccountFK=%s and ServiceType in ('electric', 'gas')
        """
        result_set = self.fetch_all(query, account_pk)
        # Check our requirement that each statement has data about a single POD id
        pod_ids = [mtr["PODid"] for mtr in result_set]
        if len(set(pod_ids)) > 1:
            msg = (
                "This scraper requires each statement to "
                "contain information for a single meter/PODid. "
                "Violated by: Statement PK=={1}"
            )
            msg = msg.format(account_pk)
            raise ScraperPreconditionError(msg)

        return [UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set]
Example #20
0
    def load_meters(self, account_pk: int) -> List[Meter]:
        """LADWP formats these bills so that the 'meter number' is often on two lines.

        Urjanet pulls in that second line with a space. Gridium often munges the whole
        thing into a single number. It's unclear who is right. So we use a bit of replace()
        magic to just flatten the whole thing into a single number to normalize this.
        """
        query = """
            SELECT *
            FROM Meter
            WHERE
                AccountFK=%s
                AND replace(Meter.MeterNumber, ' ', '') LIKE %s
                AND ServiceType in ('electric', 'natural_gas')
        """
        result_set = self.fetch_all(query, account_pk,
                                    "%%%s%%" % self.service_id)
        return [
            UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
        ]
 def test_parse_meter_row(self):
     """Test the basic functionality of the parse_meter_row function."""
     meter_row = {
         "PK": 1,
         "Tariff": "test_tariff",
         "ServiceType": "test_service",
         "PODid": "12345",
         "MeterNumber": "67890",
         "IntervalStart": date(2000, 2, 1),
         "IntervalEnd": date(2000, 3, 1),
         "__EXTRA1": "EXTRA1",  # It's okay to have extra fields
         "__EXTRA2": "EXTRA2",
     }
     result = UrjanetPyMySqlDataSource.parse_meter_row(meter_row)
     for field in meter_row:
         if field.startswith("__EXTRA"):
             with self.assertRaises(AttributeError):
                 getattr(result, field)
         else:
             self.assertEqual(getattr(result, field), meter_row[field])
Example #22
0
    def load_meters(self, account_pk: int) -> List[Meter]:
        """Load all meters for an account.

        Normally we'd pull only bill data that matches our service ID. However, FPL has a habit of
        reassigning new service IDs to the same meter. To handle that we're just always going
        to assume that meters in the same account are the same meter, regardless of the ID. This
        assumption depends on the arrangement in which only a single meter is ever attached
        to one statement. If that isn't true, bail out and fix this some other way.
        """
        query = """
            select *
            from Meter
            where Meter.AccountFK=%s
        """
        result_set = self.fetch_all(query, account_pk)
        assert len(result_set) <= 1

        return [
            UrjanetPyMySqlDataSource.parse_meter_row(row) for row in result_set
        ]