Ejemplo n.º 1
0
def purge_entry(pk):
    """
        Once a subscriber's promo subscription expires, this task will remove
        the entry from pcari_promo_subscriptions table
        Also, it sends an SMS to inform the subscriber that the
        promo has expired
    Args:
        pk: primary key of PromoSubscriptions entry

    Returns: None
    """

    subscription = PromoSubscription.objects.get(pk=pk)
    promoname = subscription.promo.keyword
    callerid = subscription.contact.callerid

    # we should also create an event
    balance = endaga_sub.get_account_balance(subscription.contact.imsi)
    reason = "Promo Expiration: %s" % subscription.promo.keyword
    events.create_sms_event(subscription.contact.imsi, balance, 0, reason,
                            '555')

    subscription.delete()

    # inform user that promo has expired
    msg = "Your %s promo subscription has already expired." % promoname
    send_sms(callerid, '0000', msg)
Ejemplo n.º 2
0
    def post(self, request, format=None):
        needed_fields = ["imsi", "keyword"]
        if not all(i in request.POST for i in needed_fields):
            return Response("Missing Args", status=status.HTTP_400_BAD_REQUEST)

        imsi = request.data['imsi']
        keyword = request.data['keyword']
        callerid = endaga_sub.get_numbers_from_imsi(imsi)[0]
        subscriptions = PromoSubscription.objects.filter(
            contact__imsi__exact=imsi, promo__keyword=keyword)
        if not subscriptions:
            send_sms.delay(callerid, '0000',
                           _("You have no %s subscriptions.") % keyword)
            ret = 'FAIL UNSUBSCRIBE'
        else:
            for item in subscriptions:
                app.control.revoke(str(item.id), terminate=True)
            subscriptions.delete()
            msg = _("You are now unsubscribed from your %s promos.") % keyword
            send_sms.delay(callerid, '0000', msg)
            ret = 'OK UNSUBSCRIBE'

            # we should also create an event
            balance = endaga_sub.get_account_balance(imsi)
            reason = "Promo Cancel Subscription: %s" % keyword
            events.create_sms_event(imsi, balance, 0, reason, '555')

        return Response(ret, status=status.HTTP_200_OK)
Ejemplo n.º 3
0
def add_promo(request, pk=None, template_name='contacts/addpromo_form.html'):
    """
        This function ties a promo (creates a promo subscription)
        to a SIM card (Contact)
    Args:
        request:
        pk: primary key passed is the SIM card's callerid
        template_name:

    Returns:

    """
    if pk:
        contact = get_object_or_404(Contact, callerid=pk)
    else:
        contact = None
    form = ContactAddPromoForm(request.POST or None, contact=contact)

    if form.is_valid():
        instance = form.save(commit=False)
        promo = form.cleaned_data.get('promo')
        contact = form.cleaned_data.get('contact')
        instance.local_sms = promo.local_sms
        instance.local_call = promo.local_call
        instance.outside_sms = promo.outside_sms
        instance.outside_call = promo.outside_call
        instance.date_expiration = timezone.now() + timedelta(promo.validity)
        instance.save()

        send_sms.delay(
            contact.callerid, '0000',
            _('You are automatically subscribed to %(promo)s promo. '
              'To opt out, text REMOVE %(keyword)s to 555.') %
            ({
                'promo': promo.name,
                'keyword': promo.keyword
            }))
        purge_entry.apply_async(eta=instance.date_expiration,
                                args=[instance.pk],
                                task_id=str(instance.pk))

        # we should also create an event
        balance = endaga_sub.get_account_balance(contact.imsi)
        reason = "Promo Auto Subscription: %s" % promo.keyword
        events.create_sms_event(contact.imsi, balance, 0, reason, '555')

        alerts.success(
            request,
            _("You've successfully added '%(promo)s' promo to "
              "contact '%(contact)s.'") % ({
                  'promo': promo,
                  'contact': contact
              }))
        return contact_list(request)
    return render(request, template_name, {'form': form})
