Example #1
0
 def test_testability(self):  # TODO: This should be in members.tests
     title = "TITLE"
     message = "MESSAGE"
     notify(self.manager_member, title, message)
     self.assertEqual(notify.MOST_RECENT_MEMBER, self.manager_member)
     self.assertEqual(notify.MOST_RECENT_TITLE, title)
     self.assertEqual(notify.MOST_RECENT_MESSSAGE, message)
Example #2
0
def staffing_update_notification(sender, **kwargs):
    unused(sender)
    try:
        if kwargs.get('created', True):
            claim = kwargs.get('instance')  # type: Claim
            message = None
            if claim.status in [
                    Claim.STAT_UNINTERESTED, Claim.STAT_ABANDONED,
                    Claim.STAT_EXPIRED
            ]:
                message = "{0} will NOT work '{1}' on {2:%a %m/%d}".format(
                    claim.claiming_member.friendly_name,
                    claim.claimed_task.short_desc,
                    claim.claimed_task.scheduled_date)
            if claim.status == Claim.STAT_CURRENT and claim.date_verified is not None:
                message = "{0} WILL work '{1}' on {2:%a %m/%d}".format(
                    claim.claiming_member.friendly_name,
                    claim.claimed_task.short_desc,
                    claim.claimed_task.scheduled_date)
            if message is not None:
                try:
                    recipient = Member.objects.get(
                        auth_user__username=USER_VOLUNTEER)
                    notifications.notify(recipient, "Staffing Update", message)
                except Member.DoesNotExist:
                    return

    except Exception as e:
        logger.error("Problem sending staffing update.")
Example #3
0
def squareup_webhook(request):

    _logger.info(request.body)

    # For sending notice via Pushover:
    recipient = Member.objects.get(auth_user__username='******')

    json_body = json.loads(request.body.decode())
    location_id = json_body['location_id']
    payment_id = json_body['entity_id']
    event_type = json_body['event_type']

    get_headers = {
        'Authorization': "Bearer " + SQUAREUP_APIV1_TOKEN,
        'Accept': "application/json",
    }

    try:
        payment_url = "https://connect.squareup.com/v1/{}/payments/{}".format(
            location_id, payment_id)
        response = requests.get(payment_url, headers=get_headers)
        response.raise_for_status()
        itemizations = json.loads(response.text)['itemizations']
        for item in itemizations:
            sku = item['item_detail']['sku']
            qty = int(float(item['quantity']))
            msg = "{}, qty {}".format(sku, qty)
            notifications.notify(recipient, "SquareUp Purchase", msg)
        return HttpResponse("Ok")
    except requests.exceptions.ConnectionError:
        _logger.error("Couldn't get purchase info from SquareUp.")
        return HttpResponse("Error")
Example #4
0
def notify_staff_of_checkin(sender, **kwargs):
    """Notify a staffer of a visitor's paid status when that visitor checks in."""
    # TODO: Per feedback from Annette, don't send notices if it's currently "open house".
    unused(sender)
    try:
        if kwargs.get('created', True):
            visit = kwargs.get('instance')

            # We're only interested in arrivals
            if visit.event_type != VisitEvent.EVT_ARRIVAL:
                return

            if visit.who.is_currently_paid():
                # Let's not overwhelm the staffer with info that doesn't require action.
                # A paid visitor is welcome anytime, so don't notify the staffer.
                return

            recipient = Worker.scheduled_receptionist()
            if recipient is None:
                return

            if visit.debounced():
                vname = "{} {}".format(visit.who.first_name,
                                       visit.who.last_name).strip()
                vname = "Anonymous" if len(vname) == 0 else vname
                vstat = "Paid" if visit.who.is_currently_paid() else "Unpaid"
                message = "{}\n{}\n{}".format(visit.who.username, vname, vstat)
                notifications.notify(recipient, "Check-In", message)

    except Exception as e:
        # Makes sure that problems here do not prevent the visit event from being saved!
        logger.error("Problem in note_checkin: %s", str(e))
