예제 #1
0
파일: digests.py 프로젝트: dimagi/WBNigeria
def send_activity_digest_sms(sender, instance, created, **kwargs):
    """
    Uses threadless_router to send the activity digest via SMS to
    all available contacts associated with the user. This will happen only
    once when the NotificationVisibility object is created.

    The default SMS handling provided by rapidsms-alerts is not compatible
    with threadless router.
    """
    alert_types = [PBFDigestNotification.alert_type, FadamaDigestNotification.alert_type]
    sent = False
    if created and instance.notif.alert_type in alert_types:
        notification = instance.notif
        contacts = instance.user.contact_set.all()
        for contact in contacts:
            connection = contact.default_connection
            if connection:
                backend = connection.backend
                message = OutgoingMessage(connection, notification.text)
                router = ThreadlessRouter()
                response = router.outgoing(message)
                sent = True
    if sent:
        # Don't show this notification on the dashboard as we've already sent
        # it as a text message.
        instance.delete()
예제 #2
0
def patient_onetime_message(request, patient_id):
    """Send a onetime message to a patient.
    Default to getting it from their feeds but allow editing that."""

    patient = get_object_or_404(patients.Patient, pk=patient_id)
    if request.method == 'POST':
        form = PatientOnetimeMessageForm(request.POST)
        if form.is_valid():
            message = form.cleaned_data['message']
            connection = patient.contact.default_connection
            msg = OutgoingMessage(connection, message)
            router = Router()
            success = True
            try:
                router.outgoing(msg)
            except Exception, e:
                logger.exception(e)
                success = False
            if success:
                messages.success(
                    request,
                    "Message sent to patient %s" % patient.subject_number)
            else:
                messages.error(
                    request,
                    "An error occurred while trying to send the message to patient %s"
                    % patient.subject_number)

            return redirect('patient-list')
예제 #3
0
파일: views.py 프로젝트: dimagi/WBNigeria
def reimburse():
    '''
    Start reimbursement process, entailing interaction with special numbers
    '''
    counter = 0
    network_name_map = dict([(v, k) for k, v in NAME_NETWORK_MAP.items()])
    reimbursements = ReimbursementRecord.objects.exclude(
            status__in=(ReimbursementRecord.COMPLETED, ReimbursementRecord.ERROR)
            )

    #import pdb;pdb.set_trace()
    for network, _ in Subscriber.NETWORKS:
        print 'network: %s'%network
        if reimbursements.filter(
                status__in=(
                    ReimbursementRecord.IN_PROGRESS, ReimbursementRecord.QUEUED),
                subscriber__network=network):
            continue
        else:
            #there is no reimbursement in progress for "network"
            subscribers = Subscriber.objects.filter(balance__gt=0, network=network)
            min_time = settings.REIMBURSEMENT_MIN_TIME
            qualified = qualify(subscribers, min_time)
            if qualified:
                subscriber = qualified[0]
            else:
                continue

            network_name = network_name_map.get(network)
            _amount = max(subscriber.balance, settings.MINIMUM_TRANSFERS.get(network_name))
            backend_name = subscriber.get_backend()
            backend, _ = Backend.objects.get_or_create(name=backend_name)
            text = subscriber.first_message % {
                    'number': '0%s'%subscriber.number[-10:],
                    'amount': _amount,
                    'pin': settings.NETWORK_PINS.get(network_name)
                    }
            logging.info('message to send is %s'%text)
            to_number = REIMBURSEMENT_NUMBERS.get(network_name)
            if len(to_number) < 11:#If it is a short-code, prefix with 's'
                to_number = 's%s'%to_number
            connection, _ = Connection.objects.get_or_create(
                    backend=backend, identity=to_number)
            msg = OutgoingMessage(connection=connection, template=text)
            try:
                msg.send()
            except:
                router = Router()
                #router.start()
                router.outgoing(msg)
            ReimbursementRecord.objects.create(
                subscriber=subscriber,
                amount=_amount,
                status=ReimbursementRecord.IN_PROGRESS)
            counter += 1
    return counter
