コード例 #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)
コード例 #6
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)
コード例 #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)
コード例 #14
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
コード例 #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)
コード例 #21
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"]
コード例 #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
ファイル: __init__.py プロジェクト: dimagi/WBNigeria
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"]