def process_confirm(from_imsi, code):
    """Process a confirmation request.

    Args:
      from_imsi: sender's IMSI
      code: the input confirmation code string
    """
    # Step one: delete all the confirm codes older than some time.
    db = sqlite3.connect(config_db['pending_transfer_db_path'])
    db.execute("DELETE FROM pending_transfers"
               " WHERE time - ? > 600", (time.time(),))
    db.commit()

    # Step two: check if this (from_imsi, code) combo is valid.
    r = db.execute("SELECT from_acct, to_acct, amount FROM pending_transfers"
                   " WHERE code=? AND from_acct=?", (code, from_imsi))
    res = r.fetchone()
    if res and len(res) == 3:
        from_imsi, to_imsi, amount = res
        from_num = subscriber.get_numbers_from_imsi(from_imsi)[0]
        to_num = subscriber.get_numbers_from_imsi(to_imsi)[0]
        reason = "SMS transfer from %s to %s" % (from_num, to_num)
        # Deduct credit from the sender.
        from_imsi_old_credit = subscriber.get_account_balance(from_imsi)
        from_imsi_new_credit = int(from_imsi_old_credit) - int(amount)
        events.create_transfer_event(from_imsi, from_imsi_old_credit,
                                     from_imsi_new_credit, reason,
                                     from_number=from_num, to_number=to_num)
        subscriber.subtract_credit(from_imsi, str(int(amount)))
        # Add credit to the recipient.
        to_imsi_old_credit = subscriber.get_account_balance(to_imsi)
        to_imsi_new_credit = int(to_imsi_old_credit) + int(amount)
        events.create_transfer_event(to_imsi, to_imsi_old_credit,
                                     to_imsi_new_credit, reason,
                                     from_number=from_num, to_number=to_num)
        subscriber.add_credit(to_imsi, str(int(amount)))
        # Humanize credit strings
        amount_str = freeswitch_strings.humanize_credits(amount)
        to_balance_str = freeswitch_strings.humanize_credits(
                to_imsi_new_credit)
        from_balance_str = freeswitch_strings.humanize_credits(
                from_imsi_new_credit)
        # Let the recipient know they got credit.
        message = gt("You've received %(amount)s credits from %(from_num)s!"
                     " Your new balance is %(new_balance)s.") % {
                     'amount': amount_str, 'from_num': from_num,
                     'new_balance': to_balance_str}
        sms.send(str(to_num), str(config_db['app_number']), str(message))
        # Remove this particular the transfer as it's no longer pending.
        db.execute("DELETE FROM pending_transfers WHERE code=?"
                   " AND from_acct=?", (code, from_imsi))
        db.commit()
        # Tell the sender that the operation succeeded.
        return True, gt("You've transferred %(amount)s to %(to_num)s. "
                        "Your new balance is %(new_balance)s.") % {
                                'amount': amount_str, 'to_num': to_num,
                                'new_balance': from_balance_str}
    return False, gt("That transfer confirmation code doesn't exist"
                     " or has expired.")