예제 #4
0
def session_end(sender, **kwargs):
    session = kwargs['session']
    canceled = kwargs['canceled']
    message = kwargs['message']

    # for convenience
    PatientSurvey = aremind.apps.adherence.models.PatientSurvey

    # find the patient
    connection = session.connection
    try:
        patient = Patient.objects.get(contact=connection.contact)
    except Patient.DoesNotExist:
        # No patient, this session might not be relevant to this app
        return

    survey = PatientSurvey.find_active(patient, QUERY_TYPE_SMS)

    if not survey:
        return

    if canceled:
        survey.completed(PatientSurvey.STATUS_NOT_COMPLETED)
        return

    tree = session.tree
    entries = session.entries

    if entries.count() < 1:
        survey.completed(PatientSurvey.STATUS_NOT_COMPLETED)
        return

    entry = entries.all()[0]
    # Pick the relevant part of the answer
    text = re.match(ANSWER_RE, entry.text).group(1)
    num_pills = int(text)
    if not survey.is_test:
        aremind.apps.adherence.models.PillsMissed(
            patient=patient, num_missed=num_pills,
            source=QUERY_TYPE_SMS).save()
    survey.completed(PatientSurvey.STATUS_COMPLETE)

    # After completing survey, tell patient what their current adherence is
    connection = patient.contact.default_connection
    adherence = patient.adherence()  # integer percentage
    response_text = _(
        "Thank you. Your adherence is %(adherence)s%%, as measured by the black study pillbox."
    )
    kwargs = dict(adherence=adherence)
    if message:
        message.respond(response_text, **kwargs)
    else:
        msg = OutgoingMessage(connection, response_text, **kwargs)
        router = Router()
        router.outgoing(msg)
예제 #5
0
def incoming(backend_name, identity, text):
    backend = settings.INSTALLED_BACKENDS.get(backend_name, {})
    if "HANDLER" in backend:
        module = try_import(backend['HANDLER'])
        if module:
            module.incoming(backend_name, identity, text)
    else:
        backend, _ = Backend.objects.get_or_create(name=backend_name)
        connection, _ = backend.connection_set.get_or_create(identity=identity)
        message = IncomingMessage(connection, text, datetime.datetime.now())
        router = Router()
        response = router.incoming(message)
def incoming(backend_name, identity, text):
    backend = settings.INSTALLED_BACKENDS.get(backend_name, {})
    if "HANDLER" in backend:
        module = try_import(backend["HANDLER"])
        if module:
            module.incoming(backend_name, identity, text)
    else:
        backend, _ = Backend.objects.get_or_create(name=backend_name)
        connection, _ = backend.connection_set.get_or_create(identity=identity)
        message = IncomingMessage(connection, text, datetime.datetime.now())
        router = Router()
        response = router.incoming(message)
예제 #7
0
파일: sms.py 프로젝트: boyombo/WBNigeria
def session_end(sender, **kwargs):
    session = kwargs["session"]
    canceled = kwargs["canceled"]
    message = kwargs["message"]

    # for convenience
    PatientSurvey = aremind.apps.adherence.models.PatientSurvey

    # find the patient
    connection = session.connection
    try:
        patient = Patient.objects.get(contact=connection.contact)
    except Patient.DoesNotExist:
        # No patient, this session might not be relevant to this app
        return

    survey = PatientSurvey.find_active(patient, QUERY_TYPE_SMS)

    if not survey:
        return

    if canceled:
        survey.completed(PatientSurvey.STATUS_NOT_COMPLETED)
        return

    tree = session.tree
    entries = session.entries

    if entries.count() < 1:
        survey.completed(PatientSurvey.STATUS_NOT_COMPLETED)
        return

    entry = entries.all()[0]
    # Pick the relevant part of the answer
    text = re.match(ANSWER_RE, entry.text).group(1)
    num_pills = int(text)
    if not survey.is_test:
        aremind.apps.adherence.models.PillsMissed(patient=patient, num_missed=num_pills, source=QUERY_TYPE_SMS).save()
    survey.completed(PatientSurvey.STATUS_COMPLETE)

    # After completing survey, tell patient what their current adherence is
    connection = patient.contact.default_connection
    adherence = patient.adherence()  # integer percentage
    response_text = _("Thank you. Your adherence is %(adherence)s%%, as measured by the black study pillbox.")
    kwargs = dict(adherence=adherence)
    if message:
        message.respond(response_text, **kwargs)
    else:
        msg = OutgoingMessage(connection, response_text, **kwargs)
        router = Router()
        router.outgoing(msg)
