예제 #1
0
 def __init__(self, user, *args, **kwargs):
     super(DuplicateCampaignForm, self).__init__(*args, **kwargs)
     self.fields['campaign_code'].initial = get_unique_code(length=5)
     for i in self.fields.keyOrder:
         self.fields[i].widget.attrs['class'] = "form-control"
     if user:
         phonebook_list = get_phonebook_list(user)
         self.fields['phonebook'].choices = phonebook_list
         self.fields['phonebook'].initial = str(phonebook_list[0][0])
예제 #2
0
    def __init__(self, user, *args, **kwargs):
        super(DuplicateCampaignForm, self).__init__(*args, **kwargs)
        self.fields['campaign_code'].initial = get_unique_code(length=5)

        if user:
            list_pb = []
            list_pb.append((0, '---'))
            list = Phonebook.objects.values_list('id', 'name')\
                .filter(user=user).order_by('id')
            for l in list:
                list_pb.append((l[0], l[1]))
            self.fields['phonebook'].choices = list_pb
예제 #3
0
    def __init__(self, user, *args, **kwargs):
        super(DuplicateCampaignForm, self).__init__(*args, **kwargs)
        self.fields['campaign_code'].initial = get_unique_code(length=5)

        if user:
            list_pb = []
            list_pb.append((0, '---'))
            list = Phonebook.objects.values_list('id', 'name')\
                .filter(user=user).order_by('id')
            for l in list:
                list_pb.append((l[0], l[1]))
            self.fields['phonebook'].choices = list_pb