Beispiel #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)
Beispiel #3
0
    def post(self, request):
        """ POST method for submitting a report """
        needed_fields = ["imsi", "keyword", "message"]
        if not all(i in request.POST for i in needed_fields):
            return Response("ERROR: Missing arguments.",
                            status=status.HTTP_400_BAD_REQUEST)

        imsi = request.data['imsi']
        try:
            subscriber = Contact.objects.get(imsi__exact=imsi)
        except BaseException:
            send_sms.delay(
                endaga_sub.get_numbers_from_imsi(imsi)[0], '0000',
                _("You are currently not registered to the BTS. "
                  "Please register."))
            return Response("ERROR: Not registered subscriber.",
                            status=status.HTTP_400_BAD_REQUEST)

        try:
            report = Report.objects.filter(
                Q(keyword=request.data['keyword'].upper()) & Q(status='P'))[0]
        except BaseException:
            send_sms.delay(
                subscriber.callerid, '0000',
                _("Sorry we can't process your request. "
                  "Invalid keyword."))
            return Response("ERROR: Invalid keyword.",
                            status=status.HTTP_400_BAD_REQUEST)

        new_report = ReportMessages()
        new_report.sender = subscriber
        new_report.report = report
        new_report.message = request.data['message']
        new_report.date = timezone.now()
        new_report.save()

        send_sms.delay(
            subscriber.callerid, '0000',
            _("You have successfully sent a report to %s.") % report.keyword)
        for manager in report.managers.all():
            send_sms.delay(
                manager.callerid, '0000',
                _("New report from %(manager)s. "
                  "%(keyword)s:%(msg)s") % ({
                      'manager': manager.callerid,
                      'keyword': report.keyword,
                      'msg': new_report.message
                  }))

        return Response('OK CREATED', status=status.HTTP_200_OK)
Beispiel #4
0
    def post(self, request):
        """ POST method to send message to service's subscribers. """
        needed_fields = ["imsi", "keyword", "message"]
        if not all(i in request.POST for i in needed_fields):
            return Response("ERROR: Missing arguments.",
                            status=status.HTTP_400_BAD_REQUEST)

        imsi = request.data['imsi']
        keyword = request.data['keyword']
        try:
            service = Service.objects.filter(keyword=keyword.upper(),
                                             status='P')[0]
        except BaseException:
            send_sms.delay(
                endaga_sub.get_numbers_from_imsi(imsi)[0], '0000',
                _("Sorry we can't process your request. "
                  "Invalid service."))
            return Response("ERROR: Invalid service.",
                            status=status.HTTP_400_BAD_REQUEST)

        # check first if sender is the service manager
        # if so, propagate message to all service subscribers
        if service.managers.filter(imsi=request.data['imsi']).exists():
            for subscriber in service.subscribers.all():
                send_sms.delay(subscriber.callerid, '0000',
                               _("ANNOUNCEMENT: %s") % request.data['message'])
            return Response('ANNOUNCEMENT SENT', status=status.HTTP_200_OK)

        else:
            send_sms.delay(
                endaga_sub.get_numbers_from_imsi(imsi)[0], '0000',
                _("You are not allowed to send message to %s's "
                  "subscribers.") % keyword)
            return Response("ERROR: No administrative privileges to send to "
                            "this %s's subscribers." % keyword,
                            status=status.HTTP_400_BAD_REQUEST)
Beispiel #5
0
    def post(self, request):
        """ POST method for subscribing to a service """
        needed_fields = ["imsi", "keyword"]
        if not all(i in request.POST for i in needed_fields):
            return Response("ERROR: Missing arguments.",
                            status=status.HTTP_400_BAD_REQUEST)

        imsi = request.data['imsi']

        try:
            subscriber = Contact.objects.get(imsi__exact=imsi)
        except BaseException:
            send_sms.delay(
                endaga_sub.get_numbers_from_imsi(imsi)[0], '0000',
                _("You are currently not registered to the BTS. "
                  "Please register."))
            return Response("ERROR: Not registered subscriber.",
                            status=status.HTTP_404_NOT_FOUND)

        try:
            service = Service.objects.filter(
                keyword=request.data['keyword'].upper(),
                service_type='P',
                status='P')[0]
        except BaseException:
            send_sms.delay(
                subscriber.callerid, '0000',
                _("Sorry we can't process your request. "
                  "Invalid keyword."))
            return Response("ERROR: Invalid keyword.",
                            status=status.HTTP_400_BAD_REQUEST)

        is_subscribed = ServiceSubscribers.objects. \
            filter(service=service, subscriber=subscriber).exists()

        if is_subscribed:
            send_sms.delay(subscriber.callerid, '0000',
                           _("You are subscribed to %s.") % service.name)
            return Response('OK STATUS - SUBSCRIBED',
                            status=status.HTTP_200_OK)

        else:
            send_sms.delay(subscriber.callerid, '0000',
                           _("You are not subscribed to %s.") % service.name)
            return Response('OK STATUS - NOT SUBSCRIBED',
                            status=status.HTTP_200_OK)