예제 #8
0
    def handle(self, *args, **options):
        if len(args) != 1: raise CommandError('Please specify %s.' % self.label)

        message = args[0]
        all_connections = Connection.objects.all()
        success = []
        failed = []
        router = Router()
        for conn in all_connections:
            try:
                router.outgoing(OutgoingMessage(conn, message))
                success.append(conn)
            except Exception, e:
                print "failed to send to %s because %s" % (conn, e)
                failed.append(conn)
예제 #9
0
파일: forms.py 프로젝트: dimagi/aremind
 def save(self):
     number = self.cleaned_data['number']
     backend = self.cleaned_data['backend']
     connection, _ = Connection.objects.get_or_create(backend=backend,
                                                      identity=number)
     msg = OutgoingMessage(connection, self.cleaned_data['message'])
     router = Router()
     return router.backends[backend.name].send(msg)
예제 #10
0
파일: models.py 프로젝트: dimagi/aremind
    def start(self):
        logger.debug("PatientSurvey.start")
        if self.status != self.STATUS_CREATED:
            raise SurveyAlreadyStartedException()

        if self.query_type == QUERY_TYPE_SMS:
            tree = aremind.apps.adherence.sms.get_tree()
            aremind.apps.adherence.sms.start_tree_for_patient(tree, self.patient)
        elif self.query_type == QUERY_TYPE_IVR:
            url = reverse('patient-ivr-callback',
                          kwargs={'patient_id': self.patient.pk})
            backend = Router().backends['tropo']
            backend.call_tropo(url, message_type='voice')
            # tropo will POST to our callback which will continue things
        else:
            raise SurveyUnknownQueryTypeException()

        self.status = self.STATUS_STARTED
        self.save()
예제 #11
0
파일: tests.py 프로젝트: dimagi/aremind
 def setUp(self):
     super(DailyReportTest, self).setUp()
     group_name = settings.DEFAULT_DAILY_REPORT_GROUP_NAME
     self.group = self.create_group(data={'name': group_name})
     self.test_contact = self.create_contact(
         data={'email': '*****@*****.**'})
     self.group.contacts.add(self.test_contact)
     self.test_patient = self.create_patient()
     self.other_patient = self.create_patient()
     self.unrelated_patient = self.create_patient()
     self.router = Router()
예제 #12
0
class TestScript(LegacyTestScript):
    def setUp(self):
        backends = {'mockbackend': {"ENGINE": MockBackend}}
        self.router = Router(apps=self.apps, backends=backends)
        self.router.join = lambda: None
        self._init_log(logging.DEBUG)
        self.backend = self.router.backends["mockbackend"]

    def sendMessage(self, num, txt, date=None):
        self.router.debug('sending {0} to {1}'.format(txt, num))
        return super(TestScript, self).sendMessage(num, txt, date)

    def receiveMessage(self):
        msg = super(TestScript, self).receiveMessage()
        self.router.debug(msg)
        return msg

    def startRouter(self):
        pass

    def stopRouter(self):
        pass
예제 #13
0
def start_tree_for_patient(tree, patient):
    """Trigger tree for a given patient.
    Will result in our sending them the first question in the tree."""

    connection = patient.contact.default_connection

    # if one is in progress, end it
    Router().get_app('decisiontree').end_sessions(connection)

    # fake an incoming message from our patient that triggers the tree

    backend_name = connection.backend.name
    address = connection.identity
    incoming(backend_name, address, tree.trigger)
class TestScript(LegacyTestScript):

    def setUp (self):
        backends = {'mockbackend': {"ENGINE": MockBackend}}
        self.router = Router(apps=self.apps, backends=backends)
        self.router.join = lambda: None
        self._init_log(logging.DEBUG)
        self.backend = self.router.backends["mockbackend"]

    def sendMessage(self, num, txt, date=None):
        self.router.debug('sending {0} to {1}'.format(txt, num))
        return super(TestScript, self).sendMessage(num, txt, date)

    def receiveMessage(self):
        msg = super(TestScript, self).receiveMessage()
        self.router.debug(msg)
        return msg

    def startRouter(self):
        pass

    def stopRouter(self):
        pass