예제 #4
0
    def __init__(self, user, *args, **kwargs):
        super(CampaignForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        self.fields['campaign_code'].initial = get_unique_code(length=5)
        self.fields['description'].widget.attrs['class'] = "input-xlarge"

        if user:
            self.fields['ds_user'].initial = user
            list_gw = []
            list_pb = []
            dnc_list = []

            list_pb.append((0, '---'))
            list = Phonebook.objects.values_list('id', 'name')\
                .filter(user=user).order_by('id')
            for l in list:
                list_pb.append((l[0], l[1]))
            self.fields['phonebook'].choices = list_pb

            list = user.get_profile().userprofile_gateway.all()
            gw_list = ((l.id, l.name) for l in list)

            dnc_list.append(('', '---'))
            list = DNC.objects.values_list('id', 'name')\
                .filter(user=user).order_by('id')
            for l in list:
                dnc_list.append((l[0], l[1]))
            self.fields['dnc'].choices = dnc_list

            for i in gw_list:
                list_gw.append((i[0], i[1]))
            self.fields['aleg_gateway'].choices = list_gw

            if instance.has_been_duplicated:
                from survey.models import Survey
                available_objects = Survey.objects.filter(user=user, campaign=instance)
                object_choices = get_object_choices(available_objects)
                self.fields['content_object'].widget.attrs['readonly'] = True
            else:
                from survey.models import Survey_template
                available_objects = Survey_template.objects.filter(user=user)
                object_choices = get_object_choices(available_objects)

            self.fields['content_object'].choices = object_choices

            # Voicemail setting is not enabled by default
            if settings.AMD:
                from survey.forms import get_audiofile_list
                self.fields['voicemail_audiofile'].choices = get_audiofile_list(user)

        # if campaign is running
        if instance.status == CAMPAIGN_STATUS.START:
            self.fields['name'].widget.attrs['readonly'] = True
            self.fields['caller_name'].widget.attrs['readonly'] = True
            self.fields['callerid'].widget.attrs['readonly'] = True
            self.fields['extra_data'].widget.attrs['readonly'] = True
            self.fields['phonebook'].widget.attrs['disabled'] = 'disabled'

            selected_phonebook = ''
            if instance.phonebook.all():
                selected_phonebook = \
                    ",".join(["%s" % (i.id) for i in instance.phonebook.all()])
            self.fields['selected_phonebook'].initial = selected_phonebook

            self.fields['content_object'].widget.attrs['disabled'] = 'disabled'
            self.fields['content_object'].required = False
            self.fields['selected_content_object'].initial = "type:%s-id:%s" \
                % (instance.content_type.id, instance.object_id)
예제 #5
0
 def __init__(self, *args, **kwargs):
     super(CampaignAdminForm, self).__init__(*args, **kwargs)
     self.fields['campaign_code'].widget.attrs['readonly'] = True
     self.fields['campaign_code'].initial = get_unique_code(length=5)
예제 #6
0
class Campaign(Model):
    """This defines the Campaign

    **Attributes**:

        * ``campaign_code`` - Auto-generated campaign code to identify the campaign
        * ``name`` - Campaign name
        * ``description`` - Description about the Campaign
        * ``status`` - Campaign status
        * ``callerid`` - Caller ID
        * ``startingdate`` - Starting date of the Campaign
        * ``expirationdate`` - Expiry date of the Campaign
        * ``daily_start_time`` - Start time
        * ``daily_stop_time`` - End time
        * ``week_day_setting`` (monday, tuesday, wednesday, thursday, friday, \
        saturday, sunday)
        * ``frequency`` - Frequency, speed of the campaign. number of calls/min
        * ``callmaxduration`` - Max retry allowed per user
        * ``maxretry`` - Max retry allowed per user
        * ``intervalretry`` - Time to wait between retries in seconds
        * ``completion_maxretry`` - Amount of retries until a contact is completed
        * ``completion_intervalretry`` - Time delay in seconds before retrying \
        contact for completion
        * ``calltimeout`` - Number of seconds to timeout on calls
        * ``aleg_gateway`` - Gateway to use to reach the contact
        * ``extra_data`` - Additional data to pass to the application
        * ``totalcontact`` - Total Contact for this campaign
        * ``completed`` - Total Contact that completed Call / Survey
        * ``has_been_started`` - campaign started flag
        * ``has_been_duplicated`` - campaign duplicated flag
        * ``voicemail`` - Enable Voicemail Detection
        * ``amd_behavior`` - Detection Behaviour

    **Relationships**:

        * ``content_type`` - Defines the application (``survey``) \
        to use when the call is established on the A-Leg

        * ``object_id`` - Defines the object of content_type application

        * ``content_object`` - Used to define the Voice App or the Survey with generic ForeignKey

        * ``phonebook`` - Many-To-Many relationship to the Phonebook model.

        * ``user`` - Foreign key relationship to the a User model. \
        Each campaign assigned to a User

        * ``voicemail_audiofile`` - Foreign key relationship to the a AudioFile model.

        * ``dnc`` - Foreign key relationship to the a DNC model.

    **Name of DB table**: dialer_campaign
    """
    campaign_code = models.CharField(
        unique=True,
        max_length=20,
        blank=True,
        verbose_name=_("campaign code"),
        help_text=
        _('this code is auto-generated by the platform, this is used to identify the campaign'
          ),
        default=(lambda: get_unique_code(length=5)))
    name = models.CharField(max_length=100, verbose_name=_('name'))
    description = models.TextField(verbose_name=_('description'),
                                   blank=True,
                                   null=True,
                                   help_text=_("campaign description"))
    user = models.ForeignKey('auth.User', related_name='Campaign owner')
    status = models.IntegerField(choices=list(CAMPAIGN_STATUS),
                                 default=CAMPAIGN_STATUS.PAUSE,
                                 verbose_name=_("status"),
                                 blank=True,
                                 null=True)
    callerid = models.CharField(max_length=80,
                                blank=True,
                                verbose_name=_("callerID"),
                                help_text=_("outbound caller-ID"))
    caller_name = models.CharField(max_length=80,
                                   blank=True,
                                   verbose_name=_("caller name"),
                                   help_text=_("outbound caller-Name"))
    #General Starting & Stopping date
    startingdate = models.DateTimeField(
        default=(lambda: datetime.now()),
        verbose_name=_('start'),
        help_text=_("date format: YYYY-mm-DD HH:MM:SS"))
    expirationdate = models.DateTimeField(
        default=(lambda: datetime.now() + relativedelta(days=+1)),
        verbose_name=_('finish'),
        help_text=_("date format: YYYY-mm-DD HH:MM:SS"))
    #Per Day Starting & Stopping Time
    daily_start_time = models.TimeField(default='00:00:00',
                                        verbose_name=_('daily start time'),
                                        help_text=_("time format: HH:MM:SS"))
    daily_stop_time = models.TimeField(default='23:59:59',
                                       verbose_name=_('daily stop time'),
                                       help_text=_("time format: HH:MM:SS"))
    monday = models.BooleanField(default=True, verbose_name=_('monday'))
    tuesday = models.BooleanField(default=True, verbose_name=_('tuesday'))
    wednesday = models.BooleanField(default=True, verbose_name=_('wednesday'))
    thursday = models.BooleanField(default=True, verbose_name=_('thursday'))
    friday = models.BooleanField(default=True, verbose_name=_('friday'))
    saturday = models.BooleanField(default=True, verbose_name=_('saturday'))
    sunday = models.BooleanField(default=True, verbose_name=_('sunday'))
    #Campaign Settings
    frequency = models.IntegerField(default='10',
                                    blank=True,
                                    null=True,
                                    verbose_name=_('frequency'),
                                    help_text=_("calls per minute"))
    callmaxduration = models.IntegerField(
        default='1800',
        blank=True,
        null=True,
        verbose_name=_('max call duration'),
        help_text=_("maximum call duration in seconds"))
    #max retry on failure - Note that the answered call not completed are counted
    maxretry = models.IntegerField(default='0',
                                   blank=True,
                                   null=True,
                                   verbose_name=_('max retries'),
                                   help_text=_("maximum retries per contact"))
    intervalretry = models.IntegerField(
        default='300',
        blank=True,
        null=True,
        verbose_name=_('time between retries'),
        help_text=_("time delay in seconds before retrying contact"))
    completion_maxretry = models.IntegerField(
        default='0',
        blank=True,
        null=True,
        verbose_name=_('completion max retries'),
        help_text=_("amount of retries until a contact is completed"))
    completion_intervalretry = models.IntegerField(
        default='900',
        blank=True,
        null=True,
        verbose_name=_('completion time between retries'),
        help_text=_(
            "time delay in seconds before retrying contact for completion"))
    calltimeout = models.IntegerField(
        default='45',
        blank=True,
        null=True,
        verbose_name=_('timeout on call'),
        help_text=_("connection timeout in seconds"))
    aleg_gateway = models.ForeignKey(Gateway,
                                     verbose_name=_("A-Leg gateway"),
                                     related_name="A-Leg Gateway",
                                     help_text=_("select outbound gateway"))
    content_type = models.ForeignKey(
        ContentType,
        verbose_name=_("type"),
        limit_choices_to={"model__in": ["survey_template"]})
    object_id = models.PositiveIntegerField(verbose_name=_("application"))
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    extra_data = models.CharField(
        max_length=120,
        blank=True,
        verbose_name=_("extra parameters"),
        help_text=_("additional application parameters."))
    phonebook = models.ManyToManyField(Phonebook, blank=True, null=True)
    imported_phonebook = models.CharField(max_length=500,
                                          default='',
                                          blank=True,
                                          verbose_name=_('imported phonebook'))
    totalcontact = models.IntegerField(
        default=0,
        blank=True,
        null=True,
        verbose_name=_('total contact'),
        help_text=_("total contact for this campaign"))
    completed = models.IntegerField(
        default=0,
        blank=True,
        null=True,
        verbose_name=_('completed'),
        help_text=_("total contact that completed call / survey"))
    #Flags
    has_been_started = models.BooleanField(default=False,
                                           verbose_name=_('has been started'))
    has_been_duplicated = models.BooleanField(
        default=False, verbose_name=_('has been duplicated'))
    dnc = models.ForeignKey(DNC,
                            null=True,
                            blank=True,
                            verbose_name=_("DNC"),
                            help_text=_("do not call list"),
                            related_name='DNC')
    #Voicemail
    voicemail = models.BooleanField(
        default=False, verbose_name=_('enable voicemail detection'))
    amd_behavior = models.IntegerField(choices=list(AMD_BEHAVIOR),
                                       default=AMD_BEHAVIOR.ALWAYS,
                                       verbose_name=_("detection behaviour"),
                                       blank=True,
                                       null=True)
    voicemail_audiofile = models.ForeignKey(
        AudioFile,
        null=True,
        blank=True,
        verbose_name=_("voicemail audio file"))

    created_date = models.DateTimeField(auto_now_add=True,
                                        verbose_name=_('date'))
    updated_date = models.DateTimeField(auto_now=True)

    objects = CampaignManager()

    def __unicode__(self):
        return u"%s" % (self.name)

    class Meta:
        permissions = (("view_campaign", _('can see campaign')),
                       ("view_dashboard", _('can see campaign dashboard')))
        db_table = u'dialer_campaign'
        verbose_name = _("campaign")
        verbose_name_plural = _("campaigns")

    def update_campaign_status(self):
        """Update the campaign's status

        For example,
        If campaign is active, you can change status to 'Pause' or 'Stop'
        """
        if self.status == CAMPAIGN_STATUS.START:
            return "<a href='%s'>Pause</a> | <a href='%s'>Abort</a> | <a href='%s'>Stop</a>" % \
                (reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.PAUSE]),
                 reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.ABORT]),
                 reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.END]))

        if self.status == CAMPAIGN_STATUS.PAUSE:
            return "<a href='%s'>Start</a> | <a href='%s'>Abort</a> | <a href='%s'>Stop</a>" % \
                (reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.START]),
                 reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.ABORT]),
                 reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.END]))

        if self.status == CAMPAIGN_STATUS.ABORT:
            return "<a href='%s'>Start</a> | <a href='%s'>Pause</a> | <a href='%s'>Stop</a>" % \
                (reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.START]),
                 reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.PAUSE]),
                 reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.END]))

        if self.status == CAMPAIGN_STATUS.END:
            return "<a href='%s'>Start</a> | <a href='%s'>Pause</a> | <a href='%s'>Abort</a>" % \
                (reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.START]),
                 reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.PAUSE]),
                 reverse('dialer_campaign.views.update_campaign_status_admin',
                         args=[self.pk, CAMPAIGN_STATUS.ABORT]))

    update_campaign_status.allow_tags = True
    update_campaign_status.short_description = _('action')

    def is_authorized_contact(self, dialersetting, str_contact):
        """Check if a contact is authorized"""
        return common_contact_authorization(dialersetting, str_contact)

    def get_campaign_type(self):
        """Get campaign type"""
        if self.content_type.name[0:6] == 'Survey':
            return ugettext('survey')
        return ugettext('voice app')

    def get_active_max_frequency(self):
        """Get the active max frequency"""
        try:
            obj_userprofile = self.user.get_profile()
        except UserProfile.DoesNotExist:
            return self.frequency

        max_frequency = obj_userprofile.dialersetting.max_frequency
        if max_frequency < self.frequency:
            return max_frequency

        return self.frequency

    def get_active_callmaxduration(self):
        """Get the active call max duration"""
        try:
            obj_userprofile = self.user.get_profile()
        except UserProfile.DoesNotExist:
            return self.frequency

        callmaxduration = obj_userprofile.dialersetting.callmaxduration
        if callmaxduration < self.callmaxduration:
            return callmaxduration

        return self.callmaxduration

    def get_active_contact(self):
        """Get all the active Contacts from the phonebook"""
        list_contact =\
            Contact.objects.filter(phonebook__campaign=self.id, status=CONTACT_STATUS.ACTIVE).all()
        if not list_contact:
            return False
        return list_contact

    def progress_bar(self):
        """Progress bar generated based on no of contacts"""
        # Cache subscriber_count
        count_contact = \
            Contact.objects.filter(phonebook__campaign=self.id).count()

        # Cache need to be set per campaign
        # subscriber_count_key_campaign_id_1
        subscriber_count = cache.get('subscriber_count_key_campaign_id_' +
                                     str(self.id))

        if subscriber_count is None:
            list_contact = Contact.objects.values_list('id', flat=True)\
                .filter(phonebook__campaign=self.id)

            subscriber_count = 0
            try:
                subscriber_count += Subscriber.objects\
                    .filter(contact__in=list_contact,
                            campaign=self.id,
                            status=SUBSCRIBER_STATUS.SENT)\
                    .count()
            except:
                pass

            cache.set("subscriber_count_key_campaign_id_%s" % str(self.id),
                      subscriber_count, 5)

        subscriber_count = int(subscriber_count)
        count_contact = int(count_contact)

        if count_contact > 0:
            percentage_pixel = \
                (float(subscriber_count) / count_contact) * 100
            percentage_pixel = int(percentage_pixel)
        else:
            percentage_pixel = 0
        subscriber_count_string = "subscribers (" + str(subscriber_count) + ")"
        return "<div title='%s' style='width: 100px; border: 1px solid #ccc;'><div style='height: 4px; width: %dpx; background: #555; '></div></div>" % \
            (subscriber_count_string, percentage_pixel)

    progress_bar.allow_tags = True
    progress_bar.short_description = _('progress')

    def subscriber_detail(self):
        """This will link to subscribers who are associated with
        the campaign"""
        model_name = Subscriber._meta.object_name.lower()
        app_label = self._meta.app_label
        link = '/admin/%s/%s/' % (app_label, model_name)
        link += '?campaign__id=%d' % self.id
        display_link = _("<a href='%(link)s'>%(name)s</a>") % \
            {'link': link, 'name': _('details')}
        return display_link

    subscriber_detail.allow_tags = True
    subscriber_detail.short_description = _('subscriber')

    # OPTIMIZATION - GOOD
    def get_pending_subscriber_update(self, limit, status):
        """Get all the pending subscribers from the campaign"""
        #TODO: Improve this part with a PL/SQL

        #We cannot use select_related here as it's not compliant with locking the rows
        list_subscriber = Subscriber.objects.select_for_update()\
            .filter(campaign=self.id, status=SUBSCRIBER_STATUS.PENDING)\
            .all()[:limit]
        if not list_subscriber:
            return (False, 0)
        id_list_sb = []
        count = 0
        for elem_subscriber in list_subscriber:
            count = count + 1
            id_list_sb.append(elem_subscriber.id)
        #Update in bulk
        Subscriber.objects.filter(id__in=id_list_sb).update(status=status)
        return (list_subscriber, count)