Beispiel #6
0
    def post(self, request, format=None):
        needed_fields = ["keyword", "imsi"]
        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]

        try:
            promo = Promo.objects.get(keyword__exact=keyword)
            msg = promo.description
        except BaseException:
            msg = "You have entered an invalid promo keyword."
        send_sms.delay(callerid, '0000', msg)

        return Response('OK', status=status.HTTP_200_OK)
Beispiel #7
0
def process_transfer(from_imsi, to_imsi, amount):
    """Process a transfer request.

    Args:
      from_imsi: the sender's IMSI
      to_imsi: the recipient's IMSI
      amount: an amount of credit to add (type?)

    Returns:
      boolean indicating success
    """
    # Error when user tries to transfer to his own account
    if from_imsi == to_imsi:
        return False, gt("Transaction Failed. Sharing load to "
                         "your own account is not allowed.")
    from_balance = int(subscriber.get_account_balance(from_imsi))
    # Error when user tries to transfer more credit than they have.
    if not from_balance or from_balance < amount:
        return False, gt("Your account doesn't have sufficient funds for"
                         " the transfer.")
    # Error when user tries to transfer to a non-existent user.
    #       Could be 0!  Need to check if doesn't exist.
    if not to_imsi or (subscriber.get_account_balance(to_imsi) == None):
        return False, gt("The number you're sending to doesn't exist."
                         " Try again.")
    # Add the pending transfer.
    code = ''
    for _ in range(int(config_db['code_length'])):
        code += str(random.randint(0, 9))
    db = sqlite3.connect(config_db['pending_transfer_db_path'])
    db.execute("INSERT INTO pending_transfers VALUES (?, ?, ?, ?, ?)",
               (code, time.time(), from_imsi, to_imsi, amount))
    db.commit()
    db.close()
    to_num = subscriber.get_numbers_from_imsi(to_imsi)[0]
    amount_str = freeswitch_strings.humanize_credits(amount)
    response = gt("Reply to this message with %(code)s to confirm your"
                  " transfer of %(amount)s to %(to_num)s. Code expires in ten"
                  " minutes.") % {
                      'code': code,
                      'amount': amount_str,
                      'to_num': to_num
                  }
    return True, response
Beispiel #8
0
def handle_incoming(from_imsi, request):
    """Called externally by an FS script.

    Args:
      from_imsi: sender's IMSI
      request: a credit transfer or credit transfer confirmation request
    """
    request = request.strip()

    # This parses a to_number (length 1 or more) and an amount that can
    # be formatted using a comma for a thousands seperator and a period for
    # the decimal place
    transfer_command = re.compile(
        r'^(?P<to_number>[0-9]+)'
        r'\*'
        r'(?P<amount>[0-9]*(?:,[0-9]{3})*(?:\.[0-9]*)?)$')
    transfer = transfer_command.match(request)

    confirm_command = re.compile(r'^(?P<confirm_code>[0-9]{%d})$' %
                                 int(config_db['code_length']))
    confirm = confirm_command.match(request)
    _init_pending_transfer_db()
    if transfer:
        to_number, amount = transfer.groups()
        amount = freeswitch_strings.parse_credits(amount).amount_raw
        # Translate everything into IMSIs.
        try:
            to_imsi = subscriber.get_imsi_from_number(to_number)
            _, resp = process_transfer(from_imsi, to_imsi, amount)
        except SubscriberNotFound:
            resp = gt("Invalid phone number: %(number)s" %
                      {'number': to_number})
    elif confirm:
        # The code is the whole request, so no need for groups.
        code = request.strip()
        _, resp = process_confirm(from_imsi, code)
    else:
        # NOTE: Sent when the user tries to transfer credit with the wrong
        #       format message.
        resp = gt("To transfer credit, reply with a message in the"
                  " format 'NUMBER*AMOUNT'.")
    from_number = subscriber.get_numbers_from_imsi(from_imsi)[0]
    sms.send(str(from_number), str(config_db['app_number']), str(resp))
