Пример #1
0
def summary_email(engine, timestamp_utc=None):
    """
    Prepares and sends out the summary email

    Arguments:
        engine - an sql engine instance
        timestamp_utc - summary timestamp
    Returns:
        success - flag if the action was succesful
        error - error message
    """

    if timestamp_utc is None:
        timestamp_utc = datetime.now(timezone.utc)

    log("Preparing summary email", level=1)

    success, error, html_content = _prep_summary_email(engine, timestamp_utc)

    if success:
        log("Sending summary email", level=1)
        success, error = send_summary_email(html_content, timestamp_utc)

    if success:
        success, error = new_log(engine, timestamp_utc)

    return success, error
Пример #2
0
def _indv_emails(engine,
                 lab_dict,
                 sub_dict,
                 new_sub_list,
                 upd_sub_list,
                 timestamp_utc=None):
    """
    Prepares and sends out individual emails for new and updated subscriptions.

    Arguments:
        engine - an sql engine instance
        lab_dict - lab name /internal id dictionary
        sub_dict - subscription id /internal id dictionary
        new_sub_list - a list of details of new subscriptions
        upd_sub_list - a list of tuple (before, after) of subscription details
        timestamp_utc - timestamp when emails were sent (for testing purposes)
    Returns:
        success - flag if the action was succesful
        error - error message
        new_count - the number of new subscription nutifications sent
        upd_count - the number of subscription update nutifications sent
    """

    new_count = 0
    upd_count = 0

    session = session_open(engine)

    # Notifying about new subscriptions
    for new_sub in new_sub_list:

        # generating html content
        success, _, html_content = indiv_email_new(lab_dict, sub_dict, new_sub)

        if success:
            # sending email
            log(
                "Sending new subscription email to: %s " %
                (new_sub.subscription_users),
                level=1,
            )
            success, _ = send_email(
                new_sub.subscription_users,
                CONST_EMAIL_SUBJECT_NEW,
                html_content,
            )

            # let's note that the email was sent successfully
            if success:

                if timestamp_utc is not None:
                    notice_sent_timestamp = timestamp_utc
                else:
                    notice_sent_timestamp = datetime.now(timezone.utc)

                session.query(DetailsClass).filter(
                    DetailsClass.id == new_sub.id).update(
                        {"new_notice_sent": notice_sent_timestamp})

                session.commit()

                new_count += 1

    # Notifying about updates
    for _, sub_update in enumerate(upd_sub_list):

        prev_details = sub_update[0]
        new_details = sub_update[1]

        send_upd_email = False

        # check which subsciptions have chaged details
        if details_changed(prev_details, new_details):
            send_upd_email = True

        # # checks if the unchanged cancelled subscription's consumption
        # #   has been updated, if so, sends a update notifcation email.
        # switching this functionality off as it takes few days (about 2)
        # for usage date to arrive and the service tends
        # to send too many emails.
        # if (
        #     (
        #         new_details.subscription_status.lower()
        #         == CONST_SUB_CANCELLED.lower()
        #     )
        #     and not details_changed(prev_details, new_details)
        #     and (
        #       prev_details.handout_consumed != new_details.handout_consumed
        #     )
        # ):

        #     send_upd_email = True

        if send_upd_email:

            success, _, html_content = indiv_email_upd(lab_dict, sub_dict,
                                                       sub_update)

            if success:
                log(
                    "Sending subscription update email to: %s " %
                    (new_details.subscription_users),
                    level=1,
                )
                success, _ = send_email(
                    new_details.subscription_users,
                    CONST_EMAIL_SUBJECT_UPD,
                    html_content,
                )

                # let's note that the email was sent successfully
                if success:

                    if timestamp_utc is not None:
                        notice_sent_timestamp = timestamp_utc
                    else:
                        notice_sent_timestamp = datetime.now(timezone.utc)

                    session.query(DetailsClass).filter(
                        DetailsClass.id == new_details.id).update(
                            {"update_notice_sent": notice_sent_timestamp})

                    session_close(session)

                    upd_count += 1

    session_close(session)

    return True, None, new_count, upd_count