def note_checkin(sender, **kwargs):
    try:
        if kwargs.get('created', True):
            visit = kwargs.get('instance')

            # We're only interested in arrivals
            if visit.event_type != VisitEvent.EVT_ARRIVAL:
                return

            # TODO: Shouldn't have a hard-coded userid here. Make configurable, perhaps with tags.
            recipient = Member.objects.get(auth_user__username='******')
            if visit.who == recipient:
                # No need to inform the recipient that they're visiting
                return

            # RFID checkin systems may fire multiple times. Skip checkin if "too close" to the prev checkin time.
            try:
                recent_visit = VisitEvent.objects.filter(who=visit.who, event_type=VisitEvent.EVT_ARRIVAL).latest('when')
                delta = visit.when - recent_visit.when
            except VisitEvent.DoesNotExist:
                delta = timedelta.max
            if delta < timedelta(hours=1):
                return

            vname = "{} {}".format(visit.who.first_name, visit.who.last_name).strip()
            vname = "Anonymous" if len(vname) == "" else vname
            vstat = "Paid" if visit.who.is_currently_paid() else "Unpaid"

            message = "{}\n{}\n{}".format(visit.who.username, vname, vstat)
            notifications.notify(recipient, "Check-In", message)

    except Exception as e:
        # Makes sure that problems here do not prevent the visit event from being saved!
        logger.error("Problem in note_checkin: %s", str(e))
def note_login(sender, user, request, **kwargs):  # https://code.djangoproject.com/ticket/22111
    try:
        ip = get_ip_address(request)
        if ip is None:
            # IP is none when connecting from Client in tests.
            # TODO: Assert that this is a dev machine?
            return
        logger.info("Login: %s at %s" % (user, ip))
        MemberLogin.objects.create(member=user.member, ip=ip)

        # TODO: Shouldn't have a hard-coded userid here. Make configurable, perhaps with tags.
        recipient = Member.objects.get(auth_user__username='******')
        if recipient.auth_user != user:
            message = "{}\n{}".format(user.username, ip)
            notifications.notify(recipient, "Log-In", message)

    except Exception as e:
        # Failures here should not prevent the login from completing normally.
        try:
            logger.error("Problem noting login of %s from %s: %s", str(user), str(ip), str(e))
        except Exception as e2:
            logger.error("Problem noting login exception: %s", str(e2))
Example #7
0
def notify_manager_re_staff_arrival(sender, **kwargs):
    """Notify the Volunteer Coordinator when a staffer checks in around the time they're scheduled to work a task."""
    unused(sender)
    try:
        if kwargs.get('created', True):
            visit = kwargs.get('instance')  # type: VisitEvent

            # We're only interested in arrivals
            if visit.event_type != VisitEvent.EVT_ARRIVAL:
                return

            try:
                recipient = Member.objects.get(
                    auth_user__username=USER_VOLUNTEER)
            except Member.DoesNotExist:
                return

            if visit.debounced():
                claims = Claim.objects.filter(
                    claiming_member=visit.who,
                    claimed_task__priority=Task.PRIO_HIGH,
                    claimed_task__scheduled_date=datetime.now().date(),
                    status=Claim.STAT_CURRENT,
                    # TODO: Is a window around the claimed start time necessary?
                )

                if len(claims) == 0:
                    return

                task = claims[0].claimed_task  # type: Task
                title = "{} Arrived".format(visit.who.friendly_name)
                message = "Scheduled to work {} at {}".format(
                    task.short_desc, task.window_start_time())
                notifications.notify(recipient, title, message)

    except Exception as e:
        # Makes sure that problems here do not prevent the visit event from being saved!
        logger.error("Problem in notify_manager_re_staff_arrival: %s", str(e))