Beispiel #9
0
    def post(self, request):
        """ POST method for opting out from a service """
        needed_fields = ["imsi", "keyword"]
        if not all(i in request.POST for i in needed_fields):
            return Response("ERROR: Missing arguments.",
                            status=status.HTTP_400_BAD_REQUEST)

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

        try:
            subscriber = Contact.objects.get(imsi__exact=imsi)
        except BaseException:
            send_sms.delay(
                endaga_sub.get_numbers_from_imsi(imsi)[0], '0000',
                _("You are currently not registered to the BTS. "
                  "Please register."))
            return Response("ERROR: Not registered subscriber.",
                            status=status.HTTP_400_BAD_REQUEST)

        try:
            subscription = ServiceSubscribers.objects.filter(
                service__keyword__exact=keyword,
                subscriber__imsi__exact=request.data['imsi'])[0]
            subscription.delete()
            send_sms.delay(
                subscriber.callerid, '0000',
                _("You have successfully unsubscribed to %s.") %
                subscription.service.name)
            return Response('OK UNSUBSCRIBED', status=status.HTTP_200_OK)
        except BaseException:
            send_sms.delay(
                subscriber.callerid, '0000',
                _("You are not currently subscribed to the service."))
            return Response("ERROR: You are not currently subscribed to "
                            "the %s service." % keyword,
                            status=status.HTTP_400_BAD_REQUEST)
Beispiel #10
0
    def post(self, request, format=None):
        needed_fields = ["imsi"]
        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]

        if not keyword:
            subscriptions = PromoSubscription.objects.filter(
                contact__imsi__exact=imsi). \
                order_by('date_expiration')
        else:
            subscriptions = PromoSubscription.objects.filter(
                contact__imsi__exact=imsi, promo__keyword=keyword). \
                order_by('date_expiration')
        if not subscriptions:
            send_sms.delay(callerid, '0000',
                           _("You have no %s subscriptions.") % keyword)

        else:
            msg = ""

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

            for item in subscriptions:
                msg += "Your %s promo status: \\n" % item.promo.keyword
                expiry = item.date_expiration. \
                    astimezone(tz).strftime("%m/%d/%y %I:%M%p")

                if item.promo.promo_type == 'D' or item.promo.promo_type == 'G':
                    if item.local_sms:
                        msg += "%s local texts discount price: P%s\\n" % (
                            item.promo.keyword, mc_to_float(item.local_sms))
                    if item.local_call:
                        msg += "%s local call/min discount price: P%s\\n" % (
                            item.promo.keyword, mc_to_float(item.local_call))
                    if item.globe_sms:
                        msg += "%s Globe texts discount price: P%s\\n" % (
                            item.promo.keyword, mc_to_float(item.globe_sms))
                    if item.globe_call:
                        msg += "%s Globe call/min discount price: P%s\\n" % (
                            item.promo.keyword, mc_to_float(item.globe_call))
                    if item.outside_sms:
                        msg += "%s outside texts discount price: P%s\\n" % (
                            item.promo.keyword, mc_to_float(item.outside_sms))
                    if item.outside_call:
                        msg += "%s outside call/min discount price: P%s\\n" % (
                            item.promo.keyword, mc_to_float(item.outside_call))
                elif item.promo.promo_type == 'B':
                    if item.local_sms:
                        msg += "%s local texts: %s\\n" % (item.promo.keyword,
                                                          item.local_sms)
                    if item.local_call:
                        msg += "%s local call mins: %s\\n" % (
                            item.promo.keyword, item.local_call)
                    if item.globe_sms:
                        msg += "%s Globe texts: %s\\n" % (item.promo.keyword,
                                                          item.globe_sms)
                    if item.globe_call:
                        msg += "%s Globe call mins: %s\\n" % (
                            item.promo.keyword, item.globe_call)
                    if item.outside_sms:
                        msg += "%s outside texts: %s\\n" % (item.promo.keyword,
                                                            item.outside_sms)
                    if item.outside_call:
                        msg += "%s outside call mins: %s\\n" % (
                            item.promo.keyword, item.outside_call)
                elif item.promo.promo_type == 'U':
                    if item.local_sms:
                        msg += "%s unli local texts\\n" % item.promo.keyword
                    if item.local_call:
                        msg += "%s unli local calls\\n" % item.promo.keyword
                    if item.globe_sms:
                        msg += "%s unli Globe texts\\n" % item.promo.keyword
                    if item.globe_call:
                        msg += "%s unli Globe calls\\n" % item.promo.keyword
                    if item.outside_sms:
                        msg += "%s unli outside texts\\n" % item.promo.keyword
                    if item.outside_call:
                        msg += "%s unli outside calls\\n" % item.promo.keyword
                msg += "Exp: %s\\n" % expiry

            send_sms.delay(callerid, '0000', msg[:-2])

        return Response('OK', status=status.HTTP_200_OK)
