def gather_answer_email_context(answer): site = Site.objects.get_current() if answer.created_by.company == 'Gluu': support_plan = "Staff" else: plan = get_support_plan(answer.created_by) if not plan or not plan['support_plan']: support_plan = "Community" else: support_plan = plan['support_plan'] ticket_link = '{}#at{}'.format(generate_ticket_url(answer.ticket), answer.id) context = { 'site_name': site.name, 'ticket_id': answer.ticket.id, 'ticket_title': answer.ticket.title, 'support_plan': support_plan, 'ticket_link': ticket_link, 'answer_created_by': answer.created_by, 'answer_created_by_comp': answer.created_by.get_company(), 'answer_body': answer.answer, 'subscription_link': generate_subscribe_link(answer.ticket) } return context
def get_support_details(request): if request.user.is_named: company = request.user.company_association support_plan = crm_interface.get_support_plan(request.user) if support_plan: cmp = Company.objects.get(id=company.id) if cmp.entitlements != "[]": response = json.loads(cmp.entitlements) available_support_time = response['support_hours'] available_review_time = response['review_hours'] support_plan['named_contacts'] = response['named_contacts'] support_plan['available_support_time'] = available_support_time support_plan['available_review_time'] = available_review_time support_plan['remaining_support_time'] = format_minutes( (available_support_time * 60) - get_spent_meeting_minutes( company, 'SUP', support_plan['start_date'])) support_plan['remaining_review_time'] = format_minutes( (available_review_time * 60) - get_spent_meeting_minutes( company, 'REV', support_plan['start_date'])) return support_plan else: return [] else: return []
def support_plan(self): plan = get_support_plan(self.created_by) support_level = 'Community' if plan: if plan['support_plan'] == 'blank': support_level = "Community" else: support_level = plan['support_plan'] return support_level
def handle(self, *args, **options): staff_users = UserProfile.objects.filter( is_active=True, crm_type__in=[constants.STAFF, constants.ADMIN, constants.MANAGER] ) for user in staff_users: tickets = Ticket.objects.filter( assigned_to=user, is_deleted=False, status__in=['pending', 'inprogress', 'assigned']).order_by('date_modified') named_tickets = [] community_tickets = [] if not tickets: continue for ticket in tickets: if ticket.owned_by.is_named: if not ticket.issue_type: logger.error('Named ticket without issue type: {}'.format(ticket.id)) ticket.support_plan = crm_interface.get_support_plan(ticket.owned_by) if not ticket.support_plan or not ticket.support_plan['support_plan']: logger.error('Named ticket without support plan: {}'.format(ticket.id)) ticket.is_overdue = ticket.date_modified < timezone.now() - timedelta(days=10) named_tickets.append(ticket) else: community_tickets.append(ticket) context = { 'base_url': get_base_url(), 'user': user, 'community_tickets': community_tickets, 'named_tickets': named_tickets, 'tickets_count': tickets.count() } logger.info(u'Daily digest sent to staff {}'.format(user.email)) send_mail( subject_template_name='emails/reminders/staff_digest_subject.txt', email_template_name='emails/reminders/staff_digest.txt', to_email=user.email, context=context, html_email_template_name='emails/reminders/staff_digest.html', bcc=settings.DEFAULT_RECIPIENT_IDLE_TICKET_REMINDERS )
def handle(self, *arg, **option): try: tickets = Ticket.objects.filter( is_deleted=False, issue_type__in=['outage', 'impaired'], status__in=['pending', 'inprogress', 'assigned', 'new'], ) account_sid = "Your twilio account sid" auth_token = "Your twilio auth token" client = Client(account_sid, auth_token) for ticket in tickets: support_plan = get_support_plan(ticket.created_by) if support_plan: support_level = support_plan.get('support_plan') if support_level == "Enterprise" and ticket.issue_type == "outage": self.send_notification(5, ticket.issue_type, client, ticket) elif support_level == "Premium" and ticket.issue_type == "outage": self.send_notification(30, ticket.issue_type, client, ticket) elif support_level == "Standard" and ticket.issue_type == "outage": self.send_notification(60, ticket.issue_type, client, ticket) elif support_level == "Basic" and ticket.issue_type == "outage": self.send_notification(120, ticket.issue_type, client, ticket) elif support_level == "Enterprise" and ticket.issue_type == "impaired": self.send_notification(30, ticket.issue_type, client, ticket) elif support_level == "Premium" and ticket.issue_type == "impaired": self.send_notification(30, ticket.issue_type, client, ticket) elif support_level == "Standard" and ticket.issue_type == "impaired": self.send_notification(120, ticket.issue_type, client, ticket) elif support_level == "Basic" and ticket.issue_type == "impaired": self.send_notification(120, ticket.issue_type, client, ticket) else: continue except Exception as e: pass
def handle(self, *args, **options): if options['notify_email']: notify_email = True else: notify_email = False tickets = Ticket.objects.filter( status__in=['new', 'assigned'], issue_type='outage', is_deleted=False ) for ticket in tickets: if ticket.owned_by.is_admin: continue if ticket.owned_by.is_basic: log_emails('New Ticket Reminder: Ticket with issue type by basic user {}'.format( ticket.id), 'ERROR') continue support_plan = get_support_plan(ticket.owned_by) if not support_plan or not support_plan['support_plan']: log_emails('New Ticket Reminder Outage: No support plan found for {}'.format( ticket.owned_by.get_company()), 'ERROR') continue if support_plan['managed_service'] == 1: support_plan = 'Enterprise' else: support_plan = support_plan['support_plan'] sla_time_delta = SLA_MATRIX_NEW[support_plan]['outage'] if ticket.last_updated_at < timezone.now() - timedelta(minutes=sla_time_delta): send_new_ticket_reminder(ticket, support_plan, notify_email)
def dashboard(request, page_type=''): u = request.user q = [Q(is_deleted=False)] exq = [] filter_by_page = [] columns = [ 'id', 'title', 'ticket_category', 'status', 'issue_type', 'date_added', 'assigned_to__first_name' ] order_dash = ['-id'] if page_type == 'my-assignments' and u.is_admin: q.append(Q(assigned_to=u)) exq.append(Q(status='closed')) elif page_type == 'in-progress-tickets' and u.is_admin: q.append(Q(assigned_to=u) & Q(status="inprogress")) elif page_type == 'pending-tickets' and u.is_admin: q.append(Q(assigned_to=u) & Q(status="pending")) elif page_type == 'unassigned' and u.is_admin: q.append(Q(assigned_to__isnull=True)) exq.append(Q(status='closed')) elif page_type == 'open-tickets' and u.is_admin: exq.append(Q(status='closed')) elif page_type == 'closed-tickets' and u.is_admin: q.append(Q(status='closed')) elif page_type == 'my-alerts': q.append(Q(ticket_alerts__user=u)) elif page_type == 'my-tickets': q.append((Q(created_by=u) & Q(created_for=None)) | Q(created_for=u)) elif page_type == 'my-named-tickets' and u.is_named: q.append(Q(company_association=u.company_association)) elif page_type == 'named-open-tickets' and u.is_named: q.append(Q(company_association=u.company_association)) exq.append(Q(status='closed')) elif page_type == 'named-closed-tickets' and u.is_named: q.append( Q(company_association=u.company_association) & Q(status='closed')) elif page_type == 'my-open-tickets': q.append((Q(created_by=u) & Q(created_for=None)) | Q(created_for=u)) exq.append(Q(status='closed')) elif page_type == 'my-closed-tickets': q.append(((Q(created_by=u) & Q(created_for=None)) | Q(created_for=u)) & Q(status='closed')) elif page_type == 'partner-tickets': client = request.GET.get('partner', None) if client: q.append(Q(company_association__name=client)) elif page_type == 'company-users': return add_company_user(request) elif page_type == 'company-partners': return add_company_partner(request) elif page_type == 'company-booking': return book_meeting(request) elif page_type == 'my-profile': return my_profile(request) elif page_type == 'oxd-config': return oxd_form(request) elif page_type == 'all-tickets' and u.is_admin: pass elif page_type == 'view-users' and u.is_admin: return view_users(request, page_type) else: messages.error(request, _('You are not authorized to see requested page!')) return HttpResponseRedirect( reverse('profile:dashboard', kwargs={'page_type': 'my-tickets'})) filters = FilterTicketsForm(request.GET, user=request.user) if filters.is_valid(): if filters.cleaned_data['named']: q.append((Q(created_by__crm_type='named') & Q(created_for=None)) | Q(created_for__crm_type='named')) if filters.cleaned_data['status']: q.append(Q(status__in=filters.cleaned_data['status'])) if filters.cleaned_data['category']: q.append(Q(ticket_category__in=filters.cleaned_data['category'])) if filters.cleaned_data['issue_type']: if 'community' in filters.cleaned_data['issue_type']: q.append( Q(issue_type__in=filters.cleaned_data['issue_type']) | Q(issue_type='')) else: q.append(Q(issue_type__in=filters.cleaned_data['issue_type'])) if filters.cleaned_data['company']: q.append( (Q(created_by__company__in=filters.cleaned_data['company']) & Q(created_for=None)) | Q(created_for__company__in=filters.cleaned_data['company'])) if filters.cleaned_data['assigned_to']: q.append(Q(assigned_to__in=filters.cleaned_data['assigned_to'])) if filters.cleaned_data['created_by']: q.append((Q(created_by__in=filters.cleaned_data['created_by']) & Q(created_for=None)) | Q(created_for__in=filters.cleaned_data['created_by'])) if filters.cleaned_data['created_date'] or filters.cleaned_data[ 'created_filters']: dd = filters.cleaned_data['created_date'] now = timezone.now() today = now.date() if filters.cleaned_data['created_filters'] == "eq" and dd: s, f = cstm_dates(dd, dd) q.append(Q(date_added__gte=s) & Q(date_added__lte=f)) if filters.cleaned_data['created_filters'] == "not_eq" and dd: s, f = cstm_dates(dd, dd) q.append(Q(date_added__lt=s) & Q(date_added__gt=f)) if filters.cleaned_data['created_filters'] == "gt" and dd: q.append(Q(date_added__gt=dd)) if filters.cleaned_data['created_filters'] == "lt" and dd: q.append(Q(date_added__lt=dd)) if filters.cleaned_data['created_filters'] == "last_7_days": last_7_days = now.date() - timedelta(days=7) s, f = cstm_dates(last_7_days, today) q.append(Q(date_added__gte=s) & Q(date_added__lte=f)) if filters.cleaned_data['created_filters'] == "last_30_days": last_30_days = now.date() - timedelta(days=30) s, f = cstm_dates(last_30_days, today) q.append(Q(date_added__gte=s) & Q(date_added__lte=f)) if filters.cleaned_data['created_filters'] == "last_month": first_last_month = today.replace(month=today.month - 1, day=1) last_last_month = today.replace(month=today.month, day=1) s, f = cstm_dates(first_last_month, last_last_month) q.append(Q(date_added__gte=s) & Q(date_added__lt=f)) if filters.cleaned_data['created_filters'] == "this_month": this_month = today.replace(day=1) next_month = today.replace(month=today.month + 1, day=1) s, f = cstm_dates(this_month, next_month) q.append(Q(date_added__gte=s) & Q(date_added__lte=f)) if filters.cleaned_data['created_filters'] == "last_year": last_year = today.replace(year=today.year - 1, month=1, day=1) q.append(Q(date_added__year=last_year.year)) if filters.cleaned_data['created_filters'] == "this_year": q.append(Q(date_added__year=today.year)) filter_by_page = q # TODO Decouple from the rest if request.method == 'POST': user_filters = [] if 'search[value]' in request.POST and len( request.POST['search[value]']) >= 3: search_value = request.POST['search[value]'].strip() if len(search_value) == 3 and len(search_value.split(' ')) > 1: for word in search_value.split(' '): user_filters.extend([ (Q(created_by__first_name=word) & Q(created_for=None)) | Q(created_for__first_name=word) | (Q(created_by__last_name=word) & Q(created_for=None)) | Q(created_for__last_name=word) | Q(assigned_to__first_name=word) ]) else: q.extend([ Q(id__icontains=request.POST['search[value]']) | (Q(created_by__first_name=request.POST['search[value]']) & Q(created_for=None)) | Q(created_for__first_name=request.POST['search[value]']) | (Q(created_by__last_name=request.POST['search[value]']) & Q(created_for=None)) | Q(created_for__last_name=request.POST['search[value]']) | (Q(created_by__email__icontains=search_value) & Q(created_for=None)) | Q(created_for__email__icontains=search_value) | Q(ticket_category=request.POST['search[value]']) | Q(status__icontains=request.POST['search[value]']) | Q(issue_type__icontains=request.POST['search[value]']) | Q(title__icontains=request.POST['search[value]']) | Q(assigned_to__first_name__icontains=request. POST['search[value]']) # Q(["CONCAT_WS(' ', profiles_userprofile.first_name, profiles_userprofile.last_name) like '"+request.POST['search[value]']+"' "]) ]) if 'order[0][column]' in request.POST: order_sign = '-' if request.POST['order[0][dir]'] == 'desc' else '' order_dash = [ '%s%s' % (order_sign, columns[int(request.POST['order[0][column]'])]) ] results = { "draw": request.POST['draw'], "recordsTotal": 0, "recordsFiltered": int(request.POST['length']), "data": [] } cur = int(request.POST['start']) cur_length = int(request.POST['length']) + cur if len(user_filters) > 1: tickets = Ticket.objects.get_active(u).filter(*q).exclude( *exq).filter(*user_filters).order_by( *order_dash)[cur:cur_length] else: tickets = Ticket.objects.get_active(u).filter(*q).exclude( *exq).order_by(*order_dash)[cur:cur_length] if len(user_filters) > 1: results['recordsTotal'] = Ticket.objects.get_active(u).filter( *filter_by_page).exclude(*exq).filter(*user_filters).count() results['recordsFiltered'] = Ticket.objects.get_active(u).filter( *q).exclude(*exq).filter(*user_filters).count() else: results['recordsTotal'] = Ticket.objects.get_active(u).filter( *filter_by_page).exclude(*exq).count() results['recordsFiltered'] = Ticket.objects.get_active(u).filter( *q).exclude(*exq).count() staff = UserProfile.objects.filter( is_active=True, crm_type__in=['staff', 'admin', 'manager']) for t in tickets: support_level = "" support_plan = crm_interface.get_support_plan(t.owned_by) if support_plan: support_level = support_plan.get('support_plan') if support_level == "blank": support_level = "Community" else: if t.owned_by.get_company() == "Gluu": support_level = "Staff" else: support_level = "Community" ht = '' description = u''' <a style="display:block;font-size:15px;word-break: break-all;" href="{0}">{1}</a> by {2} <span data-toggle="tooltip" class="glyphicon glyphicon-info-sign" title="Company: {3} <br /> Support Level: {4} <br /> Last update by: {5} <br /> Last update: {6} <br /> Total responses: {7}"> </span>'''.format(generate_ticket_link(t), t.title, t.owned_by, t.owned_by.get_company(), support_level, t.last_updated, get_fancy_time(t.date_modified), t.answers_no) if u.is_admin: ht = u'''<select data-ticket={0} class="dashboard_assign_staff" style="width:100px;" name="assigned_to"> <option selected value="">Assign ticket</option>'''.format( t.id) for u in staff: selected = '' if t.assigned_to == u: selected = 'selected' ht += u'''<option {0} value="{1}">{2}</option>'''.format( selected, u.id, u) ht += '</select>' row = [ t.id, description, t.get_ticket_category_display(), '<span class="label-table label-{0}">{1}</span>'.format( t.status.lower(), t.status), '<span class="label-table label-{0}">{1}</span>'.format( t.priority, t.priority), '{:%m-%d-%Y}'.format(t.date_added) ] if ht != '': row.append(ht) results["data"].append(row) return HttpResponse(json.dumps(results), content_type="application/json") clients = Company.objects.filter( clients__is_deleted=False, clients__partner=request.user.company_association) support_details = {} try: support_details = utils.get_support_details(request) except (KeyError, TypeError) as e: log_crm( 'Unexpected support plan value: {}, {}'.format(support_details, e), 'ERROR') pass return render( request, 'profiles/dashboard.html', { 'page': 'dashboard', 'filters_form': filters, 'page_type': page_type, 'clients': clients, 'support_details': support_details })