def meeting_assistant_start(request, meeting_pk=None): meeting = get_object_or_404(Meeting, pk=meeting_pk, started=None) nocheck = request.GET.get('nocheck', False) if settings.DEBUG else False for top in meeting.timetable_entries.filter(submission__isnull=False): with sudo(): recommendation_exists = Task.objects.for_submission(top.submission).filter(task_type__workflow_node__uid__in=['thesis_recommendation', 'thesis_recommendation_review', 'expedited_recommendation', 'localec_recommendation']).open().exists() if recommendation_exists and not nocheck: return render(request, 'meetings/assistant/error.html', { 'active': 'assistant', 'meeting': meeting, 'message': _('There are open recommendations. You can start the meeting assistant when all recommendations are done.'), }) with sudo(): vote_preparation_exists = Task.objects.filter( task_type__workflow_node__uid='vote_preparation' ).for_submission(top.submission).open().exists() if vote_preparation_exists and not nocheck: return render(request, 'meetings/assistant/error.html', { 'active': 'assistant', 'meeting': meeting, 'message': _('There are open vote preparations. You can start the meeting assistant when all vote preparations are done.'), }) meeting.started = timezone.now() meeting.save() on_meeting_start.send(Meeting, meeting=meeting) return redirect('ecs.meetings.views.meeting_assistant', meeting_pk=meeting.pk)
def get_reviewing_parties(sf, active=None): parties = PartyList() anonymous = get_current_user( ) and not get_current_user().profile.is_internal with sudo(): tasks = Task.objects.for_submission(sf.submission).filter( assigned_to__isnull=False, deleted_at=None).exclude(task_type__workflow_node__uid__in=( 'resubmission', 'b2_resubmission' )).order_by('created_at').select_related('task_type').distinct() if active: tasks = tasks.open() tasks = list(tasks) for task in tasks: if task.task_type.workflow_node.uid == 'external_review': parties.add(user=task.assigned_to, involvement=task.task_type.trans_name, anonymous=anonymous) else: party = Party(user=task.assigned_to, involvement=task.task_type.trans_name) if party not in parties: parties.append(party) for temp_auth in sf.submission.temp_auth.filter(end__gt=timezone.now()): parties.add(user=temp_auth.user, involvement=_('Temporary Authorization')) return parties
def create_specialist_reviews(self): task_type = TaskType.objects.get( workflow_node__uid='specialist_review', workflow_node__graph__auto_start=True) for amc in self.medical_categories.exclude(specialist=None): entries = (self.timetable_entries.filter( submission__workflow_lane=SUBMISSION_LANE_BOARD, submission__medical_categories=amc.category).exclude( submission__biased_board_members=amc.specialist).distinct( )) for entry in entries: participation, created = entry.participations.get_or_create( medical_category=amc.category, user=amc.specialist) if created: with sudo(): bm_task_exists = Task.objects.for_data( entry.submission ).filter( task_type__workflow_node__uid='specialist_review', assigned_to=amc.specialist).open().exists() if not bm_task_exists: token = task_type.workflow_node.bind( entry.submission.workflow.workflows[0] ).receive_token(None) token.task.created_by = self.expert_assignment_user token.task.assign(user=amc.specialist)
def _inner(wf): with sudo(): if Task.objects.for_data( wf.data).filter(task_type__workflow_node__uid=node_uid, **kwargs).exists(): return False return func(wf)
def emit_token(self, deadline=False, trail=()): tokens = super().emit_token(deadline=deadline, trail=trail) with sudo(): Task.objects.for_data(self.workflow.data).filter( task_type__workflow_node__uid='categorization_review').open( ).update(review_for=trail[0].task) return tokens
def _gen_submission_info(self): submissions = list( self.instance.meeting.submissions.filter( medical_categories=self.instance.category).for_board_lane(). select_related('current_submission_form').prefetch_related( 'biased_board_members').order_by('ec_number')) with sudo(): tasks = list( Task.objects.filter( content_type=ContentType.objects.get_for_model(Submission), data_id__in=[s.id for s in submissions], task_type__workflow_node__uid='specialist_review', assigned_to=self.instance.specialist, deleted_at=None).order_by('-created_at')) self._submissions_in_progress = [] self._submissions_completed = [] self._submissions_without_review = [] for submission in submissions: for task in tasks: if task.data == submission: if task.closed_at: self._submissions_completed.append(submission) else: self._submissions_in_progress.append(submission) break else: self._submissions_without_review.append(submission) if self.instance.specialist in submission.biased_board_members.all( ): submission.biased = True
def catalog(request): with sudo(): votes = Vote.objects.filter(result__in=('1', '1a'), submission_form__sponsor_agrees_to_publishing=True, published_at__isnull=False, published_at__lte=datetime.now()).order_by('-top__meeting__start', '-published_at') return render(request, 'submissions/catalog.html', { 'votes': votes, })
def test_import_export(self): with sudo(User.objects.get_or_create(username='******')[0]): sf = self.create_submission_form() buf = StringIO() serializer = Serializer() serializer.write(sf, buf) cp = serializer.read(buf) self.compare(sf, cp)
def timetable_pdf(request, meeting_pk=None): meeting = get_object_or_404(Meeting, pk=meeting_pk) filename = '{}-{}-{}.pdf'.format(slugify(meeting.title), timezone.localtime(meeting.start).strftime('%d-%m-%Y'), slugify(_('time slot'))) with sudo(): pdf = meeting.get_timetable_pdf(request) return pdf_response(pdf, filename=filename)
def allows_resubmission(self, user): s = self.submission with sudo(): if s.meetings.filter(started__isnull=False, ended=None).exists(): return False pending_vote = s.current_pending_vote has_unpublished_vote = pending_vote and not pending_vote.is_draft return self.allows_edits(user) and not has_unpublished_vote
def needs_expedited_vote_preparation(wf): with sudo(): unfinished = wf.tokens.filter(node__graph__workflows=wf, node__uid='expedited_recommendation', consumed_at=None).exists() negative = ChecklistAnswer.objects.filter( question__number='1', answer=False, checklist__submission=wf.data, checklist__blueprint__slug='expedited_review') return not unfinished and not negative.exists()
def download_document(request, meeting_pk=None, document_pk=None, view=False): meeting = get_object_or_404(Meeting, pk=meeting_pk) with sudo(): doc = get_object_or_404( Document, content_type=ContentType.objects.get_for_model(SubmissionForm), object_id__in=SubmissionForm.objects.filter( submission__in=meeting.timetable_entries.values('submission_id')), pk=document_pk ) return handle_download(request, doc, view=view)
def amendment_reviewer(notification): with sudo(): closed_tasks = Task.objects.for_data( notification.amendmentnotification).closed() try: task = closed_tasks.filter( task_type__workflow_node__uid='executive_amendment_review' ).order_by('-created_at')[0] return task.assigned_to except IndexError: pass
def delete_task(request, submission_pk=None, task_pk=None): submission = get_object_or_404(Submission, pk=submission_pk) with sudo(): task = get_object_or_404( Task.objects.for_submission(submission).open(), pk=task_pk, task_type__is_dynamic=True) task.mark_deleted() if task.task_type.is_dynamic and task.created_by and \ task.created_by != request.user: send_delete_message(task, request.user) return redirect('ecs.tasks.views.task_backlog', submission_pk=submission_pk)
def task_backlog(request, submission_pk=None): submission = get_object_or_404(Submission, pk=submission_pk) with sudo(): tasks = list( Task.objects.for_submission(submission).select_related( 'task_type', 'task_type__group', 'assigned_to', 'assigned_to__profile', 'medical_category').order_by('created_at')) return render(request, 'tasks/log.html', { 'tasks': tasks, 'submission': submission, })
def notification_list(request, meeting_pk=None): meeting = get_object_or_404(Meeting, pk=meeting_pk) b1ized = Vote.unfiltered.filter( result='1', upgrade_for__result='2', published_at__isnull=False ).select_related( 'submission_form', 'submission_form__submission', 'submission_form__submitter', 'submission_form__submitter__profile', ).order_by('submission_form__submission__ec_number') answers = NotificationAnswer.unfiltered.exclude( notification__amendmentnotification__is_substantial=True ).exclude(published_at=None).select_related( 'notification', 'notification__type', 'notification__safetynotification', 'notification__centerclosenotification' ).prefetch_related( Prefetch('notification__submission_forms', queryset=SubmissionForm.unfiltered.select_related('submission')) ).order_by( 'notification__type__position', 'notification__safetynotification__safety_type', 'published_at' ) with sudo(): start = Meeting.objects.filter(start__lt=meeting.start).aggregate( Max('protocol_sent_at'))['protocol_sent_at__max'] if start: b1ized = b1ized.filter(published_at__gt=start) answers = answers.filter(published_at__gt=start) end = meeting.protocol_sent_at if end: b1ized = b1ized.filter(published_at__lte=end) answers = answers.filter(published_at__lte=end) substantial_amendments = meeting.amendments.prefetch_related( Prefetch('submission_forms', queryset=SubmissionForm.unfiltered.select_related('submission')) ).order_by('submission_forms__submission__ec_number') return render(request, 'meetings/tabs/notifications.html', { 'meeting': meeting, 'substantial_amendments': substantial_amendments, 'b1ized': b1ized, 'answers': answers, })
def on_initial_review(sender, **kwargs): submission, submission_form = kwargs['submission'], kwargs['form'] if submission_form.is_acknowledged: send_submission_message(submission, submission.presenter, _('Acknowledgement of Receipt'), 'submissions/acknowledge_message.txt') if not submission.current_submission_form == submission_form: pending_vote = submission.current_pending_vote if pending_vote and pending_vote.is_draft: pending_vote.submission_form = submission_form pending_vote.save() submission_form.mark_current() vote = submission.current_published_vote if vote and vote.is_recessed: receivers = submission_form.get_presenting_parties().get_users( ) with sudo(): for task in Task.objects.for_submission(submission).filter( task_type__workflow_node__uid__in=[ 'categorization', 'internal_vote_review' ], assigned_to__isnull=False): receivers.add(task.assigned_to) for task in Task.objects.for_submission(submission).filter( task_type__workflow_node__uid='specialist_review', assigned_to__isnull=False).open(): receivers.add(task.assigned_to) else: receivers = submission_form.get_involved_parties().get_users() receivers = receivers.difference( [submission_form.presenter, get_current_user()]) for u in receivers: send_submission_message( submission, u, _('Changes to study EC-Nr. {ec_number}'), 'submissions/change_message.txt', reply_receiver=get_office_user(submission=submission)) else: send_submission_message(submission, submission.presenter, _('Submission not accepted'), 'submissions/decline_message.txt')
def timetable_editor(request, meeting_pk=None): meeting = get_object_or_404(Meeting, pk=meeting_pk) from ecs.meetings.tasks import _eval_timetable with sudo(): recommendations_not_done = Task.objects.for_submissions( meeting.timetable_entries.filter(submission__isnull=False).values('pk') ).filter(task_type__workflow_node__uid__in=[ 'thesis_recommendation', 'thesis_recommendation_review', 'expedited_recommendation', 'localec_recommendation' ]).open().exists() return render(request, 'meetings/timetable/editor.html', { 'meeting': meeting, 'running_optimization': bool(meeting.optimization_task_id), 'readonly': bool(meeting.optimization_task_id) or not meeting.started is None, 'score': _eval_timetable(meeting.metrics), 'recommendations_not_done': recommendations_not_done, })
def on_presenter_change(sender, **kwargs): submission = kwargs['submission'] user = kwargs['user'] old_presenter, new_presenter = kwargs['old_presenter'], kwargs[ 'new_presenter'] send_submission_message(submission, new_presenter, _('Studie {ec_number}'), 'submissions/presenter_change_new.txt') if user != old_presenter: send_submission_message(submission, old_presenter, _('Studie {ec_number}'), 'submissions/presenter_change_previous.txt') with sudo(): for task in Task.objects.for_data(submission).filter( task_type__workflow_node__uid__in=[ 'resubmission', 'b2_resubmission' ]).open(): task.assign(new_presenter)
def save(self, **kwargs): if not self.presenter_id: self.presenter = get_current_user() if not self.susar_presenter_id: self.susar_presenter = get_current_user() if not self.ec_number: with sudo(): year = timezone.now().year max_num = Submission.objects.filter(ec_number__range=( year * 10000, (year + 1) * 10000 - 1)).aggregate( models.Max('ec_number'))['ec_number__max'] if max_num is None: max_num = 10000 * year + MIN_EC_NUMBER else: year, num = divmod(max_num, 10000) max_num = year * 10000 + max(num, MIN_EC_NUMBER) # XXX: this breaks if there are more than 9999 studies per year (FMD2) self.ec_number = max_num + 1 return super().save(**kwargs)
def batch_action(request, action=None): request.sign_data.delete() if action in ['skip', 'pushback']: task_pk = request.sign_session.pop_listitem('tasks', 0) task = _get_tasks(request.user).get(pk=task_pk) if action == 'pushback' and task: task.done(choice=False) with sudo(): previous_task = task.trail.closed().exclude(pk=task.pk).order_by('-closed_at')[0] new_task = previous_task.reopen() new_task.review_for = previous_task.review_for new_task.save() elif action == 'cancel': request.sign_session.delete() url = reverse('ecs.dashboard.views.view_dashboard') if action in ['retry', 'skip', 'pushback']: url = reverse('ecs.signature.views.batch_sign', kwargs={'sign_session_id': request.sign_session.id}) return redirect(url)
def emit_token(self, *args, **kwargs): s = self.workflow.data with sudo(): tasks = Task.objects.for_data(s).filter( deleted_at=None, task_type__workflow_node__uid='expedited_recommendation') tasks.filter(assigned_to=None, closed_at=None).exclude( medical_category__in=s.medical_categories.values( 'pk')).mark_deleted() missing_cats = list( s.medical_categories.exclude( pk__in=tasks.values('medical_category_id'))) tokens = [] for cat in missing_cats: cat_tokens = super().emit_token(*args, **kwargs) for token in cat_tokens: token.task.medical_category = cat token.task.save() tokens += cat_tokens return tokens
def categorization_tasks(request, submission_pk=None): submission = get_object_or_404(Submission, pk=submission_pk) uids = ( 'gcp_review', 'insurance_review', 'legal_and_patient_review', 'statistical_review', ) created = False if 'start' in request.GET: uid = request.GET['start'] if not uid in uids: raise Http404() task_type = TaskType.objects.get(workflow_node__uid=uid, workflow_node__graph__auto_start=True) token = task_type.workflow_node.bind( submission.workflow.workflows[0]).receive_token(None) created = True task = token.task task.created_by = request.user task.save() tasks = [] for uid in uids: task_type = TaskType.objects.get(workflow_node__uid=uid, workflow_node__graph__auto_start=True) with sudo(): task = Task.objects.for_submission(submission).filter( deleted_at=None, task_type__workflow_node__uid=uid).last() tasks.append((task_type, task)) return render(request, 'checklists/categorization_tasks.html', { 'tasks': tasks, 'created': created, })
def on_categorization(sender, **kwargs): submission = kwargs['submission'] meeting = submission.schedule_to_meeting() meeting.update_assigned_categories() with sudo(): tasks = Task.objects.for_submission(submission).open() for lane, uids in LANE_TASKS.items(): if not submission.workflow_lane == lane: tasks.filter( task_type__workflow_node__uid__in=uids).mark_deleted() if submission.workflow_lane == SUBMISSION_LANE_RETROSPECTIVE_THESIS: for task in tasks.filter( task_type__workflow_node__uid='initial_review'): if task.workflow_node.graph.nodes.filter( uid='initial_thesis_review').exists(): task.mark_deleted() vote_preparation_tasks = tasks.filter( task_type__workflow_node__uid='vote_preparation') source_uid = VOTE_PREPARATION_SOURCES.get(submission.workflow_lane) for task in vote_preparation_tasks: if task.workflow_token.source.uid != source_uid: task.mark_deleted() first = not Task.unfiltered.for_data(submission).filter( task_type__workflow_node__uid='categorization', deleted_at=None, ).exclude(closed_at=None).exists() if first: specialist_reviews = Task.unfiltered.for_data(submission).filter( task_type__workflow_node__uid='specialist_review', deleted_at=None, ) entry = submission.timetable_entries.get() for task in specialist_reviews: entry.participations.create(user=task.assigned_to, task=task)
def on_study_change(sender, **kwargs): submission = kwargs['submission'] old_sf, new_sf = kwargs['old_form'], kwargs['new_form'] if not old_sf: # first version of the submission for u in new_sf.get_involved_parties().get_users().difference( [submission.presenter]): send_submission_message( submission, u, _('Submission of study EC-Nr. {ec_number}'), 'submissions/creation_message.txt', reply_receiver=submission.presenter) else: reopen = True current_vote = submission.current_published_vote if current_vote: if current_vote.result in PERMANENT_VOTE_RESULTS: reopen = False elif current_vote.result == '2': pending_vote = submission.current_pending_vote if not pending_vote or pending_vote.is_draft: reopen = False if reopen: with sudo(): initial_review_tasks = Task.objects.for_data( submission).filter( task_type__workflow_node__uid__in=( 'initial_review', 'initial_thesis_review'), deleted_at=None, ) if not initial_review_tasks.open().exists(): initial_review_tasks.order_by( '-created_at').first().reopen()
def reschedule_submission(request, submission_pk=None): submission = get_object_or_404(Submission, pk=submission_pk) form = SubmissionReschedulingForm(request.POST or None, submission=submission) if form.is_valid(): from_meeting = form.cleaned_data['from_meeting'] to_meeting = form.cleaned_data['to_meeting'] old_entry = from_meeting.timetable_entries.get(submission=submission) assert not hasattr(old_entry, 'vote') visible = (not old_entry.timetable_index is None) new_entry = to_meeting.add_entry(submission=submission, duration=old_entry.duration, title=old_entry.title, visible=visible) old_entry.participations.exclude(task=None).update(entry=new_entry) old_entry.participations.all().delete() old_entry.delete() old_experts = set(from_meeting.medical_categories .exclude(specialist=None) .filter(category__in=submission.medical_categories.values('pk')) .values_list('specialist_id', flat=True)) new_experts = set(to_meeting.medical_categories .exclude(specialist=None) .filter(category__in=submission.medical_categories.values('pk')) .values_list('specialist_id', flat=True)) with sudo(): Task.objects.for_data(submission).filter( task_type__workflow_node__uid='specialist_review', assigned_to__in=(old_experts - new_experts) ).open().mark_deleted() return redirect('view_submission', submission_pk=submission.pk) return render(request, 'meetings/reschedule.html', { 'submission': submission, 'form': form, })
def receive_token(self, *args, **kwargs): c = self.workflow.data token = super().receive_token(*args, **kwargs) token.task.assign(c.user) if c.status == 'new': with sudo(): meeting = Meeting.objects.filter( timetable_entries__submission=c.submission, started=None).order_by('start').first() price = Price.objects.get_review_price() url = reverse('ecs.tasks.views.do_task', kwargs={'task_pk': token.task.pk}) send_system_message_template( c.user, _('Request for review'), 'checklists/external_reviewer_invitation.txt', { 'task': token.task, 'meeting': meeting, 'price': price, 'ABSOLUTE_URL_PREFIX': settings.ABSOLUTE_URL_PREFIX, 'url': url }, submission=c.submission) return token
def test_submission_auth(self): ''' Test that users can only see the submissions he/she is entitled to see. Makes sure that each user group (and status of a user to a submission) only sees the submissions he/she is entitled to; Checked are role, status and type of the user in relation to the submission (anyone, submitter, sponsor, investigator, etc. ) ''' with sudo(self.anyone): self.assertEqual(Submission.objects.count(), 0) with sudo(self.submitter_user): self.assertEqual(Submission.objects.count(), 1) with sudo(self.sponsor_user): self.assertEqual(Submission.objects.count(), 1) with sudo(self.primary_investigator_user): self.assertEqual(Submission.objects.count(), 1) with sudo(self.internal_user): self.assertEqual(Submission.objects.count(), 1) with sudo(self.board_member_user): self.assertEqual(Submission.objects.count(), 1) with sudo(self.another_board_member_user): self.assertEqual(Submission.objects.count(), 0)
def is_locked(self): with sudo(): s = self.workflow.data return not s.allows_categorization()
def render(self, context): with sudo(): return self.nodelist.render(context)
def test_submission_auth(self): with sudo(self.unapproved_user): self.failUnlessEqual(Submission.objects.count(), 0) with sudo(self.anyone): self.failUnlessEqual(Submission.objects.count(), 0) with sudo(self.submitter_user): self.failUnlessEqual(Submission.objects.count(), 1) with sudo(self.sponsor_user): self.failUnlessEqual(Submission.objects.count(), 1) with sudo(self.primary_investigator_user): self.failUnlessEqual(Submission.objects.count(), 1) with sudo(self.additional_review_user): self.failUnlessEqual(Submission.objects.count(), 1) with sudo(self.internal_user): self.failUnlessEqual(Submission.objects.count(), 1) with sudo(self.external_review_user): self.failUnlessEqual(Submission.objects.count(), 1) with sudo(self.board_member_user): self.failUnlessEqual(Submission.objects.count(), 1) with sudo(self.another_board_member_user): self.failUnlessEqual(Submission.objects.count(), 0) with sudo(self.thesis_review_user): self.failUnlessEqual(Submission.objects.count(), 0) self.sf.submission.thesis = True self.sf.submission.save() with sudo(self.thesis_review_user): self.failUnlessEqual(Submission.objects.count(), 1) with sudo(self.expedited_review_user): self.failUnlessEqual(Submission.objects.count(), 0) self.sf.submission.expedited = True self.sf.submission.save() with sudo(self.thesis_review_user): self.failUnlessEqual(Submission.objects.count(), 1)
def on_vote_published(sender, **kwargs): vote = kwargs['vote'] sf = vote.submission_form if sf and not sf.is_categorized_multicentric_and_local: parties = sf.get_presenting_parties() reply_receiver = None with sudo(): try: task = Task.objects.for_data(vote).closed().filter( task_type__group__name='EC-Office').order_by( '-closed_at')[0] reply_receiver = task.assigned_to except IndexError: pass parties.send_message( _('Vote {ec_number}').format(ec_number=vote.get_ec_number()), 'submissions/vote_publish.txt', {'vote': vote}, submission=sf.submission, reply_receiver=reply_receiver) receivers = set() if (sf.is_amg and not sf.is_categorized_multicentric_and_local) or sf.is_mpg: receivers |= set(settings.ECS_AMG_MPG_VOTE_RECEIVERS) if sf.is_categorized_multicentric_and_main: investigators = sf.investigators.filter( ethics_commission__vote_receiver__isnull=False) receivers |= set( investigators.values_list('ethics_commission__vote_receiver', flat=True)) bits = ( 'AMG' if sf.is_amg else None, 'MPG' if sf.is_mpg else None, sf.eudract_number if sf.is_amg else sf.submission.ec_number, 'Votum {0}'.format(vote.result), ) name = slugify('_'.join(str(bit) for bit in bits if bit is not None)) vote_ct = ContentType.objects.get_for_model(Vote) doc = Document.objects.get(content_type=vote_ct, object_id=vote.id) vote_pdf = doc.retrieve_raw().read() attachments = ((name + '.pdf', vote_pdf, 'application/pdf'), ) template = loader.get_template('meetings/email/basg.txt') text = str(template.render({})) for receiver in receivers: deliver(receiver, subject=name, message=text, from_email=settings.DEFAULT_FROM_EMAIL, attachments=attachments) if vote.is_recessed: meeting = sf.submission.schedule_to_meeting() meeting.update_assigned_categories() with sudo(): tasks = Task.objects.for_submission(sf.submission).filter( task_type__workflow_node__uid='categorization', deleted_at=None) if tasks and not any(t for t in tasks if not t.closed_at): # XXX tasks[0].reopen() elif vote.is_permanent: with sudo(): Task.objects.for_data(sf.submission).exclude( task_type__workflow_node__uid='b2_review').open().mark_deleted( ) Task.objects.filter( content_type=ContentType.objects.get_for_model(Checklist), data_id__in=sf.submission.checklists.values( 'id')).open().mark_deleted() elif vote.result == '2': with sudo(): Task.objects.for_submission(sf.submission).filter( task_type__is_dynamic=True).open().mark_deleted() task_type = TaskType.objects.get(workflow_node__uid='b2_resubmission', workflow_node__graph__auto_start=True) task_type.workflow_node.bind( sf.submission.workflow.workflows[0]).receive_token(None)
def submission_billing(request): with sudo(): categorization_tasks = Task.objects.filter( task_type__workflow_node__uid='categorization').closed() submissions = Submission.objects.filter( pk__in=categorization_tasks.values('data_id').query) unbilled_submissions = list( submissions.filter(invoice=None).distinct().order_by('ec_number')) for submission in unbilled_submissions: submission.price = Price.objects.get_for_submission(submission) if request.method == 'POST': selected_fee = [] selected_remission = [] for submission in unbilled_submissions: if request.POST.get('bill_%s' % submission.pk, False): if submission.remission: selected_remission += [submission] else: selected_fee += [submission] xls = SimpleXLS() xls.write_row( 0, (_('amt.'), _('EC-Number'), _('company'), _('UID-Nr.'), _('EudraCT-Nr.'), _('applicant'), _('clinic'), _('sum')), header=True) if selected_fee: for i, submission in enumerate(selected_fee, 1): r = i submission_form = submission.current_submission_form xls.write_row(r, [ "%s." % i, submission.get_ec_number_display(), _get_address( submission_form, submission_form.invoice_name and 'invoice' or 'sponsor'), _get_uid_number( submission_form, submission_form.invoice_name and 'invoice' or 'sponsor'), submission_form.eudract_number or '?', submission_form.submitter_contact.full_name, _get_organizations(submission_form), submission.price.price, ]) r += 1 xls.write(r, 7, xlwt.Formula('SUM(H2:H%s)' % r)) r += 2 else: i = 0 r = 1 if selected_remission: xls.write_merge(r, r, 0, 2, _('fee-exempted submissions'), header=True) for i, submission in enumerate(selected_remission, i + 1): r += 1 submission_form = submission.current_submission_form xls.write_row(r, [ "%s." % i, submission.get_ec_number_display(), _get_address( submission_form, submission_form.invoice_name and 'invoice' or 'sponsor'), _get_uid_number( submission_form, submission_form.invoice_name and 'invoice' or 'sponsor'), submission_form.eudract_number or '?', submission_form.submitter_contact.full_name, _get_organizations(submission_form), ]) xls_buf = BytesIO() xls.save(xls_buf) doc = Document.objects.create_from_buffer( xls_buf.getvalue(), mimetype='application/vnd.ms-excel', doctype='invoice') invoice = Invoice.objects.create(document=doc) invoice.submissions = selected_fee + selected_remission return redirect('ecs.billing.views.view_invoice', invoice_pk=invoice.pk) return render(request, 'billing/submissions.html', { 'submissions': unbilled_submissions, })