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

DESK_REJECT added #1285

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
42 changes: 31 additions & 11 deletions api/app/outcome/api.py
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned up. I think there is no other print statement that would go in prod.

Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
from flask import g, request
from sqlalchemy.exc import SQLAlchemyError

from app.events.models import EventType
from app.outcome.models import Outcome, Status
from app.outcome.repository import OutcomeRepository as outcome_repository
from app.events.repository import EventRepository as event_repository
from app.users.repository import UserRepository as user_repository
from app.responses.repository import ResponseRepository as response_repository
from app.utils.emailer import email_user

from app.utils.auth import auth_required, event_admin_required
Expand All @@ -26,6 +28,7 @@ def _extract_status(outcome):
'id': fields.Integer,
'status': fields.String(attribute=_extract_status),
'timestamp': fields.DateTime(dt_format='iso8601'),
'reason': fields.String,
}

user_fields = {
Expand Down Expand Up @@ -75,6 +78,7 @@ def post(self, event_id):
req_parser = reqparse.RequestParser()
req_parser.add_argument('user_id', type=int, required=True)
req_parser.add_argument('outcome', type=str, required=True)
req_parser.add_argument('reason', type=str)
args = req_parser.parse_args()

event = event_repository.get_by_id(event_id)
Expand All @@ -85,8 +89,13 @@ def post(self, event_id):
if not user:
return errors.USER_NOT_FOUND

response = response_repository.get_submitted_by_user_id_for_event(args['user_id'], event_id)
if not response:
return errors.RESPONSE_NOT_FOUND

try:
status = Status[args['outcome']]

except KeyError:
return errors.OUTCOME_STATUS_NOT_VALID

Expand All @@ -101,20 +110,31 @@ def post(self, event_id):
event_id,
args['user_id'],
status,
g.current_user['id'])
g.current_user['id'],
reason=args['reason']
)

outcome_repository.add(outcome)
db.session.commit()

if (status == Status.REJECTED or status == Status.WAITLIST): # Email will be sent with offer for accepted candidates
email_user(
'outcome-rejected' if status == Status.REJECTED else 'outcome-waitlist',
template_parameters=dict(
host=misc.get_baobab_host()
),
event=event,
user=user,
)
if status in [Status.REJECTED, Status.WAITLIST, Status.DESK_REJECTED]:
email_template = {
Status.REJECTED: 'outcome-rejected' if not event.event_type == EventType.JOURNAL else 'outcome-journal-rejected',
Status.WAITLIST: 'outcome-waitlist',
Status.DESK_REJECTED: 'outcome-desk-rejected' if not event.event_type == EventType.JOURNAL else 'outcome-journal-desk-rejected'
}.get(status)

if email_template:
email_user(
email_template,
template_parameters=dict(
host=misc.get_baobab_host(),
reason=args['reason'],
response_id=response.id
),
event=event,
user=user

)

return outcome, 201

Expand Down
9 changes: 6 additions & 3 deletions api/app/outcome/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Status(Enum):
REVIEW = "in review"
ACCEPT_W_REVISION = "accept with minor revision"
REJECT_W_ENCOURAGEMENT = "reject with encouragement to resubmit"
DESK_REJECTED = "desk rejected"

class Outcome(db.Model):
id = db.Column(db.Integer(), primary_key = True, nullable = False)
Expand All @@ -18,7 +19,8 @@ class Outcome(db.Model):
timestamp = db.Column(db.DateTime(), nullable = False)
latest = db.Column(db.Boolean(), nullable = False)
updated_by_user_id = db.Column(db.Integer(), db.ForeignKey('app_user.id'), nullable=False)

reason = db.Column(db.String(255), nullable=True)

event = db.relationship('Event', foreign_keys=[event_id])
user = db.relationship('AppUser', foreign_keys=[user_id])
updated_by_user = db.relationship('AppUser', foreign_keys=[updated_by_user_id])
Expand All @@ -27,14 +29,15 @@ def __init__(self,
event_id,
user_id,
status,
updated_by_user_id
):
updated_by_user_id,
reason=None):
self.event_id = event_id
self.user_id = user_id
self.status = status
self.timestamp = datetime.now()
self.latest = True
self.updated_by_user_id = updated_by_user_id
self.reason = reason

def reset_latest(self):
self.latest = False
11 changes: 10 additions & 1 deletion api/app/utils/emailer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ def email_user(
event=None,
subject_parameters=None,
file_name='',
file_path=''
file_path='',
reason=None,
response_id=None
):
"""Send an email to a specified user using an email template. Handles resolving the correct language."""


if user is None:
raise ValueError('You must specify a user!')

