コード例 #1
0
def fsapi(session, stream, env, args):
    """Handles data from the FS API.

    Args:
      string of the form <service_type>|<call_or_sms>|<destination_number>
    """
    service_type, call_or_sms, destination_number = args.split('|')
    # Sanitize the destination number.
    destination_number = number_utilities.strip_number(destination_number)
    res = str(billing.get_service_tariff(
        service_type, call_or_sms, destination_number=destination_number))
    consoleLog('info', "Returned FSAPI: " + res + "\n")
    stream.write(res)
コード例 #2
0
def chat(message, args):
    """Handles data from the chatplan.

    Args:
      string of the form <service_type>|<call_or_sms>|<destination_number>
    """
    service_type, call_or_sms, destination_number = args.split('|')
    # Sanitize the destination number.
    destination_number = number_utilities.strip_number(destination_number)
    res = str(billing.get_service_tariff(
        service_type, call_or_sms, destination_number=destination_number))
    consoleLog('info', "Returned Chat: " + res + "\n")
    message.chat_execute('set', 'service_type=%s' % res)
コード例 #3
0
    def process_cdr(self, cdr_xml):
        """Processes the XML CDR for the caller."""
        cdr_dom = xml.parseString(cdr_xml)
        # Handle only b-legs for billing.
        origin = cdr_dom.getElementsByTagName("origination")
        if origin:
            return
        # Handle only b-legs for billing.
        # For our purposes, billsec is how long the call lasted. call_duration
        # captures the amount of time spent ringing, which we don't charge for,
        # so don't include here. Caller and callee are just used for logging
        # and reason statements.
        # TODO(matt): what happens if the tag does not exist?
        call_duration = int(
            get_tag_text(
                cdr_dom.getElementsByTagName("duration")[0].childNodes))
        billsec = int(
            get_tag_text(
                cdr_dom.getElementsByTagName("billsec")[0].childNodes))
        # In b-leg cdrs, there are multiple destinations -- the sip one (IMSI)
        # and the dialed one (MSISDN).  We want the latter.
        callees = cdr_dom.getElementsByTagName("destination_number")
        callee = ''
        for c in callees:
            c = get_tag_text(c.childNodes)
            # NOT THE IMSI
            if c[0:4] != IMSI_PREFIX:
                callee = c
                break
        if callee[0] == "+":
            callee = callee[1:]
        hangupcause = get_hangup_cause(cdr_dom)
        # This is where we get the info we need to do billing.
        if len(cdr_dom.getElementsByTagName("service_type")) > 0:
            service_type = get_tag_text(
                cdr_dom.getElementsByTagName("service_type")[0].childNodes)
            # Get caller / callee info.  See the 'CDR notes' doc in drive for
            # more info.
            from_imsi, from_number, to_imsi, to_number = 4 * [None]
            # We always get 'from_imsi' from the <username> tag with the
            # <caller_profile> parent element. If it's a BTS-originated call,
            # this will be an IMSI; otherwise, it'll be an MSISDN.
            if service_type not in ['incoming_call']:
                elements = cdr_dom.getElementsByTagName('username')
                for element in elements:
                    if element.parentNode.nodeName == 'caller_profile':
                        username = get_tag_text(element.childNodes)
                        from_imsi = subscriber.get_imsi_from_username(username)
                        break
            # Get 'from_number' (only available for outside and local calls).
            if service_type in ['outside_call', 'local_call', 'incoming_call']:
                elements = cdr_dom.getElementsByTagName('caller_id_name')
                for element in elements:
                    if element.parentNode.nodeName == 'caller_profile':
                        from_number = get_tag_text(element.childNodes)
                        break
            # Get 'to_imsi' (only available for local/incoming calls).
            if service_type in ['local_call', 'incoming_call']:
                elements = cdr_dom.getElementsByTagName('callee_id_number')
                for element in elements:
                    if element.parentNode.nodeName == 'caller_profile':
                        callee_id = get_tag_text(element.childNodes)
                        if callee_id[0:4] == IMSI_PREFIX:
                            to_imsi = callee_id
                        else:
                            # callee_id_number in the CDR is MSISDN.
                            to_imsi = subscriber.get_imsi_from_number(
                                callee_id)
                        break

            # Get 'to_number' (slightly different for local/incoming calls).
            if service_type in ['outside_call', 'free_call', 'error_call']:
                elements = cdr_dom.getElementsByTagName('destination_number')
                for element in elements:
                    if element.parentNode.nodeName == 'caller_profile':
                        to_number = get_tag_text(element.childNodes)
                        break
            elif service_type in ['local_call', 'incoming_call']:
                elements = cdr_dom.getElementsByTagName('destination_number')
                for element in elements:
                    if (element.parentNode.nodeName ==
                            'originator_caller_profile'):
                        to_number = get_tag_text(element.childNodes)
                        break
            # Generate billing information for the caller, if the caller is
            # local to the BTS.
            if service_type != 'incoming_call':
                tariff = billing.get_service_tariff(
                    service_type, 'call', destination_number=to_number)
                cost = billing.get_call_cost(billsec,
                                             service_type,
                                             destination_number=to_number)
                reason = "%s sec call to %s (%s/%s)" % (
                    billsec, to_number, service_type, hangupcause)
                old_balance = subscriber.get_account_balance(from_imsi)
                subscriber.subtract_credit(from_imsi, str(cost))
                owner_imsi = from_imsi
                kind = service_type
                events.create_call_event(owner_imsi, from_imsi, from_number,
                                         to_imsi, to_number, old_balance, cost,
                                         kind, reason, tariff, call_duration,
                                         billsec)

            # Create a call record for the callee, if applicable.
            if service_type in ['local_call', 'incoming_call']:
                if service_type == 'local_call':
                    service_type = 'local_recv_call'
                tariff = billing.get_service_tariff(service_type, 'call')
                cost = billing.get_call_cost(billsec, service_type)
                reason = "%d sec call from %s (%s/%s)" % (
                    billsec, from_number, service_type, hangupcause)
                # Note! This is different than how we bill for a caller --
                # we're deducting from the 'to_imsi' (the callee) instead.
                old_balance = subscriber.get_account_balance(to_imsi)
                subscriber.subtract_credit(to_imsi, str(cost))
                owner_imsi = to_imsi
                kind = service_type
                events.create_call_event(owner_imsi, from_imsi, from_number,
                                         to_imsi, to_number, old_balance, cost,
                                         kind, reason, tariff, call_duration,
                                         billsec)

        else:
            username = get_tag_text(
                cdr_dom.getElementsByTagName("username")[0].childNodes)
            from_imsi = subscriber.get_imsi_from_username(username)
            message = "No rate info for this call. (from: %s, billsec: %s)" % (
                from_imsi, billsec)
            logger.error(message)