Ejemplo n.º 4
0
 def bill(self, to_number, from_number):
     try:
         if from_number == DASHBOARD_FROM_NUMBER:
             self.tariff_type = 'free_sms'
         tariff = billing.get_sms_cost(self.tariff_type,
                                       destination_number=to_number)
         username = subscriber.get_imsi_from_number(to_number)
         if username:
             reason = 'SMS from %s to %s (incoming_sms)' % (
                 from_number, username)
             old_balance = subscriber.get_account_balance(username)
             subscriber.subtract_credit(username, str(int(tariff)))
             events.create_sms_event(username, old_balance, tariff, reason,
                                     to_number, from_number=from_number)
     except Exception as e:
         logger.error("Endaga bill error:" + traceback.format_exc(e))
Ejemplo n.º 5
0
 def POST(self):
     """Handles POST requests."""
     data = web.input()
     if ('from_name' not in data or 'service_type' not in data or
             'destination' not in data):
         raise web.BadRequest()
     # Process the CDR data.
     cost_in_credits = billing.get_sms_cost(
         data.service_type, destination_number=data.destination)
     try:
         old_balance = subscriber.get_account_balance(data.from_name)
         subscriber.subtract_credit(data.from_name, str(cost_in_credits))
     except SubscriberNotFound:
         # The subscriber does not exist yet but has sent an SMS
         if data.service_type == 'free_sms':
             # But that is OK for a free service like provisioning
             old_balance = 0
         else:
             raise
     reason = "SMS sent to %s (%s)" % (data.destination, data.service_type)
     events.create_sms_event(
         data.from_name, old_balance, cost_in_credits, reason,
         data.destination, from_imsi=data.from_name,
         from_number=data.from_number)
     # If this was an in-network event, find the cost for the recipient.  We
     # can lookup the recipient by data.destination (the "to number").
     if 'local' in data.service_type:
         recipient_imsi = subscriber.get_imsi_from_number(data.destination)
         old_balance = subscriber.get_account_balance(recipient_imsi)
         cost_in_credits = billing.get_sms_cost(
             'local_recv_sms', destination_number=data.destination)
         subscriber.subtract_credit(recipient_imsi, str(cost_in_credits))
         reason = "SMS received from %s (local_recv_sms)" % data.from_name
         events.create_sms_event(
             recipient_imsi, old_balance, cost_in_credits, reason,
             data.destination, from_imsi=data.from_name,
             from_number=data.from_number)
     # Return 200 OK.
     headers = {
         'Content-type': 'text/plain'
     }
     raise web.OK(None, headers)
Ejemplo n.º 6
0
def promo_delete_subscription(request,
                              pk,
                              template_name='promos/subscription_'
                              'confirm_delete.html'):
    subscription = get_object_or_404(PromoSubscription, pk=pk)
    if request.method == 'POST':
        revoke(str(pk), terminate=True)
        msg = _("You were automatically unsubscribed from your %s promo."
                ) % subscription.promo.keyword
        send_sms.delay(subscription.contact.callerid, '0000', msg)

        # we should also create an event
        balance = endaga_sub.get_account_balance(subscription.contact.imsi)
        reason = "Promo Cancel Subscription: %s" % subscription.promo.keyword
        events.create_sms_event(subscription.contact.imsi, balance, 0, reason,
                                '555')

        subscription.delete()
        return redirect(request.GET.get('from', 'promos'))
    return render(request, template_name, {'subscription': subscription})
