示例#1
0
def send_problems_report(problem_message_records):
    """Send report of problems that affect metadata syncing.

    Args:
        problem_message_records (dict): Mapping of provlem messages to collection of
            records where that problem occurred during sync.

    """
    body_template = """
        <p>Problems were found that prevent certain metadata records from syncing
            between Geoportal and the datasets.<br />
        </p>
        <table style="width:100%">
            {}{}
        </table>
    """
    table_header = ("<tr><th>Count</th><th>ID</th><th>Title</th>" +
                    "<th>Problem</th><th>Dataset Path</th></tr>")
    row_template = "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>"
    if problem_message_records:
        LOG.warning("Found syncing problem records: sending report.")
        table_rows = []
        i = 0
        for message, records in sorted(problem_message_records.items()):
            for record in sorted(records):
                i += 1
                table_rows.append(
                    row_template.format(i, record.id, record.title, message,
                                        record.dataset_path))
        KWARGS_PROBLEMS_REPORT_MESSAGE["body"] = body_template.format(
            table_header, table_rows)
        send_email(**KWARGS_PROBLEMS_REPORT_MESSAGE)
    else:
        LOG.info("No syncing problem records found. Not sending report.")
def publication_issues_message_etl():
    """Send message of issues that affect address publication."""
    field_names = ["description", "postcomm", "address", "address_id"]
    issues = sorted(
        arcetl.attributes.as_iters(
            dataset.TILLAMOOK_ADDRESS_POINT_ISSUES.path(),
            field_names,
            dataset_where_sql="ok_to_publish = 0",
        ))
    LOG.warning("Found validation publication issues: sending email.")
    table_header = "<tr>{}</tr>".format("".join("<th>{}</th>".format(column)
                                                for column in field_names))
    row_template = "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>"
    table_rows = "".join(row_template.format(*issue) for issue in issues)
    KWARGS_ISSUES_MESSAGE["body"] = KWARGS_ISSUES_MESSAGE["body"].format(
        table_header, table_rows)
    send_email(**KWARGS_ISSUES_MESSAGE)
示例#3
0
def warehouse_issues():
    """Run check for issues in RLIDGeo update."""
    all_dataset_kwargs = {}
    for tag in DATASET_KWARGS:
        all_dataset_kwargs.update(DATASET_KWARGS[tag])
    datasets = {
        "existing":
        sorted(
            name.split(".", 1)[-1]
            for name in arcetl.workspace.dataset_names(database.RLIDGEO.path)),
        "listed":
        sorted(all_dataset_kwargs),
        "unlisted": [],
        "listed_not_exist": [],
    }
    datasets["existing_lower"] = {
        name.lower()
        for name in datasets["existing"]
    }
    datasets["listed_lower"] = {name.lower() for name in datasets["listed"]}
    for dataset_name in datasets["existing"]:
        if dataset_name.lower() not in datasets["listed_lower"]:
            datasets["unlisted"].append(dataset_name)
    for dataset_name in datasets["listed"]:
        if dataset_name.lower() not in datasets["existing_lower"]:
            datasets["listed_not_exist"].append(dataset_name)
    message_body = ""
    if datasets["unlisted"]:
        message_body += "<h2>Datasets not listed in DATASET_KWARGS</h2><ul>{}</ul>".format(
            "".join("<li>{}</li>".format(item)
                    for item in datasets["unlisted"]))
    if datasets["listed_not_exist"]:
        message_body += "<h2>Datasets listed in DATASET_KWARGS that do not exist</h2><ul>{}</ul>".format(
            "".join("<li>{}</li>".format(item)
                    for item in datasets["listed_not_exist"]))
    if message_body:
        LOG.info("Found update issues: sending email.")
        send_email(subject="RLIDGeo Update Issues",
                   body=message_body,
                   body_format="HTML",
                   **KWARGS_ISSUES_MESSAGE)
    else:
        LOG.info("No update issues found.")
def send_publication_issues_message():
    """Send message of issues that affect address publication."""
    keys = ["description", "city_name", "concat_address", "geofeat_id"]
    issues = sorted(
        arcetl.attributes.as_iters(
            dataset.ADDRESS_ISSUES.path(),
            field_names=keys,
            dataset_where_sql="update_publication = 0",
        ))
    table_header = "<tr>{}</tr>".format("".join("<th>{}</th>".format(key)
                                                for key in keys))
    row_template = "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>"
    if issues:
        LOG.warning("Found validation publication issues: sending email.")
        table_rows = "".join(row_template.format(*issue) for issue in issues)
        KWARGS_ISSUES_MESSAGE["body"] = KWARGS_ISSUES_MESSAGE["body"].format(
            table_header, table_rows)
        send_email(**KWARGS_ISSUES_MESSAGE)
    else:
        LOG.info("No validation publication issues found. Not sending email.")
