Skip to content

Commit

Permalink
Add contribution program code assignment API
Browse files Browse the repository at this point in the history
  • Loading branch information
ThiefMaster committed Oct 26, 2021
1 parent df064f0 commit 77350cb
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Improvements
- Support TLS certificates for SMTP authentication (:pr:`5100`, thanks :user:`dweinholz`)
- Add CSV/Excel contribution list exports containing affiliations (:issue:`5114`, :pr:`5118`)
- Include program codes in contribution PDFs and spreadsheets (:pr:`5126`)
- Add an API for bulk-assigning contribution program codes programmatically (:issue:`5115`,
:pr:`5120`)

Bugfixes
^^^^^^^^
Expand Down
3 changes: 3 additions & 0 deletions indico/modules/events/management/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
program_codes.RHAssignProgramCodesContributions, methods=('GET', 'POST'))
_bp.add_url_rule('/program-codes/assign/subcontributions', 'assign_program_codes_subcontributions',
program_codes.RHAssignProgramCodesSubContributions, methods=('GET', 'POST'))
# Program Codes API
_bp.add_url_rule('/api/program-codes/contributions', 'api_program_codes_contributions',
program_codes.RHProgramCodesAPIContributions, methods=('GET', 'PATCH'))


for object_type, prefixes in event_management_object_url_prefixes.items():
Expand Down
62 changes: 47 additions & 15 deletions indico/modules/events/management/controllers/program_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
# modify it under the terms of the MIT License; see the
# LICENSE file for more details.

from flask import flash, request, session
from flask import flash, jsonify, request, session
from webargs import fields
from webargs.flaskparser import abort

from indico.core.db import db
from indico.modules.events import EventLogKind, EventLogRealm
Expand All @@ -22,6 +24,7 @@
from indico.modules.events.timetable import TimetableEntry
from indico.util.i18n import _
from indico.util.placeholders import render_placeholder_info
from indico.web.args import use_kwargs
from indico.web.forms.base import FormDefaults
from indico.web.util import jsonify_data, jsonify_form, jsonify_template

Expand Down Expand Up @@ -52,6 +55,20 @@ def _process(self):
return jsonify_form(form)


def _get_update_log_data(updates):
changes = {}
fields = {}
for obj, change in updates.items():
title = getattr(obj, 'full_title', obj.title)
friendly_id = getattr(obj, 'friendly_id', None)
if friendly_id is not None:
title = f'#{friendly_id}: {title}'
key = f'obj_{obj.id}'
fields[key] = {'type': 'string', 'title': title}
changes[key] = change
return {'Changes': make_diff_log(changes, fields)}


class RHAssignProgramCodesBase(RHManageEventBase):
object_type = None
show_dates = True
Expand All @@ -64,19 +81,6 @@ def _process_args(self):
def _get_objects(self):
raise NotImplementedError

def _get_update_log_data(self, updates):
changes = {}
fields = {}
for obj, change in updates.items():
title = getattr(obj, 'full_title', obj.title)
friendly_id = getattr(obj, 'friendly_id', None)
if friendly_id is not None:
title = f'#{friendly_id}: {title}'
key = f'obj_{obj.id}'
fields[key] = {'type': 'string', 'title': title}
changes[key] = change
return {'Changes': make_diff_log(changes, fields)}

def _process(self):
if 'assign' in request.form:
updates = {}
Expand All @@ -89,7 +93,7 @@ def _process(self):
flash(_('The program codes have been successfully assigned'), 'success')
self.event.log(EventLogRealm.management, EventLogKind.change, 'Program',
'Program codes assigned to {}'.format(self.object_type.replace('-', ' ')),
session.user, data=self._get_update_log_data(updates))
session.user, data=_get_update_log_data(updates))
else:
flash(_('No codes have been changed'), 'info')
return jsonify_data()
Expand Down Expand Up @@ -158,3 +162,31 @@ def _get_objects(self):
db.func.lower(Contribution.title),
SubContribution.position)
.all())


class RHProgramCodesAPIContributions(RHManageEventBase):
"""RESTful API to bulk-update contribution codes."""

def _process_GET(self):
return jsonify({c.friendly_id: c.code for c in self.event.contributions})

@use_kwargs({
'codes': fields.Dict(keys=fields.Int, values=fields.String, required=True)
})
def _process_PATCH(self, codes):
contribs = {c.friendly_id: c
for c in Contribution.query.with_parent(self.event).filter(Contribution.friendly_id.in_(codes))}
if invalid := (codes - contribs.keys()):
abort(422, messages={'codes': [f'Invalid IDs: {", ".join(map(str, invalid))}']})

updates = {}
for friendly_id, code in codes.items():
contrib = contribs[friendly_id]
if code != contrib.code:
updates[contrib] = (contrib.code, code)
contrib.code = code

self.event.log(EventLogRealm.management, EventLogKind.change, 'Program',
'Program codes assigned to contributions',
session.user, data=_get_update_log_data(updates))
return jsonify({contrib.friendly_id: changes for contrib, changes in updates.items()})

0 comments on commit 77350cb

Please sign in to comment.