Beispiel #11
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)
Beispiel #12
0
    def post(self, request):
        """ POST method for subscribing to a service """
        needed_fields = ["imsi", "keyword"]
        if not all(i in request.POST for i in needed_fields):
            return Response("ERROR: Missing arguments.",
                            status=status.HTTP_400_BAD_REQUEST)

        imsi = request.data['imsi']

        try:
            subscriber = Contact.objects.get(imsi__exact=imsi)
        except BaseException:
            send_sms.delay(
                endaga_sub.get_numbers_from_imsi(imsi)[0], '0000',
                _("You are currently not registered to the BTS. "
                  "Please register."))
            return Response("ERROR: Not registered subscriber.",
                            status=status.HTTP_400_BAD_REQUEST)

        try:
            service = Service.objects.filter(
                keyword=request.data['keyword'].upper(),
                service_type='P',
                status='P')[0]
        except BaseException:
            send_sms.delay(
                subscriber.callerid, '0000',
                _("Sorry we can't process your request. "
                  "Invalid keyword."))
            return Response("ERROR: Invalid keyword.",
                            status=status.HTTP_400_BAD_REQUEST)

        is_duplicate = ServiceSubscribers.objects. \
            filter(service=service, subscriber=subscriber).exists()

        if is_duplicate:
            send_sms.delay(
                subscriber.callerid, '0000',
                _("You are already subscribed to %s.") % service.name)
            return Response('OK ALREADY SUBSCRIBED', status=status.HTTP_200_OK)

        else:
            # check if subscriber has enough balance
            balance = endaga_sub.get_account_balance(imsi)
            if balance - service.price < 0:
                send_sms.delay(
                    subscriber.callerid, '0000',
                    _("You do not have sufficient balance to "
                      "subscribe to %s.") % service.name)
                return Response("Insufficient balance",
                                status=status.HTTP_402_PAYMENT_REQUIRED)

            # user passes above check, has enough balance, so sign him up!
            new_subscription = ServiceSubscribers(subscriber=subscriber,
                                                  service=service)
            new_subscription.date_joined = timezone.now()
            new_subscription.save()
            # finally, deduct service.price from subscriber's balance
            # price is expressed in millicents
            endaga_sub.subtract_credit(imsi, str(service.price))

            send_sms.delay(
                subscriber.callerid, '0000',
                _("You have successfully subscribed to %s.") % service.name)
            return Response('OK SUBSCRIBED', status=status.HTTP_200_OK)