Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dds 1691 -- New API endpoint to extend the deadline: ProjectStatus.patch #1480

Merged
merged 49 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
724322d
new functionality
rv0lt Oct 9, 2023
ef340d2
started tests
rv0lt Oct 9, 2023
ffa340b
status code
rv0lt Oct 10, 2023
5df28d6
finalized tests
rv0lt Oct 10, 2023
294d9b7
fix test
rv0lt Oct 10, 2023
9c3805a
change fixture
rv0lt Oct 10, 2023
996cc08
go back to first approach of test
rv0lt Oct 10, 2023
c410d46
improved
rv0lt Oct 11, 2023
52e8e5c
Merge branch 'dev' into DDS-1691-New-API-endpoint-ProjectStatus.put
rv0lt Oct 11, 2023
0ad3d5d
better comments
rv0lt Oct 11, 2023
c7976cb
more coverage
rv0lt Oct 12, 2023
19ec5e2
coverage
rv0lt Oct 12, 2023
fa4c46c
sprintlog
rv0lt Oct 13, 2023
261fbcf
Update dds_web/api/project.py
rv0lt Oct 13, 2023
0b531b5
Update dds_web/api/project.py
rv0lt Oct 13, 2023
5cca377
Update dds_web/api/project.py
rv0lt Oct 13, 2023
a8efc2e
Update dds_web/api/project.py
rv0lt Oct 13, 2023
7cb1d43
modified test according to comments
rv0lt Oct 13, 2023
a393914
modified test according to comments
rv0lt Oct 13, 2023
125e665
Update dds_web/api/project.py
rv0lt Oct 13, 2023
96e7368
Update dds_web/api/project.py
rv0lt Oct 13, 2023
55d40a9
Update dds_web/api/project.py
rv0lt Oct 13, 2023
4f26b2d
modified acording to comments
rv0lt Oct 13, 2023
4141b12
small fix
rv0lt Oct 13, 2023
1d0478c
black
rv0lt Oct 13, 2023
0f0bb1f
unconfirmed returns project info
rv0lt Oct 16, 2023
5df20c9
Update dds_web/api/project.py
rv0lt Oct 17, 2023
69693d5
Update dds_web/api/project.py
rv0lt Oct 17, 2023
470b3a1
moved set busy
rv0lt Oct 17, 2023
29d8eda
rollout
rv0lt Oct 19, 2023
4f4ff91
Update SPRINTLOG.md
rv0lt Oct 20, 2023
ca97094
new exceptions
rv0lt Oct 23, 2023
7cc7b17
new exceptions
rv0lt Oct 23, 2023
806e12c
default unti days
rv0lt Oct 23, 2023
181ebbc
Update dds_web/api/project.py
rv0lt Oct 23, 2023
681b4af
Update dds_web/api/project.py
rv0lt Oct 23, 2023
de4b7c5
Update dds_web/api/project.py
rv0lt Oct 23, 2023
1cc9c4d
test to match changes
rv0lt Oct 23, 2023
a4fb0f5
Update tests/api/test_project.py
rv0lt Oct 23, 2023
703fa91
feedback
rv0lt Oct 23, 2023
b3f478b
more explicative error
rv0lt Oct 23, 2023
75987af
move check for data availability
rv0lt Oct 23, 2023
bbffbd5
typo
rv0lt Oct 23, 2023
118708c
Update dds_web/api/project.py
rv0lt Oct 23, 2023
a5ab01a
Update dds_web/api/project.py
rv0lt Oct 24, 2023
78f7418
Update dds_web/api/project.py
rv0lt Oct 24, 2023
dd50770
Update dds_web/api/project.py
rv0lt Oct 24, 2023
33e78ef
fix tests
rv0lt Oct 24, 2023
494b7bc
feedback
rv0lt Oct 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions SPRINTLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,7 @@ _Nothing merged in CLI during this sprint_
- Use full DDS name in MOTD email subject ([#1477](https://github.com/ScilifelabDataCentre/dds_web/pull/1477))
- Add flag --verify-checksum to the comand in email template ([#1478])(https://github.com/ScilifelabDataCentre/dds_web/pull/1478)
- Improved email layout; Highlighted information and commands when project is released ([#1479])(https://github.com/ScilifelabDataCentre/dds_web/pull/1479)

# 2023-10-16 - 2023-10-27

- Added new API endpoint ProjectStatus.patch to extend the deadline ([#1480])(https://github.com/ScilifelabDataCentre/dds_web/pull/1480)
rv0lt marked this conversation as resolved.
Show resolved Hide resolved
129 changes: 129 additions & 0 deletions dds_web/api/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,135 @@ def post(self):

return {"message": return_message}

@auth.login_required(role=["Unit Admin", "Unit Personnel"])
@logging_bind_request
@json_required
@handle_validation_errors
@handle_db_error
def patch(self):
"""Partially update a the project status"""
# Get project ID, project and verify access
project_id = dds_web.utils.get_required_item(obj=flask.request.args, req="project")
project = dds_web.utils.collect_project(project_id=project_id)
dds_web.utils.verify_project_access(project=project)

# Get json input from request
json_input = flask.request.get_json(silent=True) # Already checked by json_required

# the status has changed at least two times,
# next time the project expires it wont change again -> error
if project.times_expired >= 2:
raise DDSArgumentError(
"Project availability limit: The maximum number of changes in data availability has been reached."
)

# Operation must be confirmed by the user - False by default
confirmed_operation = json_input.get("confirmed", False)
if not isinstance(confirmed_operation, bool):
raise DDSArgumentError(message="`confirmed` is a boolean value: True or False.")
if not confirmed_operation:
warning_message = "Operation must be confirmed before proceding."
# When not confirmed, return information about the project
project_info = ProjectInfo().get()
project_status = self.get()
json_returned = {
**project_info,
"project_status": project_status,
"warning": warning_message,
"default_unit_days": project.responsible_unit.days_in_available,
}
return json_returned

# Cannot change project status if project is busy
if project.busy:
raise ProjectBusyError(
message=(
f"The deadline for the project '{project_id}' is already in the process of being changed. "
"Please try again later. \n\nIf you know that the project is not busy, contact support."
)
)

i-oden marked this conversation as resolved.
Show resolved Hide resolved
self.set_busy(project=project, busy=True)
i-oden marked this conversation as resolved.
Show resolved Hide resolved

# Extend deadline
try:
rv0lt marked this conversation as resolved.
Show resolved Hide resolved
new_deadline_in = json_input.get(
"new_deadline_in", None
) # if not provided --> is None -> deadline is not updated

# some variable definition
send_email = False
default_unit_days = project.responsible_unit.days_in_available

# Update the deadline functionality
if new_deadline_in:
# deadline can only be extended from Available
if not project.current_status == "Available":
raise DDSArgumentError(
"You can only extend the deadline for a project that has the status 'Available'."
)

if type(new_deadline_in) is not int:
i-oden marked this conversation as resolved.
Show resolved Hide resolved
raise DDSArgumentError(
message="The deadline attribute passed should be of type Int (i.e a number)."
)

# New deadline shouldnt surpass the default unit days
if new_deadline_in > default_unit_days:
raise DDSArgumentError(
message=f"You requested the deadline to be extended {new_deadline_in} days. The number of days has to be lower than the default deadline extension number of {default_unit_days} days"
)

# the new deadline + days left shouldnt surpass 90 days
curr_date = dds_web.utils.current_time()
current_deadline = (project.current_deadline - curr_date).days
if new_deadline_in + current_deadline > 90:
raise DDSArgumentError(
message=f"You requested the deadline to be extended with {new_deadline_in} days (from {current_deadline}), giving a new total deadline of {new_deadline_in + current_deadline} days. The new deadline needs to be less than (or equal to) 90 days."
)
try:
# add a fake expire status to mimick a re-release in order to have an udpated deadline
curr_date = (
dds_web.utils.current_time()
) # call current_time before each call so it is stored with different timestamps
new_status_row = self.expire_project(
project=project,
current_time=curr_date,
deadline_in=1, # some dummy deadline bc it will re-release now again
)
project.project_statuses.append(new_status_row)

curr_date = (
dds_web.utils.current_time()
) # call current_time before each call so it is stored with different timestamps
new_status_row = self.release_project(
project=project,
current_time=curr_date,
deadline_in=new_deadline_in + current_deadline,
)
project.project_statuses.append(new_status_row)

project.busy = False # return to not busy
db.session.commit()

except (sqlalchemy.exc.OperationalError, sqlalchemy.exc.SQLAlchemyError) as err:
flask.current_app.logger.exception("Failed to extend deadline")
db.session.rollback()
raise

return_message = (
f"The project '{project.public_id}' has been given a new deadline. "
f"An e-mail notification has{' not ' if not send_email else ' '}been sent."
)
else:
# leave it for future new functionality of updating the status
return_message = "Nothing to update."
except:
self.set_busy(project=project, busy=False)
raise

return {"message": return_message}

@staticmethod
@dbsession
def set_busy(project: models.Project, busy: bool) -> None:
Expand Down
25 changes: 25 additions & 0 deletions doc/status_codes_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,31 @@
- `archive_project`
- Database or S3 issues

#### `patch`

- [Authentication errors](#authentication)
- `400 Bad Request`
- Decorators
- Json required but not provided
- Validation error
- Schemas
- Project does not exist
- Project is busy
- `extend_deadline`
- Invalid deadline
- No deadline provided
- Project is not in Available state
- Max number of times available reached
- `403 Forbidden`
- Schemas
- User does not have access to project
- `500 Internal Server Error`
- Database errors
- `delete_project`
- Database or S3 issues
- `archive_project`
- Database or S3 issues

### GetPublic

- [Authentication errors](#authentication)
Expand Down
Loading