Пример #3
0
def update_subscriptions(engine, args, timestamp_utc=None):
    """
    Sends individual notifications

    Arguments:
        engine - an sql engine instance
        args - command line arguments

    Returns:
        success - flag if the action was succesful
        error - error message
        counts - counts of notifications sent
            (new, update, time-based, usage-based)
    """

    success = True
    error = ""

    new_count = -1
    upd_count = -1
    time_count = -1
    usage_count = -1

    counts = (new_count, upd_count, time_count, usage_count)

    log("Notification service started", level=1)

    if hasattr(args, "input_df"):
        crawl_df = args.input_df

    elif hasattr(args, "input_file"):
        # read the crawl data in
        crawl_df = pd.read_csv(args.input_file)
        log("Read %d data entries" % (len(crawl_df)), level=1)
    else:
        success = False
        error = "Input data is not provided"

    if success:
        log("Appending DB with the new crawl data", level=1)
        (
            success,
            error,
            lab_dict,
            sub_dict,
            new_sub_list,
            upd_sub_list,
        ) = update_edu_data(engine, crawl_df)

    if success:
        log("Sending individual notification emails", level=1)
        success, error, counts = _notify_subscriptions(
            engine,
            lab_dict,
            sub_dict,
            new_sub_list,
            upd_sub_list,
            timestamp_utc=timestamp_utc,
        )

    return success, error, counts
Пример #4
0
def _notify_subscriptions(engine,
                          lab_dict,
                          sub_dict,
                          new_sub_list,
                          upd_sub_list,
                          timestamp_utc=None):
    """
    Sends individual notifications

    Arguments:
        engine - an sql engine instance
        lab_dict - lab name /internal id dictionary
        sub_dict - subscription id /internal id dictionary
        new_sub_list - a list of details of new subscriptions
        upd_sub_list - a list of tuple (before, after) of subscription details
        timestamp_utc - timestamp when emails were sent (for testing purposes)
    Returns:
        success - flag if the action was succesful
        error - error message
        counts - counts of notifications sent
            (new, update, time-based, usage-based)
    """

    success = True
    error = ""

    # new and update notifications
    sub_success, sub_error, new_count, upd_count = _indv_emails(
        engine,
        lab_dict,
        sub_dict,
        new_sub_list,
        upd_sub_list,
        timestamp_utc=timestamp_utc,
    )

    if not sub_success:
        success = False
        error += sub_error
        log("Time notification error: %s" % (sub_error), level=0)

    # time-based notifications
    time_success, time_error, time_count = notify_expire(
        engine, lab_dict, sub_dict, upd_sub_list, timestamp_utc=timestamp_utc)

    if not time_success:
        success = False
        error += time_error
        log("Time notification error: %s" % (time_error), level=0)

    # usage-based notifications
    usage_success, usage_error, usage_count = notify_usage(
        engine, lab_dict, sub_dict, upd_sub_list, timestamp_utc=timestamp_utc)

    if not usage_success:
        success = False
        error += usage_error
        log("Usage notification error: %s" % (usage_error), level=0)

    counts = (new_count, upd_count, time_count, usage_count)

    return success, error, counts
Пример #5
0
def _notify_expiring_sub(
    session,
    lab_dict,
    sub_dict,
    details,
    expiry_code,
    remain_days,
    timestamp_utc=None,
):
    """
    Sends a time-based notification for an expiring subscription.

    Arguments:
        session - an active sql session
        lab_dict - lab name /internal id dictionary
        sub_dict - subscription id /internal id dictionary
        details - subscription details
        expiry_code - expiration code
        remain_days - remaining number of days
        timestamp_utc - timestamp when emails were sent (for testing purposes)
    Returns:
        success - flag if the action was succesful
        error - error message
    """

    success, error, html_content = indiv_email_expiry_notification(
        lab_dict, sub_dict, details, remain_days
    )

    if success:
        log(
            "Sending subscription expiry notification email to: %s "
            % (details.subscription_users),
            level=1,
        )

        subject = "%s %d day(s)" % (CONST_EMAIL_SUBJECT_EXPIRE, remain_days)
        success, error = send_email(
            details.subscription_users, subject, html_content
        )

        if success:

            if timestamp_utc is not None:
                notice_sent_timestamp = timestamp_utc
            else:
                notice_sent_timestamp = datetime.now(timezone.utc)

            session.query(DetailsClass).filter(
                DetailsClass.id == details.id
            ).update(
                {
                    "expiry_code": expiry_code,
                    "expiry_notice_sent": notice_sent_timestamp,
                }
            )

            session.query(SubscriptionClass).filter(
                SubscriptionClass.id == details.sub_id
            ).update(
                {
                    "expiry_code": expiry_code,
                    "expiry_notice_sent": notice_sent_timestamp,
                }
            )

            session.commit()

    return success, error