コード例 #4
0
    def post(self, request, format=None):
        needed_fields = ["imsi", "trans", "dest"]
        if not all(i in request.POST for i in needed_fields):
            return Response("Missing Args", status=status.HTTP_400_BAD_REQUEST)

        promo_type, service_type = extract_types(request.data['trans'])
        imsi = request.data['imsi']
        dest = request.data['dest']

        # Assume first that regular tariffs will be applied
        # then overwrite later if promos apply.
        # Kinda weird, but this avoid 'ret' being unset if Disc
        # promo is suddenly purged by celery while traversing FS dialplan
        if 'sms' in service_type:
            call_or_sms = 'sms'
        else:
            call_or_sms = 'call'
        destination_number = number_utilities.strip_number(dest)

        # Kludge!
        if 'globe' in service_type:
            # replace first word with globe keyword
            ret = str(
                billing.get_service_tariff(
                    'outside_' + service_type.split('_')[1], call_or_sms,
                    destination_number))
        else:
            ret = str(
                billing.get_service_tariff(service_type, call_or_sms,
                                           destination_number))

        # if unli or bulk, no tariff
        if promo_type == 'U' or promo_type == 'B':
            ret = '0'

        # if discounted, get tariff from earliest subscribed discounted promo
        elif promo_type in ['D']:
            query = service_type + '__gt'
            promo = PromoSubscription.objects.filter(
                contact__imsi__exact=imsi,
                promo__promo_type=promo_type,
                **{
                    query: 0
                }).order_by('date_expiration')

            if promo:
                key = 'promo[0].%s' % service_type
                ret = str(eval(key))
                # else, regular tariffs from above will apply

        elif promo_type in ['G']:
            query = service_type + '__gt'
            promo = PromoSubscription.objects.filter(
                contact__imsi__exact=imsi,
                promo__promo_type=promo_type,
                **{
                    query: 0
                }).order_by('date_expiration')
            member = GroupMembers.objects.filter(
                group__owner__imsi__exact=imsi, user__callerid__exact=dest)

            if promo and member:
                key = 'promo[0].%s' % service_type
                ret = str(eval(key))
                # else, regular tariffs from above will apply

        return Response(ret, status=status.HTTP_200_OK)