예제 #7
0
 def __init__(self, *args, **kwargs):
     super(CampaignAdminForm, self).__init__(*args, **kwargs)
     self.fields['campaign_code'].widget.attrs['readonly'] = True
     self.fields['campaign_code'].initial = get_unique_code(length=5)
예제 #8
0
    def __init__(self, user, *args, **kwargs):
        super(CampaignForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        self.fields['campaign_code'].initial = get_unique_code(length=5)
        self.fields['description'].widget.attrs['class'] = "input-xlarge"

        if user:
            self.fields['ds_user'].initial = user
            list_gw = []
            list_pb = []
            dnc_list = []

            list_pb.append((0, '---'))
            list = Phonebook.objects.values_list('id', 'name')\
                .filter(user=user).order_by('id')
            for l in list:
                list_pb.append((l[0], l[1]))
            self.fields['phonebook'].choices = list_pb

            list = user.get_profile().userprofile_gateway.all()
            gw_list = ((l.id, l.name) for l in list)

            dnc_list.append(('', '---'))
            list = DNC.objects.values_list('id', 'name')\
                .filter(user=user).order_by('id')
            for l in list:
                dnc_list.append((l[0], l[1]))
            self.fields['dnc'].choices = dnc_list

            for i in gw_list:
                list_gw.append((i[0], i[1]))
            self.fields['aleg_gateway'].choices = list_gw

            if instance.has_been_duplicated:
                from survey.models import Survey
                available_objects = Survey.objects.filter(user=user,
                                                          campaign=instance)
                object_choices = get_object_choices(available_objects)
                self.fields['content_object'].widget.attrs['readonly'] = True
            else:
                from survey.models import Survey_template
                available_objects = Survey_template.objects.filter(user=user)
                object_choices = get_object_choices(available_objects)

            self.fields['content_object'].choices = object_choices

            # Voicemail setting is not enabled by default
            if settings.AMD:
                from survey.forms import get_audiofile_list
                self.fields[
                    'voicemail_audiofile'].choices = get_audiofile_list(user)

        # if campaign is running
        if instance.status == CAMPAIGN_STATUS.START:
            self.fields['name'].widget.attrs['readonly'] = True
            self.fields['caller_name'].widget.attrs['readonly'] = True
            self.fields['callerid'].widget.attrs['readonly'] = True
            self.fields['extra_data'].widget.attrs['readonly'] = True
            self.fields['phonebook'].widget.attrs['disabled'] = 'disabled'

            selected_phonebook = ''
            if instance.phonebook.all():
                selected_phonebook = \
                    ",".join(["%s" % (i.id) for i in instance.phonebook.all()])
            self.fields['selected_phonebook'].initial = selected_phonebook

            self.fields['content_object'].widget.attrs['disabled'] = 'disabled'
            self.fields['content_object'].required = False
            self.fields['selected_content_object'].initial = "type:%s-id:%s" \
                % (instance.content_type.id, instance.object_id)