Пример #6
0
def _notify_usage_sub(session,
                      lab_dict,
                      sub_dict,
                      details,
                      usage_code,
                      timestamp_utc=None):
    """
    Sends a usage-based notification.

    Arguments:
        session - an active sql session
        lab_dict - lab name /internal id dictionary
        sub_dict - subscription id /internal id dictionary
        details - subscription details
        usage_code - usage code
        timestamp_utc - timestamp when emails were sent (for testing purposes)
    Returns:
        success - flag if the action was succesful
        error - error message
    """

    success, error, html_content = indiv_email_usage_notification(
        lab_dict, sub_dict, details, usage_code)

    if success:
        log(
            "Sending subscription utilisation email (%d) to: %s -> %s " % (
                usage_code,
                details.subscription_name,
                details.subscription_users,
            ),
            level=1,
        )

        subject = "%s %d%%" % (CONST_EMAIL_SUBJECT_USAGE_2, usage_code)

        success, error = send_email(details.subscription_users, subject,
                                    html_content)

        if success:

            if timestamp_utc is not None:
                notice_sent_timestamp = timestamp_utc
            else:
                notice_sent_timestamp = datetime.now(timezone.utc)

            session.query(DetailsClass).filter(
                DetailsClass.id == details.id).update({
                    "usage_code":
                    usage_code,
                    "usage_notice_sent":
                    notice_sent_timestamp,
                })

            session.query(SubscriptionClass).filter(
                SubscriptionClass.id == details.sub_id).update({
                    "usage_code":
                    usage_code,
                    "usage_notice_sent":
                    notice_sent_timestamp,
                })

            session.commit()

    return success, error
Пример #7
0
def _prep_summary_email(engine, timestamp_utc=None):
    """
    Prepares and sends out a summary email of new and updated
        subscriptions and notifications sent.

    Arguments:
        engine - an sql engine instance
        timestamp_utc - summary timestamp
    Returns:
        success - flag if the action was succesful
        error - error message
        html_content - html content of the summary email
    """

    if timestamp_utc is None:
        timestamp_utc = datetime.now(timezone.utc)

    html_content = None

    log("Looking for the latest log timestamp value", level=1)
    success, error, prev_timestamp_utc = get_latest_log_timestamp(engine)

    if success:
        if prev_timestamp_utc is None:
            log("No previous logs were found", level=1, indent=2)
        else:
            log(
                "Previous update was made on %s UTC" %
                (prev_timestamp_utc.strftime("%Y-%m-%d %H:%M")),
                level=1,
                indent=2,
            )

    if success:
        log("Looking for new subscriptions", level=1)
        success, error, new_sub_list = _find_new_subs(engine,
                                                      prev_timestamp_utc)

    if success:
        log("Looking for updated subscriptions", level=1)
        success, error, upd_sub_list = _find_upd_subs(engine,
                                                      prev_timestamp_utc)

    if success:
        log("Looking for sent notifications", level=1)
        success, error, sent_noti_list = _find_sent_notifications(
            engine, prev_timestamp_utc)

    if success:
        # find all labs
        success, error, lab_dict = get_labs_dict(engine)

    if success:
        # find all subs
        success, error, sub_dict = get_subs_dict(engine)

    if success:
        # prepare html
        log("Making a summary / html of the registered changes", level=1)

        success, error, html_content = summary(
            lab_dict,
            sub_dict,
            new_sub_list,
            upd_sub_list,
            sent_noti_list,
            prev_timestamp_utc,
            timestamp_utc,
        )

    return success, error, html_content