Beispiel #1
0
 def set_history_type(self):
     WebDriverWait(self.driver, 10).until(
         EC.presence_of_element_located(self.UsageRadioButtonLocator))
     usage_radio_button = self.driver.find_element(
         *self.UsageRadioButtonLocator)
     scroll_to(self.driver, usage_radio_button)
     usage_radio_button.click()
Beispiel #2
0
    def set_displayed_bills(self):
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located(self.NumBillsDisplayedLocator))
        num_bills_displayed_select = self.driver.find_element(
            *self.NumBillsDisplayedLocator)
        scroll_to(self.driver, num_bills_displayed_select)
        num_bills_displayed_select.click()

        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located(
                self.NumBillsDisplayedOptionLocator))
        num_bills_displayed_option = self.driver.find_element(
            *self.NumBillsDisplayedOptionLocator)
        num_bills_displayed_option.click()
Beispiel #3
0
def click(
    driver,
    css_selector: str = None,
    xpath: str = None,
    elem: WebElement = None,
    scroll: bool = True,
):
    """helper method to click an element, if it is blocked by blockOverlay, waits for the overlay to disappear"""
    if elem:
        pass
    elif css_selector:
        elem = driver.find_element_by_css_selector(css_selector)
    elif xpath:
        elem = driver.find_element_by_xpath(xpath)
    else:
        raise ValueError("one of css_selector, xpath or elem must be provided")

    retries_left = 5
    while retries_left > 0:
        try:
            scroll_to(driver, elem) if scroll is True else None
            elem.click()
            break
        except ElementClickInterceptedException as e:
            if "blockUI blockOverlay" in e.msg:
                log.info(
                    "blocked by overlay, waiting for it to go before clicking again"
                )
                wait_for_block_overlay(driver)
                continue
            else:
                if not close_modal(driver):
                    raise

        finally:
            retries_left -= 1
Beispiel #4
0
    def get_bills(self, account_id: str, start: date,
                  end: date) -> List[BillingDatum]:
        """Get bills from the table.

        for each row:
          get end from Read date column (date)
          get start date from end date - (Days column (date) - 1)
          get statement date from Bill date column (date)
          if not start - end overlaps passed in start / end, continue
          get peak from On-peak Billed kW (float)
          get used from (Off-peak kWh + Shoulder kWh + On-peak kWh) (float)
          get cost from New charges (float)
          click eye icon to download PDF; wait for download to complete to self.driver.download_dir
        """
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located(self.UsageTableBodyLocator))
        usage_table_rows = self.driver.find_elements(
            *self.UsageTableRowsLocator)

        bill_data: List[BillingDatum] = []
        self.driver.screenshot(BaseWebScraper.screenshot_path("bill table"))
        for row in usage_table_rows:
            cols = row.find_elements_by_tag_name("td")
            cols = [
                c for c in cols
                if "display: none" not in c.get_attribute("style")
            ]

            col = lambda x: cols[x].text
            to_num = lambda x: "".join(d for d in col(x)
                                       if d.isdigit() or d == ".")
            to_float = lambda x: float(to_num(x)) if len(to_num(x)) > 0 else 0

            log.debug(f"statement={col(1)} end={col(2)} days={col(7)}")
            # statement date
            statement_date = date_parser.parse(col(1)).date()

            # bill end
            period_year = statement_date.year
            if statement_date.month == 1 and col(2).startswith("12"):
                period_year = statement_date.year - 1
            end_str = f"{col(2)}/{period_year}"
            bill_end = date_parser.parse(end_str).date()

            # bill start
            bill_start = bill_end - timedelta(days=int(to_float(7)) - 1)
            log.debug(f"start={bill_start} end={bill_end}")

            if not self._overlap(start, end, bill_start, bill_end):
                log.info(
                    f"skipping bill {bill_start} - {bill_end}: does not overlap requested range {start} - {end}"
                )
                continue

            # cost
            new_charges = to_float(8)
            # used
            used = to_float(4) + to_float(5) + to_float(6)
            # peak
            peak = to_float(3)

            bill_datum = BillingDatum(
                start=bill_start,
                end=bill_end,
                statement=statement_date,
                cost=new_charges,
                used=used,
                peak=peak,
                items=None,
                attachments=None,
                utility_code=None,
            )

            try:
                bill_pdf_name = "SRPbill{}{}.pdf".format(
                    statement_date.strftime("%B"), statement_date.year)
                pdf_download_link = cols[0].find_element_by_tag_name("a")
                scroll_to(self.driver, pdf_download_link)
                pdf_download_link.click()
                log.info("looking for %s in %s", bill_pdf_name,
                         self.driver.download_dir)
                self.driver.wait(60).until(
                    file_exists_in_dir(self.driver.download_dir,
                                       bill_pdf_name))
            except Exception as e:
                raise Exception(
                    f"Failed to download bill {bill_pdf_name} for statement date {statement_date}:\n {e}"
                )
            log.info(
                f"Bill {bill_pdf_name} for statement date {statement_date} downloaded successfully"
            )

            attachment_entry = None
            # open downloaded PDF and upload
            if config.enabled("S3_BILL_UPLOAD"):
                key = hash_bill_datum(account_id, bill_datum)
                with open(f"{self.driver.download_dir}/{bill_pdf_name}",
                          "rb") as pdf_data:
                    attachment_entry = upload_bill_to_s3(
                        BytesIO(pdf_data.read()),
                        key,
                        source="myaccount.srpnet.com",
                        statement=bill_datum.statement,
                        utility="utility:salt-river-project",
                        utility_account_id=account_id,
                    )
            if attachment_entry:
                bill_data.append(
                    bill_datum._replace(attachments=[attachment_entry]))
            else:
                bill_data.append(bill_datum)
        return bill_data
