class DataTableApplicationAssessorView(OfficerOrAssessorRequiredMixin, base.DataTableBaseView): """ The model of this table is not Application but Assessment. """ APPLICATION_TYPES = dict(Application.APPLICATION_TYPE_CHOICES) model = Assessment columns = [ 'application.lodgement_number', 'licence_type', 'application.applicant', 'application.application_type', 'status', 'application.lodgement_date', 'application.assigned_officer', 'assigned_assessor', 'application_pdf', 'action' ] order_columns = [ 'application.lodgement_number', [ 'application.licence_type.short_name', 'application.licence_type.name' ], [ 'application.applicant.last_name', 'application.applicant.first_name', 'application.applicant.email' ], 'application.application_type', 'status', 'application.lodgement_date', [ 'application.assigned_officer.first_name', 'application.assigned_officer.last_name', 'application.assigned_officer.email' ], [ 'assigned_assessor.first_name', 'assigned_assessor.last_name', 'assigned_assessor.email' ], '' ] columns_helpers = dict( **{ 'licence_type': { 'render': lambda self, instance: instance.application.licence_type. display_name, 'search': lambda self, search: base.build_field_query([ 'application__licence_type__short_name', 'application__licence_type__name', 'application__licence_type__version' ], search) }, 'application.lodgement_number': { 'search': lambda self, search: DataTableApplicationAssessorView. _search_lodgement_number(search), 'render': lambda self, instance: base.render_lodgement_number( instance.application) }, 'application.applicant': { 'render': lambda self, instance: render_user_name(instance.application. applicant), 'search': lambda self, search: base.build_field_query([ 'application__applicant_profile__user__last_name', 'application__applicant_profile__user__first_name' ], search), }, 'application.application_type': { 'render': lambda self, instance: self.APPLICATION_TYPES[ instance.application.application_type] }, 'application.assigned_officer': { 'render': lambda self, instance: render_user_name(instance.application. assigned_officer), 'search': lambda self, search: base.build_field_query([ 'application__assigned_officer__last_name', 'application__assigned_officer__first_name', 'application__assigned_officer__email' ], search), }, 'assigned_assessor': { 'render': lambda self, instance: render_user_name(instance. assigned_assessor), 'search': lambda self, search: base.build_field_query([ 'assigned_assessor__last_name', 'assigned_assessor__first_name', 'assigned_assessor__email' ], search), }, 'application.lodgement_date': { 'render': lambda self, instance: base.render_date(instance.application. lodgement_date), }, 'application_pdf': { 'render': lambda self, instance: base.render_application_document( instance.application) }, 'action': { 'render': lambda self, instance: DataTableApplicationAssessorView. render_action_column(instance), }, }) @staticmethod def render_action_column(obj): if obj.status == 'awaiting_assessment': return '<a href="{0}">Assess</a>'.format( reverse('wl_applications:enter_conditions_assessor', args=[obj.application.pk, obj.pk])) else: return '<a href="{0}">View (read-only)</a>'.format( reverse('wl_applications:view_assessment', args=[obj.application.pk, obj.pk])) @staticmethod def _search_lodgement_number(search): # testing to see if search term contains no spaces and two hyphens, meaning it's a lodgement number with a sequence if search and search.count(' ') == 0 and search.count('-') == 2: components = search.split('-') lodgement_number, lodgement_sequence = '-'.join( components[:2]), '-'.join(components[2:]) return Q(application__lodgement_number__icontains=lodgement_number) & \ Q(application__lodgement_sequence__icontains=lodgement_sequence) else: return Q(application__lodgement_number__icontains=search) @staticmethod def filter_licence_type(value): return Q(application__licence_type__pk=value ) if value.lower() != 'all' else None @staticmethod def filter_status(value): return Q(status=value) if value.lower() != 'all' else None def get_initial_queryset(self): groups = self.request.user.assessorgroup_set.all() assessments = self.model.objects.filter( assessor_group__in=groups).all() return assessments
class DataTableReturnsCustomerView(base.DataTableBaseView): model = Return columns = [ 'lodgement_number', 'licence.licence_type', 'lodgement_date', 'due_date', 'status', 'licence', 'action' ] order_columns = [ 'lodgement_number', ['licence.licence_type.short_name', 'licence.licence_type.name'], 'lodgement_date', 'due_date', 'status', '', '' ] columns_helpers = { 'lodgement_number': { 'render': lambda self, instance: instance.lodgement_number }, 'licence.licence_type': { 'render': lambda self, instance: instance.licence.licence_type.display_name, 'search': lambda self, search: base.build_field_query([ 'licence__licence_type__short_name', 'licence__licence_type__name', 'licence__licence_type__version' ], search) }, 'lodgement_date': { 'render': lambda self, instance: base.render_date(instance.lodgement_date) }, 'due_date': { 'render': lambda self, instance: base.render_date(instance.due_date) }, 'licence': { 'render': lambda self, instance: base.render_licence_number(instance.licence ), 'search': lambda self, search: DataTableReturnsCustomerView. _search_licence_number(search) }, 'action': { 'render': lambda self, instance: self._render_action(instance) }, 'status': { 'render': lambda self, instance: self._render_status(instance) } } @staticmethod def _render_action(instance): if instance.status == 'current': url = reverse('wl_returns:enter_return', args=(instance.pk, )) return '<a href="{0}">Enter Return</a>'.format(url) elif instance.status == 'draft': url = reverse('wl_returns:enter_return', args=(instance.pk, )) return '<a href="{0}">Edit Return</a>'.format(url) elif instance.status == 'amendment_required': url = reverse('wl_returns:enter_return', args=(instance.pk, )) return '<a href="{0}">Amend Return</a>'.format(url) else: url = reverse('wl_returns:view_return', args=(instance.pk, )) return '<a href="{0}">View Return (read-only)</a>'.format(url) @staticmethod def _render_status(instance): status = instance.status if status == 'current': if is_return_overdue(instance): return '<span class="label label-danger">Overdue</span>' elif is_return_due_soon(instance): return '<span class="label label-warning">Due soon</span>' else: return 'Current' else: suffix = ' (Nil)' if status == 'submitted' and instance.nil_return else '' return dict(Return.STATUS_CHOICES)[status] + suffix @staticmethod def _search_licence_number(search): # testing to see if search term contains no spaces and two hyphens, # meaning it's a lodgement number with a sequence if search and search.count(' ') == 0 and search.count('-') == 2: components = search.split('-') licence_number, licence_sequence = '-'.join( components[:2]), '-'.join(components[2:]) return Q(licence__licence_number__icontains=licence_number) & Q( licence__licence_sequence__icontains=licence_sequence) else: return Q(licence__licence_number__icontains=search) def get_initial_queryset(self): return Return.objects.filter( licence__holder=self.request.user).exclude(status='future')
class DataTableReturnsOfficerView(OfficerRequiredMixin, base.DataTableBaseView): model = Return columns = [ 'lodgement_number', 'licence.licence_type', 'licence.profile.user', 'lodgement_date', 'due_date', 'status', 'licence_number', 'action', ] order_columns = [ 'lodgement_number', 'licence.licence_type', ['licence.profile.user.last_name', 'licence.profile.user.first_name'], 'lodgement_date', 'due_date', 'status', '', '' ] columns_helpers = dict( base.DataTableBaseView.columns_helpers.items(), **{ 'licence.licence_type': { 'render': lambda self, instance: instance.licence.licence_type. display_name, 'search': lambda self, search: base.build_field_query([ 'licence__licence_type__short_name', 'licence__licence_type__name', 'licence__licence_type__version' ], search) }, 'lodgement_number': { 'render': lambda self, instance: instance.lodgement_number }, 'lodgement_date': { 'render': lambda self, instance: base.render_date(instance.lodgement_date ) }, 'licence.profile.user': { 'render': lambda self, instance: base.render_user_name( instance.licence.profile.user, first_name_first=False), 'search': lambda self, search: base.build_field_query([ 'licence__profile__user__last_name', 'licence__profile__user__first_name' ], search), }, 'due_date': { 'render': lambda self, instance: base.render_date(instance.due_date) }, 'status': { 'render': lambda self, instance: self._render_status(instance) }, 'licence_number': { 'render': lambda self, instance: base.render_licence_number(instance. licence), 'search': lambda self, search: DataTableReturnsOfficerView. _search_licence_number(search), }, 'action': { 'render': lambda self, instance: self._render_action(instance) } }) @staticmethod def _render_status(instance): status = instance.status if status == 'current': if is_return_overdue(instance): return '<span class="label label-danger">Overdue</span>' elif is_return_due_soon(instance): return '<span class="label label-warning">Due soon</span>' else: return 'Current' else: suffix = ' (Nil)' if status == 'submitted' and instance.nil_return else '' return dict(Return.STATUS_CHOICES)[status] + suffix @staticmethod def _render_action(instance): if instance.status == 'current' or instance.status == 'future': url = reverse('wl_returns:enter_return', args=(instance.pk, )) return '<a href="{0}">Enter Return</a>'.format(url) elif instance.status == 'draft': url = reverse('wl_returns:enter_return', args=(instance.pk, )) return '<a href="{0}">Edit Return</a>'.format(url) elif instance.status in ['submitted', 'amended', 'amendment_required']: text = 'Curate Return' url = reverse('wl_returns:curate_return', args=(instance.pk, )) return '<a href="{0}">{1}</a>'.format(url, text) else: url = reverse('wl_returns:view_return', args=(instance.pk, )) return '<a href="{0}">View Return (read-only)</a>'.format(url) @staticmethod def filter_licence_type(value): if value.lower() != 'all': return Q(return_type__licence_type__pk=value) else: return None @staticmethod def filter_status(value): if value == TablesReturnsOfficerView.STATUS_FILTER_ALL_BUT_DRAFT_OR_FUTURE: return ~Q(status__in=['draft', 'future']) elif value == TablesReturnsOfficerView.OVERDUE_FILTER: return Q(due_date__lt=datetime.date.today()) & ~Q( status__in=['future', 'submitted', 'accepted', 'declined']) elif value == 'all': return None else: return Q(status=value) @staticmethod def _search_licence_number(search): # testing to see if search term contains no spaces and two hyphens, # meaning it's a licence number with a sequence if search and search.count(' ') == 0 and search.count('-') == 2: components = search.split('-') licence_number, licence_sequence = '-'.join( components[:2]), '-'.join(components[2:]) return Q(licence__licence_number__icontains=licence_number) & Q( licence__licence_sequence__icontains=licence_sequence) else: return Q(licence__licence_number__icontains=search) def get_initial_queryset(self): return Return.objects.all()
class DataTableLicencesOfficerView(OfficerRequiredMixin, base.DataTableBaseView): model = WildlifeLicence columns = [ 'licence_number', 'licence_type', 'profile.user', 'issue_date', 'end_date', 'licence', 'cover_letter', 'renewal_letter', 'status', 'action' ] order_columns = [ 'licence_number', ['licence_type.short_name', 'licence_type.name'], ['profile.user.last_name', 'profile.user.first_name'], 'issue_date', 'end_date', '', '' ] columns_helpers = dict( base.DataTableBaseView.columns_helpers.items(), **{ 'licence_number': { 'search': lambda self, search: DataTableLicencesOfficerView. _search_licence_number(search), 'render': lambda self, instance: base.render_licence_number(instance) }, 'profile.user': { 'render': lambda self, instance: base.render_user_name( instance.profile.user, first_name_first=False), 'search': lambda self, search: base.build_field_query([ 'profile__user__last_name', 'profile__user__first_name' ], search), }, 'issue_date': { 'render': lambda self, instance: base.render_date(instance.issue_date) }, 'start_date': { 'render': lambda self, instance: base.render_date(instance.start_date) }, 'end_date': { 'render': lambda self, instance: base.render_date(instance.end_date) }, 'licence': { 'render': lambda self, instance: base.render_licence_document(instance) }, 'cover_letter': { 'render': lambda self, instance: _render_cover_letter_document(instance) }, 'renewal_letter': { 'render': lambda self, instance: self._render_renewal_letter(instance) }, 'status': { 'render': lambda self, instance: self._render_status(instance) }, 'action': { 'render': lambda self, instance: self._render_action(instance) } }) @staticmethod def filter_status(value): today = datetime.date.today() if value == TablesLicencesOfficerView.STATUS_FILTER_ACTIVE: return Q(start_date__lte=today) & Q(end_date__gte=today) elif value == TablesLicencesOfficerView.STATUS_FILTER_RENEWABLE: return Q(is_renewable=True) & Q(end_date__gte=today) & Q( end_date__lte=today + datetime.timedelta(days=30)) elif value == TablesLicencesOfficerView.STATUS_FILTER_EXPIRED: return Q(end_date__lt=today) else: return None @staticmethod def filter_licence_type(value): if value.lower() != 'all': return Q(licence_type__pk=value) else: return None @staticmethod def filter_expiry_after(value): if value: try: date = date_parse(value, dayfirst=True).date() return Q(end_date__gte=date) except: pass return None @staticmethod def filter_expiry_before(value): if value: try: date = date_parse(value, dayfirst=True).date() return Q(end_date__lte=date) except: pass return None @staticmethod def _search_licence_number(search): # testing to see if search term contains no spaces and two hyphens, # meaning it's a lodgement number with a sequence if search and search.count(' ') == 0 and search.count('-') == 2: components = search.split('-') licence_number, licence_sequence = '-'.join( components[:2]), '-'.join(components[2:]) return Q(licence_number__icontains=licence_number) & Q( licence_sequence__icontains=licence_sequence) else: return Q(licence_number__icontains=search) @staticmethod def _render_renewal_letter(instance): if instance.is_renewable: return '<a href="{0}" target="_blank">Create PDF</a><img height="20" src="{1}"></img>'. \ format(reverse('wl_main:licence_renewal_pdf', args=(instance.pk,)), static('wl/img/pdf.png')) else: return 'Not renewable' @staticmethod def _render_status(instance): if not instance.is_issued: return 'Unissued' try: application = Application.objects.get(licence=instance) replacing_application = Application.objects.get( previous_application=application) if replacing_application.application_type == 'amendment': return 'Amended' else: return 'Renewed' except Application.DoesNotExist: pass if instance.end_date is not None: expiry_days = (instance.end_date - datetime.date.today()).days if instance.end_date < datetime.date.today(): return '<span class="label label-danger">Expired</span>' elif expiry_days <= 30 and instance.is_renewable: return '<span class="label label-warning">Due for renewal</span>' else: return 'Current' else: # should not happen message = "The licence ref:{ref} pk:{pk} has no end date!".format( ref=instance.reference, pk=instance.pk) logger.exception(Exception(message)) return 'Unissued' @staticmethod def _render_action(instance): try: application = Application.objects.get(licence=instance) if Application.objects.filter( previous_application=application).exists(): return 'N/A' except Application.DoesNotExist: application = None if not instance.is_issued: return '<a href="{0}">Issue</a>'.format( reverse('wl_applications:issue_licence', args=(application.pk, ))) amend_url = reverse('wl_applications:amend_licence', args=(instance.pk, )) renew_url = reverse('wl_applications:renew_licence', args=(instance.pk, )) reissue_url = reverse('wl_applications:reissue_licence', args=(instance.pk, )) if instance.end_date is not None: expiry_days = (instance.end_date - datetime.date.today()).days if instance.is_renewable: if 30 >= expiry_days > 0: return '<a href="{0}">Amend</a> / <a href="{1}">Renew</a> / <a href="{2}">Reissue</a>'.\ format(amend_url, renew_url, reissue_url) elif expiry_days <= 30: return '<a href="{0}">Renew</a>'.format(renew_url) if instance.end_date >= datetime.date.today(): return '<a href="{0}">Amend</a> / <a href="{1}">Reissue</a>'.format( amend_url, reissue_url) else: return 'N/A' else: return '<a href="{0}">Issue</a>'.format( reverse('wl_applications:issue_licence', args=(application.pk, ))) def get_initial_queryset(self): return WildlifeLicence.objects.all()
class DataTableApplicationsOfficerView(OfficerRequiredMixin, base.DataTableApplicationBaseView): columns = [ 'lodgement_number', 'licence_type', 'applicant', 'application_type', 'processing_status', 'lodgement_date', 'assigned_officer', 'payment', 'application_pdf', 'action' ] order_columns = [ 'lodgement_number', ['licence_type.short_name', 'licence_type.name'], ['applicant.last_name', 'applicant.first_name', 'applicant.email'], 'application_type', 'processing_status', 'lodgement_date', [ 'assigned_officer.first_name', 'assigned_officer.last_name', 'assigned_officer.email' ], '' '' ] columns_helpers = dict( base.DataTableApplicationBaseView.columns_helpers.items(), **{ 'lodgement_number': { 'search': lambda self, search: DataTableApplicationsOfficerView. _search_lodgement_number(search), 'render': lambda self, instance: base.render_lodgement_number(instance), }, 'lodgement_date': { 'render': lambda self, instance: base.render_date(instance.lodgement_date ) }, 'assigned_officer': { 'search': lambda self, search: base.build_field_query([ 'assigned_officer__last_name', 'assigned_officer__first_name' ], search), 'render': lambda self, instance: base.render_user_name(instance. assigned_officer) }, 'payment': { 'render': lambda self, instance: base.render_payment( instance, self.request.build_absolute_uri( reverse('wl_dashboard:tables_applications_officer'))) }, 'application_pdf': { 'render': lambda self, instance: base.render_application_document( instance) }, 'action': { 'render': lambda self, instance: DataTableApplicationsOfficerView. _render_action_column(instance), } }) SESSION_SAVE_SETTINGS = True @staticmethod def _get_pending_processing_statuses(): return [ s[0] for s in Application.PROCESSING_STATUS_CHOICES if s[0] != 'draft' and s[0] != 'issued' and s[0] != 'declined' ] @staticmethod def filter_status(value): # officers should not see applications in draft mode. if value.lower() == TablesApplicationsOfficerView.STATUS_PENDING: return Q(processing_status__in=DataTableApplicationsOfficerView. _get_pending_processing_statuses()) return Q(processing_status=value) if value != 'all' else ~Q( customer_status='draft') @staticmethod def _search_lodgement_number(search): # testing to see if search term contains no spaces and two hyphens, meaning it's a lodgement number with a sequence if search and search.count(' ') == 0 and search.count('-') == 2: components = search.split('-') lodgement_number, lodgement_sequence = '-'.join( components[:2]), '-'.join(components[2:]) return Q(lodgement_number__icontains=lodgement_number) & Q( lodgement_sequence__icontains=lodgement_sequence) else: return Q(lodgement_number__icontains=search) @staticmethod def _render_action_column(obj): issued = obj.processing_status == 'issued' and obj.licence is not None and obj.licence.licence_document is not None discarded = obj.processing_status == 'discarded' declined = obj.processing_status == 'declined' if obj.processing_status == 'ready_for_conditions': return '<a href="{0}">Enter Conditions</a>'.format( reverse('wl_applications:enter_conditions', args=[obj.pk]), ) elif obj.processing_status == 'ready_to_issue': return '<a href="{0}">Issue Licence</a>'.format( reverse('wl_applications:issue_licence', args=[obj.pk]), ) elif any([issued, discarded, declined]): return '<a href="{0}">{1}</a>'.format( reverse('wl_applications:view_application_officer', args=[obj.pk]), 'View (read-only)') else: return '<a href="{0}">Process</a>'.format( reverse('wl_applications:process', args=[obj.pk]), ) def get_initial_queryset(self): return Application.objects.exclude( processing_status__in=['draft', 'temp']).exclude( customer_status='temp')
class DataTableLicencesOfficerView(OfficerRequiredMixin, base.DataTableBaseView): model = WildlifeLicence columns = [ 'licence_number', 'licence_type', 'profile.user', 'start_date', 'end_date', 'licence', 'cover_letter', 'renewal_letter', 'action' ] order_columns = [ 'licence_number', ['licence_type.short_name', 'licence_type.name'], ['profile.user.last_name', 'profile.user.first_name'], 'start_date', 'end_date', '', '' ] columns_helpers = dict( base.DataTableBaseView.columns_helpers.items(), **{ 'licence_number': { 'search': lambda self, search: DataTableLicencesOfficerView. _search_licence_number(search), 'render': lambda self, instance: base.render_licence_number(instance) }, 'profile.user': { 'render': lambda self, instance: base.render_user_name( instance.profile.user, first_name_first=False), 'search': lambda self, search: base.build_field_query([ 'profile__user__last_name', 'profile__user__first_name' ], search), }, 'issue_date': { 'render': lambda self, instance: base.render_date(instance.issue_date) }, 'start_date': { 'render': lambda self, instance: base.render_date(instance.start_date) }, 'end_date': { 'render': lambda self, instance: base.render_date(instance.end_date) }, 'licence': { 'render': lambda self, instance: base.render_licence_document(instance) }, 'cover_letter': { 'render': lambda self, instance: _render_cover_letter_document(instance) }, 'renewal_letter': { 'render': lambda self, instance: self._render_renewal_letter(instance) }, 'action': { 'render': lambda self, instance: self._render_action(instance) } }) @staticmethod def filter_status(value): today = datetime.date.today() if value == TableLicencesOfficerView.STATUS_FILTER_ACTIVE: return Q(start_date__lte=today) & Q(end_date__gte=today) elif value == TableLicencesOfficerView.STATUS_FILTER_RENEWABLE: return Q(is_renewable=True) & Q(end_date__gte=today) & Q( end_date__lte=today + datetime.timedelta(days=30)) elif value == TableLicencesOfficerView.STATUS_FILTER_EXPIRED: return Q(end_date__lt=today) else: return None @staticmethod def filter_licence_type(value): if value.lower() != 'all': return Q(licence_type__pk=value) else: return None @staticmethod def filter_expiry_after(value): if value: try: date = date_parse(value, dayfirst=True).date() return Q(end_date__gte=date) except: pass return None @staticmethod def filter_expiry_before(value): if value: try: date = date_parse(value, dayfirst=True).date() return Q(end_date__lte=date) except: pass return None @staticmethod def _search_licence_number(search): # testing to see if search term contains no spaces and two hyphens, meaning it's a lodgement number with a sequence if search and search.count(' ') == 0 and search.count('-') == 2: components = search.split('-') licence_number, licence_sequence = '-'.join( components[:2]), '-'.join(components[2:]) return Q(licence_number__icontains=licence_number) & Q( licence_sequence__icontains=licence_sequence) else: return Q(licence_number__icontains=search) @staticmethod def _render_renewal_letter(instance): if instance.is_renewable: return '<a href="{0}" target="_blank">Create PDF</a><img height="20" src="{1}"></img>'. \ format(reverse('wl_main:licence_renewal_pdf', args=(instance.pk,)), static('wl/img/pdf.png')) else: return 'Not renewable' @staticmethod def _render_action(instance): reissue_url = reverse('wl_applications:reissue_licence', args=(instance.pk, )) expiry_days = (instance.end_date - datetime.date.today()).days if expiry_days <= 30 and instance.is_renewable: renew_url = reverse('wl_applications:renew_licence', args=(instance.pk, )) return '<a href="{0}">Renew</a> / <a href="{1}">Reissue</a>'.format( renew_url, reissue_url) else: amend_url = reverse('wl_applications:amend_licence', args=(instance.pk, )) return '<a href="{0}">Amend</a> / <a href="{1}">Reissue</a>'.format( amend_url, reissue_url) def get_initial_queryset(self): return WildlifeLicence.objects.all()