Ejemplo n.º 7
0
def simple_upload(request, template_name='promos/upload_csv.html'):
    csv_subs_len = 2
    csv_promo_len = 12
    fail = False
    promo = True
    contact = True
    page = 'promo_upload_csv'

    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            myfile = request.FILES['docfile']
            actobj = form.cleaned_data.get(
                'action') + form.cleaned_data.get('object')

            reader = csv.reader(io.StringIO(myfile.read().decode('utf-8')))
            headers = next(reader)  # handle row header
            if actobj == '11':  # Create promos
                if len(headers) < csv_promo_len:
                    fail = True
                    alerts.warning(request, _(
                        "Missing required fields. Check your CSV file again."
                    ))
                for row in reader:
                    if len(row) < csv_promo_len:
                        break  # do nothing
                    try:
                        Promo.objects.create(
                            author=request.user,
                            name=row[0],
                            description=row[1],
                            price=row[2],
                            promo_type=row[3],
                            keyword=row[4],
                            validity=row[5],
                            local_sms=row[6],
                            local_call=row[7],
                            globe_sms=row[8],
                            globe_call=row[9],
                            outside_sms=row[10],
                            outside_call=row[11])
                    except Exception as e:
                        fail = True
                        alerts.warning(
                            request, _(
                                'Duplicate entries found in CSV file. %s' %
                                e))

            elif actobj == '12':  # Create promo subscriptions
                if len(headers) < csv_subs_len:
                    fail = True
                    alerts.warning(request, _(
                        "Missing required fields. Check your CSV file again."
                    ))
                for row in reader:
                    if len(row) < csv_subs_len:
                        break
                    try:
                        promo = Promo.objects.get(keyword=row[0])
                    except Promo.DoesNotExist:
                        promo = None
                    try:
                        contact = Contact.objects.get(callerid=row[1])
                    except Contact.DoesNotExist:
                        fail = True
                        contact = None

                    if promo and contact:
                        try:
                            instance = PromoSubscription.objects.create(
                                promo=promo,
                                contact=contact,
                                date_expiration=timezone.now() + timedelta(
                                    promo.validity),
                                local_sms=promo.local_sms,
                                local_call=promo.local_call,
                                globe_sms=promo.globe_sms,
                                globe_call=promo.globe_call,
                                outside_sms=promo.outside_sms,
                                outside_call=promo.outside_call)
                            purge_entry.apply_async(
                                eta=instance.date_expiration,
                                args=[instance.pk],
                                task_id=str(instance.pk))
                            send_sms.delay(
                                contact.callerid,
                                '0000',
                                _(
                                    'You are automatically subscribed to %(promo)s promo '
                                    'valid for %(validity)s day(s). '
                                    'To opt out, text REMOVE %(keyword)s to 555. '
                                    'For more info, text INFO %(keyword)s to 555.') % ({
                                        'promo': promo.name,
                                        'validity': promo.validity,
                                        'keyword': promo.keyword}))
                            # we should also create an event
                            balance = endaga_sub.get_account_balance(
                                contact.imsi)
                            reason = "Promo Auto Subscription: %s" % promo.keyword
                            events.create_sms_event(contact.imsi, balance,
                                                    0, reason, '555')
                        except BaseException:
                            pass

            elif actobj == '21':  # Delete promo
                pass
                # for row in reader:
                #     Promo.objects.filter(keyword=row[6]).delete()
                # # TODO: Do we also delete exisiting subscriptions?
            elif actobj == '22':  # Delete promo subscriptions
                for row in reader:
                    subscriptions = PromoSubscription.objects.filter(
                        promo__keyword__exact=row[0],
                        contact__callerid__exact=row[1])
                    for item in subscriptions:
                        app.control.revoke(str(item.id), terminate=True)
                    subscriptions.delete()
            else:
                pass

            myfile.close()
            if not fail:
                alerts.success(request, _(
                    "Batch operation completed successfully."))
                page = 'promos'
            else:
                if not contact:
                    alerts.warning(
                        request,
                        _("Operation failed. Contact does not exist.")
                    )
                elif not promo:
                    alerts.warning(
                        request,
                        _("Operation failed. Promo does not exist.")
                    )
                else:
                    alerts.warning(
                        request,
                        _("Operation failed. Unknown error.")
                    )
            return redirect(page)
    else:
        form = DocumentForm()
    return render(request, template_name, {'form': form})