def send_new_lincom_address_message():
    """Send message for any recently-added address in the Lincoln PSAP area."""
    keys = ["city_name", "concat_address", "geofeat_id", "initial_create_date"]
    addresses = sorted(addr for addr in arcetl.attributes.as_iters(
        dataset.SITE_ADDRESS.path("pub"),
        field_names=keys,
        dataset_where_sql="psap_code = 'LI' ",
    ) if (datetime.datetime.now() - addr[-1]).days < 15)
    table_header = "<tr>{}</tr>".format("".join("<th>{}</th>".format(key)
                                                for key in keys))
    row_template = "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>"
    if addresses:
        LOG.warning("Found new addresses in Lincoln PSAP area: sending email.")
        table_rows = "".join(row_template.format(*addr) for addr in addresses)
        KWARGS_NEW_LINCOLN_MESSAGE["body"] = KWARGS_NEW_LINCOLN_MESSAGE[
            "body"].format(table_header, table_rows)
        send_email(**KWARGS_NEW_LINCOLN_MESSAGE)
    else:
        LOG.info(
            "No new addresses in Lincoln PSAP area found. Not sending email.")
示例#6
0
def msag_update():
    """Run update for the Master Street Address Guide dataset in RLIDGeo warehouse."""
    LOG.info("Start: Update MSAG dataset in RLIDGeo warehouse.")
    unretired_where_sql = "expiration_date is null"
    # Do not update MSAG if there will be a significant change.
    count = {
        "current":
        arcetl.features.count(dataset.MSAG_RANGE.path("current")),
        "previous":
        arcetl.features.count(dataset.MSAG_RANGE.path("master"),
                              dataset_where_sql=unretired_where_sql),
    }
    if abs(count["current"] - count["previous"]) > count["previous"] * 0.01:
        send_email(subject="RLIDGeo MSAG Update Issues",
                   body="""
                <p>
                    Greater than 1% change in number of un-expired ranges; not applying
                    changes.
                </p>
            """,
                   body_format="HTML",
                   **KWARGS_ISSUES_MESSAGE)

    msag_keys = [
        "msag_id",
        "emergency_service_number",
        "parity_code",
        "parity",
        "from_house_number",
        "to_house_number",
        "pre_direction_code",
        "street_name",
        "street_type_code",
        "city_code",
        "city_name",
        "effective_date",
        "shape@",
    ]
    msag_id_range = {
        feature["msag_id"]: feature
        for feature in arcetl.attributes.as_dicts(
            dataset.MSAG_RANGE.path("current"), field_names=msag_keys)
    }
    feature_count = Counter(deleted=0)
    most_recent_date = max(val["effective_date"]
                           for val in msag_id_range.values())
    master_cursor = arcpy.da.UpdateCursor(
        dataset.MSAG_RANGE.path("master"),
        field_names=["msag_id", "expiration_date", "shape@"],
        where_clause=unretired_where_sql,
    )
    # Collect IDs for add-check later.
    master_ids = set()
    LOG.info("Start: Update geometry & expiration dates.")
    with master_cursor:
        for msag_id, expiration_date, geom in master_cursor:
            master_ids.add(msag_id)
            if msag_id not in msag_id_range:
                LOG.info("Range (ID=%s) not in current: set expiration date.",
                         msag_id)
                expiration_date = most_recent_date
            elif geom is None or not geom.equals(
                    msag_id_range[msag_id]["shape@"]):
                LOG.info("Range (ID=%s) changed geometry.", msag_id)
                geom = msag_id_range[msag_id]["shape@"]
            else:
                feature_count["unchanged"] += 1
                continue
            master_cursor.updateRow((msag_id, expiration_date, geom))
            feature_count["altered"] += 1
    LOG.info("End: Update.")
    LOG.info("Start: Insert new ranges from current MSAG.")
    master_cursor = arcpy.da.InsertCursor(dataset.MSAG_RANGE.path("master"),
                                          field_names=msag_keys)
    with master_cursor:
        for msag_id, range_ in msag_id_range.items():
            if msag_id not in master_ids:
                LOG.info("Range (ID=%s) new in current: adding.", msag_id)
                master_cursor.insertRow(tuple(range_[key]
                                              for key in msag_keys))
                feature_count["inserted"] += 1
    LOG.info("End: Insert.")
    record_dataset_update(
        os.path.basename(dataset.MSAG_RANGE.path("master")),
        feature_count,
        metadata_path=dataset.METADATA_DATASET_UPDATE.path("RLIDGeo"),
    )
    LOG.info("End: Update.")