Beispiel #5
0
    def export_csv(self, service_id, start: date, end: date) -> str:
        """Export CSV file and return path to downloaded file.

        Select meter service_id from Meter drop down
        Click triple bar button, then Export All Data (CSV)
        Adjust end date if needed: get latest to date from form, parse into a date, and set end to max(end, form_max_dt)
        Set from and to dates (mm/dd/yyyy) and click Download.
        Wait for file to download (.csv)
        Return path to csv file
        """

        self.driver.wait().until(
            EC.invisibility_of_element_located(
                (By.CSS_SELECTOR, "div.spinner-container")))

        self.driver.sleep(2)
        self.driver.find(self.MeterDropdownSelector).click()
        # wait for loading
        self.driver.sleep(5)

        meter_dropdown_selector = f'//table[@id="sdp_selector_table"]//a[contains(@class,"sdp-dropdown") and contains(.,"{service_id}")]'
        meter_id_dropdown_option = self.driver.find(meter_dropdown_selector,
                                                    xpath=True)
        scroll_to(self.driver, meter_id_dropdown_option)
        if not meter_id_dropdown_option:
            raise DataSourceConfigurationError(
                f"No meter found with service_id: {service_id}")

        meter_id_dropdown_option.click()
        self.driver.wait().until(
            EC.invisibility_of_element_located(
                (By.CSS_SELECTOR, "div.spinner-container")))
        self.driver.sleep(2)
        self.driver.find_element(*self.ExportCSVDropDownButtonLocator).click()
        self.driver.sleep(2)

        self.driver.find(self.ExportCSVLinkSelector).click()
        self.driver.wait().until(
            EC.visibility_of_element_located(
                (By.CSS_SELECTOR, self.FromDateInputSelector)))
        self.driver.sleep(2)
        from_date_input_field = self.driver.find(self.FromDateInputSelector)
        from_date_input_field.clear()
        from_date_input_field.send_keys(start.strftime("%m/%d/%Y"))

        to_date_input_field = self.driver.find(self.ToDateInputSelector)
        max_available_to_date = parse_date(
            to_date_input_field.get_attribute("placeholder")).date()

        end = max(max_available_to_date, end)

        to_date_input_field.clear()
        to_date_input_field.send_keys(end.strftime("%m/%d/%Y"))

        self.driver.find(self.DownloadButtonSelector).click()

        # Wait for csv to download
        download_dir = self.driver.download_dir
        filename = self.driver.wait().until(
            file_exists_in_dir(download_dir, r".*\.{}$".format("csv")))
        return os.path.join(download_dir, filename)