Ejemplo n.º 8
0
    def post(self, request):
        needed_fields = ["imsi", "keyword"]
        if not all(i in request.POST for i in needed_fields):
            return Response("Missing Args", status=status.HTTP_400_BAD_REQUEST)

        imsi = request.data['imsi']
        keyword = request.data['keyword']

        try:
            subscriber = Contact.objects.get(imsi__exact=imsi)
        except BaseException:  # subscriber not found in Contacts table
            send_sms.delay(
                endaga_sub.get_numbers_from_imsi(imsi)[0], '0000',
                _("You are not listed in the PCARI-VBTS database. "
                  "Please register."))
            return Response("Not Found", status=status.HTTP_404_NOT_FOUND)

        # We put code to optionally limit promo subscriptions
        # this depends on the limit type declared in the configs

        try:
            limit_type = Config.objects.get(key='promo_limit_type').value
        except Config.DoesNotExist:
            limit_type = 'NA'

        try:
            max_promo_subscription = int(
                Config.objects.get(key='max_promo_subscription').value)
        except Config.DoesNotExist:
            max_promo_subscription = 1

        try:
            min_balance_required = float(
                Config.objects.get(key='min_balance_required').value)
        except Config.DoesNotExist:
            min_balance_required = 0

        # type A: Limit number of subscription per promo
        if limit_type == 'A':
            count = PromoSubscription.objects.filter(
                promo__keyword__exact=keyword, contact=subscriber).count()
            if count >= max_promo_subscription:
                send_sms.delay(subscriber.callerid, '0000',
                               _("You have to many promo subscriptions."))
                return Response("Too Many Subscriptions",
                                status=status.HTTP_403_FORBIDDEN)

        # type B: Limit number of subscription for all promos
        elif limit_type == 'B':
            count = PromoSubscription.objects.filter(
                contact=subscriber).count()
            if count >= max_promo_subscription:
                send_sms.delay(subscriber.callerid, '0000',
                               _("You have to many promo subscriptions."))
                return Response("Too Many Subscriptions",
                                status=status.HTTP_403_FORBIDDEN)
        else:
            pass  # proceed as usual

        try:
            promo = Promo.objects.get(keyword__exact=keyword)
        except BaseException:  # bad promo keyword
            send_sms.delay(subscriber.callerid, '0000',
                           _("You made a bad promo request."))
            return Response("Bad promo request",
                            status=status.HTTP_400_BAD_REQUEST)

        # check account balance first
        balance = endaga_sub.get_account_balance(imsi)
        if balance - promo.price < min_balance_required:
            send_sms.delay(
                subscriber.callerid, '0000',
                _("You do not have sufficient balance to subscribe "
                  "to the %s promo.") % promo.keyword)
            return Response("Insufficient balance",
                            status=status.HTTP_402_PAYMENT_REQUIRED)

        # user passes above check, has enough balance, so sign him up!
        new_subscription = PromoSubscription()
        new_subscription.promo = promo
        new_subscription.contact = subscriber
        # save time as UTC in database
        new_subscription.date_expiration = timezone.now() + timedelta(
            promo.validity)
        new_subscription.local_sms = promo.local_sms
        new_subscription.local_call = promo.local_call
        new_subscription.globe_sms = promo.globe_sms
        new_subscription.globe_call = promo.globe_call
        new_subscription.outside_sms = promo.outside_sms
        new_subscription.outside_call = promo.outside_call
        new_subscription.save()

        # finally, deduct promo.price from subscriber's balance
        # price is expressed in millicents
        endaga_sub.subtract_credit(imsi, str(promo.price))

        try:
            tz = Config.objects.get(key='timezone').value
        except Config.DoesNotExist:
            tz = pytz_timezone('Asia/Manila')

        # present time to subscriber according to defined timezone
        expiry = new_subscription.date_expiration.astimezone(tz). \
            strftime("%m/%d/%y %I:%M%p")

        # and then lets inform the subscriber
        send_sms.delay(
            subscriber.callerid, '0000',
            _("You are now subscribed to %(keyword)s valid "
              "until %(expiry)s.") % ({
                  'keyword': promo.keyword,
                  'expiry': expiry
              }))

        # and then create a purge task
        # let's use the PK as the task_id, so that we dont have to create
        # a new field to store the id. this might be OK for now.
        purge_entry.apply_async(eta=new_subscription.date_expiration,
                                args=[new_subscription.pk],
                                task_id=str(new_subscription.pk))

        # we should also create an event
        reason = "Promo subscription: %s" % promo.keyword
        events.create_sms_event(subscriber.imsi, balance, promo.price, reason,
                                '555')

        return Response('OK SUBSCRIBE', status=status.HTTP_200_OK)