def create_project(request): mapper = ProjectAllocationMapper(request) form_args = {"request": request} user = mapper.get_user(request.user.username) if user["piEligibility"].lower() != "eligible": messages.error( request, "Only PI Eligible users can create new projects. " "If you would like to request PI Eligibility, please " '<a href="/user/profile/edit/">submit a PI Eligibility ' "request</a>.", ) return HttpResponseRedirect(reverse("projects:user_projects")) if request.POST: form = ProjectCreateForm(request.POST, **form_args) if form.is_valid(): # title, description, typeId, fieldId project = form.cleaned_data.copy() # let's check that any provided nickname is unique project["nickname"] = project["nickname"].strip() nickname_valid = (project["nickname"] and ProjectExtras.objects.filter( nickname=project["nickname"]).count() < 1 and Project.objects.filter( nickname=project["nickname"]).count() < 1) if not nickname_valid: form.add_error("__all__", "Project nickname unavailable") return render(request, "projects/create_project.html", {"form": form}) project.pop("accept_project_terms", None) # pi pi_user_id = mapper.get_portal_user_id(request.user.username) project["piId"] = pi_user_id # allocations allocation = { "resourceId": 39, "requestorId": pi_user_id, "computeRequested": 20000, } supplemental_details = project.pop("supplemental_details", None) funding_source = project.pop("funding_source", None) # if supplemental_details == None: # raise forms.ValidationError("Justifcation is required") if not supplemental_details: supplemental_details = "(none)" if funding_source: allocation[ "justification"] = "%s\n\n--- Funding source(s) ---\n\n%s" % ( supplemental_details, funding_source, ) else: allocation["justification"] = supplemental_details project["allocations"] = [allocation] # startup project["typeId"] = 2 # source project["source"] = "Chameleon" try: created_project = mapper.save_project(project, request.get_host()) logger.info("newly created project: " + json.dumps(created_project)) messages.success(request, "Your project has been created!") return HttpResponseRedirect( reverse("projects:view_project", args=[created_project["id"]])) except: logger.exception("Error creating project") form.add_error( "__all__", "An unexpected error occurred. Please try again") else: form.add_error( "__all__", "There were errors processing your request. " "Please see below for details.", ) else: form = ProjectCreateForm(**form_args) return render(request, "projects/create_project.html", {"form": form})
def create_allocation(request, project_id, allocation_id=-1): mapper = ProjectAllocationMapper(request) user = mapper.get_user(request.user.username) if user["piEligibility"].lower() != "eligible": messages.error( request, "Only PI Eligible users can request allocations. If you would " "like to request PI Eligibility, please " '<a href="/user/profile/edit/">submit a PI Eligibility ' "request</a>.", ) return HttpResponseRedirect(reverse("projects:user_projects")) project = mapper.get_project(project_id) allocation = None allocation_id = int(allocation_id) if allocation_id > 0: for a in project.allocations: if a.id == allocation_id: allocation = a # goofiness that we should clean up later; requires data cleansing abstract = project.description if "--- Supplemental details ---" in abstract: additional = abstract.split("\n\n--- Supplemental details ---\n\n") abstract = additional[0] additional = additional[1].split("\n\n--- Funding source(s) ---\n\n") justification = additional[0] if len(additional) > 1: funding_source = additional[1] else: funding_source = "" elif allocation: justification = allocation.justification if "--- Funding source(s) ---" in justification: parts = justification.split("\n\n--- Funding source(s) ---\n\n") justification = parts[0] funding_source = parts[1] else: funding_source = "" else: justification = "" funding_source = "" if request.POST: form = AllocationCreateForm( request.POST, initial={ "description": abstract, "supplemental_details": justification, "funding_source": funding_source, }, ) if form.is_valid(): allocation = form.cleaned_data.copy() allocation["computeRequested"] = 20000 # Also update the project project.description = allocation.pop("description", None) supplemental_details = allocation.pop("supplemental_details", None) logger.error(supplemental_details) funding_source = allocation.pop("funding_source", None) # if supplemental_details == None: # raise forms.ValidationError("Justifcation is required") # This is required if not supplemental_details: supplemental_details = "(none)" logger.error(supplemental_details) if funding_source: allocation[ "justification"] = "%s\n\n--- Funding source(s) ---\n\n%s" % ( supplemental_details, funding_source, ) else: allocation["justification"] = supplemental_details allocation["projectId"] = project_id allocation["requestorId"] = mapper.get_portal_user_id( request.user.username) allocation["resourceId"] = "39" if allocation_id > 0: allocation["id"] = allocation_id try: logger.info( "Submitting allocation request for project %s: %s" % (project.id, allocation)) updated_project = mapper.save_project(project.as_dict()) mapper.save_allocation(allocation, project.chargeCode, request.get_host()) messages.success( request, "Your allocation request has been submitted!") return HttpResponseRedirect( reverse("projects:view_project", args=[updated_project["id"]])) except: logger.exception("Error creating allocation") form.add_error( "__all__", "An unexpected error occurred. Please try again") else: form.add_error( "__all__", "There were errors processing your request. " "Please see below for details.", ) else: form = AllocationCreateForm( initial={ "description": abstract, "supplemental_details": justification, "funding_source": funding_source, }) context = { "form": form, "project": project, "alloc_id": allocation_id, "alloc": allocation, } return render(request, "projects/create_allocation.html", context)
def create_allocation(request, project_id, allocation_id=-1): mapper = ProjectAllocationMapper(request) user = mapper.get_user(request.user.username) if user["piEligibility"].lower() != "eligible": messages.error( request, "Only PI Eligible users can request allocations. If you would " "like to request PI Eligibility, please " '<a href="/user/profile/edit/">submit a PI Eligibility ' "request</a>.", ) return HttpResponseRedirect(reverse("projects:user_projects")) project = mapper.get_project(project_id) allocation = None allocation_id = int(allocation_id) if allocation_id > 0: for a in project.allocations: if a.id == allocation_id: allocation = a abstract = project.description if allocation: justification = allocation.justification else: justification = "" funding_source = [ model_to_dict(f) for f in Funding.objects.filter(project__id=project_id, is_active=True) ] # add extra form funding_source.append({}) if request.POST: form = AllocationCreateForm( request.POST, initial={ "description": abstract, "justification": justification, }, ) formset = FundingFormset( request.POST, initial=funding_source, ) consent_form = ConsentForm(request.POST) if form.is_valid() and formset.is_valid() and consent_form.is_valid(): allocation = form.cleaned_data.copy() allocation["computeRequested"] = 20000 # Also update the project and fundings project.description = allocation.pop("description", None) justification = allocation.pop("justification", None) allocation["projectId"] = project_id allocation["requestorId"] = mapper.get_portal_user_id( request.user.username) allocation["resourceId"] = "39" allocation["justification"] = justification if allocation_id > 0: allocation["id"] = allocation_id try: logger.info( "Submitting allocation request for project %s: %s" % (project.id, allocation)) with transaction.atomic(): updated_project = mapper.save_project(project.as_dict()) mapper.save_allocation(allocation, project.chargeCode, request.get_host()) new_funding_source = _save_fundings(formset, project_id) _remove_fundings(funding_source, new_funding_source) messages.success( request, "Your allocation request has been submitted!") return HttpResponseRedirect( reverse("projects:view_project", args=[updated_project["id"]])) except: logger.exception("Error creating allocation") form.add_error( "__all__", "An unexpected error occurred. Please try again") else: form.add_error( "__all__", "There were errors processing your request. " "Please see below for details.", ) else: form = AllocationCreateForm(initial={ "description": abstract, "justification": justification, }) formset = FundingFormset(initial=funding_source) consent_form = ConsentForm() context = { "form": form, "funding_formset": formset, "consent_form": consent_form, "project": project, "alloc_id": allocation_id, "alloc": allocation, } return render(request, "projects/create_allocation.html", context)
def create_project(request): mapper = ProjectAllocationMapper(request) form_args = {"request": request} user = mapper.get_user(request.user.username) if user["piEligibility"].lower() != "eligible": messages.error( request, "Only PI Eligible users can create new projects. " "If you would like to request PI Eligibility, please " '<a href="/user/profile/edit/">submit a PI Eligibility ' "request</a>.", ) return HttpResponseRedirect(reverse("projects:user_projects")) if request.POST: form = ProjectCreateForm(request.POST, **form_args) allocation_form = AllocationCreateForm( request.POST, initial={"publication_up_to_date": True}) allocation_form.fields[ "publication_up_to_date"].widget = forms.HiddenInput() funding_formset = FundingFormset(request.POST, initial=[{}]) consent_form = ConsentForm(request.POST) if (form.is_valid() and allocation_form.is_valid() and funding_formset.is_valid() and consent_form.is_valid()): # title, description, typeId, fieldId project = form.cleaned_data.copy() allocation_data = allocation_form.cleaned_data.copy() # let's check that any provided nickname is unique project["nickname"] = project["nickname"].strip() nickname_valid = (project["nickname"] and ProjectExtras.objects.filter( nickname=project["nickname"]).count() < 1 and Project.objects.filter( nickname=project["nickname"]).count() < 1) if not nickname_valid: form.add_error("__all__", "Project nickname unavailable") return render(request, "projects/create_project.html", {"form": form}) # pi pi_user_id = mapper.get_portal_user_id(request.user.username) project["piId"] = pi_user_id # allocations allocation = { "resourceId": 39, "requestorId": pi_user_id, "computeRequested": 20000, "justification": allocation_data.pop("justification", None), } project["allocations"] = [allocation] project["description"] = allocation_data.pop("description", None) # source project["source"] = "Chameleon" created_project = None try: with transaction.atomic(): created_project = mapper.save_project( project, request.get_host()) _save_fundings(funding_formset, created_project["id"]) logger.info("newly created project: " + json.dumps(created_project)) messages.success(request, "Your project has been created!") return HttpResponseRedirect( reverse("projects:view_project", args=[created_project["id"]])) except: # delete project from keycloak if created_project: keycloak_client = KeycloakClient() keycloak_client.delete_project( created_project["chargeCode"]) logger.exception("Error creating project") form.add_error( "__all__", "An unexpected error occurred. Please try again") else: form.add_error( "__all__", "There were errors processing your request. " "Please see below for details.", ) else: form = ProjectCreateForm(**form_args) allocation_form = AllocationCreateForm( initial={"publication_up_to_date": True}) allocation_form.fields[ "publication_up_to_date"].widget = forms.HiddenInput() funding_formset = FundingFormset(initial=[{}]) consent_form = ConsentForm() return render( request, "projects/create_project.html", { "form": form, "allocation_form": allocation_form, "funding_formset": funding_formset, "consent_form": consent_form, }, )
def approval(request): resp = {} errors = {} status = "" if request.POST: mapper = ProjectAllocationMapper(request) data = json.loads(request.body) data["reviewer"] = request.user.username data["reviewerId"] = mapper.get_portal_user_id(request.user.username) logger.info("Allocation approval requested by admin: %s", request.user) logger.info("Allocation approval request data: %s", json.dumps(data)) validate_datestring = validators.RegexValidator(r"^\d{4}-\d{2}-\d{2}$") validate_datetimestring = validators.RegexValidator( r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$") if not data["decisionSummary"]: errors["decisionSummary"] = "Decision Summary is required." if not data["status"]: errors["status"] = "Status is required. " elif not data["status"] in [ "Pending", "pending", "Approved", "approved", "Rejected", "rejected", "Waiting", "waiting", ]: errors[ "status"] = 'Status must be "Pending", "pending", "Approved", "approved", "Rejected", "rejected"' else: if data["start"]: try: validate_datestring(data["start"]) except ValidationError: errors[ "start"] = 'Start date must be a valid date string e.g. "2015-05-20" .' elif data["status"].lower() == "approved": errors["start"] = "Start date is required." if data["end"]: try: validate_datestring(data["end"]) except ValidationError: errors[ "end"] = 'Start date must be a valid date string e.g. "2015-05-20" .' elif data["status"].lower() == "approved": errors["end"] = "Start date is required." if data["computeAllocated"]: try: data["computeAllocated"] = int(data["computeAllocated"]) except ValueError: errors[ "computeAllocated"] = "Compute Allocated must be a number." if data["computeRequested"]: try: data["computeRequested"] = int(data["computeRequested"]) except ValueError: errors[ "computeRequested"] = "Compute Requested must be a number." if data["storageAllocated"]: try: data["storageAllocated"] = int(data["storageAllocated"]) except ValueError: errors[ "storageAllocated"] = "Storage Allocated must be a number." if data["storageRequested"]: try: data["storageRequested"] = int(data["storageRequested"]) except ValueError: errors[ "storageRequested"] = "Storage Requested must be a number." if data["memoryAllocated"]: try: data["memoryAllocated"] = int(data["memoryAllocated"]) except ValueError: errors[ "memoryAllocated"] = "Memory Allocated must be a number." if data["memoryRequested"]: try: data["memoryRequested"] = int(data["memoryRequested"]) except ValueError: errors[ "memoryRequested"] = "Memory Requested must be a number." if data["projectId"]: try: data["projectId"] = int(data["projectId"]) except ValueError: errors["projectId"] = "Project id must be number." else: errors["projectId"] = "Project id is required." if not data["project"]: errors["project"] = "Project charge code is required." if data["reviewerId"]: try: data["reviewerId"] = int(data["reviewerId"]) except ValueError: errors["reviewerId"] = "Reviewer id must be number." else: errors["reviewerId"] = "Reviewer id is required." if not data["reviewer"]: errors["reviewer"] = "Reviewer username is required." if data["dateRequested"]: try: validate_datetimestring(data["dateRequested"]) except ValidationError: errors[ "dateRequested"] = 'Requested date must be a valid date string e.g. "2015-05-20T05:00:00Z" .' # else: # errors['dateRequested'] = 'Requested date is required.' if data["dateReviewed"]: try: validate_datestring(data["dateReviewed"]) except ValidationError: errors[ "dateReviewed"] = 'Reviewed date must be a valid date string e.g. "2015-05-20" .' else: errors["dateReviewed"] = "Reviewed date is required." if len(errors) == 0: # source data["source"] = "Chameleon" try: mapper.allocation_approval(data, request.get_host()) status = "success" except Exception as e: logger.exception("Error processing allocation approval.") status = "error" errors[ "message"] = "An unexpected error occurred. If this problem persists please create a help ticket." else: logger.info("Request data failed validation. %s", list(errors.values())) status = "error" else: status = "error" errors["message"] = "Only POST method allowed." resp["status"] = status resp["errors"] = errors return HttpResponse(json.dumps(resp), content_type="application/json")