Example #8
0
 def test(self):
     if pushover_available:
         notifications.notify(self.user.member, "Testing Pushover", "This is a test.")
Example #9
0
 def test(self):
     if pushover_available:
         notifications.notify(self.user.member, "Testing Pushover",
                              "This is a test.")
Example #10
0
def maintenance_nag(sender, **kwargs):
    unused(sender)
    try:
        visit = kwargs.get('instance')  # type: VisitEvent

        # We're only interested in arrivals
        if visit.event_type != VisitEvent.EVT_ARRIVAL:
            return

        # Only act on a member's first visit of the day.
        start_of_today = localtime(timezone.now()).replace(
            hour=
            4,  # For the purpose of this nag, I'm going to say that day begins at 4am.
            minute=0,
            second=0,
            microsecond=0,
        )
        num_visits_today = VisitEvent.objects.filter(
            who=visit.who,
            event_type=VisitEvent.EVT_ARRIVAL,
            when__gte=start_of_today,
        ).count()
        if num_visits_today > 1:
            return

        # This gets tasks that are scheduled like maintenance tasks.
        # I.e. those that need to be done every X days, but can slide.
        tasks = Task.objects.filter(
            eligibleclaimant2__member=visit.who,
            eligibleclaimant2__should_nag=True,
            scheduled_date=date.today(),
            status=Task.STAT_ACTIVE,
            should_nag=True,
            recurring_task_template__repeat_interval__isnull=False,
            recurring_task_template__missed_date_action=RecurringTaskTemplate.
            MDA_SLIDE_SELF_AND_LATER,
        )

        # We're going to want to send msgs to a manager to let them know that people were asked to do the work.
        # TODO: Shouldn't have a hard-coded userid here. Make configurable, perhaps with tags.
        try:
            mgr = Member.objects.get(auth_user__username=USER_VOLUNTEER)
        except Member.DoesNotExist:
            mgr = None

        # Nag the visitor by sending a notification for each task they could work.
        for task in tasks:  # type: Task

            # Create the nag
            b64, md5 = Member.generate_auth_token_str(
                lambda token: Nag.objects.filter(auth_token_md5=token).count(
                ) == 0  # uniqueness test
            )
            nag = Nag.objects.create(who=visit.who, auth_token_md5=md5)
            nag.tasks.add(task)

            # Generate an informative message
            try:
                last_done = Task.objects.filter(
                    scheduled_date__lt=date.today(),
                    status=Task.STAT_DONE,
                    recurring_task_template=task.recurring_task_template,
                ).latest('scheduled_date')
                delta = date.today(
                ) - last_done.scheduled_date  # type: timedelta
                message = "This task was last completed {} days ago!".format(
                    delta.days)
            except Task.DoesNotExist:
                message = ""
            message += " If you can complete this task today, please click the link AFTER the work is done."

            relative = reverse('task:note-task-done',
                               kwargs={
                                   'task_pk': task.id,
                                   'auth_token': b64
                               })
            # Send the notification
            was_sent = notifications.notify(
                visit.who,
                task.short_desc,
                message,
                url=HOST + relative,
                url_title="I Did It!",
            )

            if was_sent:
                # Let manager know:
                if visit.who != mgr:
                    notifications.notify(
                        mgr,
                        task.short_desc,
                        visit.who.friendly_name +
                        " was asked to work this task.",
                    )
            else:
                # If the notification wasn't sent, then the user wasn't actually nagged.
                nag.delete()

    except Exception as e:
        # Makes sure that problems here do not prevent subsequent processing.
        logger.error("Problem in maintenance_nag: %s", str(e))
Example #11
0
def rfid_entry_denied(request, rfid_cardnum):
    # TODO: Shouldn't have a hard-coded userid here. Make configurable, perhaps with tags.
    recipient = Member.objects.get(auth_user__username='******')
    notify(recipient, "Entry Denied", rfid_cardnum)
    return JsonResponse({'success': "Information noted."})