Expand All @@ -46,8 +50,13 @@ def email_user(
template_parameters['lastname'] = user.lastname
if event is not None and 'event_name' not in template_parameters:
template_parameters['event_name'] = event.get_name(language) if event.has_specific_translation(language) else event.get_name('en')
if reason is not None and reason not in template_parameters:
template_parameters['reason'] = reason
if response_id is not None and response_id not in template_parameters:
template_parameters['response_id'] = response_id

body_text = email_template.template.format(**template_parameters)

send_mail(recipient=user.email, subject=subject, body_text=body_text, file_name=file_name, file_path=file_path)


Expand Down
57 changes: 57 additions & 0 deletions api/migrations/versions/3447b1bb8210_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""empty message

Revision ID: 3447b1bb8210
Revises: d2c160b0cbe5
Create Date: 2024-09-21 11:30:45.546768

"""

# revision identifiers, used by Alembic.
revision = '3447b1bb8210'
down_revision = 'd2c160b0cbe5'

from alembic import op
import sqlalchemy as sa


def upgrade():

op.execute("""INSERT INTO email_template (id, key, template, language, subject)
VALUES (71, 'outcome-desk-rejected', 'Dear {title} {firstname} {lastname},

Thank you very much for submitting the application, with submission number {response_id}, to the {event_name}.

We regret to inform you that your submission is desk rejected, with the following motivation by the editors:

{reason}

Best wishes,
The {event_name} Editors', 'en', '{event_name} Application Status Update')""")

op.execute("""INSERT INTO email_template (id, key, template, language, subject)
VALUES (72, 'outcome-journal-desk-rejected', 'Dear {title} {firstname} {lastname},

Thank you very much for submitting your paper with submission number {response_id} to the {event_name}.

We regret to inform you that your submission is desk rejected, with the following motivation by the editors:

{reason}

Best wishes,
The {event_name} Editors', 'en', '{event_name} Application Status Update')""")

op.execute("""INSERT INTO email_template (id, key, template, language, subject)
VALUES (73, 'outcome-journal-rejected', 'Dear {title} {firstname} {lastname},

Thank you very much for submitting your paper with submission number {response_id} to the {event_name}.

We regret to inform you that your submission is rejected, with the following motivation by the editors:

{reason}

Best wishes,
The {event_name} Editors', 'en', '{event_name} Application Status Update')""")

def downgrade():
# Remove the added email template rows
op.execute("DELETE FROM email_template WHERE key IN ('outcome-journal-rejected', 'outcome-journal-desk-rejected', 'outcome-desk-rejected')")
26 changes: 26 additions & 0 deletions api/migrations/versions/d2c160b0cbe5_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""empty message

Revision ID: d2c160b0cbe5
Revises: fb6d5f943621
Create Date: 2024-09-16 08:42:06.110593

"""

# revision identifiers, used by Alembic.
revision = 'd2c160b0cbe5'
down_revision = 'fb6d5f943621'

from alembic import op
import sqlalchemy as sa


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('outcome', sa.Column('reason', sa.String(length=255), nullable=True))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('outcome', 'reason')
# ### end Alembic commands ###
28 changes: 28 additions & 0 deletions api/migrations/versions/fb6d5f943621_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""empty message

Revision ID: fb6d5f943621
Revises: d4f153e3cea2
Create Date: 2024-09-16 07:53:51.262038

"""

# revision identifiers, used by Alembic.
revision = 'fb6d5f943621'
down_revision = 'd4f153e3cea2'

from alembic import op
import sqlalchemy as sa


def upgrade():
op.execute("CREATE TYPE outcome_status_new AS ENUM ('ACCEPTED', 'REJECTED', 'WAITLIST', 'REVIEW', 'ACCEPT_W_REVISION', 'REJECT_W_ENCOURAGEMENT', 'DESK_REJECTED')")
op.execute("ALTER TABLE outcome ALTER COLUMN status TYPE outcome_status_new USING status::text::outcome_status_new")
op.execute("DROP TYPE outcome_status")
op.execute("ALTER TYPE outcome_status_new RENAME TO outcome_status")

def downgrade():
op.execute("UPDATE outcome SET status = 'REJECTED' WHERE status = 'DESK_REJECTED'")
op.execute("CREATE TYPE outcome_status_old AS ENUM ('ACCEPTED', 'REJECTED', 'WAITLIST', 'REVIEW', 'ACCEPT_W_REVISION', 'REJECT_W_ENCOURAGEMENT')")
op.execute("ALTER TABLE outcome ALTER COLUMN status TYPE outcome_status_old USING status::text::outcome_status_old")
op.execute("DROP TYPE outcome_status")
op.execute("ALTER TYPE outcome_status_old RENAME TO outcome_status")
Loading