예제 #15
0
def make_fake_message(request, patient_id):
    """Make up a message for the patient's wisepill device
    and fake it coming in"""
    logger.debug('make_fake_message')
    patient = get_object_or_404(Patient, pk=patient_id)
    msisdn = patient.wisepill_msisdn
    if not msisdn:
        messages.error(request, "Must set patient's MSISDN before we can fake a wisepill message from them")
        return redirect('patient-list')

    timestamp = datetime.datetime.now()
    # 50-50 whether to make a delayed message
    is_delayed = random.randint(0,99) > 50
    if is_delayed:
        timestamp -= datetime.timedelta(minutes=10)
    
    delay_value = "03" if is_delayed else "02"
    # DDMMYYHHMMSS
    time_value = timestamp.strftime("%d%m%y%H%M%S")

    # 50-50 old format or new format
    new_format = random.randint(0,99) > 50
    if new_format:
        start = "AT={delay_value},".format(**locals())
    else:
        start = "@={delay_value},".format(**locals())

    text = start + "CN={msisdn},SN=fake,T={time_value},S=20,B=3800,PC=1,U=fake,M=1,CE=0".format(**locals())

    connection = patient.contact.default_connection

    msg = IncomingMessage(connection=connection,
                          text=text)
    router = Router()
    router.incoming(msg)
    messages.info(request, "Sent fake wisepill message from %s" % patient)
    return redirect('patient-list')
예제 #16
0
파일: views.py 프로젝트: boyombo/WBNigeria
def make_fake_message(request, patient_id):
    """Make up a message for the patient's wisepill device
    and fake it coming in"""
    logger.debug("make_fake_message")
    patient = get_object_or_404(Patient, pk=patient_id)
    msisdn = patient.wisepill_msisdn
    if not msisdn:
        messages.error(request, "Must set patient's MSISDN before we can fake a wisepill message from them")
        return redirect("patient-list")

    timestamp = datetime.datetime.now()
    # 50-50 whether to make a delayed message
    is_delayed = random.randint(0, 99) > 50
    if is_delayed:
        timestamp -= datetime.timedelta(minutes=10)

    delay_value = "03" if is_delayed else "02"
    # DDMMYYHHMMSS
    time_value = timestamp.strftime("%d%m%y%H%M%S")

    # 50-50 old format or new format
    new_format = random.randint(0, 99) > 50
    if new_format:
        start = "AT={delay_value},".format(**locals())
    else:
        start = "@={delay_value},".format(**locals())

    text = start + "CN={msisdn},SN=fake,T={time_value},S=20,B=3800,PC=1,U=fake,M=1,CE=0".format(**locals())

    connection = patient.contact.default_connection

    msg = IncomingMessage(connection=connection, text=text)
    router = Router()
    router.incoming(msg)
    messages.info(request, "Sent fake wisepill message from %s" % patient)
    return redirect("patient-list")
예제 #17
0
파일: views.py 프로젝트: dimagi/aremind
def patient_onetime_message(request, patient_id):
    """Send a onetime message to a patient.
    Default to getting it from their feeds but allow editing that."""

    patient = get_object_or_404(patients.Patient, pk=patient_id)
    if request.method == 'POST':
        form = PatientOnetimeMessageForm(request.POST)
        if form.is_valid():
            message = form.cleaned_data['message']
            connection = patient.contact.default_connection
            msg = OutgoingMessage(connection, message)
            router = Router()
            success = True
            try:
                router.outgoing(msg)
            except Exception, e:
                logger.exception(e)
                success = False
            if success:
                messages.success(request, "Message sent to patient %s" % patient.subject_number)
            else:
                messages.error(request, "An error occurred while trying to send the message to patient %s" % patient.subject_number)

            return redirect('patient-list')
예제 #18
0
파일: tasks.py 프로젝트: dimagi/aremind
 def run(self):
     router = Router()
     app = router.get_app("aremind.apps.adherence")
     app.cronjob()
