def create_outage(request): """ Create a reservation for a user. """ try: start, end = extract_times(request.POST) except Exception as e: return HttpResponseBadRequest(str(e)) tool = get_object_or_404(Tool, name=request.POST.get('tool_name')) # Create the new reservation: outage = ScheduledOutage() outage.creator = request.user outage.category = request.POST.get('category', '')[:200] outage.tool = tool outage.start = start outage.end = end # If there was a problem in saving the reservation then return the error... policy_problem = check_policy_to_create_outage(outage) if policy_problem: return HttpResponseBadRequest(policy_problem) # Make sure there is at least an outage title if not request.POST.get('title'): dictionary = {'categories': ScheduledOutageCategory.objects.all()} return render(request, 'calendar/scheduled_outage_information.html', dictionary) outage.title = request.POST['title'] outage.details = request.POST.get('details', '') outage.save() return HttpResponse()
def past_comments_and_tasks(request): start, end = extract_times(request.GET, start_required=False, end_required=False) search = request.GET.get("search") if not start and not end and not search: return HttpResponseBadRequest( "Please enter a search keyword, start date or end date.") tool_id = request.GET.get("tool_id") try: tasks = Task.objects.filter(tool_id=tool_id) comments = Comment.objects.filter(tool_id=tool_id, staff_only=False) if start: tasks = tasks.filter(creation_time__gt=start) comments = comments.filter(creation_date__gt=start) if end: tasks = tasks.filter(creation_time__lt=end) comments = comments.filter(creation_date__lt=end) if search: tasks = tasks.filter(problem_description__icontains=search) comments = comments.filter(content__icontains=search) except: return HttpResponseBadRequest("Task and comment lookup failed.") past = list(chain(tasks, comments)) past.sort(key=lambda x: getattr(x, "creation_time", None) or getattr( x, "creation_date", None)) past.reverse() dictionary = {"past": past} return render(request, "tool_control/past_tasks_and_comments.html", dictionary)
def create_reservation(request): """ Create a reservation for a user. """ try: start, end = extract_times(request.POST) item_type = request.POST['item_type'] item_id = request.POST.get('item_id') except Exception as e: return HttpResponseBadRequest(str(e)) return create_item_reservation(request, start, end, ReservationItemType(item_type), item_id)
def past_comments_and_tasks(request): try: start, end = extract_times(request.GET) except: return HttpResponseBadRequest('Please enter a start and end date.') tool_id = request.GET.get('tool_id') try: tasks = Task.objects.filter(tool_id=tool_id, creation_time__gt=start, creation_time__lt=end) comments = Comment.objects.filter(tool_id=tool_id, creation_date__gt=start, creation_date__lt=end) except: return HttpResponseBadRequest('Task and comment lookup failed.') past = list(chain(tasks, comments)) past.sort(key=lambda x: getattr(x, 'creation_time', None) or getattr(x, 'creation_date', None)) past.reverse() dictionary = { 'past': past, } return render(request, 'tool_control/past_tasks_and_comments.html', dictionary)
def usage_data_history(request, tool_id): """ This method return a dictionary of headers and rows containing run_data information for Usage Events """ csv_export = bool(request.POST.get("csv", False)) start, end = extract_times(request.POST, start_required=False, end_required=False) last = request.POST.get("data_history_last") user_id = request.POST.get("data_history_user_id") if not last and not start and not end: # Default to last 25 records last = 25 usage_events = UsageEvent.objects.filter( tool_id=tool_id, end__isnull=False).order_by("-end") if start: usage_events = usage_events.filter( end__gte=beginning_of_the_day(start)) if end: usage_events = usage_events.filter(end__lte=end_of_the_day(end)) if user_id: try: usage_events = usage_events.filter(user_id=int(user_id)) except ValueError: pass if last: try: last = int(last) except ValueError: last = 25 usage_events = usage_events[:last] table_result = BasicDisplayTable() table_result.add_header(("user", "User")) table_result.add_header(("date", "Date")) for usage_event in usage_events: if usage_event.run_data: usage_data = {} try: user_data = f"{usage_event.user.first_name} {usage_event.user.last_name}" date_data = usage_event.end.astimezone( timezone.get_current_timezone()).strftime( "%m/%d/%Y @ %I:%M %p") run_data: Dict = loads(usage_event.run_data) for question_key, question in run_data.items(): if "user_input" in question: if question["type"] == "group": for sub_question in question["questions"]: table_result.add_header( (sub_question["name"], sub_question["title"])) for index, user_inputs in question[ "user_input"].items(): if index == "0": # Special case here the "initial" group of user inputs will go along with the rest of the non-group user inputs for name, user_input in user_inputs.items( ): usage_data[name] = user_input else: # For the other groups of user inputs, we have to add a whole new row group_usage_data = {} for name, user_input in user_inputs.items( ): group_usage_data[name] = user_input if group_usage_data: group_usage_data["user"] = user_data group_usage_data["date"] = date_data table_result.add_row(group_usage_data) else: table_result.add_header( (question_key, question["title"])) usage_data[question_key] = question["user_input"] if usage_data: usage_data["user"] = user_data usage_data["date"] = date_data table_result.add_row(usage_data) except JSONDecodeError: tool_control_logger.debug("error decoding run_data: " + usage_event.run_data) if csv_export: response = table_result.to_csv() filename = f"tool_usage_data_export_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.csv" response["Content-Disposition"] = f'attachment; filename="{filename}"' return response else: dictionary = { "tool_id": tool_id, "data_history_start": start, "data_history_end": end, "data_history_last": str(last), "usage_data_table": table_result, "data_history_user": User.objects.get(id=user_id) if user_id else None, "users": User.objects.filter(is_active=True) } return render(request, "tool_control/usage_data.html", dictionary)
def create_reservation(request): """ Create a reservation for a user. """ try: start, end = extract_times(request.POST) except Exception as e: return HttpResponseBadRequest(str(e)) tool = get_object_or_404(Tool, name=request.POST.get('tool_name')) explicit_policy_override = False if request.user.is_staff: try: user = User.objects.get(id=request.POST['impersonate']) except: user = request.user try: explicit_policy_override = request.POST[ 'explicit_policy_override'] == 'true' except: pass else: user = request.user # Create the new reservation: new_reservation = Reservation() new_reservation.user = user new_reservation.creator = request.user new_reservation.tool = tool new_reservation.start = start new_reservation.end = end new_reservation.short_notice = determine_insufficient_notice(tool, start) policy_problems, overridable = check_policy_to_save_reservation( None, new_reservation, user, explicit_policy_override) # If there was a problem in saving the reservation then return the error... if policy_problems: return render( request, 'calendar/policy_dialog.html', { 'policy_problems': policy_problems, 'overridable': overridable and request.user.is_staff }) # All policy checks have passed. # If the user only has one project then associate it with the reservation. # Otherwise, present a dialog box for the user to choose which project to associate. active_projects = user.active_projects() if len(active_projects) == 1: new_reservation.project = active_projects[0] else: try: new_reservation.project = Project.objects.get( id=request.POST['project_id']) except: return render(request, 'calendar/project_choice.html', {'active_projects': active_projects}) # Make sure the user is actually enrolled on the project. We wouldn't want someone # forging a request to reserve against a project they don't belong to. if new_reservation.project not in new_reservation.user.active_projects(): return render(request, 'calendar/project_choice.html', {'active_projects': active_projects()}) configured = (request.POST.get('configured') == "true") # If a reservation is requested and the tool does not require configuration... if not tool.is_configurable(): new_reservation.save() return HttpResponse() # If a reservation is requested and the tool requires configuration that has not been submitted... elif tool.is_configurable() and not configured: configuration_information = tool.get_configuration_information( user=user, start=start) return render(request, 'calendar/configuration.html', configuration_information) # If a reservation is requested and configuration information is present also... elif tool.is_configurable() and configured: new_reservation.additional_information, new_reservation.self_configuration = extract_configuration( request) # Reservation can't be short notice if the user is configuring the tool themselves. if new_reservation.self_configuration: new_reservation.short_notice = False new_reservation.save() return HttpResponse() return HttpResponseBadRequest( "Reservation creation failed because invalid parameters were sent to the server." )
def create_outage(request): """ Create an outage. """ try: start, end = extract_times(request.POST) item_type = ReservationItemType(request.POST['item_type']) item_id = request.POST.get('item_id') except Exception as e: return HttpResponseBadRequest(str(e)) item = get_object_or_404(item_type.get_object_class(), id=item_id) # Create the new reservation: outage = ScheduledOutage() outage.creator = request.user outage.category = request.POST.get('category', '')[:200] outage.outage_item = item outage.start = start outage.end = end # If there is a policy problem for the outage then return the error... policy_problem = check_policy_to_create_outage(outage) if policy_problem: return HttpResponseBadRequest(policy_problem) # Make sure there is at least an outage title if not request.POST.get('title'): dictionary = { 'categories': ScheduledOutageCategory.objects.all(), 'recurrence_intervals': recurrence_frequency_display, 'recurrence_date_start': start.date(), } return render(request, 'calendar/scheduled_outage_information.html', dictionary) outage.title = request.POST['title'] outage.details = request.POST.get('details', '') if request.POST.get('recurring_outage') == 'on': # we have to remove tz before creating rules otherwise 8am would become 7am after DST change for example. start_no_tz = outage.start.replace(tzinfo=None) end_no_tz = outage.end.replace(tzinfo=None) submitted_frequency = request.POST.get('recurrence_frequency') submitted_date_until = request.POST.get('recurrence_until', None) date_until = end.replace(hour=0, minute=0, second=0) if submitted_date_until: date_until = localize(datetime.strptime(submitted_date_until, '%m/%d/%Y')) date_until += timedelta(days=1, seconds=-1) # set at the end of the day by_week_day = None if submitted_frequency == 'DAILY_WEEKDAYS': by_week_day = (rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR) elif submitted_frequency == 'DAILY_WEEKENDS': by_week_day = (rrule.SA, rrule.SU) frequency = recurrence_frequencies.get(submitted_frequency, rrule.DAILY) rules: Iterable[datetime] = rrule.rrule(dtstart=start, freq=frequency, interval=int(request.POST.get('recurrence_interval',1)), until=date_until, byweekday=by_week_day) for rule in list(rules): recurring_outage = ScheduledOutage() recurring_outage.creator = outage.creator recurring_outage.category = outage.category recurring_outage.outage_item = outage.outage_item recurring_outage.title = outage.title recurring_outage.details = outage.details recurring_outage.start = localize(start_no_tz.replace(year=rule.year, month=rule.month, day=rule.day)) recurring_outage.end = localize(end_no_tz.replace(year=rule.year, month=rule.month, day=rule.day)) recurring_outage.save() else: outage.save() return HttpResponse()