예제 #19
0
파일: tasks.py 프로젝트: boyombo/WBNigeria
 def run(self):
     router = Router()
     app = router.get_app("aremind.apps.adherence")
     app.cronjob()
예제 #20
0
 def setUp(self):
     super(SimpleRouterMixin, self).setUp()
     backends = {'mockbackend': {"ENGINE": MockBackend}}
     self.router = Router(backends=backends)
 def setUp (self):
     backends = {'mockbackend': {"ENGINE": MockBackend}}
     self.router = Router(apps=self.apps, backends=backends)
     self.router.join = lambda: None
     self._init_log(logging.DEBUG)
     self.backend = self.router.backends["mockbackend"]
예제 #22
0
 def run(self, backend_name, identity, text):
     backend, _ = Backend.objects.get_or_create(name=backend_name)
     connection, _ = backend.connection_set.get_or_create(identity=identity)
     message = IncomingMessage(connection, text, datetime.datetime.now())
     router = Router()
     response = router.incoming(message)
예제 #23
0
파일: fadama.py 프로젝트: boyombo/WBNigeria
def message_report_beneficiary(report, message_text):
    "Send a message to a user based on a report."
    template = u'{0} {1}'.format(communicator_prefix(), message_text)
    message = OutgoingMessage(connection=report.reporter, template=template)
    router = Router()
    router.outgoing(message)
예제 #24
0
 def run(self):
     router = Router()
     scheduler_callback(router)
예제 #25
0
def reimbursement_detail(request, number):
    reimbursements = ReimbursementLog.objects.filter(phone=number).order_by('-reimbursed_on')
    num_messages = Message.objects.filter(connection__identity=number, direction='I').count()
    owed = settings.REIMBURSEMENT_RATES[network_for_number(number)] * num_messages - sum([r.amount for r in reimbursements])

    from django import forms
    from django.contrib.admin.widgets import AdminDateWidget
    class ReimbursementForm(forms.Form):
        amount = forms.IntegerField()
        when = forms.DateField(widget=AdminDateWidget, required=False)

        def clean_amount(self):
            data = self.cleaned_data['amount']
            if data <= 0:
                raise forms.ValidationError('can\'t be 0 or negative')
            return data

    if request.method == 'POST':
        form = ReimbursementForm(request.POST)
        if form.is_valid():
            entry_date = form.cleaned_data['when']
            entry = ReimbursementLog(
                phone=number,
                amount=form.cleaned_data['amount'],
                reimbursed_on=datetime.now() if (not entry_date or entry_date == date.today()) else entry_date,
            )
            entry.save()

            network_name = network_for_number(number)
            network = NAME_NETWORK_MAP.get(network_name)
            try:
                subscriber = Subscriber.objects.get(
                        number=number[-13:], network=network)
            except Subscriber.DoesNotExist:
                pass
            else:
                balance = subscriber.balance - form.cleaned_data['amount']
                subscriber.balance = max(balance, 0)
                subscriber.save()

            #import pdb;pdb.set_trace()
            backend_name = get_backend_name(network_name)
            backend, _ = Backend.objects.get_or_create(name=backend_name)
            try:
                conn = Connection.objects.get(identity=number, backend=backend)
            except Exception:
                #log somewhere?
                pass
            else:
                notice = OutgoingMessage(connection=conn, template=settings.REIMBURSEMENT_NOTICE)
                router = Router()
                router.outgoing(notice)

            return HttpResponseRedirect('/dashboard/reimbursement/')
    else:
        form = ReimbursementForm()

    return render(request, 'dashboard/reimbursement_detail.html', {
            'number': disp_number(number),
            'network': network_for_number(number),
            'owed': owed,
            'over': owed < 0,
            'over_amt': -owed,
            'history': reimbursements,
            'form': form,
        })
예제 #26
0
 def run(self):
     router = Router()
     daily_email_callback(router)
예제 #27
0
 def setUp(self):
     backends = {'mockbackend': {"ENGINE": MockBackend}}
     self.router = Router(apps=self.apps, backends=backends)
     self.router.join = lambda: None
     self._init_log(logging.DEBUG)
     self.backend = self.router.backends["mockbackend"]